MSP430: Fix relocation overflow when using #lo(EXP) macro
authorJozef Lawrynowicz <jozef.l@mittosystems.com>
Wed, 15 Jan 2020 13:17:27 +0000 (13:17 +0000)
committerJozef Lawrynowicz <jozef.l@mittosystems.com>
Wed, 15 Jan 2020 13:23:06 +0000 (13:23 +0000)
gas/ChangeLog:

2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* config/tc-msp430.c (CHECK_RELOC_MSP430): Always generate 430X
relocations when the target is 430X, except when extracting part of an
expression.
(msp430_srcoperand): Adjust comment.
Initialize the expp member of the msp430_operand_s struct as
appropriate.
(msp430_dstoperand): Likewise.
* testsuite/gas/msp430/msp430.exp: Run new test.
* testsuite/gas/msp430/reloc-lo-430x.d: New test.
* testsuite/gas/msp430/reloc-lo-430x.s: New test.

include/ChangeLog:

2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* opcode/msp430.h (enum msp430_expp_e): New.
(struct msp430_operand_s): Add expp member to struct.

ld/ChangeLog:

2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* testsuite/ld-msp430-elf/msp430-elf.exp: Run new test.
* testsuite/ld-msp430-elf/reloc-lo-430x.s: New test.

gas/ChangeLog
gas/config/tc-msp430.c
gas/testsuite/gas/msp430/msp430.exp
gas/testsuite/gas/msp430/reloc-lo-430x.d [new file with mode: 0644]
gas/testsuite/gas/msp430/reloc-lo-430x.s [new file with mode: 0644]
include/ChangeLog
include/opcode/msp430.h
ld/ChangeLog
ld/testsuite/ld-msp430-elf/msp430-elf.exp
ld/testsuite/ld-msp430-elf/reloc-lo-430x.s [new file with mode: 0644]

index 0555b29f97da4df39dbcc1305a052e4534ed077c..d88d15cbe0e257bd674c3e3c3ea7357c2019e699 100644 (file)
@@ -1,3 +1,16 @@
+2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * config/tc-msp430.c (CHECK_RELOC_MSP430): Always generate 430X
+       relocations when the target is 430X, except when extracting part of an
+       expression.
+       (msp430_srcoperand): Adjust comment.
+       Initialize the expp member of the msp430_operand_s struct as
+       appropriate.
+       (msp430_dstoperand): Likewise.
+       * testsuite/gas/msp430/msp430.exp: Run new test.
+       * testsuite/gas/msp430/reloc-lo-430x.d: New test.
+       * testsuite/gas/msp430/reloc-lo-430x.s: New test.
+
 2020-01-15  Alan Modra  <amodra@gmail.com>
 
        * configure.tgt: Add sparc-*-freebsd case.
index b627740f50e95ac21bcda4d7079d87be3f22744c..57538824e9299a0db66d9f38222f55d434cec8f0 100644 (file)
@@ -275,21 +275,21 @@ target_is_430xv2 (void)
   return selected_isa == MSP_ISA_430Xv2;
 }
 
-/* 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.
+/* Generate an absolute 16-bit relocation, for 430 (!extended_op) instructions
+   only.
+   For the 430X we generate a 430 relocation only for the case where part of an
+   expression is being extracted (e.g. #hi(EXP), #lo(EXP). Otherwise generate
+   a 430X relocation.
    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(OP)                         \
   (target_is_430x ()                                   \
-  ? (extended_op                                       \
-     ? BFD_RELOC_16                                    \
-     : ((OP).vshift == 1)                              \
-     ? BFD_RELOC_MSP430_ABS_HI16                       \
-     : BFD_RELOC_MSP430X_ABS16)                                \
+   ? ((OP).expp == MSP_EXPP_ALL                                \
+       ? BFD_RELOC_MSP430X_ABS16                       \
+       : ((OP).vshift == 1                             \
+         ? BFD_RELOC_MSP430_ABS_HI16 : BFD_RELOC_16))  \
    : ((imm_op || byte_op)                              \
       ? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16))
 
@@ -1909,13 +1909,15 @@ msp430_srcoperand (struct msp430_operand_s * op,
       char *h = l;
       int vshift = -1;
       int rval = 0;
+      /* Use all parts of the constant expression by default.  */
+      enum msp430_expp_e expp = MSP_EXPP_ALL;
 
       /* Check if there is:
         llo(x) - least significant 16 bits, x &= 0xffff
         lhi(x) - x = (x >> 16) & 0xffff,
         hlo(x) - x = (x >> 32) & 0xffff,
         hhi(x) - x = (x >> 48) & 0xffff
-        The value _MUST_ be constant expression: #hlo(1231231231).  */
+        The value _MUST_ be an immediate expression: #hlo(1231231231).  */
 
       *imm_op = TRUE;
 
@@ -1923,31 +1925,37 @@ msp430_srcoperand (struct msp430_operand_s * op,
        {
          vshift = 0;
          rval = 3;
+         expp = MSP_EXPP_LLO;
        }
       else if (strncasecmp (h, "#lhi(", 5) == 0)
        {
          vshift = 1;
          rval = 3;
+         expp = MSP_EXPP_LHI;
        }
       else if (strncasecmp (h, "#hlo(", 5) == 0)
        {
          vshift = 2;
          rval = 3;
+         expp = MSP_EXPP_HLO;
        }
       else if (strncasecmp (h, "#hhi(", 5) == 0)
        {
          vshift = 3;
          rval = 3;
+         expp = MSP_EXPP_HHI;
        }
       else if (strncasecmp (h, "#lo(", 4) == 0)
        {
          vshift = 0;
          rval = 2;
+         expp = MSP_EXPP_LO;
        }
       else if (strncasecmp (h, "#hi(", 4) == 0)
        {
          vshift = 1;
          rval = 2;
+         expp = MSP_EXPP_HI;
        }
 
       op->reg = 0;             /* Reg PC.  */
@@ -1956,6 +1964,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       __tl = h + 1 + rval;
       op->mode = OP_EXP;
       op->vshift = vshift;
+      op->expp = expp;
 
       end = parse_exp (__tl, &(op->exp));
       if (end != NULL && *end != 0 && *end != ')' )
@@ -2167,6 +2176,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
        }
       op->mode = OP_EXP;
       op->vshift = 0;
+      op->expp = MSP_EXPP_ALL;
       if (op->exp.X_op == O_constant)
        {
          int x = op->exp.X_add_number;
@@ -2275,6 +2285,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       *h = 0;
       op->mode = OP_EXP;
       op->vshift = 0;
+      op->expp = MSP_EXPP_ALL;
       end = parse_exp (__tl, &(op->exp));
       if (end != NULL && *end != 0)
        {
@@ -2348,6 +2359,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
   op->am = (*l == '-' ? 3 : 1);
   op->ol = 1;
   op->vshift = 0;
+  op->expp = MSP_EXPP_ALL;
   __tl = l;
   end = parse_exp (__tl, &(op->exp));
   if (end != NULL && * end != 0)
@@ -2382,6 +2394,7 @@ msp430_dstoperand (struct msp430_operand_s * op,
       op->am = 1;
       op->ol = 1;
       op->vshift = 0;
+      op->expp = MSP_EXPP_ALL;
       (void) parse_exp (__tl, &(op->exp));
 
       if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
index 6eaa659c54edebc86a818852e37ed2967e6e188e..624867f33b4d915302f3c5a41a35ee9c440734e3 100644 (file)
@@ -52,4 +52,5 @@ if [expr [istarget "msp430-*-*"]]  then {
     run_dump_test "attr-430x-large-lower-good"
     run_dump_test "attr-430x-large-any-bad"
     run_dump_test "attr-430x-large-any-good"
+    run_dump_test "reloc-lo-430x"
 }
diff --git a/gas/testsuite/gas/msp430/reloc-lo-430x.d b/gas/testsuite/gas/msp430/reloc-lo-430x.d
new file mode 100644 (file)
index 0000000..78adb84
--- /dev/null
@@ -0,0 +1,5 @@
+#as: -ml
+#readelf: -r
+#...
+.*R_MSP430_ABS16.*P \+ 0
+#...
diff --git a/gas/testsuite/gas/msp430/reloc-lo-430x.s b/gas/testsuite/gas/msp430/reloc-lo-430x.s
new file mode 100644 (file)
index 0000000..a593ac4
--- /dev/null
@@ -0,0 +1,22 @@
+.text
+       .balign 2
+       .global foo
+       .type   foo, @function
+foo:
+  MOV.W        #lo (P), R8
+       RETA
+       .size   foo, .-foo
+
+       .balign 2
+       .global main
+       .type   main, @function
+main:
+       CALLA   #foo
+.L4:
+       BRA     #.L4
+       .size   main, .-main
+       .section        .bss,"aw",@nobits
+       .balign 2
+       .global P
+P:
+       .zero   4
index 64a03f2f10f02af88a98a9140cab68e9f69666bd..f6ad34d12294e3a152bd9f23613850de5c2bd4ed 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * opcode/msp430.h (enum msp430_expp_e): New.
+       (struct msp430_operand_s): Add expp member to struct.
+
 2020-01-13  Claudiu Zissulescu  <claziss@gmail.com>
 
        * elf/arc-cpu.def: Update ARC cpu list.
index aaf0990bf8f4bcfafbc23fa243bc8cd6ec9f2235..96fe674c8fb54c2af4d8aec3ad3a02311abf7f63 100644 (file)
 #ifndef __MSP430_H_
 #define __MSP430_H_
 
+enum msp430_expp_e
+{
+  MSP_EXPP_ALL = 0,    /* Use full the value of the expression - default.  */
+  MSP_EXPP_LO,         /* Extract least significant word from expression.  */
+  MSP_EXPP_HI,         /* Extract 2nd word from expression.  */
+  MSP_EXPP_LLO,                /* Extract least significant word from an
+                          immediate value.  */
+  MSP_EXPP_LHI,                /* Extract 2nd word from an immediate value.  */
+  MSP_EXPP_HLO,                /* Extract 3rd word from an immediate value.  */
+  MSP_EXPP_HHI,                /* Extract 4th word from an immediate value.  */
+};
+
 struct msp430_operand_s
 {
   int ol;      /* Operand length words.  */
@@ -28,6 +40,9 @@ struct msp430_operand_s
   int reg;     /* Register.  */
   int mode;    /* Operand mode.  */
   int vshift;   /* Number of bytes to shift operand down.  */
+  enum msp430_expp_e expp;     /* For when the operand is a constant
+                                  expression, the part of the expression to
+                                  extract.  */
 #define OP_REG         0
 #define OP_EXP         1
 #ifndef DASM_SECTION
index c68d92038c05527fe96b02081bca28103fbfaaa3..7e83e2b822eeb3b239cf35d2d2f06e862202fbfb 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * testsuite/ld-msp430-elf/msp430-elf.exp: Run new test.
+       * testsuite/ld-msp430-elf/reloc-lo-430x.s: New test.
+
 2020-01-15  Alan Modra  <amodra@gmail.com>
 
        * testsuite/ld-powerpc/ambiguousv1b.d: Adjust expected output.
index c9d4bee3eb73248a86155976c2fd81f94a9415cd..777b358a745724660c8b5847fc331957d1f1e8a2 100644 (file)
@@ -174,6 +174,8 @@ run_ld_link_tests $msp430eithershuffletests
 run_ld_link_tests $msp430warntests
 
 run_dump_test valid-map
+run_ld_link_tests {{ "Check no reloc overflow with #lo and data in the upper region"
+        "-m msp430X" "" "" {reloc-lo-430x.s} {} "reloc-lo-430x"}}
 
 # Don't run data region tests if a data region is specified
 if {[string match "*-mdata-region*" [board_info [target_info name] multilib_flags]]} {
diff --git a/ld/testsuite/ld-msp430-elf/reloc-lo-430x.s b/ld/testsuite/ld-msp430-elf/reloc-lo-430x.s
new file mode 100644 (file)
index 0000000..8709e79
--- /dev/null
@@ -0,0 +1,22 @@
+.text
+       .balign 2
+       .global foo
+       .type   foo, @function
+foo:
+  MOV.W        #lo (P), R8
+       RETA
+       .size   foo, .-foo
+
+       .balign 2
+       .global main
+       .type   main, @function
+main:
+       CALLA   #foo
+.L4:
+       BRA     #.L4
+       .size   main, .-main
+       .section        .bss,"aw",@nobits
+       .balign 2
+       .global P
+P:
+       .zero 4