Fix MSP430 assembler to support #hi(<symbol>).
authorNick Clifton <nickc@redhat.com>
Tue, 20 May 2014 09:28:42 +0000 (10:28 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 20 May 2014 09:28:42 +0000 (10:28 +0100)
* config/tc-msp430.c (CHECK_RELOC_MSP430): Add OP parameter.
Generate BFD_RELOC_MSP430_ABS_HI16 if vshift is 1.
(msp430_srcoperand): Store vshift value in operand.

* msp430.h (struct msp430_operand_s): Add vshift field.

* gas/elf/struct.d: Expect extra output from some toolchains.
* gas/symver/symver0.d: Likewise.
* gas/symver/symver1.d: Likewise.

gas/ChangeLog
gas/config/tc-msp430.c
gas/testsuite/ChangeLog
gas/testsuite/gas/elf/struct.d
gas/testsuite/gas/symver/symver0.d
gas/testsuite/gas/symver/symver1.d
include/opcode/ChangeLog
include/opcode/msp430.h

index 26cef7f..f873e2b 100644 (file)
@@ -1,3 +1,9 @@
+2014-05-20  Nick Clifton  <nickc@redhat.com>
+
+       * config/tc-msp430.c (CHECK_RELOC_MSP430): Add OP parameter.
+       Generate BFD_RELOC_MSP430_ABS_HI16 if vshift is 1.
+       (msp430_srcoperand): Store vshift value in operand.
+
 2014-05-19  Nick Clifton  <nickc@redhat.com>
 
        PR gas/16858
index 948117c..2db0fc0 100644 (file)
@@ -278,16 +278,22 @@ target_is_430xv2 (void)
   return selected_isa == MSP_ISA_430Xv2;
 }
 
-/* Generate a 16-bit relocation.
-   For the 430X we generate a relocation without linkwer range checking
-   if the value is being used in an extended (ie 20-bit) instruction.
+/* Generate an absolute 16-bit relocation.
+   For the 430X we generate a relocation without linker range checking
+    if the value is being used in an extended (ie 20-bit) instruction,
+    otherwise if have a shifted expression we use a HI reloc.
    For the 430 we generate a relocation without assembler range checking
-   if we are handling an immediate value or a byte-width instruction.  */
+    if we are handling an immediate value or a byte-width instruction.  */
+
 #undef  CHECK_RELOC_MSP430
-#define CHECK_RELOC_MSP430                                  \
-  (target_is_430x ()                                        \
-   ? (extended_op ? BFD_RELOC_16 : BFD_RELOC_MSP430X_ABS16)  \
-   : ((imm_op || byte_op)                                   \
+#define CHECK_RELOC_MSP430(OP)                         \
+  (target_is_430x ()                                   \
+  ? (extended_op                                       \
+     ? BFD_RELOC_16                                    \
+     : ((OP).vshift == 1)                              \
+     ? BFD_RELOC_MSP430_ABS_HI16                       \
+     : BFD_RELOC_MSP430X_ABS16)                                \
+   : ((imm_op || byte_op)                              \
       ? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16))
 
 /* Generate a 16-bit pc-relative relocation.
@@ -1038,7 +1044,7 @@ static int
 msp430_srcoperand (struct msp430_operand_s * op,
                   char * l,
                   int bin,
-                  int * imm_op,
+                  bfd_boolean * imm_op,
                   bfd_boolean allow_20bit_values,
                   bfd_boolean constants_allowed)
 {
@@ -1058,7 +1064,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
         hhi(x) - x = (x >> 48) & 0xffff
         The value _MUST_ be constant expression: #hlo(1231231231).  */
 
-      *imm_op = 1;
+      *imm_op = TRUE;
 
       if (strncasecmp (h, "#llo(", 5) == 0)
        {
@@ -1096,6 +1102,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       op->ol = 1;              /* Immediate will follow an instruction.  */
       __tl = h + 1 + rval;
       op->mode = OP_EXP;
+      op->vshift = vshift;
 
       parse_exp (__tl, &(op->exp));
       if (op->exp.X_op == O_constant)
@@ -1111,6 +1118,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
            {
              x = (x >> 16) & 0xffff;
              op->exp.X_add_number = x;
+             op->vshift = 0;
            }
          else if (vshift > 1)
            {
@@ -1119,6 +1127,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
              else
                op->exp.X_add_number = 0;       /* Nothing left.  */
              x = op->exp.X_add_number;
+             op->vshift = 0;
            }
 
          if (allow_20bit_values)
@@ -1208,6 +1217,8 @@ msp430_srcoperand (struct msp430_operand_s * op,
        }
       else if (op->exp.X_op == O_symbol)
        {
+         if (vshift > 1)
+           as_bad (_("error: unsupported #foo() directive used on symbol"));
          op->mode = OP_EXP;
        }
       else if (op->exp.X_op == O_big)
@@ -1219,6 +1230,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
              op->exp.X_op = O_constant;
              op->exp.X_add_number = 0xffff & generic_bignum[vshift];
              x = op->exp.X_add_number;
+             op->vshift = 0;
            }
          else
            {
@@ -1292,6 +1304,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       __tl = h + 1;
       parse_exp (__tl, &(op->exp));
       op->mode = OP_EXP;
+      op->vshift = 0;
       if (op->exp.X_op == O_constant)
        {
          int x = op->exp.X_add_number;
@@ -1366,7 +1379,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       char *m = strrchr (l, ')');
       char *t;
 
-      *imm_op = 1;
+      *imm_op = TRUE;
 
       if (!h)
        break;
@@ -1399,6 +1412,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       __tl = l;
       *h = 0;
       op->mode = OP_EXP;
+      op->vshift = 0;
       parse_exp (__tl, &(op->exp));
       if (op->exp.X_op == O_constant)
        {
@@ -1460,6 +1474,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       /* An expression starting with a minus sign is a constant, not an address.  */
       op->am = (*l == '-' ? 3 : 1);
       op->ol = 1;
+      op->vshift = 0;
       __tl = l;
       parse_exp (__tl, &(op->exp));
       return 0;
@@ -1494,6 +1509,7 @@ msp430_dstoperand (struct msp430_operand_s * op,
       op->mode = OP_EXP;
       op->am = 1;
       op->ol = 1;
+      op->vshift = 0;
       parse_exp (__tl, &(op->exp));
 
       if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
@@ -1791,7 +1807,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   struct msp430_operand_s op1, op2;
   int res = 0;
   static short ZEROS = 0;
-  int byte_op, imm_op;
+  bfd_boolean byte_op, imm_op;
   int op_length = 0;
   int fmt;
   int extended = 0x1800;
@@ -1808,7 +1824,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
      or
      .b @r2+, 5(R1).  */
 
-  byte_op = 0;
+  byte_op = FALSE;
   addr_op = FALSE;
   if (*line == '.')
     {
@@ -1820,7 +1836,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
        case 'b':
          /* Byte operation.  */
          bin |= BYTE_OPERATION;
-         byte_op = 1;
+         byte_op = TRUE;
          check = TRUE;
          break;
 
@@ -1902,7 +1918,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   memset (&op1, 0, sizeof (op1));
   memset (&op2, 0, sizeof (op2));
 
-  imm_op = 0;
+  imm_op = FALSE;
 
   if ((fmt = opcode->fmt) < 0)
     {
@@ -2073,7 +2089,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op1.reg)
                        fix_new_exp (frag_now, where, 2,
-                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2175,7 +2191,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op1.reg || (op1.reg == 0 && op1.am == 3))     /* Not PC relative.  */
                        fix_new_exp (frag_now, where, 2,
-                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2199,7 +2215,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op2.reg)      /* Not PC relative.  */
                        fix_new_exp (frag_now, where, 2,
-                                    &(op2.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op2.exp), FALSE, CHECK_RELOC_MSP430 (op2));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2223,8 +2239,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          if (res)
            break;
 
-         byte_op = 0;
-         imm_op = 0;
+         byte_op = FALSE;
+         imm_op = FALSE;
          bin |= ((op1.reg << 8) | (op1.am << 4));
          op_length = 2 + 2 * op1.ol;
          frag = frag_more (op_length);
@@ -2245,7 +2261,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
                  if (op1.reg || (op1.reg == 0 && op1.am == 3))
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2260,14 +2276,14 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          fix_emitted = FALSE;
 
          line = extract_operand (line, l1, sizeof (l1));
-         imm_op = 0;
+         imm_op = FALSE;
 
          res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op,
                                   extended_op, FALSE);
          if (res)
            break;
 
-         byte_op = 0;
+         byte_op = FALSE;
 
          op_length = 2 + 2 * op1.ol;
          frag = frag_more (op_length);
@@ -2594,7 +2610,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          }
 
        case 9: /* MOVA, BRA, RETA.  */
-         imm_op = 0;
+         imm_op = FALSE;
          bin = opcode->bin_opcode;
 
          if (is_opcode ("reta"))
@@ -2819,7 +2835,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2844,7 +2860,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op2.reg)          /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                            &(op2.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op2.exp), FALSE, CHECK_RELOC_MSP430 (op2));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2952,7 +2968,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -3352,6 +3368,12 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
          bfd_putl16 ((bfd_vma) value, where);
          break;
 
+       case BFD_RELOC_MSP430_ABS_HI16:
+         value >>= 16;
+         value &= 0xffff;      /* Get rid of extended sign.  */
+         bfd_putl16 ((bfd_vma) value, where);
+         break;
+         
        case BFD_RELOC_32:
          bfd_putl16 ((bfd_vma) value, where);
          break;
index db8eb2e..a9c1a8a 100644 (file)
@@ -1,3 +1,9 @@
+2014-05-20  Nick Clifton  <nickc@redhat.com>
+
+       * gas/elf/struct.d: Expect extra output from some toolchains.
+       * gas/symver/symver0.d: Likewise.
+       * gas/symver/symver1.d: Likewise.
+
 2014-05-09  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gas/i386/nops-1-core2.d: Replace data32 with data16.
index 420c6e5..dac6b56 100644 (file)
@@ -1,8 +1,11 @@
 #nm: --extern-only
 #name: ELF struct
-
+#
 # Test the .struct pseudo-op.
+# The #... is there to match extra symbols inserted by
+# some toolchains, eg msp430-elf will add _crt0_movedata.
 
+#...
 0+0 D l1
 0+4 D l2
 0+2 A w1
index 9ad6c88..c7accc7 100644 (file)
@@ -4,6 +4,7 @@
 # The #... and #pass are there to match extra symbols inserted by
 # some toolchains, eg arm-elf toolchain will add $d.
 
+#...
 [      ]+U foo@version1
 #...
 0+0000000 D foo1
index ab9b949..b480e37 100644 (file)
@@ -4,6 +4,7 @@
 # The #... and #pass are there to match extra symbols inserted by
 # some toolchains, eg arm-elf toolchain will add $d.
 
+#...
 [      ]+U foo@version1
 #...
 0+0000000 D foo1@@version1
index e76a4fd..754933b 100644 (file)
@@ -1,3 +1,7 @@
+2014-05-19  Nick Clifton  <nickc@redhat.com>
+
+       * msp430.h (struct msp430_operand_s): Add vshift field.
+
 2014-05-07  Andrew Bennett  <andrew.bennett@imgtec.com>
 
        * mips.h (INSN_ISA_MASK): Updated.
index 910565c..0e73815 100644 (file)
@@ -26,7 +26,8 @@ struct msp430_operand_s
   int ol;      /* Operand length words.  */
   int am;      /* Addr mode.  */
   int reg;     /* Register.  */
-  int mode;    /* Pperand mode.  */
+  int mode;    /* Operand mode.  */
+  int vshift;   /* Number of bytes to shift operand down.  */
 #define OP_REG         0
 #define OP_EXP         1
 #ifndef DASM_SECTION