gas/
[deliverable/binutils-gdb.git] / gas / config / tc-m32c.c
index 8ee44f81b07bc5fae8e32a54fa2987d2f830450b..cae3302132e928f28274f83d7b653a628a40d4c4 100644 (file)
@@ -1,12 +1,12 @@
 /* tc-m32c.c -- Assembler for the Renesas M32C.
 /* tc-m32c.c -- Assembler for the Renesas M32C.
-   Copyright (C) 2005 Free Software Foundation.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation.
    Contributed by RedHat.
 
    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
    Contributed by RedHat.
 
    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,
@@ -19,7 +19,6 @@
    the Free Software Foundation, 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
    the Free Software Foundation, 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <stdio.h>
 #include "as.h"
 #include "subsegs.h"     
 #include "symcat.h"
 #include "as.h"
 #include "subsegs.h"     
 #include "symcat.h"
@@ -29,7 +28,6 @@
 #include "elf/common.h"
 #include "elf/m32c.h"
 #include "libbfd.h"
 #include "elf/common.h"
 #include "elf/m32c.h"
 #include "libbfd.h"
-#include "libiberty.h"
 #include "safe-ctype.h"
 
 /* Structure to hold all of the different components
 #include "safe-ctype.h"
 
 /* Structure to hold all of the different components
@@ -54,6 +52,9 @@ typedef struct
 }
 m32c_insn;
 
 }
 m32c_insn;
 
+#define rl_for(_insn) (CGEN_ATTR_CGEN_INSN_RL_TYPE_VALUE (&((_insn).insn->base->attrs)))
+#define relaxable(_insn) (CGEN_ATTR_CGEN_INSN_RELAXABLE_VALUE (&((_insn).insn->base->attrs)))
+
 const char comment_chars[]        = ";";
 const char line_comment_chars[]   = "#";
 const char line_separator_chars[] = "|";
 const char comment_chars[]        = ";";
 const char line_comment_chars[]   = "#";
 const char line_separator_chars[] = "|";
@@ -66,11 +67,15 @@ const char * md_shortopts = M32C_SHORTOPTS;
 /* assembler options */
 #define OPTION_CPU_M16C               (OPTION_MD_BASE)
 #define OPTION_CPU_M32C        (OPTION_MD_BASE + 1)
 /* assembler options */
 #define OPTION_CPU_M16C               (OPTION_MD_BASE)
 #define OPTION_CPU_M32C        (OPTION_MD_BASE + 1)
+#define OPTION_LINKRELAX       (OPTION_MD_BASE + 2)
+#define OPTION_H_TICK_HEX      (OPTION_MD_BASE + 3)
 
 struct option md_longopts[] =
 {
   { "m16c",       no_argument,       NULL, OPTION_CPU_M16C   },
   { "m32c",       no_argument,       NULL, OPTION_CPU_M32C   },
 
 struct option md_longopts[] =
 {
   { "m16c",       no_argument,       NULL, OPTION_CPU_M16C   },
   { "m32c",       no_argument,       NULL, OPTION_CPU_M32C   },
+  { "relax",      no_argument,       NULL, OPTION_LINKRELAX   },
+  { "h-tick-hex", no_argument,       NULL, OPTION_H_TICK_HEX  },
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
@@ -83,16 +88,18 @@ size_t md_longopts_size = sizeof (md_longopts);
 static unsigned long m32c_mach = bfd_mach_m16c;
 static int cpu_mach = (1 << MACH_M16C);
 static int insn_size;
 static unsigned long m32c_mach = bfd_mach_m16c;
 static int cpu_mach = (1 << MACH_M16C);
 static int insn_size;
+static int m32c_relax = 0;
 
 /* Flags to set in the elf header */
 static flagword m32c_flags = DEFAULT_FLAGS;
 
 
 /* Flags to set in the elf header */
 static flagword m32c_flags = DEFAULT_FLAGS;
 
-static unsigned int m32c_isa = (1 << ISA_M16C);
+static char default_isa = 1 << (7 - ISA_M16C);
+static CGEN_BITSET m32c_isa = {1, & default_isa};
 
 static void
 set_isa (enum isa_attr isa_num)
 {
 
 static void
 set_isa (enum isa_attr isa_num)
 {
-  m32c_isa = (1 << isa_num);
+  cgen_bitset_set (& m32c_isa, isa_num);
 }
 
 static void s_bss (int);
 }
 
 static void s_bss (int);
@@ -116,6 +123,14 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
       set_isa (ISA_M32C);
       break;
 
       set_isa (ISA_M32C);
       break;
 
+    case OPTION_LINKRELAX:
+      m32c_relax = 1;
+      break;
+
+    case OPTION_H_TICK_HEX:
+      enable_h_tick_hex = 1;
+      break;
+
     default:
       return 0;
     }
     default:
       return 0;
     }
@@ -142,6 +157,7 @@ s_bss (int ignore ATTRIBUTE_UNUSED)
 const pseudo_typeS md_pseudo_table[] =
 {
   { "bss",     s_bss,          0},
 const pseudo_typeS md_pseudo_table[] =
 {
   { "bss",     s_bss,          0},
+  { "3byte",   cons,           3 },
   { "word",    cons,           4 },
   { NULL,      NULL,           0 }
 };
   { "word",    cons,           4 },
   { NULL,      NULL,           0 }
 };
@@ -151,7 +167,7 @@ void
 md_begin (void)
 {
   /* Initialize the `cgen' interface.  */
 md_begin (void)
 {
   /* Initialize the `cgen' interface.  */
-  
+
   /* Set the machine number and endian.  */
   gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
                                          CGEN_CPU_OPEN_ENDIAN,
   /* Set the machine number and endian.  */
   gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
                                          CGEN_CPU_OPEN_ENDIAN,
@@ -179,10 +195,13 @@ m32c_md_end (void)
 {
   int i, n_nops;
 
 {
   int i, n_nops;
 
-  /* Pad with nops for objdump.  */
-  n_nops = (32 - ((insn_size) % 32)) / 8;
-  for (i = 1; i <= n_nops; i++)
-    md_assemble ("nop");
+  if (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)
+    {
+      /* Pad with nops for objdump.  */
+      n_nops = (32 - ((insn_size) % 32)) / 8;
+      for (i = 1; i <= n_nops; i++)
+       md_assemble ("nop");
+    }
 }
 
 void
 }
 
 void
@@ -315,6 +334,8 @@ md_assemble (char * str)
   static int last_insn_had_delay_slot = 0;
   m32c_insn insn;
   char *    errmsg;
   static int last_insn_had_delay_slot = 0;
   m32c_insn insn;
   char *    errmsg;
+  finished_insnS results;
+  int rl_type;
 
   if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
     return;
 
   if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
     return;
@@ -327,17 +348,50 @@ md_assemble (char * str)
   
   if (!insn.insn)
     {
   
   if (!insn.insn)
     {
-      as_bad (errmsg);
+      as_bad ("%s", errmsg);
       return;
     }
 
       return;
     }
 
+  results.num_fixups = 0;
   /* Doesn't really matter what we pass for RELAX_P here.  */
   gas_cgen_finish_insn (insn.insn, insn.buffer,
   /* Doesn't really matter what we pass for RELAX_P here.  */
   gas_cgen_finish_insn (insn.insn, insn.buffer,
-                       CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
+                       CGEN_FIELDS_BITSIZE (& insn.fields), 1, &results);
 
   last_insn_had_delay_slot
     = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
   insn_size = CGEN_INSN_BITSIZE(insn.insn);
 
   last_insn_had_delay_slot
     = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
   insn_size = CGEN_INSN_BITSIZE(insn.insn);
+
+  rl_type = rl_for (insn);
+
+  /* We have to mark all the jumps, because we need to adjust them
+     when we delete bytes, but we only need to mark the displacements
+     if they're symbolic - if they're not, we've already picked the
+     shortest opcode by now.  The linker, however, will still have to
+     check any operands to see if they're the displacement type, since
+     we don't know (nor record) *which* operands are relaxable.  */
+  if (m32c_relax
+      && rl_type != RL_TYPE_NONE
+      && (rl_type == RL_TYPE_JUMP || results.num_fixups)
+      && !relaxable (insn))
+    {
+      int reloc = 0;
+      int addend = results.num_fixups + 16 * insn_size/8;
+
+      switch (rl_for (insn))
+       {
+       case RL_TYPE_JUMP:  reloc = BFD_RELOC_M32C_RL_JUMP;  break;
+       case RL_TYPE_1ADDR: reloc = BFD_RELOC_M32C_RL_1ADDR; break;
+       case RL_TYPE_2ADDR: reloc = BFD_RELOC_M32C_RL_2ADDR; break;
+       }
+      if (insn.insn->base->num == M32C_INSN_JMP16_S
+         || insn.insn->base->num == M32C_INSN_JMP32_S)
+       addend = 0x10;
+
+      fix_new (results.frag,
+              results.addr - results.frag->fr_literal,
+              0, abs_section_sym, addend, 0,
+              reloc);
+    }
 }
 
 /* The syntax in the manual says constants begin with '#'.
 }
 
 /* The syntax in the manual says constants begin with '#'.
@@ -395,7 +449,17 @@ const relax_typeS md_relax_table[] =
  /* 15 */ {     8,      1, 1, 16 }, /* jmp32.s */
  /* 16 */ {   127,   -128, 2, 17 }, /* jmp32.b */
  /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */
  /* 15 */ {     8,      1, 1, 16 }, /* jmp32.s */
  /* 16 */ {   127,   -128, 2, 17 }, /* jmp32.b */
  /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */
- /* 18 */ {     0,      0, 4,  0 }  /* jmp32.a */
+ /* 18 */ {     0,      0, 4,  0 }, /* jmp32.a */
+
+ /* 19 */ { 32767, -32768, 3, 20 }, /* jsr16.w */
+ /* 20 */ {     0,      0, 4,  0 }, /* jsr16.a */
+ /* 21 */ { 32767, -32768, 3, 11 }, /* jsr32.w */
+ /* 22 */ {     0,      0, 4,  0 }, /* jsr32.a */
+
+ /* 23 */ {     0,      0, 3,  0 }, /* adjnz pc8 */
+ /* 24 */ {     0,      0, 4,  0 }, /* adjnz disp8 pc8 */
+ /* 25 */ {     0,      0, 5,  0 }, /* adjnz disp16 pc8 */
+ /* 26 */ {     0,      0, 6,  0 }  /* adjnz disp24 pc8 */
 };
 
 enum {
 };
 
 enum {
@@ -405,6 +469,11 @@ enum {
   M32C_MACRO_JCND16_A,
   M32C_MACRO_JCND32_W,
   M32C_MACRO_JCND32_A,
   M32C_MACRO_JCND16_A,
   M32C_MACRO_JCND32_W,
   M32C_MACRO_JCND32_A,
+  /* the digit is the array index of the pcrel byte */
+  M32C_MACRO_ADJNZ_2,
+  M32C_MACRO_ADJNZ_3,
+  M32C_MACRO_ADJNZ_4,
+  M32C_MACRO_ADJNZ_5,
 } M32C_Macros;
 
 static struct {
 } M32C_Macros;
 
 static struct {
@@ -436,7 +505,17 @@ static struct {
  /* 15 */ {  M32C_INSN_JMP32_S,     1, M32C_INSN_JMP32_A,     0 },
  /* 16 */ {  M32C_INSN_JMP32_B,     2, M32C_INSN_JMP32_A,     1 },
  /* 17 */ {  M32C_INSN_JMP32_W,     3, M32C_INSN_JMP32_A,     2 },
  /* 15 */ {  M32C_INSN_JMP32_S,     1, M32C_INSN_JMP32_A,     0 },
  /* 16 */ {  M32C_INSN_JMP32_B,     2, M32C_INSN_JMP32_A,     1 },
  /* 17 */ {  M32C_INSN_JMP32_W,     3, M32C_INSN_JMP32_A,     2 },
- /* 18 */ {  M32C_INSN_JMP32_A,     4, M32C_INSN_JMP32_A,     0 }
+ /* 18 */ {  M32C_INSN_JMP32_A,     4, M32C_INSN_JMP32_A,     0 },
+
+ /* 19 */ {  M32C_INSN_JSR16_W,     3, M32C_INSN_JSR16_A,     2 },
+ /* 20 */ {  M32C_INSN_JSR16_A,     4, M32C_INSN_JSR16_A,     0 },
+ /* 21 */ {  M32C_INSN_JSR32_W,     3, M32C_INSN_JSR32_A,     2 },
+ /* 22 */ {  M32C_INSN_JSR32_A,     4, M32C_INSN_JSR32_A,     0 },
+
+ /* 23 */ { -M32C_MACRO_ADJNZ_2,    3, -M32C_MACRO_ADJNZ_2,    0 },
+ /* 24 */ { -M32C_MACRO_ADJNZ_3,    4, -M32C_MACRO_ADJNZ_3,    0 },
+ /* 25 */ { -M32C_MACRO_ADJNZ_4,    5, -M32C_MACRO_ADJNZ_4,    0 },
+ /* 26 */ { -M32C_MACRO_ADJNZ_5,    6, -M32C_MACRO_ADJNZ_5,    0 }
 };
 #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
 
 };
 #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
 
@@ -451,11 +530,21 @@ m32c_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
 }
 
 static int
 }
 
 static int
-insn_to_subtype (int insn)
+insn_to_subtype (int inum, const CGEN_INSN *insn)
 {
   unsigned int i;
 {
   unsigned int i;
+
+  if (insn
+      && (strncmp (insn->base->mnemonic, "adjnz", 5) == 0
+         || strncmp (insn->base->mnemonic, "sbjnz", 5) == 0))
+    {
+      i = 23 + insn->base->bitsize/8 - 3;
+      /*printf("mapping %d used for %s\n", i, insn->base->mnemonic);*/
+      return i;
+    }
+
   for (i=0; i<NUM_MAPPINGS; i++)
   for (i=0; i<NUM_MAPPINGS; i++)
-    if (insn == subtype_mappings[i].insn)
+    if (inum == subtype_mappings[i].insn)
       {
        /*printf("mapping %d used\n", i);*/
        return i;
       {
        /*printf("mapping %d used\n", i);*/
        return i;
@@ -480,14 +569,14 @@ md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED)
   int where = fragP->fr_opcode - fragP->fr_literal;
 
   if (fragP->fr_subtype == 1)
   int where = fragP->fr_opcode - fragP->fr_literal;
 
   if (fragP->fr_subtype == 1)
-    fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
+    fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num, fragP->fr_cgen.insn);
 
   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
     {
       int new_insn;
 
       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
 
   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
     {
       int new_insn;
 
       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
-      fragP->fr_subtype = insn_to_subtype (new_insn);
+      fragP->fr_subtype = insn_to_subtype (new_insn, 0);
     }
 
   if (fragP->fr_cgen.insn->base
     }
 
   if (fragP->fr_cgen.insn->base
@@ -536,18 +625,26 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
   int operand;
   int new_insn;
   int where = fragP->fr_opcode - fragP->fr_literal;
   int operand;
   int new_insn;
   int where = fragP->fr_opcode - fragP->fr_literal;
+  int rl_where = fragP->fr_opcode - fragP->fr_literal;
   unsigned char *op = (unsigned char *)fragP->fr_opcode;
   unsigned char *op = (unsigned char *)fragP->fr_opcode;
+  int op_base = 0;
+  int op_op = 0;
+  int rl_addend = 0;
 
   addend = target_address_for (fragP) - (fragP->fr_address + where);
   new_insn = subtype_mappings[fragP->fr_subtype].insn;
 
   fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
 
 
   addend = target_address_for (fragP) - (fragP->fr_address + where);
   new_insn = subtype_mappings[fragP->fr_subtype].insn;
 
   fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
 
+  op_base = 0;
+
   switch (subtype_mappings[fragP->fr_subtype].insn)
     {
     case M32C_INSN_JCND16_5:
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
   switch (subtype_mappings[fragP->fr_subtype].insn)
     {
     case M32C_INSN_JCND16_5:
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
+      op_op = 1;
+      rl_addend = 0x21;
       break;
 
     case -M32C_MACRO_JCND16_5_W:
       break;
 
     case -M32C_MACRO_JCND16_5_W:
@@ -559,6 +656,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_16;
       where += 2;
       new_insn = M32C_INSN_JMP16_W;
       operand = M32C_OPERAND_LAB_8_16;
       where += 2;
       new_insn = M32C_INSN_JMP16_W;
+      op_base = 2;
+      op_op = 3;
+      rl_addend = 0x51;
       break;
 
     case -M32C_MACRO_JCND16_5_A:
       break;
 
     case -M32C_MACRO_JCND16_5_A:
@@ -568,12 +668,18 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_24;
       where += 2;
       new_insn = M32C_INSN_JMP16_A;
       operand = M32C_OPERAND_LAB_8_24;
       where += 2;
       new_insn = M32C_INSN_JMP16_A;
+      op_base = 2;
+      op_op = 3;
+      rl_addend = 0x61;
       break;
 
 
     case M32C_INSN_JCND16:
       op[2] = addend - 2;
       operand = M32C_OPERAND_LAB_16_8;
       break;
 
 
     case M32C_INSN_JCND16:
       op[2] = addend - 2;
       operand = M32C_OPERAND_LAB_16_8;
+      op_base = 0;
+      op_op = 2;
+      rl_addend = 0x31;
       break;
 
     case -M32C_MACRO_JCND16_W:
       break;
 
     case -M32C_MACRO_JCND16_W:
@@ -585,6 +691,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_16;
       where += 3;
       new_insn = M32C_INSN_JMP16_W;
       operand = M32C_OPERAND_LAB_8_16;
       where += 3;
       new_insn = M32C_INSN_JMP16_W;
+      op_base = 3;
+      op_op = 4;
+      rl_addend = 0x61;
       break;
 
     case -M32C_MACRO_JCND16_A:
       break;
 
     case -M32C_MACRO_JCND16_A:
@@ -594,17 +703,26 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_24;
       where += 3;
       new_insn = M32C_INSN_JMP16_A;
       operand = M32C_OPERAND_LAB_8_24;
       where += 3;
       new_insn = M32C_INSN_JMP16_A;
+      op_base = 3;
+      op_op = 4;
+      rl_addend = 0x71;
       break;
 
     case M32C_INSN_JMP16_S:
       op[0] = 0x60 | ((addend-2) & 0x07);
       operand = M32C_OPERAND_LAB_5_3;
       break;
 
     case M32C_INSN_JMP16_S:
       op[0] = 0x60 | ((addend-2) & 0x07);
       operand = M32C_OPERAND_LAB_5_3;
+      op_base = 0;
+      op_op = 0;
+      rl_addend = 0x10;
       break;
 
     case M32C_INSN_JMP16_B:
       op[0] = 0xfe;
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
       break;
 
     case M32C_INSN_JMP16_B:
       op[0] = 0xfe;
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x21;
       break;
 
     case M32C_INSN_JMP16_W:
       break;
 
     case M32C_INSN_JMP16_W:
@@ -612,6 +730,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       op[1] = addend - 1;
       op[2] = (addend - 1) >> 8;
       operand = M32C_OPERAND_LAB_8_16;
       op[1] = addend - 1;
       op[2] = (addend - 1) >> 8;
       operand = M32C_OPERAND_LAB_8_16;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x31;
       break;
 
     case M32C_INSN_JMP16_A:
       break;
 
     case M32C_INSN_JMP16_A:
@@ -620,11 +741,17 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       op[2] = 0;
       op[3] = 0;
       operand = M32C_OPERAND_LAB_8_24;
       op[2] = 0;
       op[3] = 0;
       operand = M32C_OPERAND_LAB_8_24;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x41;
       break;
 
     case M32C_INSN_JCND32:
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
       break;
 
     case M32C_INSN_JCND32:
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x21;
       break;
 
     case -M32C_MACRO_JCND32_W:
       break;
 
     case -M32C_MACRO_JCND32_W:
@@ -636,6 +763,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_16;
       where += 2;
       new_insn = M32C_INSN_JMP32_W;
       operand = M32C_OPERAND_LAB_8_16;
       where += 2;
       new_insn = M32C_INSN_JMP32_W;
+      op_base = 2;
+      op_op = 3;
+      rl_addend = 0x51;
       break;
 
     case -M32C_MACRO_JCND32_A:
       break;
 
     case -M32C_MACRO_JCND32_A:
@@ -645,6 +775,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       operand = M32C_OPERAND_LAB_8_24;
       where += 2;
       new_insn = M32C_INSN_JMP32_A;
       operand = M32C_OPERAND_LAB_8_24;
       where += 2;
       new_insn = M32C_INSN_JMP32_A;
+      op_base = 2;
+      op_op = 3;
+      rl_addend = 0x61;
       break;
 
 
       break;
 
 
@@ -653,12 +786,18 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       addend = ((addend-2) & 0x07);
       op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30);
       operand = M32C_OPERAND_LAB32_JMP_S;
       addend = ((addend-2) & 0x07);
       op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30);
       operand = M32C_OPERAND_LAB32_JMP_S;
+      op_base = 0;
+      op_op = 0;
+      rl_addend = 0x10;
       break;
 
     case M32C_INSN_JMP32_B:
       op[0] = 0xbb;
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
       break;
 
     case M32C_INSN_JMP32_B:
       op[0] = 0xbb;
       op[1] = addend - 1;
       operand = M32C_OPERAND_LAB_8_8;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x21;
       break;
 
     case M32C_INSN_JMP32_W:
       break;
 
     case M32C_INSN_JMP32_W:
@@ -666,6 +805,9 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       op[1] = addend - 1;
       op[2] = (addend - 1) >> 8;
       operand = M32C_OPERAND_LAB_8_16;
       op[1] = addend - 1;
       op[2] = (addend - 1) >> 8;
       operand = M32C_OPERAND_LAB_8_16;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x31;
       break;
 
     case M32C_INSN_JMP32_A:
       break;
 
     case M32C_INSN_JMP32_A:
@@ -674,6 +816,73 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       op[2] = 0;
       op[3] = 0;
       operand = M32C_OPERAND_LAB_8_24;
       op[2] = 0;
       op[3] = 0;
       operand = M32C_OPERAND_LAB_8_24;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x41;
+      break;
+
+
+    case M32C_INSN_JSR16_W:
+      op[0] = 0xf5;
+      op[1] = addend - 1;
+      op[2] = (addend - 1) >> 8;
+      operand = M32C_OPERAND_LAB_8_16;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x31;
+      break;
+
+    case M32C_INSN_JSR16_A:
+      op[0] = 0xfd;
+      op[1] = 0;
+      op[2] = 0;
+      op[3] = 0;
+      operand = M32C_OPERAND_LAB_8_24;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x41;
+      break;
+
+    case M32C_INSN_JSR32_W:
+      op[0] = 0xcf;
+      op[1] = addend - 1;
+      op[2] = (addend - 1) >> 8;
+      operand = M32C_OPERAND_LAB_8_16;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x31;
+      break;
+
+    case M32C_INSN_JSR32_A:
+      op[0] = 0xcd;
+      op[1] = 0;
+      op[2] = 0;
+      op[3] = 0;
+      operand = M32C_OPERAND_LAB_8_24;
+      op_base = 0;
+      op_op = 1;
+      rl_addend = 0x41;
+      break;
+
+    case -M32C_MACRO_ADJNZ_2:
+      rl_addend = 0x31;
+      op[2] = addend - 2;
+      operand = M32C_OPERAND_LAB_16_8;
+      break;
+    case -M32C_MACRO_ADJNZ_3:
+      rl_addend = 0x41;
+      op[3] = addend - 2;
+      operand = M32C_OPERAND_LAB_24_8;
+      break;
+    case -M32C_MACRO_ADJNZ_4:
+      rl_addend = 0x51;
+      op[4] = addend - 2;
+      operand = M32C_OPERAND_LAB_32_8;
+      break;
+    case -M32C_MACRO_ADJNZ_5:
+      rl_addend = 0x61;
+      op[5] = addend - 2;
+      operand = M32C_OPERAND_LAB_40_8;
       break;
 
 
       break;
 
 
@@ -684,18 +893,32 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
       abort();
     }
 
       abort();
     }
 
+  if (m32c_relax)
+    {
+      if (operand != M32C_OPERAND_LAB_8_24)
+       fragP->fr_offset = (fragP->fr_address + where);
+
+      fix_new (fragP,
+              rl_where,
+              0, abs_section_sym, rl_addend, 0,
+              BFD_RELOC_M32C_RL_JUMP);
+    }
+
   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
-      || operand == M32C_OPERAND_LAB_8_24)
+      || operand == M32C_OPERAND_LAB_8_24
+      || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3
+                        && operand != M32C_OPERAND_LAB32_JMP_S)))
     {
     {
-      assert (fragP->fr_cgen.insn != 0);
-      gas_cgen_record_fixup (fragP,
-                            where,
-                            fragP->fr_cgen.insn,
-                            (fragP->fr_fix - where) * 8,
-                            cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
-                                                        operand),
-                            fragP->fr_cgen.opinfo,
-                            fragP->fr_symbol, fragP->fr_offset);
+      fixS *fixP;
+      gas_assert (fragP->fr_cgen.insn != 0);
+      fixP = gas_cgen_record_fixup (fragP,
+                                   where,
+                                   fragP->fr_cgen.insn,
+                                   (fragP->fr_fix - where) * 8,
+                                   cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
+                                                               operand),
+                                   fragP->fr_cgen.opinfo,
+                                   fragP->fr_symbol, fragP->fr_offset);
     }
 }
 \f
     }
 }
 \f
@@ -738,10 +961,50 @@ md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
     int offset;
   } op_reloc_table[] = {
 
     int offset;
   } op_reloc_table[] = {
 
+    /* PC-REL relocs for 8-bit fields.  */
+    { M32C_OPERAND_LAB_8_8,    BFD_RELOC_8_PCREL, 1 },
+    { M32C_OPERAND_LAB_16_8,   BFD_RELOC_8_PCREL, 2 },
+    { M32C_OPERAND_LAB_24_8,   BFD_RELOC_8_PCREL, 3 },
+    { M32C_OPERAND_LAB_32_8,   BFD_RELOC_8_PCREL, 4 },
+    { M32C_OPERAND_LAB_40_8,   BFD_RELOC_8_PCREL, 5 },
+
+    /* PC-REL relocs for 16-bit fields.  */
+    { M32C_OPERAND_LAB_8_16,   BFD_RELOC_16_PCREL, 1 },
+
+    /* Absolute relocs for 8-bit fields.  */
+    { M32C_OPERAND_IMM_8_QI,   BFD_RELOC_8, 1 },
+    { M32C_OPERAND_IMM_16_QI,  BFD_RELOC_8, 2 },
+    { M32C_OPERAND_IMM_24_QI,  BFD_RELOC_8, 3 },
+    { M32C_OPERAND_IMM_32_QI,  BFD_RELOC_8, 4 },
+    { M32C_OPERAND_IMM_40_QI,  BFD_RELOC_8, 5 },
+    { M32C_OPERAND_IMM_48_QI,  BFD_RELOC_8, 6 },
+    { M32C_OPERAND_IMM_56_QI,  BFD_RELOC_8, 7 },
+    { M32C_OPERAND_DSP_8_S8,   BFD_RELOC_8, 1 },
+    { M32C_OPERAND_DSP_16_S8,  BFD_RELOC_8, 2 },
+    { M32C_OPERAND_DSP_24_S8,  BFD_RELOC_8, 3 },
+    { M32C_OPERAND_DSP_32_S8,  BFD_RELOC_8, 4 },
+    { M32C_OPERAND_DSP_40_S8,  BFD_RELOC_8, 5 },
+    { M32C_OPERAND_DSP_48_S8,  BFD_RELOC_8, 6 },
+    { M32C_OPERAND_DSP_8_U8,   BFD_RELOC_8, 1 },
+    { M32C_OPERAND_DSP_16_U8,  BFD_RELOC_8, 2 },
+    { M32C_OPERAND_DSP_24_U8,  BFD_RELOC_8, 3 },
+    { M32C_OPERAND_DSP_32_U8,  BFD_RELOC_8, 4 },
+    { M32C_OPERAND_DSP_40_U8,  BFD_RELOC_8, 5 },
+    { M32C_OPERAND_DSP_48_U8,  BFD_RELOC_8, 6 },
+    { M32C_OPERAND_BITBASE32_16_S11_UNPREFIXED, BFD_RELOC_8, 2 },
+    { M32C_OPERAND_BITBASE32_16_U11_UNPREFIXED, BFD_RELOC_8, 2 },
+    { M32C_OPERAND_BITBASE32_24_S11_PREFIXED, BFD_RELOC_8, 3 },
+    { M32C_OPERAND_BITBASE32_24_U11_PREFIXED, BFD_RELOC_8, 3 },
+
     /* Absolute relocs for 16-bit fields.  */
     /* Absolute relocs for 16-bit fields.  */
+    { M32C_OPERAND_IMM_8_HI,   BFD_RELOC_16, 1 },
     { M32C_OPERAND_IMM_16_HI,  BFD_RELOC_16, 2 },
     { M32C_OPERAND_IMM_24_HI,  BFD_RELOC_16, 3 },
     { M32C_OPERAND_IMM_32_HI,  BFD_RELOC_16, 4 },
     { M32C_OPERAND_IMM_16_HI,  BFD_RELOC_16, 2 },
     { M32C_OPERAND_IMM_24_HI,  BFD_RELOC_16, 3 },
     { M32C_OPERAND_IMM_32_HI,  BFD_RELOC_16, 4 },
+    { M32C_OPERAND_IMM_40_HI,  BFD_RELOC_16, 5 },
+    { M32C_OPERAND_IMM_48_HI,  BFD_RELOC_16, 6 },
+    { M32C_OPERAND_IMM_56_HI,  BFD_RELOC_16, 7 },
+    { M32C_OPERAND_IMM_64_HI,  BFD_RELOC_16, 8 },
     { M32C_OPERAND_DSP_16_S16, BFD_RELOC_16, 2 },
     { M32C_OPERAND_DSP_24_S16, BFD_RELOC_16, 3 },
     { M32C_OPERAND_DSP_32_S16, BFD_RELOC_16, 4 },
     { M32C_OPERAND_DSP_16_S16, BFD_RELOC_16, 2 },
     { M32C_OPERAND_DSP_24_S16, BFD_RELOC_16, 3 },
     { M32C_OPERAND_DSP_32_S16, BFD_RELOC_16, 4 },
@@ -750,13 +1013,27 @@ md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
     { M32C_OPERAND_DSP_16_U16, BFD_RELOC_16, 2 },
     { M32C_OPERAND_DSP_24_U16, BFD_RELOC_16, 3 },
     { M32C_OPERAND_DSP_32_U16, BFD_RELOC_16, 4 },
     { M32C_OPERAND_DSP_16_U16, BFD_RELOC_16, 2 },
     { M32C_OPERAND_DSP_24_U16, BFD_RELOC_16, 3 },
     { M32C_OPERAND_DSP_32_U16, BFD_RELOC_16, 4 },
+    { M32C_OPERAND_DSP_40_U16, BFD_RELOC_16, 5 },
+    { M32C_OPERAND_DSP_48_U16, BFD_RELOC_16, 6 },
+    { M32C_OPERAND_BITBASE32_16_S19_UNPREFIXED, BFD_RELOC_16, 2 },
+    { M32C_OPERAND_BITBASE32_16_U19_UNPREFIXED, BFD_RELOC_16, 2 },
+    { M32C_OPERAND_BITBASE32_24_S19_PREFIXED, BFD_RELOC_16, 3 },
+    { M32C_OPERAND_BITBASE32_24_U19_PREFIXED, BFD_RELOC_16, 3 },
 
     /* Absolute relocs for 24-bit fields.  */
     { M32C_OPERAND_LAB_8_24,   BFD_RELOC_24, 1 },
 
     /* Absolute relocs for 24-bit fields.  */
     { M32C_OPERAND_LAB_8_24,   BFD_RELOC_24, 1 },
+    { M32C_OPERAND_DSP_8_S24,  BFD_RELOC_24, 1 },
+    { M32C_OPERAND_DSP_8_U24,  BFD_RELOC_24, 1 },
     { M32C_OPERAND_DSP_16_U24, BFD_RELOC_24, 2 },
     { M32C_OPERAND_DSP_24_U24, BFD_RELOC_24, 3 },
     { M32C_OPERAND_DSP_32_U24, BFD_RELOC_24, 4 },
     { M32C_OPERAND_DSP_40_U24, BFD_RELOC_24, 5 },
     { M32C_OPERAND_DSP_16_U24, BFD_RELOC_24, 2 },
     { M32C_OPERAND_DSP_24_U24, BFD_RELOC_24, 3 },
     { M32C_OPERAND_DSP_32_U24, BFD_RELOC_24, 4 },
     { M32C_OPERAND_DSP_40_U24, BFD_RELOC_24, 5 },
+    { M32C_OPERAND_DSP_48_U24, BFD_RELOC_24, 6 },
+    { M32C_OPERAND_DSP_16_U20, BFD_RELOC_24, 2 },
+    { M32C_OPERAND_DSP_24_U20, BFD_RELOC_24, 3 },
+    { M32C_OPERAND_DSP_32_U20, BFD_RELOC_24, 4 },
+    { M32C_OPERAND_BITBASE32_16_U27_UNPREFIXED, BFD_RELOC_24, 2 },
+    { M32C_OPERAND_BITBASE32_24_U27_PREFIXED, BFD_RELOC_24, 3 },
 
     /* Absolute relocs for 32-bit fields.  */
     { M32C_OPERAND_IMM_16_SI,  BFD_RELOC_32, 2 },
 
     /* Absolute relocs for 32-bit fields.  */
     { M32C_OPERAND_IMM_16_SI,  BFD_RELOC_32, 2 },
@@ -776,18 +1053,86 @@ md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
         {
           fixP->fx_where += or->offset;
           fixP->fx_size -= or->offset;
         {
           fixP->fx_where += or->offset;
           fixP->fx_size -= or->offset;
+
+         if (fixP->fx_cgen.opinfo
+             && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
+           return fixP->fx_cgen.opinfo;
+
           return or->reloc;
         }
     }
 
   fprintf
     (stderr,
           return or->reloc;
         }
     }
 
   fprintf
     (stderr,
-     "Error: tc-m32c.c:md_cgen_lookup_reloc Unimplemented relocation %d\n",
-     operand->type);
+     "Error: tc-m32c.c:md_cgen_lookup_reloc Unimplemented relocation for operand %s\n",
+     operand->name);
 
   return BFD_RELOC_NONE;
 }
 
 
   return BFD_RELOC_NONE;
 }
 
+void
+m32c_cons_fix_new (fragS *     frag,
+                  int          where,
+                  int          size,
+                  expressionS *exp)
+{
+  bfd_reloc_code_real_type type;
+
+  switch (size)
+    {
+    case 1:
+      type = BFD_RELOC_8;
+      break;
+    case 2:
+      type = BFD_RELOC_16;
+      break;
+    case 3:
+      type = BFD_RELOC_24;
+      break;
+    case 4:
+    default:
+      type = BFD_RELOC_32;
+      break;
+    case 8:
+      type = BFD_RELOC_64;
+      break;
+    }
+
+  fix_new_exp (frag, where, (int) size, exp, 0, type);
+}
+
+void
+m32c_apply_fix (struct fix *f, valueT *t, segT s)
+{
+  if (f->fx_r_type == BFD_RELOC_M32C_RL_JUMP
+      || f->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
+      || f->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
+    return;
+  gas_cgen_md_apply_fix (f, t, s);
+}
+
+arelent *
+tc_gen_reloc (asection *sec, fixS *fx)
+{
+  if (fx->fx_r_type == BFD_RELOC_M32C_RL_JUMP
+      || fx->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
+      || fx->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
+    {
+      arelent * reloc;
+      reloc = xmalloc (sizeof (* reloc));
+      reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+      *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy);
+      reloc->address = fx->fx_frag->fr_address + fx->fx_where;
+      reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type);
+      reloc->addend = fx->fx_offset;
+      return reloc;
+
+    }
+  return gas_cgen_tc_gen_reloc (sec, fx);
+}
+
 /* See whether we need to force a relocation into the output file.
    This is used to force out switch and PC relative relocations when
    relaxing.  */
 /* See whether we need to force a relocation into the output file.
    This is used to force out switch and PC relative relocations when
    relaxing.  */
@@ -812,12 +1157,40 @@ m32c_force_relocation (fixS * fixp)
        case M32C_OPERAND_DSP_24_U16:
        case M32C_OPERAND_IMM_24_HI:
          return 1;
        case M32C_OPERAND_DSP_24_U16:
        case M32C_OPERAND_IMM_24_HI:
          return 1;
+
+        /* If we're doing linker relaxing, we need to keep all the
+          pc-relative jumps in case we need to fix them due to
+          deleted bytes between the jump and its destination.  */
+       case M32C_OPERAND_LAB_8_8:
+       case M32C_OPERAND_LAB_8_16:
+       case M32C_OPERAND_LAB_8_24:
+       case M32C_OPERAND_LAB_16_8:
+       case M32C_OPERAND_LAB_24_8:
+       case M32C_OPERAND_LAB_32_8:
+       case M32C_OPERAND_LAB_40_8:
+         if (m32c_relax)
+           return 1;
+       default:
+         break;
        }
     }
   else
     {
        }
     }
   else
     {
-      if (fixp->fx_r_type == BFD_RELOC_16)
-       return 1;
+      switch (fixp->fx_r_type)
+       {
+       case BFD_RELOC_16:
+         return 1;
+
+       case BFD_RELOC_M32C_RL_JUMP:
+       case BFD_RELOC_M32C_RL_1ADDR:
+       case BFD_RELOC_M32C_RL_2ADDR:
+       case BFD_RELOC_8_PCREL:
+       case BFD_RELOC_16_PCREL:
+         if (m32c_relax)
+           return 1;
+       default:
+         break;
+       }
     }
 
   return generic_force_reloc (fixp);
     }
 
   return generic_force_reloc (fixp);
@@ -841,47 +1214,7 @@ md_number_to_chars (char * buf, valueT val, int n)
 char *
 md_atof (int type, char * litP, int * sizeP)
 {
 char *
 md_atof (int type, char * litP, int * sizeP)
 {
-  int              i;
-  int              prec;
-  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
-  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;
-
-   /* FIXME: Some targets allow other format chars for bigger sizes here.  */
-
-    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 (i = 0; i < prec; i++)
-    {
-      md_number_to_chars (litP, (valueT) words[i],
-                         sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
-    }
-     
-  return 0;
+  return ieee_md_atof (type, litP, sizeP, TRUE);
 }
 
 bfd_boolean
 }
 
 bfd_boolean
@@ -963,12 +1296,13 @@ m32c_fix_adjustable (fixS * fixP)
   if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE)
     return 0;
 
   if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE)
     return 0;
 
+  if (m32c_relax)
+    return 0;
+
   return 1;
 }
 
 /* Worker function for m32c_is_colon_insn().  */
   return 1;
 }
 
 /* Worker function for m32c_is_colon_insn().  */
-static char restore_colon PARAMS ((int));
-
 static char
 restore_colon (int advance_i_l_p_by)
 {
 static char
 restore_colon (int advance_i_l_p_by)
 {
@@ -1014,4 +1348,3 @@ m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED)
 
   return 0;
 }
 
   return 0;
 }
-
This page took 0.03546 seconds and 4 git commands to generate.