diff options
author | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-01-15 13:17:27 +0000 |
---|---|---|
committer | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-01-15 13:23:06 +0000 |
commit | 131cb553d6d10412b20cf49bb0e3a5e736a90a36 (patch) | |
tree | 3965e30e6016b4b61a6bb11cb7be81bbd57a99ab /gas | |
parent | c24d0e8d4850d4913a1630a53e272c930849406d (diff) | |
download | gdb-131cb553d6d10412b20cf49bb0e3a5e736a90a36.zip gdb-131cb553d6d10412b20cf49bb0e3a5e736a90a36.tar.gz gdb-131cb553d6d10412b20cf49bb0e3a5e736a90a36.tar.bz2 |
MSP430: Fix relocation overflow when using #lo(EXP) macro
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 13 | ||||
-rw-r--r-- | gas/config/tc-msp430.c | 35 | ||||
-rw-r--r-- | gas/testsuite/gas/msp430/msp430.exp | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/msp430/reloc-lo-430x.d | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/msp430/reloc-lo-430x.s | 22 |
5 files changed, 65 insertions, 11 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 0555b29..d88d15c 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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. diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index b627740..5753882 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -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) diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp index 6eaa659..624867f 100644 --- a/gas/testsuite/gas/msp430/msp430.exp +++ b/gas/testsuite/gas/msp430/msp430.exp @@ -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 index 0000000..78adb84 --- /dev/null +++ b/gas/testsuite/gas/msp430/reloc-lo-430x.d @@ -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 index 0000000..a593ac4 --- /dev/null +++ b/gas/testsuite/gas/msp430/reloc-lo-430x.s @@ -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 |