* gas/config/tc-avr.c: Change ISA for devices with USB support to
[external/binutils.git] / gas / config / tc-moxie.c
index b791078..fa8ace5 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-moxie.c -- Assemble code for moxie
-   Copyright 2009
+   Copyright 2009, 2012
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -43,6 +43,12 @@ const pseudo_typeS md_pseudo_table[] =
 const char FLT_CHARS[] = "rRsSfFdDxXpP";
 const char EXP_CHARS[] = "eE";
 
+static valueT md_chars_to_number (char * buf, int n);
+
+/* Byte order.  */
+extern int target_big_endian;
+const char *moxie_target_format = DEFAULT_TARGET_FORMAT;
+
 void
 md_operand (expressionS *op __attribute__((unused)))
 {
@@ -67,7 +73,7 @@ md_begin (void)
   for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
     hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
-  for (count = 0, opcode = moxie_form3_opc_info; count++ < 4; opcode++)
+  for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
     hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
@@ -95,7 +101,7 @@ parse_register_operand (char **ptr)
 
   if (*s != '$')
     {
-      as_bad ("expecting register");
+      as_bad (_("expecting register"));
       ignore_rest_of_line ();
       return -1;
     }
@@ -114,7 +120,7 @@ parse_register_operand (char **ptr)
       reg = s[2] - '0';
       if ((reg < 0) || (reg > 9))
        {
-         as_bad ("illegal register number");
+         as_bad (_("illegal register number"));
          ignore_rest_of_line ();
          return -1;
        }
@@ -130,7 +136,7 @@ parse_register_operand (char **ptr)
     }
   else
     {
-      as_bad ("illegal register number");
+      as_bad (_("illegal register number"));
       ignore_rest_of_line ();
       return -1;
     }
@@ -197,11 +203,11 @@ md_assemble (char *str)
        reg = parse_register_operand (&op_end);
        iword += (reg << 8);
        if (*op_end != ',')
-         as_warn ("expecting comma delimeted register operands");
+         as_warn (_("expecting comma delimited register operands"));
        op_end++;
        op_end = parse_exp_save_ilp (op_end, &arg);
        fix_new_exp (frag_now,
-                    ((p+1) - frag_now->fr_literal),
+                    ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
                     1,
                     &arg,
                     0,
@@ -216,14 +222,14 @@ md_assemble (char *str)
        int dest, src;
        dest = parse_register_operand (&op_end);
        if (*op_end != ',')
-         as_warn ("expecting comma delimeted register operands");
+         as_warn (_("expecting comma delimited register operands"));
        op_end++;
        src  = parse_register_operand (&op_end);
        iword += (dest << 4) + src;
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
       }
       break;
     case MOXIE_F1_A4:
@@ -243,7 +249,7 @@ md_assemble (char *str)
 
        if (*op_end != ',')
          {
-           as_bad ("expecting comma delimited operands");
+           as_bad (_("expecting comma delimited operands"));
            ignore_rest_of_line ();
            return;
          }
@@ -283,7 +289,7 @@ md_assemble (char *str)
       while (ISSPACE (*op_end))
        op_end++;
       if (*op_end != 0)
-       as_warn ("extra stuff on line ignored");
+       as_warn (_("extra stuff on line ignored"));
       break;
     case MOXIE_F1_A:
       iword = opcode->opcode << 8;
@@ -295,7 +301,7 @@ md_assemble (char *str)
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
        iword += (reg << 4);
       }
       break;
@@ -307,11 +313,11 @@ md_assemble (char *str)
        int a, b;
        a = parse_register_operand (&op_end);
        if (*op_end != ',')
-         as_warn ("expecting comma delimeted register operands");
+         as_warn (_("expecting comma delimited register operands"));
        op_end++;
        if (*op_end != '(')
          {
-           as_bad ("expecting indirect register `($rA)'");
+           as_bad (_("expecting indirect register `($rA)'"));
            ignore_rest_of_line ();
            return;
          }
@@ -319,7 +325,7 @@ md_assemble (char *str)
        b = parse_register_operand (&op_end);
        if (*op_end != ')')
          {
-           as_bad ("missing closing parenthesis");
+           as_bad (_("missing closing parenthesis"));
            ignore_rest_of_line ();
            return;
          }
@@ -328,7 +334,7 @@ md_assemble (char *str)
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
       }
       break;
     case MOXIE_F1_AiB:
@@ -339,7 +345,7 @@ md_assemble (char *str)
        int a, b;
        if (*op_end != '(')
          {
-           as_bad ("expecting indirect register `($rA)'");
+           as_bad (_("expecting indirect register `($rA)'"));
            ignore_rest_of_line ();
            return;
          }
@@ -347,20 +353,20 @@ md_assemble (char *str)
        a = parse_register_operand (&op_end);
        if (*op_end != ')')
          {
-           as_bad ("missing closing parenthesis");
+           as_bad (_("missing closing parenthesis"));
            ignore_rest_of_line ();
            return;
          }
        op_end++;
        if (*op_end != ',')
-         as_warn ("expecting comma delimeted register operands");
+         as_warn (_("expecting comma delimited register operands"));
        op_end++;
        b = parse_register_operand (&op_end);
        iword += (a << 4) + b;
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
       }
       break;
     case MOXIE_F1_4A:
@@ -383,7 +389,7 @@ md_assemble (char *str)
 
        if (*op_end != ',')
          {
-           as_bad ("expecting comma delimited operands");
+           as_bad (_("expecting comma delimited operands"));
            ignore_rest_of_line ();
            return;
          }
@@ -393,7 +399,7 @@ md_assemble (char *str)
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
 
        iword += (a << 4);
       }
@@ -413,7 +419,7 @@ md_assemble (char *str)
 
        if (*op_end != ',')
          {
-           as_bad ("expecting comma delimited operands");
+           as_bad (_("expecting comma delimited operands"));
            ignore_rest_of_line ();
            return;
          }
@@ -430,7 +436,7 @@ md_assemble (char *str)
 
        if (*op_end != '(')
          {
-           as_bad ("expecting indirect register `($rX)'");
+           as_bad (_("expecting indirect register `($rX)'"));
            ignore_rest_of_line ();
            return;
          }
@@ -438,7 +444,7 @@ md_assemble (char *str)
        b = parse_register_operand (&op_end);
        if (*op_end != ')')
          {
-           as_bad ("missing closing parenthesis");
+           as_bad (_("missing closing parenthesis"));
            ignore_rest_of_line ();
            return;
          }
@@ -447,7 +453,7 @@ md_assemble (char *str)
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
 
        iword += (a << 4) + b;
       }
@@ -472,7 +478,7 @@ md_assemble (char *str)
 
        if (*op_end != '(')
          {
-           as_bad ("expecting indirect register `($rX)'");
+           as_bad (_("expecting indirect register `($rX)'"));
            ignore_rest_of_line ();
            return;
          }
@@ -480,7 +486,7 @@ md_assemble (char *str)
        a = parse_register_operand (&op_end);
        if (*op_end != ')')
          {
-           as_bad ("missing closing parenthesis");
+           as_bad (_("missing closing parenthesis"));
            ignore_rest_of_line ();
            return;
          }
@@ -488,7 +494,7 @@ md_assemble (char *str)
 
        if (*op_end != ',')
          {
-           as_bad ("expecting comma delimited operands");
+           as_bad (_("expecting comma delimited operands"));
            ignore_rest_of_line ();
            return;
          }
@@ -501,7 +507,7 @@ md_assemble (char *str)
        while (ISSPACE (*op_end))
          op_end++;
        if (*op_end != 0)
-         as_warn ("extra stuff on line ignored");
+         as_warn (_("extra stuff on line ignored"));
 
        iword += (a << 4) + b;
       }
@@ -511,10 +517,26 @@ md_assemble (char *str)
       while (ISSPACE (*op_end))
        op_end++;
       if (*op_end != 0)
-       as_warn ("extra stuff on line ignored");
+       as_warn (_("extra stuff on line ignored"));
+      break;
+    case MOXIE_F3_PCREL:
+      iword = (3<<14) | (opcode->opcode << 10);
+      while (ISSPACE (*op_end))
+       op_end++;
+      {
+       expressionS arg;
+
+       op_end = parse_exp_save_ilp (op_end, &arg);
+       fix_new_exp (frag_now,
+                    (p - frag_now->fr_literal),
+                    2,
+                    &arg,
+                    TRUE,
+                    BFD_RELOC_MOXIE_10_PCREL);
+      }
       break;
     default:
-      abort();
+      abort ();
     }
 
   md_number_to_chars (p, iword, 2);
@@ -523,10 +545,10 @@ md_assemble (char *str)
     op_end++;
 
   if (*op_end != 0)
-    as_warn ("extra stuff on line ignored");
+    as_warn (_("extra stuff on line ignored"));
 
   if (pending_reloc)
-    as_bad ("Something forgot to clean up\n");
+    as_bad (_("Something forgot to clean up\n"));
 }
 
 /* Turn a string in input_line_pointer into a floating point constant
@@ -571,58 +593,115 @@ md_atof (int type, char *litP, int *sizeP)
 
   return NULL;
 }
-\f
-const char *md_shortopts = "";
+
+enum options
+{
+  OPTION_EB = OPTION_MD_BASE,
+  OPTION_EL,
+};
 
 struct option md_longopts[] =
 {
-  {NULL, no_argument, NULL, 0}
+  { "EB",          no_argument, NULL, OPTION_EB},
+  { "EL",          no_argument, NULL, OPTION_EL},
+  { NULL,          no_argument, NULL, 0}
 };
+
 size_t md_longopts_size = sizeof (md_longopts);
+\f
+const char *md_shortopts = "";
 
-/* We have no target specific options yet, so these next
-   two functions are empty.  */
 int
 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
 {
-  return 0;
+  switch (c)
+    {
+    case OPTION_EB: 
+      target_big_endian = 1; 
+      moxie_target_format = "elf32-bigmoxie";
+      break;
+    case OPTION_EL: 
+      target_big_endian = 0;
+      moxie_target_format = "elf32-littlemoxie";
+      break;
+    default:        
+      return 0;
+    }
+
+  return 1;
 }
 
 void
 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
 {
+  fprintf (stream, _("\
+  -EB                     assemble for a big endian system (default)\n\
+  -EL                     assemble for a little endian system\n"));
 }
 
 /* Apply a fixup to the object file.  */
 
 void
-md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
+md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, 
+             valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   long val = *valP;
+  long newval;
   long max, min;
-  int shift;
 
   max = min = 0;
-  shift = 0;
   switch (fixP->fx_r_type)
     {
     case BFD_RELOC_32:
-      *buf++ = val >> 24;
-      *buf++ = val >> 16;
-      *buf++ = val >> 8;
-      *buf++ = val >> 0;
+      if (target_big_endian)
+       {
+         buf[0] = val >> 24;
+         buf[1] = val >> 16;
+         buf[2] = val >> 8;
+         buf[3] = val >> 0;
+       }
+      else
+       {
+         buf[3] = val >> 24;
+         buf[2] = val >> 16;
+         buf[1] = val >> 8;
+         buf[0] = val >> 0;
+       }
+      buf += 4;
       break;
 
     case BFD_RELOC_16:
-      *buf++ = val >> 8;
-      *buf++ = val >> 0;
+      if (target_big_endian)
+       {
+         buf[0] = val >> 8;
+         buf[1] = val >> 0;
+       }
+      else
+       {
+         buf[1] = val >> 8;
+         buf[0] = val >> 0;
+       }
+      buf += 2;
       break;
 
     case BFD_RELOC_8:
       *buf++ = val;
       break;
 
+    case BFD_RELOC_MOXIE_10_PCREL:
+      if (!val)
+       break;
+      if (val < -1024 || val > 1022)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                      _("pcrel too far BFD_RELOC_MOXIE_10"));
+      /* 11 bit offset even numbered, so we remove right bit.  */
+      val >>= 1;
+      newval = md_chars_to_number (buf, 2);
+      newval |= val & 0x03ff;
+      md_number_to_chars (buf, newval, 2);
+      break;
+
     default:
       abort ();
     }
@@ -634,12 +713,43 @@ md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, valueT * valP ATTRIBUTE_UNUSED, segT
     fixP->fx_done = 1;
 }
 
-/* Put number into target byte order (big endian).  */
+/* Put number into target byte order.  */
 
 void
-md_number_to_chars (char *ptr, valueT use, int nbytes)
+md_number_to_chars (char * ptr, valueT use, int nbytes)
+{
+  if (target_big_endian)
+    number_to_chars_bigendian (ptr, use, nbytes);
+  else
+    number_to_chars_littleendian (ptr, use, nbytes);
+}
+
+/* Convert from target byte order to host byte order.  */
+
+static valueT
+md_chars_to_number (char * buf, int n)
 {
-  number_to_chars_bigendian (ptr, use, nbytes);
+  valueT result = 0;
+  unsigned char * where = (unsigned char *) buf;
+
+  if (target_big_endian)
+    {
+      while (n--)
+       {
+         result <<= 8;
+         result |= (*where++ & 255);
+       }
+    }
+  else
+    {
+      while (n--)
+       {
+         result <<= 8;
+         result |= (where[n] & 255);
+       }
+    }
+
+  return result;
 }
 
 /* Generate a machine-dependent relocation.  */
@@ -654,6 +764,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
     case BFD_RELOC_32:
       code = fixP->fx_r_type;
       break;
+    case BFD_RELOC_MOXIE_10_PCREL:
+      code = fixP->fx_r_type;
+      break;
     default:
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
@@ -661,7 +774,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
     }
 
   relP = xmalloc (sizeof (arelent));
-  assert (relP != 0);
+  gas_assert (relP != 0);
   relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
@@ -719,12 +832,13 @@ md_pcrel_from (fixS *fixP)
 {
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 
-  fprintf (stderr, "md_pcrel_from 0x%d\n", fixP->fx_r_type);
-
   switch (fixP->fx_r_type)
     {
     case BFD_RELOC_32:
       return addr + 4;
+    case BFD_RELOC_MOXIE_10_PCREL:
+      /* Offset is from the end of the instruction.  */
+      return addr + 2;
     default:
       abort ();
       return addr;