diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 1 | ||||
-rw-r--r-- | bfd/libbfd.h | 1 | ||||
-rw-r--r-- | bfd/reloc.c | 2 | ||||
-rw-r--r-- | gas/ChangeLog | 8 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 52 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/thumb2_add.d | 18 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/thumb2_add.s | 20 |
9 files changed, 100 insertions, 13 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6c4773e..4ce004e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2006-07-18 Paul Brook <paul@codesourcery.com> + + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + * reloc.c: Add BFD_RELOC_ARM_T32_ADD_IMM. + 2006-07-18 Nick Clifton <nickc@redhat.com> * elfxx-mips.c (_bfd_mips_elf_common_definition): New function. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index df3bae8..381ae55 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2966,6 +2966,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_ADD_IMM, BFD_RELOC_ARM_T32_IMM12, BFD_RELOC_ARM_T32_ADD_PC12, BFD_RELOC_ARM_SHIFT_IMM, diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 0f41f5f..0aa7046 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1263,6 +1263,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_ADD_IMM", "BFD_RELOC_ARM_T32_IMM12", "BFD_RELOC_ARM_T32_ADD_PC12", "BFD_RELOC_ARM_SHIFT_IMM", diff --git a/bfd/reloc.c b/bfd/reloc.c index 414a41c..60ebf36 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2822,6 +2822,8 @@ ENUMX ENUMX BFD_RELOC_ARM_T32_IMMEDIATE ENUMX + BFD_RELOC_ARM_T32_ADD_IMM +ENUMX BFD_RELOC_ARM_T32_IMM12 ENUMX BFD_RELOC_ARM_T32_ADD_PC12 diff --git a/gas/ChangeLog b/gas/ChangeLog index 80c46cd..6b414dc 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2006-07-18 Paul Brook <paul@codesourcery.com> + + * tc-arm.c (do_t_add_sub): Use addw/subw when source is PC. + (md_convert_frag): Use correct reloc for add_pc. Use + BFD_RELOC_ARM_T32_ADD_IMM for normal add/sum. + (md_apply_fix): Handle BFD_RELOC_ARM_T32_ADD_IMM. + (arm_force_relocation): Handle BFD_RELOC_ARM_T32_ADD_IMM. + 2006-07-17 Mat Hostetter <mat@lcs.mit.edu> * symbols.c (report_op_error): Fix pasto. Don't use as_bad_where diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 1bfe5b3..fe9d775 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -8186,13 +8186,13 @@ do_t_add_sub (void) narrow = (current_it_mask != 0); if (!inst.operands[2].isreg) { + int add; + + add = (inst.instruction == T_MNEM_add + || inst.instruction == T_MNEM_adds); opcode = 0; if (inst.size_req != 4) { - int add; - - add = (inst.instruction == T_MNEM_add - || inst.instruction == T_MNEM_adds); /* Attempt to use a narrow opcode, with relaxation if appropriate. */ if (Rd == REG_SP && Rs == REG_SP && !flags) @@ -8222,12 +8222,24 @@ do_t_add_sub (void) if (inst.size_req == 4 || (inst.size_req != 2 && !opcode)) { - /* ??? Convert large immediates to addw/subw. */ - inst.instruction = THUMB_OP32 (inst.instruction); - inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000; + if (Rs == REG_PC) + { + /* Always use addw/subw. */ + inst.instruction = add ? 0xf20f0000 : 0xf2af0000; + inst.reloc.type = BFD_RELOC_ARM_T32_IMM12; + } + else + { + inst.instruction = THUMB_OP32 (inst.instruction); + inst.instruction = (inst.instruction & 0xe1ffffff) + | 0x10000000; + if (flags) + inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE; + else + inst.reloc.type = BFD_RELOC_ARM_T32_ADD_IMM; + } inst.instruction |= inst.operands[0].reg << 8; inst.instruction |= inst.operands[1].reg << 16; - inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE; } } else @@ -16136,7 +16148,10 @@ md_convert_frag (bfd *abfd, segT asec ATTRIBUTE_UNUSED, fragS *fragp) insn = THUMB_OP32 (opcode); insn |= (old_op & 0xf0) << 4; put_thumb32_insn (buf, insn); - reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE; + if (opcode == T_MNEM_add_pc) + reloc_type = BFD_RELOC_ARM_T32_IMM12; + else + reloc_type = BFD_RELOC_ARM_T32_ADD_IMM; } else reloc_type = BFD_RELOC_ARM_THUMB_ADD; @@ -16153,7 +16168,10 @@ md_convert_frag (bfd *abfd, segT asec ATTRIBUTE_UNUSED, fragS *fragp) insn |= (old_op & 0xf0) << 4; insn |= (old_op & 0xf) << 16; put_thumb32_insn (buf, insn); - reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE; + if (insn & (1 << 20)) + reloc_type = BFD_RELOC_ARM_T32_ADD_IMM; + else + reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE; } else reloc_type = BFD_RELOC_ARM_THUMB_ADD; @@ -17561,6 +17579,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_T32_IMMEDIATE: + case BFD_RELOC_ARM_T32_ADD_IMM: case BFD_RELOC_ARM_T32_IMM12: case BFD_RELOC_ARM_T32_ADD_PC12: /* We claim that this fixup has been processed here, @@ -17581,15 +17600,21 @@ md_apply_fix (fixS * fixP, newval <<= 16; newval |= md_chars_to_number (buf+2, THUMB_SIZE); - /* FUTURE: Implement analogue of negate_data_op for T32. */ - if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE) + newimm = FAIL; + if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE + || fixP->fx_r_type == BFD_RELOC_ARM_T32_ADD_IMM) { newimm = encode_thumb32_immediate (value); if (newimm == (unsigned int) FAIL) newimm = thumb32_negate_data_op (&newval, value); } - else + if (fixP->fx_r_type != BFD_RELOC_ARM_T32_IMMEDIATE + && newimm == (unsigned int) FAIL) { + /* Turn add/sum into addw/subw. */ + if (fixP->fx_r_type == BFD_RELOC_ARM_T32_ADD_IMM) + newval = (newval & 0xfeffffff) | 0x02000000; + /* 12 bit immediate for addw/subw. */ if (value < 0) { @@ -18608,6 +18633,7 @@ arm_force_relocation (struct fix * fixp) if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE + || fixp->fx_r_type == BFD_RELOC_ARM_T32_ADD_IMM || fixp->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE || fixp->fx_r_type == BFD_RELOC_ARM_T32_IMM12 || fixp->fx_r_type == BFD_RELOC_ARM_T32_ADD_PC12) diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 327364b..16b48ac 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-07-18 Paul Brook <paul@codesourcery.com> + + * gas/arm/thumb2_add.d: New test. + * gas/arm/thumb2_add.s: New test. + 2006-07-18 Maciej W. Rozycki <macro@mips.com> * gas/mips/mips4.s, gas/mips/mips4.d: Enable the "pref" test. Change diff --git a/gas/testsuite/gas/arm/thumb2_add.d b/gas/testsuite/gas/arm/thumb2_add.d new file mode 100644 index 0000000..6331acf --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_add.d @@ -0,0 +1,18 @@ +# as: -march=armv6kt2 +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section .text: +0+000 <[^>]+> f60f 0000 addw r0, pc, #2048 ; 0x800 +0+004 <[^>]+> f20f 0900 addw r9, pc, #0 ; 0x0 +0+008 <[^>]+> f20f 4900 addw r9, pc, #1024 ; 0x400 +0+00c <[^>]+> f509 6880 add.w r8, r9, #1024 ; 0x400 +0+010 <[^>]+> f209 1801 addw r8, r9, #257 ; 0x101 +0+014 <[^>]+> f201 1301 addw r3, r1, #257 ; 0x101 +0+018 <[^>]+> f6af 0000 subw r0, pc, #2048 ; 0x800 +0+01c <[^>]+> f2af 0900 subw r9, pc, #0 ; 0x0 +0+020 <[^>]+> f2af 4900 subw r9, pc, #1024 ; 0x400 +0+024 <[^>]+> f5a9 6880 sub.w r8, r9, #1024 ; 0x400 +0+028 <[^>]+> f2a9 1801 subw r8, r9, #257 ; 0x101 +0+02c <[^>]+> f2a1 1301 subw r3, r1, #257 ; 0x101 diff --git a/gas/testsuite/gas/arm/thumb2_add.s b/gas/testsuite/gas/arm/thumb2_add.s new file mode 100644 index 0000000..72d1bb1 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_add.s @@ -0,0 +1,20 @@ + .syntax unified + .text + .align 2 + .global thumb2_add + .thumb + .thumb_func + .type thumb2_add, %function +thumb2_add: + add r0, pc, #0x800 + add r9, pc, #0 + add r9, pc, #0x400 + add r8, r9, #0x400 + add r8, r9, #0x101 + add r3, r1, #0x101 + sub r0, pc, #0x800 + sub r9, pc, #0 + sub r9, pc, #0x400 + sub r8, r9, #0x400 + sub r8, r9, #0x101 + sub r3, r1, #0x101 |