From: Nick Clifton Date: Tue, 20 May 2014 09:28:42 +0000 (+0100) Subject: Fix MSP430 assembler to support #hi(). X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00b32ff21f710a5eed92c9fdf51c32103bcc4176;p=binutils-gdb.git Fix MSP430 assembler to support #hi(). * 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 26cef7ff9dd..f873e2b968e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2014-05-20 Nick Clifton + + * 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 PR gas/16858 diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 948117c0a09..2db0fc027c1 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -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; diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index db8eb2e5628..a9c1a8a7eaa 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-05-20 Nick Clifton + + * 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 * gas/i386/nops-1-core2.d: Replace data32 with data16. diff --git a/gas/testsuite/gas/elf/struct.d b/gas/testsuite/gas/elf/struct.d index 420c6e50111..dac6b56bd1f 100644 --- a/gas/testsuite/gas/elf/struct.d +++ b/gas/testsuite/gas/elf/struct.d @@ -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 diff --git a/gas/testsuite/gas/symver/symver0.d b/gas/testsuite/gas/symver/symver0.d index 9ad6c88e836..c7accc78a99 100644 --- a/gas/testsuite/gas/symver/symver0.d +++ b/gas/testsuite/gas/symver/symver0.d @@ -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 diff --git a/gas/testsuite/gas/symver/symver1.d b/gas/testsuite/gas/symver/symver1.d index ab9b9495b18..b480e37063b 100644 --- a/gas/testsuite/gas/symver/symver1.d +++ b/gas/testsuite/gas/symver/symver1.d @@ -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 diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index e76a4fde171..754933b58e0 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,7 @@ +2014-05-19 Nick Clifton + + * msp430.h (struct msp430_operand_s): Add vshift field. + 2014-05-07 Andrew Bennett * mips.h (INSN_ISA_MASK): Updated. diff --git a/include/opcode/msp430.h b/include/opcode/msp430.h index 910565cc4b6..0e73815ae53 100644 --- a/include/opcode/msp430.h +++ b/include/opcode/msp430.h @@ -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