diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0728b7fd03..c016e7fe70 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2005-07-29 Paul Brook + + * reloc.c (BFD_RELOC_ARM_T32_IMM12): Add. + * bfd-in2.h: Regeenrate. + * libbfd.h: Regenerate. + 2005-07-29 Pavel Kankovsky * peXXigen.c (pe_print_edata): Compute the size of the export diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index a936176d15..2db99a4494 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2880,6 +2880,7 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_IMMEDIATE, BFD_RELOC_ARM_ADRL_IMMEDIATE, BFD_RELOC_ARM_T32_IMMEDIATE, + BFD_RELOC_ARM_T32_IMM12, BFD_RELOC_ARM_SHIFT_IMM, BFD_RELOC_ARM_SMI, BFD_RELOC_ARM_SWI, diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6e73163566..51aa3c976b 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1211,6 +1211,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_IMMEDIATE", "BFD_RELOC_ARM_ADRL_IMMEDIATE", "BFD_RELOC_ARM_T32_IMMEDIATE", + "BFD_RELOC_ARM_T32_IMM12", "BFD_RELOC_ARM_SHIFT_IMM", "BFD_RELOC_ARM_SMI", "BFD_RELOC_ARM_SWI", diff --git a/bfd/reloc.c b/bfd/reloc.c index 671746ff99..7c2ccdbc33 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2735,6 +2735,8 @@ ENUMX BFD_RELOC_ARM_ADRL_IMMEDIATE ENUMX BFD_RELOC_ARM_T32_IMMEDIATE +ENUMX + BFD_RELOC_ARM_T32_IMM12 ENUMX BFD_RELOC_ARM_SHIFT_IMM ENUMX diff --git a/gas/ChangeLog b/gas/ChangeLog index 5bdaec66be..0e0b51639e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2005-07-29 Paul Brook + + * config/tc-arm.c (parse_tb): New function. + (enum operand_parse_code): Add OP_TB. + (parse_operands): Handle OP_TB. + (do_t_add_sub_w, do_t_tb): New functions. + (insns): Add entries for addw, subw, tbb and tbh. + (md_apply_fix): Handle BFD_RELOC_ARM_T32_IMM12. + 2005-07-29 Kazuhiro Inaoka * config/tc-m32r.c (m32r_check_fixup): Fixed X_op check. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 0c9911f767..12b4addd3a 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -3491,6 +3491,55 @@ parse_cond (char **str) return c->value; } +/* Parse the operands of a table branch instruction. Similar to a memory + operand. */ +static int +parse_tb (char **str) +{ + char * p = *str; + int reg; + + if (skip_past_char (&p, '[') == FAIL) + return FAIL; + + if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL) + { + inst.error = _(reg_expected_msgs[REG_TYPE_RN]); + return FAIL; + } + inst.operands[0].reg = reg; + + if (skip_past_comma (&p) == FAIL) + return FAIL; + + if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL) + { + inst.error = _(reg_expected_msgs[REG_TYPE_RN]); + return FAIL; + } + inst.operands[0].imm = reg; + + if (skip_past_comma (&p) == SUCCESS) + { + if (parse_shift (&p, 0, SHIFT_LSL_IMMEDIATE) == FAIL) + return FAIL; + if (inst.reloc.exp.X_add_number != 1) + { + inst.error = _("invalid shift"); + return FAIL; + } + inst.operands[0].shifted = 1; + } + + if (skip_past_char (&p, ']') == FAIL) + { + inst.error = _("']' expected"); + return FAIL; + } + *str = p; + return SUCCESS; +} + /* Matcher codes for parse_operands. */ enum operand_parse_code { @@ -3546,6 +3595,7 @@ enum operand_parse_code OP_ENDI, /* Endianness specifier */ OP_PSR, /* CPSR/SPSR mask for msr */ OP_COND, /* conditional code */ + OP_TB, /* Table branch. */ OP_RRnpc_I0, /* ARM register or literal 0 */ OP_RR_EXr, /* ARM register or expression with opt. reloc suff. */ @@ -3787,6 +3837,10 @@ parse_operands (char *str, const unsigned char *pattern) case OP_PSR: val = parse_psr (&str); break; case OP_COND: val = parse_cond (&str); break; + case OP_TB: + po_misc_or_fail (parse_tb (&str)); + break; + /* Register lists */ case OP_REGLST: val = parse_reg_list (&str); @@ -5774,6 +5828,20 @@ static const unsigned int thumb_op32[] = { T16_32_TAB }; /* Thumb instruction encoders, in alphabetical order. */ +/* ADDW or SUBW. */ +static void +do_t_add_sub_w (void) +{ + int Rd, Rn; + + Rd = inst.operands[0].reg; + Rn = inst.operands[1].reg; + + constraint (Rd == 15, _("PC not allowed as destination")); + inst.instruction |= (Rn << 16) | (Rd << 8); + inst.reloc.type = BFD_RELOC_ARM_T32_IMM12; +} + /* Parse an add or subtract instruction. We get here with inst.instruction equalling any of THUMB_OPCODE_add, adds, sub, or subs. */ @@ -7223,6 +7291,21 @@ do_t_swi (void) inst.reloc.type = BFD_RELOC_ARM_SWI; } +static void +do_t_tb (void) +{ + int half; + + half = (inst.instruction & 0x10) != 0; + constraint (inst.operands[0].imm == 15, + _("PC is not a valid index register")); + constraint (!half && inst.operands[0].shifted, + _("instruction does not allow shifted index")); + constraint (half && !inst.operands[0].shifted, + _("instruction requires shifted index")); + inst.instruction |= (inst.operands[0].reg << 16) | inst.operands[0].imm; +} + static void do_t_usat (void) { @@ -8464,6 +8547,15 @@ static const struct asm_opcode insns[] = TUE(ittee, 0, bf09, 1, (COND), it, t_it), TUE(iteee, 0, bf01, 1, (COND), it, t_it), + /* Thumb2 only instructions. */ +#undef ARM_VARIANT +#define ARM_VARIANT 0 + + TCE(addw, 0, f2000000, 3, (RR, RR, EXPi), 0, t_add_sub_w), + TCE(subw, 0, f2a00000, 3, (RR, RR, EXPi), 0, t_add_sub_w), + TCE(tbb, 0, e8d0f000, 1, (TB), 0, t_tb), + TCE(tbh, 0, e8d0f010, 1, (TB), 0, t_tb), + #undef ARM_VARIANT #define ARM_VARIANT FPU_FPA_EXT_V1 /* Core FPA instruction set (V1). */ CE(wfs, e200110, 1, (RR), rd), @@ -10439,6 +10531,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_T32_IMMEDIATE: + case BFD_RELOC_ARM_T32_IMM12: /* We claim that this fixup has been processed here, even if in fact we generate an error because we do not have a reloc for it, so tc_gen_reloc will reject it. */ @@ -10457,7 +10550,15 @@ md_apply_fix (fixS * fixP, newval <<= 16; newval |= md_chars_to_number (buf+2, THUMB_SIZE); - newimm = encode_thumb32_immediate (value); + if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMM12) + { + if (value > 0xfff) + newimm = (unsigned int) FAIL; + else + newimm = value; + } + else + newimm = encode_thumb32_immediate (value); /* FUTURE: Implement analogue of negate_data_op for T32. */ if (newimm == (unsigned int)FAIL) diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index a1183a8b6b..3638c67834 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-29 Paul Brook + + * gas/arm/thumb32.s: Add tests for addw, subw, tbb and tbh. + * gas/arm/thumb32.d: Ditto. + 2005-07-27 Jan Beulich * gas/ia64/unwind-bad.l: Uncomment patterns matching new warnings. diff --git a/gas/testsuite/gas/arm/thumb32.d b/gas/testsuite/gas/arm/thumb32.d index a74253e0d7..530ec0b1be 100644 --- a/gas/testsuite/gas/arm/thumb32.d +++ b/gas/testsuite/gas/arm/thumb32.d @@ -1011,3 +1011,11 @@ Disassembly of section .text: 0+cf4 <[^>]+> f8df 1155 ldr\.w r1, \[pc, #341\] ; 0+e4d <[^>]+> 0+cf8 <[^>]+> f85f 12aa ldr\.w r1, \[pc, #-682\] ; 0+a52 <[^>]+> 0+cfc <[^>]+> f85f 1155 ldr\.w r1, \[pc, #-341\] ; 0+bab <[^>]+> +0+d00 <[^>]+> f200 0900 addw r9, r0, #0 ; 0x0 +0+d04 <[^>]+> f60f 76ff addw r6, pc, #4095 ; 0xfff +0+d08 <[^>]+> f6a9 2685 subw r6, r9, #2693 ; 0xa85 +0+d0c <[^>]+> f2a9 567a subw r6, r9, #1402 ; 0x57a +0+d10 <[^>]+> e8df f006 tbb \[pc, r6\] +0+d14 <[^>]+> e8d0 f009 tbb \[r0, r9\] +0+d18 <[^>]+> e8df f017 tbh \[pc, r7, lsl #1\] +0+d1c <[^>]+> e8d0 f018 tbh \[r0, r8, lsl #1\] diff --git a/gas/testsuite/gas/arm/thumb32.s b/gas/testsuite/gas/arm/thumb32.s index 4baf4ff24c..096b4452df 100644 --- a/gas/testsuite/gas/arm/thumb32.s +++ b/gas/testsuite/gas/arm/thumb32.s @@ -745,3 +745,11 @@ xta: ldpcimm ldrh ldpcimm ldrsh ldpcimm ldr + addw r9, r0, #0 + addw r6, pc, #0xfff + subw r6, r9, #0xa85 + subw r6, r9, #0x57a + tbb [pc, r6] + tbb [r0, r9] + tbh [pc, r7, lsl #1] + tbh [r0, r8, lsl #1] diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index f764d0eb83..539252e50f 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2005-07-29 Paul Brook + + * arm-dis.c (thumb32_opc): Fix addressing mode for tbh. + (print_insn_thumb32): Fix decoding of thumb2 'I' operands. + 2005-07-25 DJ Delorie * m32c-asm.c Regenerate. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 0f3b65e13b..14b9901ea0 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -839,7 +839,7 @@ static const struct opcode32 thumb32_opcodes[] = {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff0ff, "mrs\t%8-11r, %20?CSPSR"}, {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"}, {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"}, - {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r]"}, + {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"}, {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"}, {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"}, {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"}, @@ -2132,7 +2132,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) unsigned int imm12 = 0; imm12 |= (given & 0x000000ffu); imm12 |= (given & 0x00007000u) >> 4; - imm12 |= (given & 0x04000000u) >> 12; + imm12 |= (given & 0x04000000u) >> 15; func (stream, "#%u\t; 0x%x", imm12, imm12); } break;