Fix the evaluation of RL78 complex relocs, by making immediate values be computed...
[deliverable/binutils-gdb.git] / gas / config / tc-rl78.c
index 337b819b5768cd8c35053830e2cb867f967c1dde..c9d5c9791d899c7269ba6cfaa675535904626bcf 100644 (file)
@@ -339,16 +339,35 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
   return 0;
 }
 
+int
+rl78_isa_g10 (void)
+{
+  return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G10;
+}
+
+int
+rl78_isa_g13 (void)
+{
+  return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G13;
+}
+
+int
+rl78_isa_g14 (void)
+{
+  return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G14;
+}
+
 void
-md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
+md_show_usage (FILE * stream)
 {
   fprintf (stream, _(" RL78 specific command line options:\n"));
+  fprintf (stream, _("  --mrelax          Enable link time relaxation\n"));
   fprintf (stream, _("  --mg10            Enable support for G10 variant\n"));
   fprintf (stream, _("  --mg13            Selects the G13 core.\n"));
   fprintf (stream, _("  --mg14            Selects the G14 core [default]\n"));
   fprintf (stream, _("  --mrl78           Alias for --mg14\n"));
   fprintf (stream, _("  --m32bit-doubles  [default]\n"));
-  fprintf (stream, _("  --m64bit-doubles\n"));
+  fprintf (stream, _("  --m64bit-doubles  Source code uses 64-bit doubles\n"));
 }
 
 static void
@@ -383,9 +402,12 @@ const pseudo_typeS md_pseudo_table[] =
   { NULL,      NULL,           0 }
 };
 
+static symbolS * rl78_abs_sym = NULL;
+
 void
 md_begin (void)
 {
+  rl78_abs_sym = symbol_make ("__rl78_abs__");
 }
 
 void
@@ -662,13 +684,23 @@ rl78_cons_fix_new (fragS *        frag,
     case BFD_RELOC_RL78_LO16:
     case BFD_RELOC_RL78_HI16:
       if (size != 2)
-       as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
-      type = exp->X_md;
+       {
+         /* Fixups to assembler generated expressions do not use %hi or %lo.  */
+         if (frag->fr_file)
+           as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
+       }
+      else
+       type = exp->X_md;
       break;
     case BFD_RELOC_RL78_HI8:
       if (size != 1)
-       as_bad (_("%%hi8 only applies to .byte"));
-      type = exp->X_md;
+       {
+         /* Fixups to assembler generated expressions do not use %hi or %lo.  */
+         if (frag->fr_file)
+           as_bad (_("%%hi8 only applies to .byte"));
+       }
+      else
+       type = exp->X_md;
       break;
     default:
       break;
@@ -823,7 +855,7 @@ rl78_frag_fix_value (fragS *    fragP,
 /* Estimate how big the opcode is after this relax pass.  The return
    value is the difference between fr_fix and the actual size.  We
    compute the total size in rl78_relax_frag and store it in fr_subtype,
-   sowe only need to subtract fx_fix and return it.  */
+   so we only need to subtract fx_fix and return it.  */
 
 int
 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
@@ -960,8 +992,8 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
   fragP->fr_subtype = newsize;
   tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
   return newsize - oldsize;
- }
+}
+
 /* This lets us test for the opcode type and the desired size in a
    switch statement.  */
 #define OPCODE(type,size) ((type) * 16 + (size))
@@ -995,12 +1027,12 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
   /* We used a new frag for this opcode, so the opcode address should
      be the frag address.  */
   mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
-  tprintf("\033[32mmypc: 0x%x\033[0m\n", (int)mypc);
+  tprintf ("\033[32mmypc: 0x%x\033[0m\n", (int)mypc);
 
   /* Try to get the target address.  If we fail here, we just use the
      largest format.  */
   if (rl78_frag_fix_value (fragP, segment, 0, & addr0,
-                        fragP->tc_frag_data->relax[ri].type != RL78_RELAX_BRANCH, 0))
+                          fragP->tc_frag_data->relax[ri].type != RL78_RELAX_BRANCH, 0))
     {
       /* We don't know the target address.  */
       keep_reloc = 1;
@@ -1211,7 +1243,17 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
   reloc[rp]->address       = fixp->fx_frag->fr_address + fixp->fx_where;       \
   reloc[++rp] = NULL
 #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
-#define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
+
+  /* FIXME: We cannot do the normal thing for an immediate value reloc,
+     ie creating a RL78_SYM reloc in the *ABS* section with an offset
+     equal to the immediate value we want to store.  This fails because
+     the reloc processing in bfd_perform_relocation and bfd_install_relocation
+     will short circuit such relocs and never pass them on to the special
+     reloc processing code.  So instead we create a RL78_SYM reloc against
+     the __rl78_abs__ symbol and arrange for the linker scripts to place
+     this symbol at address 0.  */
+#define OPIMM(IMM) OPX (BFD_RELOC_RL78_SYM, symbol_get_bfdsym (rl78_abs_sym), IMM)
+      
 #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
 #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
 
@@ -1358,6 +1400,7 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
                      val);
       /* Fall through.  */
     case BFD_RELOC_8:
+    case BFD_RELOC_RL78_SADDR: /* We need to store the 8 LSB, but this works.  */
       op[0] = val;
       break;
 
This page took 0.033597 seconds and 4 git commands to generate.