diff options
author | Nick Clifton <nickc@redhat.com> | 2014-05-20 10:28:42 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2014-05-20 10:28:42 +0100 |
commit | 00b32ff21f710a5eed92c9fdf51c32103bcc4176 (patch) | |
tree | b26adf9e6654280500869f1749f0d239f59da1c0 /gas/config/tc-msp430.c | |
parent | 273dc279306c2b69fbc1407cc695397e4b015152 (diff) | |
download | gdb-00b32ff21f710a5eed92c9fdf51c32103bcc4176.zip gdb-00b32ff21f710a5eed92c9fdf51c32103bcc4176.tar.gz gdb-00b32ff21f710a5eed92c9fdf51c32103bcc4176.tar.bz2 |
Fix MSP430 assembler to support #hi(<symbol>).
* 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.
Diffstat (limited to 'gas/config/tc-msp430.c')
-rw-r--r-- | gas/config/tc-msp430.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 948117c..2db0fc0 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; |