* config/tc-mn10300.c (md_pseudo_table): Use constant names.
[deliverable/binutils-gdb.git] / gas / config / tc-mn10300.c
index aeb68355f7811766180a4406dfbc2a33af78aed8..ae1ea16fe7b128a227ca47a324fdaed5a0ce0e60 100644 (file)
@@ -1,6 +1,5 @@
 /* tc-mn10300.c -- Assembler code for the Matsushita 10300
-
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -91,7 +90,9 @@ static int reg_name_search PARAMS ((const struct reg_name *, int, const char *))
 static boolean data_register_name PARAMS ((expressionS *expressionP));
 static boolean address_register_name PARAMS ((expressionS *expressionP));
 static boolean other_register_name PARAMS ((expressionS *expressionP));
+static void set_arch_mach PARAMS ((int));
 
+static int current_machine;
 
 /* fixups */
 #define MAX_INSN_FIXUPS (5)
@@ -103,6 +104,10 @@ struct mn10300_fixup
 };
 struct mn10300_fixup fixups[MAX_INSN_FIXUPS];
 static int fc;
+
+/* We must store the value of each register operand so that we can
+   verify that certain registers do not match.  */
+int mn10300_reg_operands[MN10300_MAX_OPERANDS];
 \f
 const char *md_shortopts = "";
 struct option md_longopts[] = {
@@ -113,9 +118,14 @@ size_t md_longopts_size = sizeof(md_longopts);
 /* The target specific pseudo-ops which we support.  */
 const pseudo_typeS md_pseudo_table[] =
 {
-  { NULL,       NULL,           0 }
+  { "am30",    set_arch_mach,          AM30 },
+  { "am33",    set_arch_mach,          AM33 },
+  { "mn10300", set_arch_mach,          MN103 },
+  {NULL, 0, 0}
 };
 
+#define HAVE_AM33 (current_machine == AM33)
+
 /* Opcode hash table.  */
 static struct hash_control *mn10300_hash;
 
@@ -138,9 +148,32 @@ static const struct reg_name address_registers[] =
 };
 #define ADDRESS_REG_NAME_CNT   (sizeof(address_registers) / sizeof(struct reg_name))
 
-/* start-sanitize-am33 */
 static const struct reg_name r_registers[] =
 {
+  { "a0", 8 },
+  { "a1", 9 },
+  { "a2", 10 },
+  { "a3", 11 },
+  { "d0", 12 },
+  { "d1", 13 },
+  { "d2", 14 },
+  { "d3", 15 },
+  { "e0", 0 },
+  { "e1", 1 },
+  { "e10", 10 },
+  { "e11", 11 },
+  { "e12", 12 },
+  { "e13", 13 },
+  { "e14", 14 },
+  { "e15", 15 },
+  { "e2", 2 },
+  { "e3", 3 },
+  { "e4", 4 },
+  { "e5", 5 },
+  { "e6", 6 },
+  { "e7", 7 },
+  { "e8", 8 },
+  { "e9", 9 },
   { "r0", 0 },
   { "r1", 1 },
   { "r10", 10 },
@@ -162,6 +195,11 @@ static const struct reg_name r_registers[] =
 
 static const struct reg_name xr_registers[] =
 {
+  { "mcrh", 2 },
+  { "mcrl", 3 },
+  { "mcvf", 4 },
+  { "mdrq", 1 },
+  { "sp", 0 },
   { "xr0", 0 },
   { "xr1", 1 },
   { "xr10", 10 },
@@ -181,7 +219,6 @@ static const struct reg_name xr_registers[] =
 };
 #define XR_REG_NAME_CNT        (sizeof(xr_registers) / sizeof(struct reg_name))
 
-/* end-sanitize-am33 */
 
 static const struct reg_name other_registers[] =
 {
@@ -223,7 +260,6 @@ reg_name_search (regs, regcount, name)
 }
 
 
-/* start-sanitize-am33 */
 /* Summary of register_name().
  *
  * in: Input_line_pointer points to 1st char of operand.
@@ -315,7 +351,6 @@ xr_register_name (expressionP)
       return false;
     }
 }
-/* end-sanitize-am33 */
 
 /* Summary of register_name().
  *
@@ -842,8 +877,14 @@ md_begin ()
 
   /* This is both a simplification (we don't have to write md_apply_fix)
      and support for future optimizations (branch shortening and similar
-     stuff in the linker.  */
+     stuff in the linker).  */
   linkrelax = 1;
+
+  /* Set the default machine type.  */
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, MN103))
+    as_warn (_("could not set architecture and machine"));
+
+  current_machine = MN103;
 }
 
 void
@@ -882,17 +923,30 @@ md_assemble (str)
 
   for(;;)
     {
-      const char *errmsg = NULL;
+      const char *errmsg;
       int op_idx;
       char *hold;
       int extra_shift = 0;
 
+
+      errmsg = _("Invalid opcode/operands");
+
+      /* Reset the array of register operands.  */
+      memset (mn10300_reg_operands, -1, sizeof (mn10300_reg_operands));
+
       relaxable = 0;
       fc = 0;
       match = 0;
       next_opindex = 0;
       insn = opcode->opcode;
       extension = 0;
+
+      /* If the instruction is not available on the current machine
+        then it can not possibly match.  */
+      if (opcode->machine
+         && !(opcode->machine == AM33 && HAVE_AM33))
+       goto error;
+
       for (op_idx = 1, opindex_ptr = opcode->operands;
           *opindex_ptr != 0;
           opindex_ptr++, op_idx++)
@@ -910,8 +964,6 @@ md_assemble (str)
              next_opindex = 0;
            }
 
-         errmsg = NULL;
-
          while (*str == ' ' || *str == ',')
            ++str;
 
@@ -967,7 +1019,6 @@ md_assemble (str)
              *input_line_pointer = c;
              goto keep_going;
            }
-         /* start-sanitize-am33 */
          else if (operand->flags & MN10300_OPERAND_RREG)
            {
              if (!r_register_name (&ex))
@@ -1072,7 +1123,6 @@ md_assemble (str)
              input_line_pointer++;
              goto keep_going;
            }
-         /* end-sanitize-am33 */
          else if (operand->flags & MN10300_OPERAND_PSW)
            {
              char *start = input_line_pointer;
@@ -1159,28 +1209,30 @@ md_assemble (str)
                      value |= 0x08;
                      *input_line_pointer = c;
                    }
-                 /* start-sanitize-am33 */
-                 else if (strcasecmp (start, "exreg0") == 0)
+                 else if (HAVE_AM33
+                          && strcasecmp (start, "exreg0") == 0)
                    {
                      value |= 0x04;
                      *input_line_pointer = c;
                    }
-                 else if (strcasecmp (start, "exreg1") == 0)
+                 else if (HAVE_AM33
+                          && strcasecmp (start, "exreg1") == 0)
                    {
                      value |= 0x02;
                      *input_line_pointer = c;
                    }
-                 else if (strcasecmp (start, "exother") == 0)
+                 else if (HAVE_AM33
+                          && strcasecmp (start, "exother") == 0)
                    {
                      value |= 0x01;
                      *input_line_pointer = c;
                    }
-                 else if (strcasecmp (start, "all") == 0)
+                 else if (HAVE_AM33
+                          && strcasecmp (start, "all") == 0)
                    {
                      value |= 0xff;
                      *input_line_pointer = c;
                    }
-                 /* end-sanitize-am33 */
                  else
                    {
                      input_line_pointer = hold;
@@ -1212,6 +1264,18 @@ md_assemble (str)
              str = hold;
              goto error;
            }
+         else if (HAVE_AM33 && r_register_name (&ex))
+           {
+             input_line_pointer = hold;
+             str = hold;
+             goto error;
+           }
+         else if (HAVE_AM33 && xr_register_name (&ex))
+           {
+             input_line_pointer = hold;
+             str = hold;
+             goto error;
+           }
          else if (*str == ')' || *str == '(')
            {
              input_line_pointer = hold;
@@ -1236,9 +1300,8 @@ md_assemble (str)
                int mask;
 
                mask = MN10300_OPERAND_DREG | MN10300_OPERAND_AREG;
-               /* start-sanitize-am33 */
-               mask |= MN10300_OPERAND_RREG | MN10300_OPERAND_XRREG;
-               /* end-sanitize-am33 */
+               if (HAVE_AM33)
+                 mask |= MN10300_OPERAND_RREG | MN10300_OPERAND_XRREG;
                if ((operand->flags & mask) == 0)
                  {
                    input_line_pointer = hold;
@@ -1255,10 +1318,10 @@ md_assemble (str)
                         || opcode->format == FMT_S6
                         || opcode->format == FMT_D5)
                  extra_shift = 16;
-               /* start-sanitize-am33 */
                else if (opcode->format == FMT_D7)
                  extra_shift = 8;
-               /* end-sanitize-am33 */
+               else if (opcode->format == FMT_D8 || opcode->format == FMT_D9)
+                 extra_shift = 8;
                else
                  extra_shift = 0;
              
@@ -1266,6 +1329,9 @@ md_assemble (str)
                                        ex.X_add_number, (char *) NULL,
                                        0, extra_shift);
 
+
+               /* And note the register number in the register array.  */
+               mn10300_reg_operands[op_idx - 1] = ex.X_add_number;
                break;
              }
 
@@ -1320,6 +1386,35 @@ keep_going:
       if (*str != ',')
        match = 1;
 
+      /* If this instruction has registers that must not match, verify
+        that they do indeed not match.  */
+      if (opcode->no_match_operands)
+       {
+         int i;
+
+         /* Look at each operand to see if it's marked.  */
+         for (i = 0; i < MN10300_MAX_OPERANDS; i++)
+           {
+             if ((1 << i) & opcode->no_match_operands)
+               {
+                 int j;
+
+                 /* operand I is marked.  Check that it does not match any
+                    operands > I which are marked.  */
+                 for (j = i + 1; j < MN10300_MAX_OPERANDS; j++)
+                   {
+                     if (((1 << j) & opcode->no_match_operands)
+                         && mn10300_reg_operands[i] == mn10300_reg_operands[j])
+                       {
+                         errmsg = _("Invalid register specification.");
+                         match = 0;
+                         goto error;
+                       }
+                   }
+               }
+           }
+       }
+
     error:
       if (match == 0)
         {
@@ -1354,13 +1449,17 @@ keep_going:
   if (opcode->format == FMT_S2 || opcode->format == FMT_D1)
     size = 3;
 
-  /* start-sanitize-am33 */
   if (opcode->format == FMT_D6)
     size = 3;
 
-  if (opcode->format == FMT_D7)
+  if (opcode->format == FMT_D7 || opcode->format == FMT_D10)
     size = 4;
-  /* end-sanitize-am33 */
+
+  if (opcode->format == FMT_D8)
+    size = 6;
+
+  if (opcode->format == FMT_D9)
+    size = 7;
 
   if (opcode->format == FMT_S4)
     size = 5;
@@ -1445,10 +1544,9 @@ keep_going:
       if (opcode->format == FMT_S0
          || opcode->format == FMT_S1
          || opcode->format == FMT_D0
-         /* start-sanitize-am33 */
          || opcode->format == FMT_D6
          || opcode->format == FMT_D7
-         /* end-sanitize-am33 */
+         || opcode->format == FMT_D10
          || opcode->format == FMT_D1)
        {
          number_to_chars_bigendian (f, insn, size);
@@ -1523,6 +1621,19 @@ keep_going:
          number_to_chars_littleendian (f + 2, temp, 4);
          number_to_chars_bigendian (f + 6, extension & 0xff, 1);
        }
+      else if (opcode->format == FMT_D8)
+       {
+          unsigned long temp = ((insn & 0xff) << 16) | (extension & 0xffff);
+          number_to_chars_bigendian (f, (insn >> 8) & 0xffffff, 3);
+          number_to_chars_bigendian (f + 3, (temp & 0xff), 1);
+          number_to_chars_littleendian (f + 4, temp >> 8, 2);
+       }
+      else if (opcode->format == FMT_D9)
+       {
+          unsigned long temp = ((insn & 0xff) << 24) | (extension & 0xffffff);
+          number_to_chars_bigendian (f, (insn >> 8) & 0xffffff, 3);
+          number_to_chars_littleendian (f + 3, temp, 4);
+       }
 
       /* Create any fixups.  */
       for (i = 0; i < fc; i++)
@@ -1563,6 +1674,8 @@ keep_going:
                 implicitly 32bits.  */
              if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
                reloc_size = 32;
+             else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
+               reloc_size = 24;
              else
                reloc_size = operand->bits;
 
@@ -1671,7 +1784,8 @@ tc_gen_reloc (seg, fixp)
     }
   else 
     {
-      reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+      reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof( asymbol *));
+      *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
       reloc->addend = fixp->fx_offset;
     }
   return reloc;
@@ -1767,15 +1881,20 @@ mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
     {
       long min, max;
       offsetT test;
+      int bits;
+
+      bits = operand->bits;
+      if (operand->flags & MN10300_OPERAND_24BIT)
+       bits = 24;
 
       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
        {
-         max = (1 << (operand->bits - 1)) - 1;
-         min = - (1 << (operand->bits - 1));
+         max = (1 << (bits - 1)) - 1;
+         min = - (1 << (bits - 1));
        }
       else
         {
-          max = (1 << operand->bits) - 1;
+          max = (1 << bits) - 1;
           min = 0;
         }
 
@@ -1802,6 +1921,12 @@ mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
       *extensionp |= ((val & ((1 << (32 - operand->bits)) - 1))
                      << operand->shift);
     }
+  else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
+    {
+      *insnp |= (val >> (24 - operand->bits)) & ((1 << operand->bits) - 1);
+      *extensionp |= ((val & ((1 << (24 - operand->bits)) - 1))
+                     << operand->shift);
+    }
   else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0)
     {
       *insnp |= (((long) val & ((1 << operand->bits) - 1))
@@ -1835,15 +1960,20 @@ check_operand (insn, operand, val)
     {
       long min, max;
       offsetT test;
+      int bits;
+
+      bits = operand->bits;
+      if (operand->flags & MN10300_OPERAND_24BIT)
+       bits = 24;
 
       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
        {
-         max = (1 << (operand->bits - 1)) - 1;
-         min = - (1 << (operand->bits - 1));
+         max = (1 << (bits - 1)) - 1;
+         min = - (1 << (bits - 1));
        }
       else
         {
-          max = (1 << operand->bits) - 1;
+          max = (1 << bits) - 1;
           min = 0;
         }
 
@@ -1857,3 +1987,13 @@ check_operand (insn, operand, val)
     }
   return 1;
 }
+
+static void
+set_arch_mach (mach)
+     int mach;
+{
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, mach))
+    as_warn (_("could not set architecture and machine"));
+
+  current_machine = mach;
+}
This page took 0.029203 seconds and 4 git commands to generate.