MIPS/GAS: Don't convert RELA JALR relocations on R6
[deliverable/binutils-gdb.git] / gas / config / tc-spu.c
index 681bc20ddced6b9837fbb3d1046fa5232d20d07d..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 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 "opcode/spu.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"
@@ -45,16 +44,17 @@ 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;
 };
 
 static const char *get_imm (const char *param, struct spu_insn *insn, int arg);
 static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
                            int accept_expr);
   enum spu_insns tag;
 };
 
 static const char *get_imm (const char *param, struct spu_insn *insn, int arg);
 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);
 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 struct hash_control *op_hash = NULL;
 
 extern char *myname;
 static struct hash_control *op_hash = NULL;
@@ -83,22 +83,30 @@ 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'},
   {"ffloat", float_cons, 'f'},
   {"global", s_globl, 0},
   {"half", cons, 2},
   {"def", s_set, 0},
   {"dfloat", float_cons, 'd'},
   {"ffloat", float_cons, 'f'},
   {"global", s_globl, 0},
   {"half", cons, 2},
-  {"bss", s_lcomm_bytes, 1},
-  {"string", stringer, 1},
-  {"word", cons, 4},
+  {"int", spu_cons, 4},
+  {"long", spu_cons, 4},
+  {"quad", spu_cons, 8},
+  {"string", stringer, 8 + 1},
+  {"word", spu_cons, 4},
   /* Force set to be treated as an instruction.  */
   {"set", NULL, 0},
   {".set", s_set, 0},
   /* Force set to be treated as an instruction.  */
   {"set", NULL, 0},
   {".set", s_set, 0},
-  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 }, 
-  {"loc", dwarf2_directive_loc, 0}, 
+  /* Likewise for eqv.  */
+  {"eqv", NULL, 0},
+  {".eqv", s_set, -1},
   {0,0,0}
 };
 
   {0,0,0}
 };
 
+/* Bits plugged into branch instruction offset field.  */
+unsigned int brinfo;
+
 void
 md_begin (void)
 {
 void
 md_begin (void)
 {
@@ -115,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"),
@@ -147,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)
     {
@@ -236,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;
@@ -262,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 */
 
@@ -298,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);
@@ -336,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);
@@ -344,28 +363,29 @@ 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,
                            &insn.exp[i],
                            pcrel,
                            reloc);
        fixP = fix_new_exp (frag_now,
                            thisfrag - frag_now->fr_literal,
                            4,
                            &insn.exp[i],
                            pcrel,
                            reloc);
-       fixP->tc_fix_data = insn.reloc_arg[i];
+       fixP->tc_fix_data.arg_format = insn.reloc_arg[i];
+       fixP->tc_fix_data.insn_tag = insn.tag;
       }
   dwarf2_emit_insn (4);
       }
   dwarf2_emit_insn (4);
+
+  /* .brinfo lasts exactly one instruction.  */
+  brinfo = 0;
 }
 
 static int
 }
 
 static int
@@ -387,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++;
@@ -484,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')
@@ -582,37 +602,37 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
   int low = 0, high = 0;
   int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 0;
 
   int low = 0, high = 0;
   int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 0;
 
-  if (strncmp (param, "%lo(", 4) == 0)
+  if (strncasecmp (param, "%lo(", 4) == 0)
     {
       param += 3;
       low = 1;
       as_warn (_("Using old style, %%lo(expr), please change to PPC style, expr@l."));
     }
     {
       param += 3;
       low = 1;
       as_warn (_("Using old style, %%lo(expr), please change to PPC style, expr@l."));
     }
-  else if (strncmp (param, "%hi(", 4) == 0)
+  else if (strncasecmp (param, "%hi(", 4) == 0)
     {
       param += 3;
       high = 1;
       as_warn (_("Using old style, %%hi(expr), please change to PPC style, expr@h."));
     }
     {
       param += 3;
       high = 1;
       as_warn (_("Using old style, %%hi(expr), please change to PPC style, expr@h."));
     }
-  else if (strncmp (param, "%pic(", 5) == 0)
+  else if (strncasecmp (param, "%pic(", 5) == 0)
     {
       /* Currently we expect %pic(expr) == expr, so do nothing here.
     {
       /* Currently we expect %pic(expr) == expr, so do nothing here.
-       * i.e. for code loaded at address 0 $toc will be 0.  */
+        i.e. for code loaded at address 0 $toc will be 0.  */
       param += 4;
     }
       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
-       * name, it's probably a mistake.   The only way to avoid this
-       * warning is to rename the symbol.  */
+        name, it's probably a mistake.  The only way to avoid this
+        warning is to rename the symbol.  */
       struct spu_insn tmp_insn;
       const char *np = get_reg (param, &tmp_insn, arg, 0);
 
       if (np)
        syntax_error_param = np;
     }
       struct spu_insn tmp_insn;
       const char *np = get_reg (param, &tmp_insn, arg, 0);
 
       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]);
@@ -620,7 +640,7 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
   input_line_pointer = save_ptr;
 
   /* Similar to ppc_elf_suffix in tc-ppc.c.  We have so few cases to
   input_line_pointer = save_ptr;
 
   /* Similar to ppc_elf_suffix in tc-ppc.c.  We have so few cases to
-   * handle we do it inlined here. */
+     handle we do it inlined here. */
   if (param[0] == '@' && !ISALNUM (param[2]) && param[2] != '@')
     {
       if (param[1] == 'h' || param[1] == 'H')
   if (param[0] == '@' && !ISALNUM (param[2]) && param[2] != '@')
     {
       if (param[1] == 'h' || param[1] == 'H')
@@ -635,18 +655,18 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
        }
     }
 
        }
     }
 
-  val = insn->exp[reloc_i].X_add_number;
-
   if (insn->exp[reloc_i].X_op == O_constant)
     {
   if (insn->exp[reloc_i].X_op == O_constant)
     {
+      val = insn->exp[reloc_i].X_add_number;
+
       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)
@@ -672,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)
@@ -681,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;
-      if (low)
-       insn->flag[reloc_i] |= 2;
+       insn->reloc[reloc_i] = BFD_RELOC_SPU_HI16;
+      else if (low)
+       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
@@ -799,6 +768,86 @@ 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)
+{
+  expressionS exp;
+
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+  do
+    {
+      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);
+         enum bfd_reloc_code_real reloc;
+
+         /* Check for identifier@suffix+constant.  */
+         input_line_pointer += 4;
+         if (*input_line_pointer == '-' || *input_line_pointer == '+')
+           {
+             expressionS new_exp;
+
+             expression (&new_exp);
+             if (new_exp.X_op == O_constant)
+               exp.X_add_number += new_exp.X_add_number;
+           }
+
+         reloc = nbytes == 4 ? BFD_RELOC_SPU_PPU32 : BFD_RELOC_SPU_PPU64;
+         fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes,
+                      &exp, 0, reloc);
+       }
+      else
+       emit_expr (&exp, nbytes);
+    }
+  while (*input_line_pointer++ == ',');
+
+  /* Put terminator back into stream.  */
+  input_line_pointer--;
+  demand_empty_rest_of_line ();
+}
+
 int
 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
                               segT segment_type ATTRIBUTE_UNUSED)
 int
 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
                               segT segment_type ATTRIBUTE_UNUSED)
@@ -814,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)
@@ -896,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;
 
@@ -934,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;
-      if (fixP->tc_fix_data > A_P)
+      mask = 0;
+      if (fixP->tc_fix_data.arg_format > A_P)
        {
        {
-         int hi = arg_encode[fixP->tc_fix_data].hi;
-         int lo = arg_encode[fixP->tc_fix_data].lo;
+         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 (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.039013 seconds and 4 git commands to generate.