* config/tc-sh.c (md_begin): Don't fill in md_relax_table here.
[deliverable/binutils-gdb.git] / gas / config / tc-sh.c
index 0f5fb0fd423dac9516b30bbba160f680f5be26db..d4e8ddf112012acbbcdb01d442c306f73e17b8a6 100644 (file)
 #define DEFINE_TABLE
 #include "../opcodes/sh-opc.h"
 #include <ctype.h>
-
 const char comment_chars[] = "!";
 const char line_separator_chars[] = ";";
-const char line_comment_chars[] = "!";
+const char line_comment_chars[] = "!#";
 
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
@@ -45,11 +44,19 @@ const char line_comment_chars[] = "!";
 void cons ();
 void s_align_bytes ();
 
+int shl = 0;
+
+static void little()
+{
+  shl = 1;
+}
+
 const pseudo_typeS md_pseudo_table[] =
 {
   {"int", cons, 4},
   {"word", cons, 2},
   {"form", listing_psize, 0},
+  {"little", little,0},
   {"heading", listing_title, 0},
   {"import", s_ignore, 0},
   {"page", listing_eject, 0},
@@ -113,7 +120,28 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
 #define UNCOND32_LENGTH 14
 
 
-const relax_typeS md_relax_table[C (END, 0)];
+const relax_typeS md_relax_table[C (END, 0)] = {
+  { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+  { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+  { 0 },
+  /* C (COND_JUMP, COND8) */
+  { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP, COND12) },
+  /* C (COND_JUMP, COND12) */
+  { COND12_F, COND12_M, COND12_LENGTH, C (COND_JUMP, COND32), },
+  /* C (COND_JUMP, COND32) */
+  { COND32_F, COND32_M, COND32_LENGTH, 0, },
+  { 0 }, { 0 }, { 0 }, { 0 },
+  { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+  { 0 },
+  /* C (UNCOND_JUMP, UNCOND12) */
+  { UNCOND12_F, UNCOND12_M, UNCOND12_LENGTH, C (UNCOND_JUMP, UNCOND32), },
+  /* C (UNCOND_JUMP, UNCOND32) */
+  { UNCOND32_F, UNCOND32_M, UNCOND32_LENGTH, 0, },
+  { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+  { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+};
 
 static struct hash_control *opcode_hash_control;       /* Opcode mnemonics */
 
@@ -127,6 +155,7 @@ md_begin ()
 {
   sh_opcode_info *opcode;
   char *prev_name = "";
+  register relax_typeS *table;
 
   opcode_hash_control = hash_new ();
 
@@ -145,35 +174,6 @@ md_begin ()
          opcode->name = prev_name;
        }
     }
-
-  /* Initialize the relax table */
-  md_relax_table[C (COND_JUMP, COND8)].rlx_forward = COND8_F;
-  md_relax_table[C (COND_JUMP, COND8)].rlx_backward = COND8_M;
-  md_relax_table[C (COND_JUMP, COND8)].rlx_length = COND8_LENGTH;
-  md_relax_table[C (COND_JUMP, COND8)].rlx_more = C (COND_JUMP, COND12);
-
-  md_relax_table[C (COND_JUMP, COND12)].rlx_forward = COND12_F;
-  md_relax_table[C (COND_JUMP, COND12)].rlx_backward = COND12_M;
-  md_relax_table[C (COND_JUMP, COND12)].rlx_length = COND12_LENGTH;
-  md_relax_table[C (COND_JUMP, COND12)].rlx_more = C (COND_JUMP, COND32);
-
-  md_relax_table[C (COND_JUMP, COND32)].rlx_forward = COND32_F;
-  md_relax_table[C (COND_JUMP, COND32)].rlx_backward = COND32_M;
-  md_relax_table[C (COND_JUMP, COND32)].rlx_length = COND32_LENGTH;
-  md_relax_table[C (COND_JUMP, COND32)].rlx_more = 0;
-
-
-  md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_forward = UNCOND12_F;
-  md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_backward = UNCOND12_M;
-  md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length = UNCOND12_LENGTH;
-  md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_more = C (UNCOND_JUMP, UNCOND32);
-
-  md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_forward = UNCOND32_F;
-  md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_backward = UNCOND32_M;
-  md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length = UNCOND32_LENGTH;
-  md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_more = 0;
-
-
 }
 
 static int reg_m;
@@ -641,7 +641,9 @@ build_relax (opcode)
      sh_opcode_info *opcode;
 {
   int len;
+  int high_byte = shl ? 1 : 0 ;
   char *p;
+
   if (opcode->arg[0] == A_BDISP8)
     {
       p = frag_var (rs_machine_dependent,
@@ -651,18 +653,18 @@ build_relax (opcode)
                    immediate.X_add_symbol,
                    immediate.X_add_number,
                    0);
-      p[0] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]);
+      p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]);
     }
   else if (opcode->arg[0] == A_BDISP12)
     {
       p = frag_var (rs_machine_dependent,
                    md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length,
-                len = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length,
+                   len = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length,
                    C (UNCOND_JUMP, 0),
                    immediate.X_add_symbol,
                    immediate.X_add_number,
                    0);
-      p[0] = (opcode->nibbles[0] << 4);
+      p[high_byte] = (opcode->nibbles[0] << 4);
     }
 
 }
@@ -678,7 +680,7 @@ build_Mytes (opcode, operand)
   int index;
   char nbuf[4];
   char *output = frag_more (2);
-
+  int low_byte = shl ? 0 : 1;
   nbuf[0] = 0;
   nbuf[1] = 0;
   nbuf[2] = 0;
@@ -702,39 +704,45 @@ build_Mytes (opcode, operand)
              nbuf[index] = reg_m;
              break;
            case DISP_4:
-             insert (output + 1, R_SH_IMM4, 0);
+             insert (output + low_byte, R_SH_IMM4, 0);
              break;
            case IMM_4BY4:
-             insert (output + 1, R_SH_IMM4BY4, 0);
+             insert (output + low_byte, R_SH_IMM4BY4, 0);
              break;
            case IMM_4BY2:
-             insert (output + 1, R_SH_IMM4BY2, 0);
+             insert (output + low_byte, R_SH_IMM4BY2, 0);
              break;
            case IMM_4:
-             insert (output + 1, R_SH_IMM4, 0);
+             insert (output + low_byte, R_SH_IMM4, 0);
              break;
            case IMM_8BY4:
-             insert (output + 1, R_SH_IMM8BY4, 0);
+             insert (output + low_byte, R_SH_IMM8BY4, 0);
              break;
            case IMM_8BY2:
-             insert (output + 1, R_SH_IMM8BY2, 0);
+             insert (output + low_byte, R_SH_IMM8BY2, 0);
              break;
            case IMM_8:
-             insert (output + 1, R_SH_IMM8, 0);
+             insert (output + low_byte, R_SH_IMM8, 0);
              break;
            case PCRELIMM_8BY4:
-             insert (output + 1, R_SH_PCRELIMM8BY4, 1);
+             insert (output, R_SH_PCRELIMM8BY4, 1);
              break;
            case PCRELIMM_8BY2:
-             insert (output + 1, R_SH_PCRELIMM8BY2, 1);
+             insert (output, R_SH_PCRELIMM8BY2, 1);
              break;
            default:
              printf ("failed for %d\n", i);
            }
        }
     }
-  output[0] = (nbuf[0] << 4) | (nbuf[1]);
-  output[1] = (nbuf[2] << 4) | (nbuf[3]);
+  if (shl) {
+    output[1] = (nbuf[0] << 4) | (nbuf[1]);
+    output[0] = (nbuf[2] << 4) | (nbuf[3]);
+  }
+  else {
+    output[0] = (nbuf[0] << 4) | (nbuf[1]);
+    output[1] = (nbuf[2] << 4) | (nbuf[3]);
+  }
 }
 
 /* This is the guts of the machine-dependent assembler.  STR points to a
@@ -843,63 +851,66 @@ DEFUN (tc_headers_hook, (headers),
  */
 char *
 md_atof (type, litP, sizeP)
-     char type;
+     int type;
      char *litP;
      int *sizeP;
 {
   int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
+  LITTLENUM_TYPE words[4];
   char *t;
-  char *atof_ieee ();
+  int i;
 
   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_NTOF()";
+      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--;)
+  *sizeP = prec * 2;
+
+  if (shl)
     {
-      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
+      for (i = prec - 1; i >= 0; i--)
+       {
+         md_number_to_chars (litP, (valueT) words[i], 2);
+         litP += 2;
+       }
     }
-  return 0;
+  else
+    {
+      for (i = 0; i < prec; i++)
+       {
+         md_number_to_chars (litP, (valueT) words[i], 2);
+         litP += 2;
+       }
+    }
+     
+  return NULL;
 }
+
+
 \f
 CONST char *md_shortopts = "";
 struct option md_longopts[] = {
-#define OPTION_RELAX (OPTION_MD_BASE)
+
+#define OPTION_RELAX  (OPTION_MD_BASE)
+#define OPTION_LITTLE (OPTION_MD_BASE+1)
+
   {"relax", no_argument, NULL, OPTION_RELAX},
+  {"little", no_argument, NULL, OPTION_LITTLE},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
@@ -914,6 +925,9 @@ md_parse_option (c, arg)
     case OPTION_RELAX:
       relax = 1;
       break;
+    case OPTION_LITTLE:
+      shl = 1;
+      break;
 
     default:
       return 0;
@@ -972,6 +986,8 @@ md_convert_frag (headers, fragP)
 {
   unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
   int donerelax = 0;
+  int highbyte = shl ? 1 : 0;
+  int lowbyte = shl ? 0 : 1;
   int targ_addr = ((fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0) + fragP->fr_offset);
   switch (fragP->fr_subtype)
     {
@@ -983,7 +999,7 @@ md_convert_frag (headers, fragP)
        int disp = targ_addr - next_inst - 2;
        disp /= 2;
        
-       md_number_to_chars (buffer + 1, disp & 0xff, 1);
+       md_number_to_chars (buffer + lowbyte, disp & 0xff, 1);
        fragP->fr_fix += 2;
        fragP->fr_var = 0;
       }
@@ -998,9 +1014,9 @@ md_convert_frag (headers, fragP)
        int disp = targ_addr - next_inst - 2;
 
        disp /= 2;
-       t = buffer[0] & 0xf0;
+       t = buffer[highbyte] & 0xf0;
        md_number_to_chars (buffer, disp & 0xfff, 2);
-       buffer[0] = (buffer[0] & 0xf) | t;
+       buffer[highbyte] = (buffer[highbyte] & 0xf) | t;
        fragP->fr_fix += 2;
        fragP->fr_var = 0;
       }
@@ -1023,22 +1039,22 @@ md_convert_frag (headers, fragP)
        int t = buffer[0] & 0x10;
 
        disp /= 2;
+abort();
+       buffer[highbyte] = 0xa0;        /* branch over move and disp */
+       buffer[lowbyte] = 3;
+       buffer[highbyte+2] = 0xd0 | JREG;       /* Build mov insn */
+       buffer[lowbyte+2] = 0x00;
 
-       buffer[0] = 0xa0;       /* branch over move and disp */
-       buffer[1] = 3;
-       buffer[2] = 0xd0 | JREG;        /* Build mov insn */
-       buffer[3] = 0x00;
+       buffer[highbyte+4] = 0;         /* space for 32 bit jump disp */
+       buffer[lowbyte+4] = 0;
+       buffer[highbyte+6] = 0;
+       buffer[lowbyte+6] = 0;
 
-       buffer[4] = 0;          /* space for 32 bit jump disp */
-       buffer[5] = 0;
-       buffer[6] = 0;
-       buffer[7] = 0;
+       buffer[highbyte+8] = 0x40 | JREG;       /* Build jmp @JREG */
+       buffer[lowbyte+8] = t ? 0xb : 0x2b;
 
-       buffer[10] = 0x40 | JREG;       /* Build jmp @JREG */
-       buffer[11] = t ? 0xb : 0x2b;
-
-       buffer[12] = 0x20;      /* build nop */
-       buffer[13] = 0x0b;
+       buffer[highbyte+10] = 0x20;     /* build nop */
+       buffer[lowbyte+10] = 0x0b;
 
        /* Make reloc for the long disp */
        fix_new (fragP,
@@ -1064,11 +1080,11 @@ md_convert_frag (headers, fragP)
        int disp = targ_addr - next_inst;
        disp /= 2;
        md_number_to_chars (buffer + 2, disp & 0xfff, 2);
-       buffer[0] ^= 0x2;       /* Toggle T/F bit */
-       buffer[1] = 1;          /* branch over jump and nop */
-       buffer[2] = (buffer[2] & 0xf) | 0xa0;   /* Build jump insn */
-       buffer[4] = 0x20;       /* Build nop */
-       buffer[5] = 0x0b;
+       buffer[highbyte] ^= 0x2;        /* Toggle T/F bit */
+       buffer[lowbyte] = 1;            /* branch over jump and nop */
+       buffer[highbyte+2] = (buffer[highbyte+2] & 0xf) | 0xa0; /* Build jump insn */
+       buffer[lowbyte+5] = 0x20;       /* Build nop */
+       buffer[lowbyte+5] = 0x0b;
        fragP->fr_fix += 6;
        fragP->fr_var = 0;
        donerelax = 1;
@@ -1093,7 +1109,7 @@ md_convert_frag (headers, fragP)
 
        int disp = targ_addr - next_inst;
        disp /= 2;
-
+abort();
        buffer[0] ^= 0x2;       /* Toggle T/F bit */
 #define JREG 14
        buffer[1] = 5;          /* branch over mov, jump, nop and ptr */
@@ -1154,6 +1170,7 @@ md_apply_fix (fixP, val)
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   int addr = fixP->fx_frag->fr_address + fixP->fx_where;
+  int lowbyte = shl ? 0 : 1;
   if (fixP->fx_r_type == 0)
     {
       if (fixP->fx_size == 2)
@@ -1196,36 +1213,57 @@ md_apply_fix (fixP, val)
        as_warn ("non aligned displacement at %x\n", addr);
 #endif
       /*      val -= (addr + 4); */
-      val += 3;
+      if (shl||1)
+       val += 1;
+      else
+       val += 3;
       val /= 4;
       if (val & ~0xff)
        as_warn ("pcrel too far at %x\n", addr);
-
-      *buf = val;
+      buf[lowbyte] = val;
       break;
 
     case R_SH_PCRELIMM8BY2:
       addr &= ~1;
-      if (val & 0x1)
-       as_bad ("odd displacement at %x\n", addr);
+      /*      if ((val & 0x1) != shl)
+             as_bad ("odd displacement at %x\n", addr);*/
       /*      val -= (addr + 4); */
-      val++;
+/*      if (!shl)
+       val++;*/
       val /= 2;
       if (val & ~0xff)
        as_warn ("pcrel too far at %x\n", addr);
-      *buf = val;
+      buf[lowbyte] = val;
       break;
 
     case R_SH_IMM32:
-      *buf++ = val >> 24;
-      *buf++ = val >> 16;
-      *buf++ = val >> 8;
-      *buf++ = val >> 0;
+      if (shl) 
+       {
+         *buf++ = val >> 0;
+         *buf++ = val >> 8;
+         *buf++ = val >> 16;
+         *buf++ = val >> 24;
+       }
+      else 
+       {
+         *buf++ = val >> 24;
+         *buf++ = val >> 16;
+         *buf++ = val >> 8;
+         *buf++ = val >> 0;
+       }
       break;
 
     case R_SH_IMM16:
-      *buf++ = val >> 8;
-      *buf++ = val >> 0;
+      if (shl) 
+       {
+         *buf++ = val >> 0;
+         *buf++ = val >> 8;
+       } 
+      else 
+       {
+         *buf++ = val >> 8;
+         *buf++ = val >> 0;
+       }
       break;
 
     default:
@@ -1310,7 +1348,10 @@ md_number_to_chars (ptr, use, nbytes)
      valueT use;
      int nbytes;
 {
-  number_to_chars_bigendian (ptr, use, nbytes);
+  if (shl)
+    number_to_chars_littleendian (ptr, use, nbytes);
+  else
+    number_to_chars_bigendian (ptr, use, nbytes);
 }
 
 long
@@ -1325,22 +1366,6 @@ short
 tc_coff_fix2rtype (fix_ptr)
      fixS *fix_ptr;
 {
-  return fix_ptr->fx_r_type;
-}
-
-void
-tc_reloc_mangle (fix_ptr, intr, base)
-     fixS *fix_ptr;
-     struct internal_reloc *intr;
-     bfd_vma base;
-
-{
-  symbolS *symbol_ptr;
-
-  symbol_ptr = fix_ptr->fx_addsy;
-
-  /* If this relocation is attached to a symbol then it's ok
-     to output it */
   if (fix_ptr->fx_r_type == RELOC_32)
     {
       /* cons likes to create reloc32's whatever the size of the reloc..
@@ -1348,43 +1373,16 @@ tc_reloc_mangle (fix_ptr, intr, base)
       switch (fix_ptr->fx_size)
        {
        case 2:
-         intr->r_type = R_IMM16;
+         return R_SH_IMM16;
          break;
        case 1:
-         intr->r_type = R_IMM8;
+         return R_SH_IMM8;
          break;
        default:
          abort ();
        }
     }
-  else
-    {
-      intr->r_type = fix_ptr->fx_r_type;
-    }
-
-  intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
-  intr->r_offset = fix_ptr->fx_offset;
-
-  /* Turn the segment of the symbol into an offset.  */
-  if (symbol_ptr)
-    {
-      symbolS *dot;
-
-      dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
-      if (dot)
-       {
-         intr->r_offset += S_GET_VALUE (symbol_ptr);
-         intr->r_symndx = dot->sy_number;
-       }
-      else
-       {
-         intr->r_symndx = symbol_ptr->sy_number;
-       }
-    }
-  else
-    {
-      intr->r_symndx = -1;
-    }
+  return R_SH_IMM32;
 }
 
 int
@@ -1393,3 +1391,8 @@ tc_coff_sizemachdep (frag)
 {
   return md_relax_table[frag->fr_subtype].rlx_length;
 }
+
+int
+sh_init_after_args()
+{
+}
This page took 0.031232 seconds and 4 git commands to generate.