[ARC] Add XY registers, update neg instruction.
[deliverable/binutils-gdb.git] / gas / config / tc-spu.c
index 995a023df9ffdc427a34f0164edb09e78f5f8af7..24969c97abd55515a8c812ca95ca7747498a152c 100644 (file)
@@ -1,12 +1,12 @@
 /* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
 
 /* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
 
-   Copyright 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2016 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    any later version.
 
    GAS is distributed in the hope that it will be useful,
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
-#include "dwarf2dbg.h" 
+#include "dwarf2dbg.h"
 
 const struct spu_opcode spu_opcodes[] = {
 #define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
 
 const struct spu_opcode spu_opcodes[] = {
 #define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
-       { MACFORMAT, (OPCODE) << (32-11), MNEMONIC, ASMFORMAT },
+       { MACFORMAT, (OPCODE ## u) << (32-11), MNEMONIC, ASMFORMAT },
 #define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
        { MACFORMAT, ((OPCODE) << (32-11)) | ((FB) << (32-18)), MNEMONIC, ASMFORMAT },
 #include "opcode/spu-insns.h"
 #define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
        { MACFORMAT, ((OPCODE) << (32-11)) | ((FB) << (32-18)), MNEMONIC, ASMFORMAT },
 #include "opcode/spu-insns.h"
@@ -44,7 +44,7 @@ struct spu_insn
   unsigned int opcode;
   expressionS exp[MAX_RELOCS];
   int reloc_arg[MAX_RELOCS];
   unsigned int opcode;
   expressionS exp[MAX_RELOCS];
   int reloc_arg[MAX_RELOCS];
-  int flag[MAX_RELOCS];
+  bfd_reloc_code_real_type reloc[MAX_RELOCS];
   enum spu_insns tag;
 };
 
   enum spu_insns tag;
 };
 
@@ -53,6 +53,7 @@ static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
                            int accept_expr);
 static int calcop (struct spu_opcode *format, const char *param,
                   struct spu_insn *insn);
                            int accept_expr);
 static int calcop (struct spu_opcode *format, const char *param,
                   struct spu_insn *insn);
+static void spu_brinfo (int);
 static void spu_cons (int);
 
 extern char *myname;
 static void spu_cons (int);
 
 extern char *myname;
@@ -82,6 +83,7 @@ const char FLT_CHARS[] = "dDfF";
 const pseudo_typeS md_pseudo_table[] =
 {
   {"align", s_align_ptwo, 4},
 const pseudo_typeS md_pseudo_table[] =
 {
   {"align", s_align_ptwo, 4},
+  {"brinfo", spu_brinfo, 0},
   {"bss", s_lcomm_bytes, 1},
   {"def", s_set, 0},
   {"dfloat", float_cons, 'd'},
   {"bss", s_lcomm_bytes, 1},
   {"def", s_set, 0},
   {"dfloat", float_cons, 'd'},
@@ -91,7 +93,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"int", spu_cons, 4},
   {"long", spu_cons, 4},
   {"quad", spu_cons, 8},
   {"int", spu_cons, 4},
   {"long", spu_cons, 4},
   {"quad", spu_cons, 8},
-  {"string", stringer, 1},
+  {"string", stringer, 8 + 1},
   {"word", spu_cons, 4},
   /* Force set to be treated as an instruction.  */
   {"set", NULL, 0},
   {"word", spu_cons, 4},
   /* Force set to be treated as an instruction.  */
   {"set", NULL, 0},
@@ -99,11 +101,12 @@ const pseudo_typeS md_pseudo_table[] =
   /* Likewise for eqv.  */
   {"eqv", NULL, 0},
   {".eqv", s_set, -1},
   /* Likewise for eqv.  */
   {"eqv", NULL, 0},
   {".eqv", s_set, -1},
-  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 }, 
-  {"loc", dwarf2_directive_loc, 0}, 
   {0,0,0}
 };
 
   {0,0,0}
 };
 
+/* Bits plugged into branch instruction offset field.  */
+unsigned int brinfo;
+
 void
 md_begin (void)
 {
 void
 md_begin (void)
 {
@@ -120,7 +123,8 @@ md_begin (void)
     {
       /* hash each mnemonic and record its position */
 
     {
       /* hash each mnemonic and record its position */
 
-      retval = hash_insert (op_hash, spu_opcodes[i].mnemonic, (PTR)&spu_opcodes[i]);
+      retval = hash_insert (op_hash, spu_opcodes[i].mnemonic,
+                           (void *) &spu_opcodes[i]);
 
       if (retval != NULL && strcmp (retval, "exists") != 0)
        as_fatal (_("Can't hash instruction '%s':%s"),
 
       if (retval != NULL && strcmp (retval, "exists") != 0)
        as_fatal (_("Can't hash instruction '%s':%s"),
@@ -152,7 +156,7 @@ static int emulate_apuasm;
 static int use_dd2 = 1;
 
 int
 static int use_dd2 = 1;
 
 int
-md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
 {
   switch (c)
     {
 {
   switch (c)
     {
@@ -241,17 +245,17 @@ insn_fmt_string (struct spu_opcode *format)
   for (i = 1; i <= format->arg[0]; i++)
     {
       int arg = format->arg[i];
   for (i = 1; i <= format->arg[0]; i++)
     {
       int arg = format->arg[i];
-      char *exp;
-      if (i > 1 && arg != A_P && format->arg[i-1] != A_P) 
+      const char *exp;
+      if (i > 1 && arg != A_P && format->arg[i-1] != A_P)
        buf[len++] =  ',';
       if (arg == A_P)
        exp = "(";
       else if (arg < A_P)
        exp = i == syntax_error_arg ? "REG" : "reg";
        buf[len++] =  ',';
       if (arg == A_P)
        exp = "(";
       else if (arg < A_P)
        exp = i == syntax_error_arg ? "REG" : "reg";
-      else 
+      else
        exp = i == syntax_error_arg ? "IMM" : "imm";
       len += sprintf (&buf[len], "%s", exp);
        exp = i == syntax_error_arg ? "IMM" : "imm";
       len += sprintf (&buf[len], "%s", exp);
-      if (i > 1 && format->arg[i-1] == A_P) 
+      if (i > 1 && format->arg[i-1] == A_P)
        buf[len++] =  ')';
     }
   buf[len] = 0;
        buf[len++] =  ')';
     }
   buf[len] = 0;
@@ -267,7 +271,7 @@ md_assemble (char *op)
   struct spu_insn insn;
   int i;
 
   struct spu_insn insn;
   int i;
 
-  assert (op);
+  gas_assert (op);
 
   /* skip over instruction to find parameters */
 
 
   /* skip over instruction to find parameters */
 
@@ -303,7 +307,7 @@ md_assemble (char *op)
          insn.exp[i].X_add_number = 0;
          insn.exp[i].X_op = O_illegal;
          insn.reloc_arg[i] = -1;
          insn.exp[i].X_add_number = 0;
          insn.exp[i].X_op = O_illegal;
          insn.reloc_arg[i] = -1;
-         insn.flag[i] = 0;
+         insn.reloc[i] = BFD_RELOC_NONE;
        }
       insn.opcode = format->opcode;
       insn.tag = (enum spu_insns) (format - spu_opcodes);
        }
       insn.opcode = format->opcode;
       insn.tag = (enum spu_insns) (format - spu_opcodes);
@@ -341,6 +345,16 @@ md_assemble (char *op)
       as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
     }
 
       as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
     }
 
+  if (brinfo != 0
+      && (insn.tag <= M_BRASL
+         || (insn.tag >= M_BRZ && insn.tag <= M_BRHNZ))
+      && (insn.opcode & 0x7ff80) == 0
+      && (insn.reloc_arg[0] == A_R18
+         || insn.reloc_arg[0] == A_S18
+         || insn.reloc_arg[1] == A_R18
+         || insn.reloc_arg[1] == A_S18))
+    insn.opcode |= brinfo << 7;
+
   /* grow the current frag and plop in the opcode */
 
   thisfrag = frag_more (4);
   /* grow the current frag and plop in the opcode */
 
   thisfrag = frag_more (4);
@@ -349,20 +363,16 @@ md_assemble (char *op)
   /* if this instruction requires labels mark it for later */
 
   for (i = 0; i < MAX_RELOCS; i++)
   /* if this instruction requires labels mark it for later */
 
   for (i = 0; i < MAX_RELOCS; i++)
-    if (insn.reloc_arg[i] >= 0) 
+    if (insn.reloc_arg[i] >= 0)
       {
         fixS *fixP;
       {
         fixS *fixP;
-        bfd_reloc_code_real_type reloc = arg_encode[insn.reloc_arg[i]].reloc;
+        bfd_reloc_code_real_type reloc = insn.reloc[i];
        int pcrel = 0;
 
        int pcrel = 0;
 
-        if (reloc == BFD_RELOC_SPU_PCREL9a
+       if (reloc == BFD_RELOC_SPU_PCREL9a
            || reloc == BFD_RELOC_SPU_PCREL9b
            || reloc == BFD_RELOC_SPU_PCREL9b
-            || reloc == BFD_RELOC_SPU_PCREL16)
+           || reloc == BFD_RELOC_SPU_PCREL16)
          pcrel = 1;
          pcrel = 1;
-       if (insn.flag[i] == 1)
-         reloc = BFD_RELOC_SPU_HI16;
-       else if (insn.flag[i] == 2)
-         reloc = BFD_RELOC_SPU_LO16;
        fixP = fix_new_exp (frag_now,
                            thisfrag - frag_now->fr_literal,
                            4,
        fixP = fix_new_exp (frag_now,
                            thisfrag - frag_now->fr_literal,
                            4,
@@ -373,6 +383,9 @@ md_assemble (char *op)
        fixP->tc_fix_data.insn_tag = insn.tag;
       }
   dwarf2_emit_insn (4);
        fixP->tc_fix_data.insn_tag = insn.tag;
       }
   dwarf2_emit_insn (4);
+
+  /* .brinfo lasts exactly one instruction.  */
+  brinfo = 0;
 }
 
 static int
 }
 
 static int
@@ -394,7 +407,7 @@ calcop (struct spu_opcode *format, const char *param, struct spu_insn *insn)
       if (arg < A_P)
         param = get_reg (param, insn, arg, 1);
       else if (arg > A_P)
       if (arg < A_P)
         param = get_reg (param, insn, arg, 1);
       else if (arg > A_P)
-        param = get_imm (param, insn,  arg);
+        param = get_imm (param, insn, arg);
       else if (arg == A_P)
        {
          paren++;
       else if (arg == A_P)
        {
          paren++;
@@ -491,7 +504,7 @@ get_reg (const char *param, struct spu_insn *insn, int arg, int accept_expr)
       saw_prefix = 1;
       param++;
     }
       saw_prefix = 1;
       param++;
     }
-    
+
   if (arg == A_H) /* Channel */
     {
       if ((param[0] == 'c' || param[0] == 'C')
   if (arg == A_H) /* Channel */
     {
       if ((param[0] == 'c' || param[0] == 'C')
@@ -607,7 +620,7 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
         i.e. for code loaded at address 0 $toc will be 0.  */
       param += 4;
     }
         i.e. for code loaded at address 0 $toc will be 0.  */
       param += 4;
     }
-      
+
   if (*param == '$')
     {
       /* Symbols can start with $, but if this symbol matches a register
   if (*param == '$')
     {
       /* Symbols can start with $, but if this symbol matches a register
@@ -619,7 +632,7 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
       if (np)
        syntax_error_param = np;
     }
       if (np)
        syntax_error_param = np;
     }
-      
+
   save_ptr = input_line_pointer;
   input_line_pointer = (char *) param;
   expression (&insn->exp[reloc_i]);
   save_ptr = input_line_pointer;
   input_line_pointer = (char *) param;
   expression (&insn->exp[reloc_i]);
@@ -648,12 +661,12 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
 
       if (emulate_apuasm)
        {
 
       if (emulate_apuasm)
        {
-         /* Convert the value to a format we expect. */ 
+         /* Convert the value to a format we expect. */
           val <<= arg_encode[arg].rshift;
          if (arg == A_U7A)
            val = 173 - val;
          else if (arg == A_U7B)
           val <<= arg_encode[arg].rshift;
          if (arg == A_U7A)
            val = 173 - val;
          else if (arg == A_U7B)
-           val = 155 - val; 
+           val = 155 - val;
        }
 
       if (high)
        }
 
       if (high)
@@ -679,7 +692,7 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
       if (arg == A_U7A)
         val = 173 - val;
       else if (arg == A_U7B)
       if (arg == A_U7A)
         val = 173 - val;
       else if (arg == A_U7B)
-        val = 155 - val; 
+        val = 155 - val;
 
       /* Branch hints have a split encoding.  Do the bottom part. */
       if (arg == A_S11 || arg == A_S11I)
 
       /* Branch hints have a split encoding.  Do the bottom part. */
       if (arg == A_S11 || arg == A_S11I)
@@ -688,76 +701,25 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
       insn->opcode |= (((val >> arg_encode[arg].rshift)
                        & ((1 << arg_encode[arg].size) - 1))
                       << arg_encode[arg].pos);
       insn->opcode |= (((val >> arg_encode[arg].rshift)
                        & ((1 << arg_encode[arg].size) - 1))
                       << arg_encode[arg].pos);
-      insn->reloc_arg[reloc_i] = -1;
-      insn->flag[reloc_i] = 0;
     }
   else
     {
       insn->reloc_arg[reloc_i] = arg;
       if (high)
     }
   else
     {
       insn->reloc_arg[reloc_i] = arg;
       if (high)
-       insn->flag[reloc_i] = 1;
+       insn->reloc[reloc_i] = BFD_RELOC_SPU_HI16;
       else if (low)
       else if (low)
-       insn->flag[reloc_i] = 2;
+       insn->reloc[reloc_i] = BFD_RELOC_SPU_LO16;
+      else
+       insn->reloc[reloc_i] = arg_encode[arg].reloc;
     }
 
   return param;
 }
 
     }
 
   return param;
 }
 
-#define MAX_LITTLENUMS 6
-
-/* Turn a string in input_line_pointer into a floating point constant of type
-   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
-   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
- */
-char *
+const char *
 md_atof (int type, char *litP, int *sizeP)
 {
 md_atof (int type, char *litP, int *sizeP)
 {
-  int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
-  char *t;
-
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-    case 's':
-    case 'S':
-      prec = 2;
-      break;
-
-    case 'd':
-    case 'D':
-    case 'r':
-    case 'R':
-      prec = 4;
-      break;
-
-    case 'x':
-    case 'X':
-      prec = 6;
-      break;
-
-    case 'p':
-    case 'P':
-      prec = 6;
-      break;
-
-    default:
-      *sizeP = 0;
-      return _("Bad call to MD_ATOF()");
-    }
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-
-  *sizeP = prec * sizeof (LITTLENUM_TYPE);
-  for (wordP = words; prec--;)
-    {
-      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
-    }
-  return 0;
+  return ieee_md_atof (type, litP, sizeP, TRUE);
 }
 
 #ifndef WORKING_DOT_WORD
 }
 
 #ifndef WORKING_DOT_WORD
@@ -806,6 +768,39 @@ md_create_long_jump (char *ptr,
 }
 #endif
 
 }
 #endif
 
+/* Handle .brinfo <priority>,<lrlive>.  */
+static void
+spu_brinfo (int ignore ATTRIBUTE_UNUSED)
+{
+  addressT priority;
+  addressT lrlive;
+
+  priority = get_absolute_expression ();
+  SKIP_WHITESPACE ();
+
+  lrlive = 0;
+  if (*input_line_pointer == ',')
+    {
+      ++input_line_pointer;
+      lrlive = get_absolute_expression ();
+    }
+
+  if (priority > 0x1fff)
+    {
+      as_bad (_("invalid priority '%lu'"), (unsigned long) priority);
+      priority = 0;
+    }
+
+  if (lrlive > 7)
+    {
+      as_bad (_("invalid lrlive '%lu'"), (unsigned long) lrlive);
+      lrlive = 0;
+    }
+
+  brinfo = (lrlive << 13) | priority;
+  demand_empty_rest_of_line ();
+}
+
 /* Support @ppu on symbols referenced in .int/.long/.word/.quad.  */
 static void
 spu_cons (int nbytes)
 /* Support @ppu on symbols referenced in .int/.long/.word/.quad.  */
 static void
 spu_cons (int nbytes)
@@ -820,8 +815,9 @@ spu_cons (int nbytes)
 
   do
     {
 
   do
     {
-      expression (&exp);
-      if (exp.X_op == O_symbol
+      deferred_expression (&exp);
+      if ((exp.X_op == O_symbol
+          || exp.X_op == O_constant)
          && strncasecmp (input_line_pointer, "@ppu", 4) == 0)
        {
          char *p = frag_more (nbytes);
          && strncasecmp (input_line_pointer, "@ppu", 4) == 0)
        {
          char *p = frag_more (nbytes);
@@ -867,12 +863,14 @@ arelent *
 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
-  reloc = (arelent *) xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  reloc = XNEW (arelent);
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   if (fixp->fx_addsy)
     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   else if (fixp->fx_subsy)
     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
   if (fixp->fx_addsy)
     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   else if (fixp->fx_subsy)
     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
+  else
+    abort ();
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
@@ -949,6 +947,7 @@ void
 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   unsigned int res;
 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   unsigned int res;
+  unsigned int mask;
   valueT val = *valP;
   char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
 
   valueT val = *valP;
   char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
 
@@ -987,90 +986,115 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
   fixP->fx_addnumber = val;
 
 
   fixP->fx_addnumber = val;
 
+  if (fixP->fx_r_type == BFD_RELOC_SPU_PPU32
+      || fixP->fx_r_type == BFD_RELOC_SPU_PPU64
+      || fixP->fx_r_type == BFD_RELOC_SPU_ADD_PIC)
+    return;
+
   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
     {
       fixP->fx_done = 1;
       res = 0;
   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
     {
       fixP->fx_done = 1;
       res = 0;
+      mask = 0;
       if (fixP->tc_fix_data.arg_format > A_P)
        {
          int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
          int lo = arg_encode[fixP->tc_fix_data.arg_format].lo;
          if (hi > lo && ((offsetT) val < lo || (offsetT) val > hi))
            as_bad_where (fixP->fx_file, fixP->fx_line,
       if (fixP->tc_fix_data.arg_format > A_P)
        {
          int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
          int lo = arg_encode[fixP->tc_fix_data.arg_format].lo;
          if (hi > lo && ((offsetT) val < lo || (offsetT) val > hi))
            as_bad_where (fixP->fx_file, fixP->fx_line,
-                         "Relocation doesn't fit. (relocation value = 0x%lx)",
+                         _("Relocation doesn't fit. (relocation value = 0x%lx)"),
                          (long) val);
        }
 
       switch (fixP->fx_r_type)
                          (long) val);
        }
 
       switch (fixP->fx_r_type)
-        {
-        case BFD_RELOC_8:
+       {
+       case BFD_RELOC_8:
          md_number_to_chars (place, val, 1);
          return;
 
          md_number_to_chars (place, val, 1);
          return;
 
-        case BFD_RELOC_16:
+       case BFD_RELOC_16:
          md_number_to_chars (place, val, 2);
          return;
 
          md_number_to_chars (place, val, 2);
          return;
 
-        case BFD_RELOC_32:
+       case BFD_RELOC_32:
+       case BFD_RELOC_32_PCREL:
          md_number_to_chars (place, val, 4);
          return;
 
          md_number_to_chars (place, val, 4);
          return;
 
-        case BFD_RELOC_64:
+       case BFD_RELOC_64:
          md_number_to_chars (place, val, 8);
          return;
 
          md_number_to_chars (place, val, 8);
          return;
 
-        case BFD_RELOC_SPU_IMM7:
-          res = (val & 0x7f) << 14;
-          break;
-
-        case BFD_RELOC_SPU_IMM8:
-          res = (val & 0xff) << 14;
-          break;
-
-        case BFD_RELOC_SPU_IMM10:
-          res = (val & 0x3ff) << 14;
-          break;
-
-        case BFD_RELOC_SPU_IMM10W:
-          res = (val & 0x3ff0) << 10;
-          break;
-
-        case BFD_RELOC_SPU_IMM16:
-          res = (val & 0xffff) << 7;
-          break;
-
-        case BFD_RELOC_SPU_IMM16W:
-          res = (val & 0x3fffc) << 5;
-          break;
-
-        case BFD_RELOC_SPU_IMM18:
-          res = (val & 0x3ffff) << 7;
-          break;
-
-        case BFD_RELOC_SPU_PCREL9a:
-          res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
-          break;
-
-        case BFD_RELOC_SPU_PCREL9b:
-          res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
-          break;
-
-        case BFD_RELOC_SPU_PCREL16:
-          res = (val & 0x3fffc) << 5;
-          break;
-
-        default:
-          as_bad_where (fixP->fx_file, fixP->fx_line,
-                        _("reloc %d not supported by object file format"),
-                        (int) fixP->fx_r_type);
-        }
-
-      if (res != 0)
-        {
-          place[0] |= (res >> 24) & 0xff;
-          place[1] |= (res >> 16) & 0xff;
-          place[2] |= (res >> 8) & 0xff;
-          place[3] |= (res) & 0xff;
-        }
+       case BFD_RELOC_SPU_IMM7:
+         res = val << 14;
+         mask = 0x7f << 14;
+         break;
+
+       case BFD_RELOC_SPU_IMM8:
+         res = val << 14;
+         mask = 0xff << 14;
+         break;
+
+       case BFD_RELOC_SPU_IMM10:
+         res = val << 14;
+         mask = 0x3ff << 14;
+         break;
+
+       case BFD_RELOC_SPU_IMM10W:
+         res = val << 10;
+         mask = 0x3ff0 << 10;
+         break;
+
+       case BFD_RELOC_SPU_IMM16:
+         res = val << 7;
+         mask = 0xffff << 7;
+         break;
+
+       case BFD_RELOC_SPU_IMM16W:
+         res = val << 5;
+         mask = 0x3fffc << 5;
+         break;
+
+       case BFD_RELOC_SPU_IMM18:
+         res = val << 7;
+         mask = 0x3ffff << 7;
+         break;
+
+       case BFD_RELOC_SPU_PCREL9a:
+         res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
+         mask = (0x1fc >> 2) | (0x600 << 14);
+         break;
+
+       case BFD_RELOC_SPU_PCREL9b:
+         res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
+         mask = (0x1fc >> 2) | (0x600 << 5);
+         break;
+
+       case BFD_RELOC_SPU_PCREL16:
+         res = val << 5;
+         mask = 0x3fffc << 5;
+         break;
+
+       case BFD_RELOC_SPU_HI16:
+         res = val >> 9;
+         mask = 0xffff << 7;
+         break;
+
+       case BFD_RELOC_SPU_LO16:
+         res = val << 7;
+         mask = 0xffff << 7;
+         break;
+
+       default:
+         as_bad_where (fixP->fx_file, fixP->fx_line,
+                       _("reloc %d not supported by object file format"),
+                       (int) fixP->fx_r_type);
+       }
+
+      res &= mask;
+      place[0] = (place[0] & (~mask >> 24)) | ((res >> 24) & 0xff);
+      place[1] = (place[1] & (~mask >> 16)) | ((res >> 16) & 0xff);
+      place[2] = (place[2] & (~mask >> 8)) | ((res >> 8) & 0xff);
+      place[3] = (place[3] & ~mask) | (res & 0xff);
     }
 }
     }
 }
This page took 0.048839 seconds and 4 git commands to generate.