From 92e90b6eb3b2c77ecc6b93fe96f0896b24039ec2 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 29 Jul 2005 17:28:33 +0000 Subject: [PATCH] 2005-07-29 Paul Brook bfd/ * reloc.c (BFD_RELOC_ARM_T32_IMM12): Add. * bfd-in2.h: Regeenrate. * libbfd.h: Regenerate. gas/ * 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. gas/testsuite/ * gas/arm/thumb32.s: Add tests for addw, subw, tbb and tbh. * gas/arm/thumb32.d: Ditto. opcodes/ * arm-dis.c (thumb32_opc): Fix addressing mode for tbh. (print_insn_thumb32): Fix decoding of thumb2 'I' operands. --- bfd/ChangeLog | 6 +++ bfd/bfd-in2.h | 1 + bfd/libbfd.h | 1 + bfd/reloc.c | 2 + gas/ChangeLog | 9 ++++ gas/config/tc-arm.c | 103 +++++++++++++++++++++++++++++++++++++++- gas/testsuite/ChangeLog | 5 ++ gas/testsuite/gas/arm/thumb32.d | 8 ++++ gas/testsuite/gas/arm/thumb32.s | 8 ++++ opcodes/ChangeLog | 5 ++ opcodes/arm-dis.c | 4 +- 11 files changed, 149 insertions(+), 3 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0728b7f..c016e7f 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 a936176..2db99a4 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 6e73163..51aa3c9 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 671746f..7c2ccdb 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2736,6 +2736,8 @@ ENUMX ENUMX BFD_RELOC_ARM_T32_IMMEDIATE ENUMX + BFD_RELOC_ARM_T32_IMM12 +ENUMX BFD_RELOC_ARM_SHIFT_IMM ENUMX BFD_RELOC_ARM_SMI diff --git a/gas/ChangeLog b/gas/ChangeLog index 5bdaec6..0e0b516 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 0c9911f..12b4add 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. */ @@ -7224,6 +7292,21 @@ do_t_swi (void) } 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) { inst.instruction |= inst.operands[0].reg << 8; @@ -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 a1183a8..3638c67 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 a74253e..530ec0b 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 4baf4ff..096b445 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 f764d0e..539252e 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 0f3b65e..14b9901 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; -- 2.7.4