2005-09-06 Paul Brook <paul@codesourcery.com>
gas/ * config/tc-arm.c (arm_it): Add relax field. (T16_32_TAB): Add addi, addis, add_pc, add_sp, dec_sp, inc_sp, b, bcond, ldr_pc, ldr_pc2, ldr_sp, str_sp, subi, subis. (do_t_add_sub, do_t_addr, do_t_branch, do_t_ldst, do_t_mov_cmp): Allow relaxation. (output_relax_insn): New function. (put_thumb32_insn): New function. (output_inst): Use new functions. (md_assemble): Don't throw error on relaxable instructions. (insns): Change "b" entry from TCE(...) to tCE(...). (md_estimate_size_before_relax): Return 2. (md_convert_frag, relax_immediate, relax_adr, relax_addsub, relax_branch, arm_relax_frag): New functions. (arm_force_relocation): Return 0 for Thumb-2 immediate operand relocations. * config/tc-arm.h (md_convert_frag): Remove definition. (md_relax_frag): Define. (arm_relax_frag): Add prototype. gas/testsuite/ * gas/arm/thumb2_relax.d: New test. * gas/arm/thumb2_relax.s: New test. * gas/arm/thumb32.d: Adjust expected results to include relaxation. * gas/arm/thumb32.s: Tweak for better coverage of relaxable instructions. Remove load/store tests.
This commit is contained in:
parent
9a64e43541
commit
0110f2b896
@ -1,3 +1,24 @@
|
||||
2005-09-06 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* config/tc-arm.c (arm_it): Add relax field.
|
||||
(T16_32_TAB): Add addi, addis, add_pc, add_sp, dec_sp, inc_sp,
|
||||
b, bcond, ldr_pc, ldr_pc2, ldr_sp, str_sp, subi, subis.
|
||||
(do_t_add_sub, do_t_addr, do_t_branch, do_t_ldst,
|
||||
do_t_mov_cmp): Allow relaxation.
|
||||
(output_relax_insn): New function.
|
||||
(put_thumb32_insn): New function.
|
||||
(output_inst): Use new functions.
|
||||
(md_assemble): Don't throw error on relaxable instructions.
|
||||
(insns): Change "b" entry from TCE(...) to tCE(...).
|
||||
(md_estimate_size_before_relax): Return 2.
|
||||
(md_convert_frag, relax_immediate, relax_adr, relax_addsub,
|
||||
relax_branch, arm_relax_frag): New functions.
|
||||
(arm_force_relocation): Return 0 for Thumb-2 immediate operand
|
||||
relocations.
|
||||
* config/tc-arm.h (md_convert_frag): Remove definition.
|
||||
(md_relax_frag): Define.
|
||||
(arm_relax_frag): Add prototype.
|
||||
|
||||
2005-09-02 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* config/tc-arm.c (do_rn_rd): Enforce SWP operand constraints.
|
||||
|
@ -213,6 +213,9 @@ struct arm_it
|
||||
int size;
|
||||
int size_req;
|
||||
int cond;
|
||||
/* Set to the opcode if the instruction needs relaxation.
|
||||
Zero if the instruction is not relaxed. */
|
||||
unsigned long relax;
|
||||
struct
|
||||
{
|
||||
bfd_reloc_code_real_type type;
|
||||
@ -5759,17 +5762,24 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
|
||||
encodings (the latter only in post-V6T2 cores). The index is the
|
||||
value used in the insns table below. When there is more than one
|
||||
possible 16-bit encoding for the instruction, this table always
|
||||
holds variant (1). */
|
||||
holds variant (1).
|
||||
Also contains several pseudo-instructions used during relaxation. */
|
||||
#define T16_32_TAB \
|
||||
X(adc, 4140, eb400000), \
|
||||
X(adcs, 4140, eb500000), \
|
||||
X(add, 1c00, eb000000), \
|
||||
X(adds, 1c00, eb100000), \
|
||||
X(addi, 0000, f1000000), \
|
||||
X(addis, 0000, f1100000), \
|
||||
X(add_pc,000f, f20f0000), \
|
||||
X(add_sp,000d, f10d0000), \
|
||||
X(adr, 000f, f20f0000), \
|
||||
X(and, 4000, ea000000), \
|
||||
X(ands, 4000, ea100000), \
|
||||
X(asr, 1000, fa40f000), \
|
||||
X(asrs, 1000, fa50f000), \
|
||||
X(b, e000, f000b000), \
|
||||
X(bcond, d000, f0008000), \
|
||||
X(bic, 4380, ea200000), \
|
||||
X(bics, 4380, ea300000), \
|
||||
X(cmn, 42c0, eb100f00), \
|
||||
@ -5777,14 +5787,19 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
|
||||
X(cpsie, b660, f3af8400), \
|
||||
X(cpsid, b670, f3af8600), \
|
||||
X(cpy, 4600, ea4f0000), \
|
||||
X(dec_sp,80dd, f1bd0d00), \
|
||||
X(eor, 4040, ea800000), \
|
||||
X(eors, 4040, ea900000), \
|
||||
X(inc_sp,00dd, f10d0d00), \
|
||||
X(ldmia, c800, e8900000), \
|
||||
X(ldr, 6800, f8500000), \
|
||||
X(ldrb, 7800, f8100000), \
|
||||
X(ldrh, 8800, f8300000), \
|
||||
X(ldrsb, 5600, f9100000), \
|
||||
X(ldrsh, 5e00, f9300000), \
|
||||
X(ldr_pc,4800, f85f0000), \
|
||||
X(ldr_pc2,4800, f85f0000), \
|
||||
X(ldr_sp,9800, f85d0000), \
|
||||
X(lsl, 0000, fa00f000), \
|
||||
X(lsls, 0000, fa10f000), \
|
||||
X(lsr, 0800, fa20f000), \
|
||||
@ -5812,8 +5827,11 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
|
||||
X(str, 6000, f8400000), \
|
||||
X(strb, 7000, f8000000), \
|
||||
X(strh, 8000, f8200000), \
|
||||
X(str_sp,9000, f84d0000), \
|
||||
X(sub, 1e00, eba00000), \
|
||||
X(subs, 1e00, ebb00000), \
|
||||
X(subi, 8000, f1a00000), \
|
||||
X(subis, 8000, f1b00000), \
|
||||
X(sxtb, b240, fa4ff080), \
|
||||
X(sxth, b200, fa0ff080), \
|
||||
X(tst, 4200, ea100f00), \
|
||||
@ -5875,17 +5893,61 @@ do_t_add_sub (void)
|
||||
|
||||
if (unified_syntax)
|
||||
{
|
||||
bfd_boolean flags;
|
||||
bfd_boolean narrow;
|
||||
int opcode;
|
||||
|
||||
flags = (inst.instruction == T_MNEM_adds
|
||||
|| inst.instruction == T_MNEM_subs);
|
||||
if (flags)
|
||||
narrow = (current_it_mask == 0);
|
||||
else
|
||||
narrow = (current_it_mask != 0);
|
||||
if (!inst.operands[2].isreg)
|
||||
{
|
||||
/* ??? Convert large immediates to addw/subw. */
|
||||
/* ??? 16-bit adds with small immediates. */
|
||||
/* For an immediate, we always generate a 32-bit opcode;
|
||||
section relaxation will shrink it later if possible. */
|
||||
inst.instruction = THUMB_OP32 (inst.instruction);
|
||||
inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
|
||||
inst.instruction |= inst.operands[0].reg << 8;
|
||||
inst.instruction |= inst.operands[1].reg << 16;
|
||||
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
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)
|
||||
opcode = add ? T_MNEM_inc_sp : T_MNEM_dec_sp;
|
||||
else if (Rd <= 7 && Rs == REG_SP && add && !flags)
|
||||
opcode = T_MNEM_add_sp;
|
||||
else if (Rd <= 7 && Rs == REG_PC && add && !flags)
|
||||
opcode = T_MNEM_add_pc;
|
||||
else if (Rd <= 7 && Rs <= 7 && narrow)
|
||||
{
|
||||
if (flags)
|
||||
opcode = add ? T_MNEM_addis : T_MNEM_subis;
|
||||
else
|
||||
opcode = add ? T_MNEM_addi : T_MNEM_subi;
|
||||
}
|
||||
if (opcode)
|
||||
{
|
||||
inst.instruction = THUMB_OP16(opcode);
|
||||
inst.instruction |= (Rd << 4) | Rs;
|
||||
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
|
||||
if (inst.size_req != 2)
|
||||
inst.relax = opcode;
|
||||
}
|
||||
else
|
||||
constraint (inst.size_req == 2, BAD_HIREG);
|
||||
}
|
||||
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;
|
||||
inst.instruction |= inst.operands[0].reg << 8;
|
||||
inst.instruction |= inst.operands[1].reg << 16;
|
||||
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5893,13 +5955,6 @@ do_t_add_sub (void)
|
||||
/* See if we can do this with a 16-bit instruction. */
|
||||
if (!inst.operands[2].shifted && inst.size_req != 4)
|
||||
{
|
||||
bfd_boolean narrow;
|
||||
|
||||
if (inst.instruction == T_MNEM_adds
|
||||
|| inst.instruction == T_MNEM_subs)
|
||||
narrow = (current_it_mask == 0);
|
||||
else
|
||||
narrow = (current_it_mask != 0);
|
||||
if (Rd > 7 || Rs > 7 || Rn > 7)
|
||||
narrow = FALSE;
|
||||
|
||||
@ -5992,10 +6047,16 @@ do_t_add_sub (void)
|
||||
static void
|
||||
do_t_adr (void)
|
||||
{
|
||||
if (unified_syntax && inst.size_req != 2)
|
||||
if (unified_syntax && inst.size_req == 0 && inst.operands[0].reg <= 7)
|
||||
{
|
||||
/* Always generate a 32-bit opcode;
|
||||
section relaxation will shrink it later if possible. */
|
||||
/* Defer to section relaxation. */
|
||||
inst.relax = inst.instruction;
|
||||
inst.instruction = THUMB_OP16 (inst.instruction);
|
||||
inst.instruction |= inst.operands[0].reg << 4;
|
||||
}
|
||||
else if (unified_syntax && inst.size_req != 2)
|
||||
{
|
||||
/* Generate a 32-bit opcode. */
|
||||
inst.instruction = THUMB_OP32 (inst.instruction);
|
||||
inst.instruction |= inst.operands[0].reg << 8;
|
||||
inst.reloc.type = BFD_RELOC_ARM_T32_ADD_PC12;
|
||||
@ -6003,6 +6064,7 @@ do_t_adr (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate a 16-bit opcode. */
|
||||
inst.instruction = THUMB_OP16 (inst.instruction);
|
||||
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
|
||||
inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
|
||||
@ -6266,29 +6328,37 @@ do_t_blx (void)
|
||||
static void
|
||||
do_t_branch (void)
|
||||
{
|
||||
if (unified_syntax && inst.size_req != 2)
|
||||
int opcode;
|
||||
if (inst.cond != COND_ALWAYS)
|
||||
opcode = T_MNEM_bcond;
|
||||
else
|
||||
opcode = inst.instruction;
|
||||
|
||||
if (unified_syntax && inst.size_req == 4)
|
||||
{
|
||||
inst.instruction = THUMB_OP32(opcode);
|
||||
if (inst.cond == COND_ALWAYS)
|
||||
{
|
||||
inst.instruction = 0xf000b000;
|
||||
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH25;
|
||||
}
|
||||
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH25;
|
||||
else
|
||||
{
|
||||
assert (inst.cond != 0xF);
|
||||
inst.instruction = (inst.cond << 22) | 0xf0008000;
|
||||
inst.instruction |= inst.cond << 22;
|
||||
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH20;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.instruction = THUMB_OP16(opcode);
|
||||
if (inst.cond == COND_ALWAYS)
|
||||
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
|
||||
else
|
||||
{
|
||||
inst.instruction = 0xd000 | (inst.cond << 8);
|
||||
inst.instruction |= inst.cond << 8;
|
||||
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
|
||||
}
|
||||
/* Allow section relaxation. */
|
||||
if (unified_syntax && inst.size_req != 2)
|
||||
inst.relax = opcode;
|
||||
}
|
||||
|
||||
inst.reloc.pc_rel = 1;
|
||||
@ -6562,21 +6632,67 @@ do_t_ldrexd (void)
|
||||
static void
|
||||
do_t_ldst (void)
|
||||
{
|
||||
unsigned long opcode;
|
||||
int Rn;
|
||||
|
||||
opcode = inst.instruction;
|
||||
if (unified_syntax)
|
||||
{
|
||||
/* Generation of 16-bit instructions for anything other than
|
||||
Rd, [Rn, Ri] is deferred to section relaxation time. */
|
||||
if (inst.operands[1].isreg && inst.operands[1].immisreg
|
||||
if (inst.operands[1].isreg
|
||||
&& !inst.operands[1].writeback
|
||||
&& !inst.operands[1].shifted && !inst.operands[1].postind
|
||||
&& !inst.operands[1].negative && inst.operands[0].reg <= 7
|
||||
&& inst.operands[1].reg <= 7 && inst.operands[1].imm <= 7
|
||||
&& inst.instruction <= 0xffff)
|
||||
&& opcode <= 0xffff
|
||||
&& inst.size_req != 4)
|
||||
{
|
||||
inst.instruction = THUMB_OP16 (inst.instruction);
|
||||
goto op16;
|
||||
/* Insn may have a 16-bit form. */
|
||||
Rn = inst.operands[1].reg;
|
||||
if (inst.operands[1].immisreg)
|
||||
{
|
||||
inst.instruction = THUMB_OP16 (opcode);
|
||||
/* [Rn, Ri] */
|
||||
if (Rn <= 7 && inst.operands[1].imm <= 7)
|
||||
goto op16;
|
||||
}
|
||||
else if ((Rn <= 7 && opcode != T_MNEM_ldrsh
|
||||
&& opcode != T_MNEM_ldrsb)
|
||||
|| ((Rn == REG_PC || Rn == REG_SP) && opcode == T_MNEM_ldr)
|
||||
|| (Rn == REG_SP && opcode == T_MNEM_str))
|
||||
{
|
||||
/* [Rn, #const] */
|
||||
if (Rn > 7)
|
||||
{
|
||||
if (Rn == REG_PC)
|
||||
{
|
||||
if (inst.reloc.pc_rel)
|
||||
opcode = T_MNEM_ldr_pc2;
|
||||
else
|
||||
opcode = T_MNEM_ldr_pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opcode == T_MNEM_ldr)
|
||||
opcode = T_MNEM_ldr_sp;
|
||||
else
|
||||
opcode = T_MNEM_str_sp;
|
||||
}
|
||||
inst.instruction = inst.operands[0].reg << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.instruction = inst.operands[0].reg;
|
||||
inst.instruction |= inst.operands[1].reg << 3;
|
||||
}
|
||||
inst.instruction |= THUMB_OP16 (opcode);
|
||||
if (inst.size_req == 2)
|
||||
inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
|
||||
else
|
||||
inst.relax = opcode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inst.instruction = THUMB_OP32 (inst.instruction);
|
||||
/* Definitely a 32-bit variant. */
|
||||
inst.instruction = THUMB_OP32 (opcode);
|
||||
inst.instruction |= inst.operands[0].reg << 12;
|
||||
encode_thumb32_addr_mode (1, /*is_t=*/FALSE, /*is_d=*/FALSE);
|
||||
return;
|
||||
@ -6708,26 +6824,41 @@ do_t_mov_cmp (void)
|
||||
{
|
||||
int r0off = (inst.instruction == T_MNEM_mov
|
||||
|| inst.instruction == T_MNEM_movs) ? 8 : 16;
|
||||
unsigned long opcode;
|
||||
bfd_boolean narrow;
|
||||
bfd_boolean low_regs;
|
||||
|
||||
low_regs = (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7);
|
||||
opcode = inst.instruction;
|
||||
if (current_it_mask)
|
||||
narrow = inst.instruction != T_MNEM_movs;
|
||||
narrow = opcode != T_MNEM_movs;
|
||||
else
|
||||
narrow = inst.instruction != T_MNEM_movs || low_regs;
|
||||
narrow = opcode != T_MNEM_movs || low_regs;
|
||||
if (inst.size_req == 4
|
||||
|| inst.operands[1].shifted)
|
||||
narrow = FALSE;
|
||||
|
||||
if (!inst.operands[1].isreg)
|
||||
{
|
||||
/* For an immediate, we always generate a 32-bit opcode;
|
||||
section relaxation will shrink it later if possible. */
|
||||
inst.instruction = THUMB_OP32 (inst.instruction);
|
||||
inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
|
||||
inst.instruction |= inst.operands[0].reg << r0off;
|
||||
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
/* Immediate operand. */
|
||||
if (current_it_mask == 0 && opcode == T_MNEM_mov)
|
||||
narrow = 0;
|
||||
if (low_regs && narrow)
|
||||
{
|
||||
inst.instruction = THUMB_OP16 (opcode);
|
||||
inst.instruction |= inst.operands[0].reg << 8;
|
||||
if (inst.size_req == 2)
|
||||
inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
|
||||
else
|
||||
inst.relax = opcode;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.instruction = THUMB_OP32 (inst.instruction);
|
||||
inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
|
||||
inst.instruction |= inst.operands[0].reg << r0off;
|
||||
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
}
|
||||
}
|
||||
else if (!narrow)
|
||||
{
|
||||
@ -7501,6 +7632,46 @@ fix_new_arm (fragS * frag,
|
||||
new_fix->tc_fix_data = thumb_mode;
|
||||
}
|
||||
|
||||
/* Create a frg for an instruction requiring relaxation. */
|
||||
static void
|
||||
output_relax_insn (void)
|
||||
{
|
||||
char * to;
|
||||
symbolS *sym;
|
||||
int offset;
|
||||
|
||||
switch (inst.reloc.exp.X_op)
|
||||
{
|
||||
case O_symbol:
|
||||
sym = inst.reloc.exp.X_add_symbol;
|
||||
offset = inst.reloc.exp.X_add_number;
|
||||
break;
|
||||
case O_constant:
|
||||
sym = NULL;
|
||||
offset = inst.reloc.exp.X_add_number;
|
||||
break;
|
||||
default:
|
||||
sym = make_expr_symbol (&inst.reloc.exp);
|
||||
offset = 0;
|
||||
break;
|
||||
}
|
||||
to = frag_var (rs_machine_dependent, INSN_SIZE, THUMB_SIZE,
|
||||
inst.relax, sym, offset, NULL/*offset, opcode*/);
|
||||
md_number_to_chars (to, inst.instruction, THUMB_SIZE);
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
dwarf2_emit_insn (INSN_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Write a 32-bit thumb instruction to buf. */
|
||||
static void
|
||||
put_thumb32_insn (char * buf, unsigned long insn)
|
||||
{
|
||||
md_number_to_chars (buf, insn >> 16, THUMB_SIZE);
|
||||
md_number_to_chars (buf + THUMB_SIZE, insn, THUMB_SIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
output_inst (const char * str)
|
||||
{
|
||||
@ -7511,6 +7682,10 @@ output_inst (const char * str)
|
||||
as_bad ("%s -- `%s'", inst.error, str);
|
||||
return;
|
||||
}
|
||||
if (inst.relax) {
|
||||
output_relax_insn();
|
||||
return;
|
||||
}
|
||||
if (inst.size == 0)
|
||||
return;
|
||||
|
||||
@ -7519,8 +7694,7 @@ output_inst (const char * str)
|
||||
if (thumb_mode && (inst.size > THUMB_SIZE))
|
||||
{
|
||||
assert (inst.size == (2 * THUMB_SIZE));
|
||||
md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
|
||||
md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
|
||||
put_thumb32_insn (to, inst.instruction);
|
||||
}
|
||||
else if (inst.size > INSN_SIZE)
|
||||
{
|
||||
@ -7819,7 +7993,7 @@ md_assemble (char *str)
|
||||
if (current_it_mask == 0x10)
|
||||
current_it_mask = 0;
|
||||
|
||||
if (!inst.error)
|
||||
if (!(inst.error || inst.relax))
|
||||
{
|
||||
assert (inst.instruction < 0xe800 || inst.instruction > 0xffff);
|
||||
inst.size = (inst.instruction > 0xffff ? 4 : 2);
|
||||
@ -8364,7 +8538,7 @@ static const struct asm_opcode insns[] =
|
||||
tC3(ldmfd, 8900000, ldmia, 2, (RRw, REGLST), ldmstm, t_ldmstm),
|
||||
|
||||
TCE(swi, f000000, df00, 1, (EXPi), swi, t_swi),
|
||||
TCE(b, a000000, e000, 1, (EXPr), branch, t_branch),
|
||||
tCE(b, a000000, b, 1, (EXPr), branch, t_branch),
|
||||
TCE(bl, b000000, f000f800, 1, (EXPr), branch, t_branch23),
|
||||
|
||||
/* Pseudo ops. */
|
||||
@ -9600,12 +9774,344 @@ md_chars_to_number (char * buf, int n)
|
||||
|
||||
/* MD interface: Sections. */
|
||||
|
||||
/* Estimate the size of a frag before relaxing. Assume everything fits in
|
||||
2 bytes. */
|
||||
|
||||
int
|
||||
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
|
||||
md_estimate_size_before_relax (fragS * fragp,
|
||||
segT segtype ATTRIBUTE_UNUSED)
|
||||
{
|
||||
as_fatal (_("md_estimate_size_before_relax\n"));
|
||||
return 1;
|
||||
fragp->fr_var = 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Convert a machine dependent frag. */
|
||||
|
||||
void
|
||||
md_convert_frag (bfd *abfd, segT asec ATTRIBUTE_UNUSED, fragS *fragp)
|
||||
{
|
||||
unsigned long insn;
|
||||
unsigned long old_op;
|
||||
char *buf;
|
||||
expressionS exp;
|
||||
fixS *fixp;
|
||||
int reloc_type;
|
||||
int pc_rel;
|
||||
int opcode;
|
||||
|
||||
buf = fragp->fr_literal + fragp->fr_fix;
|
||||
|
||||
old_op = bfd_get_16(abfd, buf);
|
||||
if (fragp->fr_symbol) {
|
||||
exp.X_op = O_symbol;
|
||||
exp.X_add_symbol = fragp->fr_symbol;
|
||||
} else {
|
||||
exp.X_op = O_constant;
|
||||
}
|
||||
exp.X_add_number = fragp->fr_offset;
|
||||
opcode = fragp->fr_subtype;
|
||||
switch (opcode)
|
||||
{
|
||||
case T_MNEM_ldr_pc:
|
||||
case T_MNEM_ldr_pc2:
|
||||
case T_MNEM_ldr_sp:
|
||||
case T_MNEM_str_sp:
|
||||
case T_MNEM_ldr:
|
||||
case T_MNEM_ldrb:
|
||||
case T_MNEM_ldrh:
|
||||
case T_MNEM_str:
|
||||
case T_MNEM_strb:
|
||||
case T_MNEM_strh:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
insn = THUMB_OP32(opcode);
|
||||
if ((old_op >> 12) == 4 || (old_op >> 12) == 9)
|
||||
{
|
||||
insn |= (old_op & 0x700) << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
insn |= (old_op & 7) << 12;
|
||||
insn |= (old_op & 0x38) << 13;
|
||||
}
|
||||
insn |= 0x00000c00;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_ARM_T32_OFFSET_IMM;
|
||||
}
|
||||
else
|
||||
{
|
||||
reloc_type = BFD_RELOC_ARM_THUMB_OFFSET;
|
||||
}
|
||||
pc_rel = (opcode == T_MNEM_ldr_pc2);
|
||||
break;
|
||||
case T_MNEM_adr:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
insn = THUMB_OP32 (opcode);
|
||||
insn |= (old_op & 0xf0) << 4;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_ARM_T32_ADD_PC12;
|
||||
}
|
||||
else
|
||||
{
|
||||
reloc_type = BFD_RELOC_ARM_THUMB_ADD;
|
||||
exp.X_add_number -= 4;
|
||||
}
|
||||
pc_rel = 1;
|
||||
break;
|
||||
case T_MNEM_mov:
|
||||
case T_MNEM_movs:
|
||||
case T_MNEM_cmp:
|
||||
case T_MNEM_cmn:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
int r0off = (opcode == T_MNEM_mov
|
||||
|| opcode == T_MNEM_movs) ? 0 : 8;
|
||||
insn = THUMB_OP32 (opcode);
|
||||
insn = (insn & 0xe1ffffff) | 0x10000000;
|
||||
insn |= (old_op & 0x700) << r0off;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
reloc_type = BFD_RELOC_ARM_THUMB_IMM;
|
||||
}
|
||||
pc_rel = 0;
|
||||
break;
|
||||
case T_MNEM_b:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
insn = THUMB_OP32(opcode);
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH25;
|
||||
}
|
||||
else
|
||||
reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH12;
|
||||
pc_rel = 1;
|
||||
break;
|
||||
case T_MNEM_bcond:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
insn = THUMB_OP32(opcode);
|
||||
insn |= (old_op & 0xf00) << 14;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH20;
|
||||
}
|
||||
else
|
||||
reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH9;
|
||||
pc_rel = 1;
|
||||
break;
|
||||
case T_MNEM_add_sp:
|
||||
case T_MNEM_add_pc:
|
||||
case T_MNEM_inc_sp:
|
||||
case T_MNEM_dec_sp:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
/* ??? Choose between add and addw. */
|
||||
insn = THUMB_OP32 (opcode);
|
||||
insn |= (old_op & 0xf0) << 4;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
}
|
||||
else
|
||||
reloc_type = BFD_RELOC_ARM_THUMB_ADD;
|
||||
pc_rel = 0;
|
||||
break;
|
||||
|
||||
case T_MNEM_addi:
|
||||
case T_MNEM_addis:
|
||||
case T_MNEM_subi:
|
||||
case T_MNEM_subis:
|
||||
if (fragp->fr_var == 4)
|
||||
{
|
||||
insn = THUMB_OP32 (opcode);
|
||||
insn |= (old_op & 0xf0) << 4;
|
||||
insn |= (old_op & 0xf) << 16;
|
||||
put_thumb32_insn (buf, insn);
|
||||
reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
|
||||
}
|
||||
else
|
||||
reloc_type = BFD_RELOC_ARM_THUMB_ADD;
|
||||
pc_rel = 0;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
fixp = fix_new_exp (fragp, fragp->fr_fix, fragp->fr_var, &exp, pc_rel,
|
||||
reloc_type);
|
||||
fixp->fx_file = fragp->fr_file;
|
||||
fixp->fx_line = fragp->fr_line;
|
||||
fragp->fr_fix += fragp->fr_var;
|
||||
}
|
||||
|
||||
/* Return the size of a relaxable immediate operand instruction.
|
||||
SHIFT and SIZE specify the form of the allowable immediate. */
|
||||
static int
|
||||
relax_immediate (fragS *fragp, int size, int shift)
|
||||
{
|
||||
offsetT offset;
|
||||
offsetT mask;
|
||||
offsetT low;
|
||||
|
||||
/* ??? Should be able to do better than this. */
|
||||
if (fragp->fr_symbol)
|
||||
return 4;
|
||||
|
||||
low = (1 << shift) - 1;
|
||||
mask = (1 << (shift + size)) - (1 << shift);
|
||||
offset = fragp->fr_offset;
|
||||
/* Force misaligned offsets to 32-bit variant. */
|
||||
if (offset & low)
|
||||
return -4;
|
||||
if (offset & ~mask)
|
||||
return 4;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Return the size of a relaxable adr pseudo-instruction or PC-relative
|
||||
load. */
|
||||
static int
|
||||
relax_adr (fragS *fragp, asection *sec)
|
||||
{
|
||||
addressT addr;
|
||||
offsetT val;
|
||||
|
||||
/* Assume worst case for symbols not known to be in the same section. */
|
||||
if (!S_IS_DEFINED(fragp->fr_symbol)
|
||||
|| sec != S_GET_SEGMENT (fragp->fr_symbol))
|
||||
return 4;
|
||||
|
||||
val = S_GET_VALUE(fragp->fr_symbol) + fragp->fr_offset;
|
||||
addr = fragp->fr_address + fragp->fr_fix;
|
||||
addr = (addr + 4) & ~3;
|
||||
/* Fix the insn as the 4-byte version if the target address is not
|
||||
sufficiently aligned. This is prevents an infinite loop when two
|
||||
instructions have contradictory range/alignment requirements. */
|
||||
if (val & 3)
|
||||
return -4;
|
||||
val -= addr;
|
||||
if (val < 0 || val > 1020)
|
||||
return 4;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Return the size of a relaxable add/sub immediate instruction. */
|
||||
static int
|
||||
relax_addsub (fragS *fragp, asection *sec)
|
||||
{
|
||||
char *buf;
|
||||
int op;
|
||||
|
||||
buf = fragp->fr_literal + fragp->fr_fix;
|
||||
op = bfd_get_16(sec->owner, buf);
|
||||
if ((op & 0xf) == ((op >> 4) & 0xf))
|
||||
return relax_immediate (fragp, 8, 0);
|
||||
else
|
||||
return relax_immediate (fragp, 3, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Return the size of a relaxable branch instruction. BITS is the
|
||||
size of the offset field in the narrow instruction. */
|
||||
|
||||
static int
|
||||
relax_branch (fragS *fragp, asection *sec, int bits)
|
||||
{
|
||||
addressT addr;
|
||||
offsetT val;
|
||||
offsetT limit;
|
||||
|
||||
/* Assume worst case for symbols not known to be in the same section. */
|
||||
if (!S_IS_DEFINED(fragp->fr_symbol)
|
||||
|| sec != S_GET_SEGMENT (fragp->fr_symbol))
|
||||
return 4;
|
||||
|
||||
val = S_GET_VALUE(fragp->fr_symbol) + fragp->fr_offset;
|
||||
addr = fragp->fr_address + fragp->fr_fix + 4;
|
||||
val -= addr;
|
||||
|
||||
/* Offset is a signed value *2 */
|
||||
limit = 1 << bits;
|
||||
if (val >= limit || val < -limit)
|
||||
return 4;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/* Relax a machine dependent frag. This returns the amount by which
|
||||
the current size of the frag should change. */
|
||||
|
||||
int
|
||||
arm_relax_frag (asection *sec, fragS *fragp, long stretch ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int oldsize;
|
||||
int newsize;
|
||||
|
||||
oldsize = fragp->fr_var;
|
||||
switch (fragp->fr_subtype)
|
||||
{
|
||||
case T_MNEM_ldr_pc2:
|
||||
newsize = relax_adr(fragp, sec);
|
||||
break;
|
||||
case T_MNEM_ldr_pc:
|
||||
case T_MNEM_ldr_sp:
|
||||
case T_MNEM_str_sp:
|
||||
newsize = relax_immediate(fragp, 8, 2);
|
||||
break;
|
||||
case T_MNEM_ldr:
|
||||
case T_MNEM_str:
|
||||
newsize = relax_immediate(fragp, 5, 2);
|
||||
break;
|
||||
case T_MNEM_ldrh:
|
||||
case T_MNEM_strh:
|
||||
newsize = relax_immediate(fragp, 5, 1);
|
||||
break;
|
||||
case T_MNEM_ldrb:
|
||||
case T_MNEM_strb:
|
||||
newsize = relax_immediate(fragp, 5, 0);
|
||||
break;
|
||||
case T_MNEM_adr:
|
||||
newsize = relax_adr(fragp, sec);
|
||||
break;
|
||||
case T_MNEM_mov:
|
||||
case T_MNEM_movs:
|
||||
case T_MNEM_cmp:
|
||||
case T_MNEM_cmn:
|
||||
newsize = relax_immediate(fragp, 8, 0);
|
||||
break;
|
||||
case T_MNEM_b:
|
||||
newsize = relax_branch(fragp, sec, 11);
|
||||
break;
|
||||
case T_MNEM_bcond:
|
||||
newsize = relax_branch(fragp, sec, 8);
|
||||
break;
|
||||
case T_MNEM_add_sp:
|
||||
case T_MNEM_add_pc:
|
||||
newsize = relax_immediate (fragp, 8, 2);
|
||||
break;
|
||||
case T_MNEM_inc_sp:
|
||||
case T_MNEM_dec_sp:
|
||||
newsize = relax_immediate (fragp, 7, 2);
|
||||
break;
|
||||
case T_MNEM_addi:
|
||||
case T_MNEM_addis:
|
||||
case T_MNEM_subi:
|
||||
case T_MNEM_subis:
|
||||
newsize = relax_addsub (fragp, sec);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (newsize < 0)
|
||||
{
|
||||
fragp->fr_var = -newsize;
|
||||
md_convert_frag (sec->owner, sec, fragp);
|
||||
frag_wane(fragp);
|
||||
return -(newsize + oldsize);
|
||||
}
|
||||
fragp->fr_var = newsize;
|
||||
return newsize - oldsize;
|
||||
}
|
||||
|
||||
/* Round up a section size to the appropriate boundary. */
|
||||
@ -11476,7 +11982,10 @@ arm_force_relocation (struct fix * fixp)
|
||||
/* Resolve these relocations even if the symbol is extern or weak. */
|
||||
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_ADRL_IMMEDIATE
|
||||
|| 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)
|
||||
return 0;
|
||||
|
||||
return generic_force_reloc (fixp);
|
||||
|
@ -79,7 +79,9 @@ struct fix;
|
||||
|
||||
#define TC_FORCE_RELOCATION(FIX) arm_force_relocation (FIX)
|
||||
|
||||
#define md_convert_frag(b, s, f) { as_fatal (_("arm convert_frag\n")); }
|
||||
#define md_relax_frag(segment, fragp, stretch) \
|
||||
arm_relax_frag(segment, fragp, stretch)
|
||||
extern int arm_relax_frag (asection *, struct frag *, long);
|
||||
|
||||
#define md_cleanup() arm_cleanup ()
|
||||
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-09-06 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* gas/arm/thumb2_relax.d: New test.
|
||||
* gas/arm/thumb2_relax.s: New test.
|
||||
* gas/arm/thumb32.d: Adjust expected results to include relaxation.
|
||||
* gas/arm/thumb32.s: Tweak for better coverage of relaxable
|
||||
instructions. Remove load/store tests.
|
||||
|
||||
2005-09-02 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* gas/arm/arm3-bad.s: New test.
|
||||
|
155
gas/testsuite/gas/arm/thumb2_relax.d
Normal file
155
gas/testsuite/gas/arm/thumb2_relax.d
Normal file
@ -0,0 +1,155 @@
|
||||
# as: -march=armv6kt2
|
||||
# objdump: -dr --prefix-addresses --show-raw-insn
|
||||
|
||||
.*: +file format .*arm.*
|
||||
|
||||
Disassembly of section .text:
|
||||
0+000 <[^>]+> 7829 ldrb r1, \[r5, #0\]
|
||||
0+002 <[^>]+> f895 1023 ldrb.w r1, \[r5, #35\]
|
||||
0+006 <[^>]+> 7fe9 ldrb r1, \[r5, #31\]
|
||||
0+008 <[^>]+> f895 101f ldrb.w r1, \[r5, #31\]
|
||||
0+00c <[^>]+> f815 1c1f ldrb.w r1, \[r5, #-31\]
|
||||
0+010 <[^>]+> f815 1b1f ldrb.w r1, \[r5\], #31
|
||||
0+014 <[^>]+> f815 1b1f ldrb.w r1, \[r5\], #31
|
||||
0+018 <[^>]+> f815 1f1f ldrb.w r1, \[r5, #31\]!
|
||||
0+01c <[^>]+> f815 1d1f ldrb.w r1, \[r5, #-31\]!
|
||||
0+020 <[^>]+> 5d29 ldrb r1, \[r5, r4\]
|
||||
0+022 <[^>]+> f819 100c ldrb.w r1, \[r9, ip\]
|
||||
0+026 <[^>]+> f89f 1014 ldrb.w r1, \[pc, #20\] ; 0+03c <[^>]+>
|
||||
0+02a <[^>]+> f89f 1010 ldrb.w r1, \[pc, #16\] ; 0+03c <[^>]+>
|
||||
0+02e <[^>]+> f89f 800c ldrb.w r8, \[pc, #12\] ; 0+03c <[^>]+>
|
||||
0+032 <[^>]+> f89f 100a ldrb.w r1, \[pc, #10\] ; 0+03e <[^>]+>
|
||||
0+036 <[^>]+> f81f 1038 ldrb.w r1, \[pc, #-56\] ; 0+000 <[^>]+>
|
||||
0+03a <[^>]+> 0000 lsls r0, r0, #0
|
||||
0+03c <[^>]+> bf00 nop
|
||||
0+03e <[^>]+> f995 1000 ldrsb.w r1, \[r5\]
|
||||
0+042 <[^>]+> f995 1023 ldrsb.w r1, \[r5, #35\]
|
||||
0+046 <[^>]+> f995 101f ldrsb.w r1, \[r5, #31\]
|
||||
0+04a <[^>]+> f995 101f ldrsb.w r1, \[r5, #31\]
|
||||
0+04e <[^>]+> f915 1c1f ldrsb.w r1, \[r5, #-31\]
|
||||
0+052 <[^>]+> f915 1b1f ldrsb.w r1, \[r5\], #31
|
||||
0+056 <[^>]+> f915 1b1f ldrsb.w r1, \[r5\], #31
|
||||
0+05a <[^>]+> f915 1f1f ldrsb.w r1, \[r5, #31\]!
|
||||
0+05e <[^>]+> f915 1d1f ldrsb.w r1, \[r5, #-31\]!
|
||||
0+062 <[^>]+> 5729 ldrsb r1, \[r5, r4\]
|
||||
0+064 <[^>]+> f919 100c ldrsb.w r1, \[r9, ip\]
|
||||
0+068 <[^>]+> f99f 1010 ldrsb.w r1, \[pc, #16\] ; 0+07c <[^>]+>
|
||||
0+06c <[^>]+> f99f 100c ldrsb.w r1, \[pc, #12\] ; 0+07c <[^>]+>
|
||||
0+070 <[^>]+> f99f 8008 ldrsb.w r8, \[pc, #8\] ; 0+07c <[^>]+>
|
||||
0+074 <[^>]+> f99f 1006 ldrsb.w r1, \[pc, #6\] ; 0+07e <[^>]+>
|
||||
0+078 <[^>]+> f91f 103e ldrsb.w r1, \[pc, #-62\] ; 0+03e <[^>]+>
|
||||
0+07c <[^>]+> bf00 nop
|
||||
0+07e <[^>]+> 8829 ldrh r1, \[r5, #0\]
|
||||
0+080 <[^>]+> f8b5 1042 ldrh.w r1, \[r5, #66\]
|
||||
0+084 <[^>]+> 8fe9 ldrh r1, \[r5, #62\]
|
||||
0+086 <[^>]+> f8b5 103e ldrh.w r1, \[r5, #62\]
|
||||
0+08a <[^>]+> f835 1c3e ldrh.w r1, \[r5, #-62\]
|
||||
0+08e <[^>]+> f835 1b3e ldrh.w r1, \[r5\], #62
|
||||
0+092 <[^>]+> f835 1b3e ldrh.w r1, \[r5\], #62
|
||||
0+096 <[^>]+> f835 1f3e ldrh.w r1, \[r5, #62\]!
|
||||
0+09a <[^>]+> f835 1d3e ldrh.w r1, \[r5, #-62\]!
|
||||
0+09e <[^>]+> 5b29 ldrh r1, \[r5, r4\]
|
||||
0+0a0 <[^>]+> f839 100c ldrh.w r1, \[r9, ip\]
|
||||
0+0a4 <[^>]+> f8bf 1010 ldrh.w r1, \[pc, #16\] ; 0+0b8 <[^>]+>
|
||||
0+0a8 <[^>]+> f8bf 100c ldrh.w r1, \[pc, #12\] ; 0+0b8 <[^>]+>
|
||||
0+0ac <[^>]+> f8bf 8008 ldrh.w r8, \[pc, #8\] ; 0+0b8 <[^>]+>
|
||||
0+0b0 <[^>]+> f8bf 1006 ldrh.w r1, \[pc, #6\] ; 0+0ba <[^>]+>
|
||||
0+0b4 <[^>]+> f83f 103a ldrh.w r1, \[pc, #-58\] ; 0+07e <[^>]+>
|
||||
0+0b8 <[^>]+> bf00 nop
|
||||
0+0ba <[^>]+> f9b5 1000 ldrsh.w r1, \[r5\]
|
||||
0+0be <[^>]+> f9b5 1042 ldrsh.w r1, \[r5, #66\]
|
||||
0+0c2 <[^>]+> f9b5 103e ldrsh.w r1, \[r5, #62\]
|
||||
0+0c6 <[^>]+> f9b5 103e ldrsh.w r1, \[r5, #62\]
|
||||
0+0ca <[^>]+> f935 1c3e ldrsh.w r1, \[r5, #-62\]
|
||||
0+0ce <[^>]+> f935 1b3e ldrsh.w r1, \[r5\], #62
|
||||
0+0d2 <[^>]+> f935 1b3e ldrsh.w r1, \[r5\], #62
|
||||
0+0d6 <[^>]+> f935 1f3e ldrsh.w r1, \[r5, #62\]!
|
||||
0+0da <[^>]+> f935 1d3e ldrsh.w r1, \[r5, #-62\]!
|
||||
0+0de <[^>]+> 5f29 ldrsh r1, \[r5, r4\]
|
||||
0+0e0 <[^>]+> f939 100c ldrsh.w r1, \[r9, ip\]
|
||||
0+0e4 <[^>]+> f9bf 1010 ldrsh.w r1, \[pc, #16\] ; 0+0f8 <[^>]+>
|
||||
0+0e8 <[^>]+> f9bf 100c ldrsh.w r1, \[pc, #12\] ; 0+0f8 <[^>]+>
|
||||
0+0ec <[^>]+> f9bf 8008 ldrsh.w r8, \[pc, #8\] ; 0+0f8 <[^>]+>
|
||||
0+0f0 <[^>]+> f9bf 1006 ldrsh.w r1, \[pc, #6\] ; 0+0fa <[^>]+>
|
||||
0+0f4 <[^>]+> f93f 103e ldrsh.w r1, \[pc, #-62\] ; 0+0ba <[^>]+>
|
||||
0+0f8 <[^>]+> bf00 nop
|
||||
0+0fa <[^>]+> 6829 ldr r1, \[r5, #0\]
|
||||
0+0fc <[^>]+> f8d5 1080 ldr.w r1, \[r5, #128\]
|
||||
0+100 <[^>]+> 6fe9 ldr r1, \[r5, #124\]
|
||||
0+102 <[^>]+> f8d5 107c ldr.w r1, \[r5, #124\]
|
||||
0+106 <[^>]+> f855 1c7c ldr.w r1, \[r5, #-124\]
|
||||
0+10a <[^>]+> f855 1b7c ldr.w r1, \[r5\], #124
|
||||
0+10e <[^>]+> f855 1b7c ldr.w r1, \[r5\], #124
|
||||
0+112 <[^>]+> f855 1f7c ldr.w r1, \[r5, #124\]!
|
||||
0+116 <[^>]+> f855 1d7c ldr.w r1, \[r5, #-124\]!
|
||||
0+11a <[^>]+> 5929 ldr r1, \[r5, r4\]
|
||||
0+11c <[^>]+> f859 100c ldr.w r1, \[r9, ip\]
|
||||
0+120 <[^>]+> 4904 ldr r1, \[pc, #16\] \(0+134 <[^>]+>\)
|
||||
0+122 <[^>]+> f8df 1010 ldr.w r1, \[pc, #16\] ; 0+134 <[^>]+>
|
||||
0+126 <[^>]+> f8df 800c ldr.w r8, \[pc, #12\] ; 0+134 <[^>]+>
|
||||
0+12a <[^>]+> f8df 100a ldr.w r1, \[pc, #10\] ; 0+136 <[^>]+>
|
||||
0+12e <[^>]+> f85f 1036 ldr.w r1, \[pc, #-54\] ; 0+0fa <[^>]+>
|
||||
0+132 <[^>]+> 0000 lsls r0, r0, #0
|
||||
0+134 <[^>]+> bf00 nop
|
||||
0+136 <[^>]+> 7029 strb r1, \[r5, #0\]
|
||||
0+138 <[^>]+> f885 1023 strb.w r1, \[r5, #35\]
|
||||
0+13c <[^>]+> 77e9 strb r1, \[r5, #31\]
|
||||
0+13e <[^>]+> f885 101f strb.w r1, \[r5, #31\]
|
||||
0+142 <[^>]+> f805 1c1f strb.w r1, \[r5, #-31\]
|
||||
0+146 <[^>]+> f805 1b1f strb.w r1, \[r5\], #31
|
||||
0+14a <[^>]+> f805 1b1f strb.w r1, \[r5\], #31
|
||||
0+14e <[^>]+> f805 1f1f strb.w r1, \[r5, #31\]!
|
||||
0+152 <[^>]+> f805 1d1f strb.w r1, \[r5, #-31\]!
|
||||
0+156 <[^>]+> 5529 strb r1, \[r5, r4\]
|
||||
0+158 <[^>]+> f809 100c strb.w r1, \[r9, ip\]
|
||||
0+15c <[^>]+> f88f 1010 strb.w r1, \[pc, #16\] ; 0+170 <[^>]+>
|
||||
0+160 <[^>]+> f88f 100c strb.w r1, \[pc, #12\] ; 0+170 <[^>]+>
|
||||
0+164 <[^>]+> f88f 8008 strb.w r8, \[pc, #8\] ; 0+170 <[^>]+>
|
||||
0+168 <[^>]+> f88f 1006 strb.w r1, \[pc, #6\] ; 0+172 <[^>]+>
|
||||
0+16c <[^>]+> f80f 103a strb.w r1, \[pc, #-58\] ; 0+136 <[^>]+>
|
||||
0+170 <[^>]+> bf00 nop
|
||||
0+172 <[^>]+> 8029 strh r1, \[r5, #0\]
|
||||
0+174 <[^>]+> f8a5 1042 strh.w r1, \[r5, #66\]
|
||||
0+178 <[^>]+> 87e9 strh r1, \[r5, #62\]
|
||||
0+17a <[^>]+> f8a5 103e strh.w r1, \[r5, #62\]
|
||||
0+17e <[^>]+> f825 1c3e strh.w r1, \[r5, #-62\]
|
||||
0+182 <[^>]+> f825 1b3e strh.w r1, \[r5\], #62
|
||||
0+186 <[^>]+> f825 1b3e strh.w r1, \[r5\], #62
|
||||
0+18a <[^>]+> f825 1f3e strh.w r1, \[r5, #62\]!
|
||||
0+18e <[^>]+> f825 1d3e strh.w r1, \[r5, #-62\]!
|
||||
0+192 <[^>]+> 5329 strh r1, \[r5, r4\]
|
||||
0+194 <[^>]+> f829 100c strh.w r1, \[r9, ip\]
|
||||
0+198 <[^>]+> f8af 1010 strh.w r1, \[pc, #16\] ; 0+1ac <[^>]+>
|
||||
0+19c <[^>]+> f8af 100c strh.w r1, \[pc, #12\] ; 0+1ac <[^>]+>
|
||||
0+1a0 <[^>]+> f8af 8008 strh.w r8, \[pc, #8\] ; 0+1ac <[^>]+>
|
||||
0+1a4 <[^>]+> f8af 1006 strh.w r1, \[pc, #6\] ; 0+1ae <[^>]+>
|
||||
0+1a8 <[^>]+> f82f 103a strh.w r1, \[pc, #-58\] ; 0+172 <[^>]+>
|
||||
0+1ac <[^>]+> bf00 nop
|
||||
0+1ae <[^>]+> 6029 str r1, \[r5, #0\]
|
||||
0+1b0 <[^>]+> f8c5 1080 str.w r1, \[r5, #128\]
|
||||
0+1b4 <[^>]+> 67e9 str r1, \[r5, #124\]
|
||||
0+1b6 <[^>]+> f8c5 107c str.w r1, \[r5, #124\]
|
||||
0+1ba <[^>]+> f845 1c7c str.w r1, \[r5, #-124\]
|
||||
0+1be <[^>]+> f845 1b7c str.w r1, \[r5\], #124
|
||||
0+1c2 <[^>]+> f845 1b7c str.w r1, \[r5\], #124
|
||||
0+1c6 <[^>]+> f845 1f7c str.w r1, \[r5, #124\]!
|
||||
0+1ca <[^>]+> f845 1d7c str.w r1, \[r5, #-124\]!
|
||||
0+1ce <[^>]+> 5129 str r1, \[r5, r4\]
|
||||
0+1d0 <[^>]+> f849 100c str.w r1, \[r9, ip\]
|
||||
0+1d4 <[^>]+> f8cf 1010 str.w r1, \[pc, #16\] ; 0+1e8 <[^>]+>
|
||||
0+1d8 <[^>]+> f8cf 100c str.w r1, \[pc, #12\] ; 0+1e8 <[^>]+>
|
||||
0+1dc <[^>]+> f8cf 8008 str.w r8, \[pc, #8\] ; 0+1e8 <[^>]+>
|
||||
0+1e0 <[^>]+> f8cf 1006 str.w r1, \[pc, #6\] ; 0+1ea <[^>]+>
|
||||
0+1e4 <[^>]+> f84f 103a str.w r1, \[pc, #-58\] ; 0+1ae <[^>]+>
|
||||
0+1e8 <[^>]+> bf00 nop
|
||||
0+1ea <[^>]+> a104 add r1, pc, #16 \(adr r1,0+1fc <[^>]+>\)
|
||||
0+1ec <[^>]+> f20f 010c addw r1, pc, #12 ; 0xc
|
||||
0+1f0 <[^>]+> f20f 0808 addw r8, pc, #8 ; 0x8
|
||||
0+1f4 <[^>]+> f20f 0106 addw r1, pc, #6 ; 0x6
|
||||
0+1f8 <[^>]+> f2af 0112 subw r1, pc, #18 ; 0x12
|
||||
0+1fc <[^>]+> bf00 nop
|
||||
0+1fe <[^>]+> bf00 nop
|
||||
0+200 <[^>]+> f20f 0104 addw r1, pc, #4 ; 0x4
|
||||
0+204 <[^>]+> f20f 0102 addw r1, pc, #2 ; 0x2
|
||||
0+208 <[^>]+> bf00 nop
|
||||
0+20a <[^>]+> bf00 nop
|
62
gas/testsuite/gas/arm/thumb2_relax.s
Normal file
62
gas/testsuite/gas/arm/thumb2_relax.s
Normal file
@ -0,0 +1,62 @@
|
||||
.text
|
||||
.thumb
|
||||
.syntax unified
|
||||
thumb2_relax:
|
||||
.macro ls op w=".w"
|
||||
1:
|
||||
\op r1, [r5]
|
||||
\op r1, [r5, #(far_\op + 4)]
|
||||
\op r1, [r5, #far_\op]
|
||||
\op\w r1, [r5, #far_\op]
|
||||
\op r1, [r5, #-far_\op]
|
||||
\op r1, [r5], #far_\op
|
||||
\op r1, [r5], #far_\op
|
||||
\op r1, [r5, #far_\op]!
|
||||
\op r1, [r5, #-far_\op]!
|
||||
\op r1, [r5, r4]
|
||||
\op r1, [r9, ip]
|
||||
\op r1, 1f
|
||||
\op\w r1, 1f
|
||||
\op r8, 1f
|
||||
\op r1, 2f
|
||||
\op r1, 1b
|
||||
.align 2
|
||||
1:
|
||||
nop
|
||||
2:
|
||||
.endm
|
||||
.equ far_ldrb, 0x1f
|
||||
.equ far_ldrsb, 0x1f
|
||||
.equ far_ldrh, 0x3e
|
||||
.equ far_ldrsh, 0x3e
|
||||
.equ far_ldr, 0x7c
|
||||
.equ far_strb, 0x1f
|
||||
.equ far_strh, 0x3e
|
||||
.equ far_str, 0x7c
|
||||
ls ldrb
|
||||
ls ldrsb
|
||||
ls ldrh
|
||||
ls ldrsh
|
||||
ls ldr
|
||||
ls strb
|
||||
ls strh
|
||||
ls str
|
||||
.purgem ls
|
||||
1:
|
||||
adr r1, 1f
|
||||
adr.w r1, 1f
|
||||
adr r8, 1f
|
||||
adr r1, 2f
|
||||
adr r1, 1b
|
||||
.align 2
|
||||
1:
|
||||
nop
|
||||
2:
|
||||
nop
|
||||
@ Relaxation with conflicting alignment requirements.
|
||||
adr r1, 1f
|
||||
adr r1, 2f
|
||||
1:
|
||||
nop
|
||||
2:
|
||||
nop
|
File diff suppressed because it is too large
Load Diff
@ -42,10 +42,11 @@ encode_thumb32_immediate:
|
||||
orr r0, r1, #0xa5 << 1
|
||||
|
||||
add_sub:
|
||||
adds r0, r0, #0 @ format 1
|
||||
@ Should be format 1, Some have equivalent format 2 encodings
|
||||
adds r0, r0, #0
|
||||
adds r5, r0, #0
|
||||
adds r0, r5, #0
|
||||
adds r0, r0, #5
|
||||
adds r0, r2, #5
|
||||
|
||||
adds r0, #129 @ format 2
|
||||
adds r0, r0, #129
|
||||
@ -83,6 +84,10 @@ add_sub:
|
||||
add.w r9, r0, #0
|
||||
add.w r0, r9, #0
|
||||
add.w r0, r0, #129
|
||||
adds r5, r3, #0x10000
|
||||
add r0, sp, #1
|
||||
add r9, sp, #0
|
||||
add.w sp, sp, #4
|
||||
|
||||
add.w r0, r0, r0 @ T32 format 2
|
||||
adds.w r0, r0, r0
|
||||
@ -102,7 +107,7 @@ add_sub:
|
||||
subs r0, r0, #0 @ format 1
|
||||
subs r5, r0, #0
|
||||
subs r0, r5, #0
|
||||
subs r0, r0, #5
|
||||
subs r0, r2, #5
|
||||
|
||||
subs r0, r0, #129
|
||||
subs r5, #8
|
||||
@ -118,6 +123,11 @@ add_sub:
|
||||
subs r8, r0 @ T32 format 2
|
||||
subs r0, r8
|
||||
subs r0, #260 @ T32 format 1
|
||||
subs.w r1, r2, #4
|
||||
subs r5, r3, #0x10000
|
||||
sub r1, sp, #4
|
||||
sub r9, sp, #0
|
||||
sub.w sp, sp, #4
|
||||
|
||||
arit3:
|
||||
.macro arit3 op ops opw opsw
|
||||
@ -197,27 +207,27 @@ branches:
|
||||
@ bl, blx have no short form.
|
||||
.balign 4
|
||||
1:
|
||||
bra beq
|
||||
bra bne
|
||||
bra bcs
|
||||
bra bhs
|
||||
bra bcc
|
||||
bra bul
|
||||
bra blo
|
||||
bra bmi
|
||||
bra bpl
|
||||
bra bvs
|
||||
bra bvc
|
||||
bra bhi
|
||||
bra bls
|
||||
bra bvc
|
||||
bra bhi
|
||||
bra bls
|
||||
bra bge
|
||||
bra blt
|
||||
bra bgt
|
||||
bra ble
|
||||
bra b
|
||||
bra beq.w
|
||||
bra bne.w
|
||||
bra bcs.w
|
||||
bra bhs.w
|
||||
bra bcc.w
|
||||
bra bul.w
|
||||
bra blo.w
|
||||
bra bmi.w
|
||||
bra bpl.w
|
||||
bra bvs.w
|
||||
bra bvc.w
|
||||
bra bhi.w
|
||||
bra bls.w
|
||||
bra bvc.w
|
||||
bra bhi.w
|
||||
bra bls.w
|
||||
bra bge.w
|
||||
bra blt.w
|
||||
bra bgt.w
|
||||
bra ble.w
|
||||
bra b.w
|
||||
bra bl
|
||||
bra blx
|
||||
.balign 4
|
||||
@ -347,30 +357,7 @@ it:
|
||||
it3 ne eq e e e
|
||||
|
||||
ldst:
|
||||
.macro ls op
|
||||
\op r1, [r5]
|
||||
\op r1, [r5, #0x330]
|
||||
\op r1, [r5, #-0x30]
|
||||
\op r1, [r5], #0x30
|
||||
\op r1, [r5], #-0x30
|
||||
\op r1, [r5, #0x30]!
|
||||
\op r1, [r5, #-0x30]!
|
||||
\op r1, [r5, r4]
|
||||
\op r1, [r9, ip]
|
||||
\op r1, 1f
|
||||
\op r1, 1b
|
||||
.endm
|
||||
1:
|
||||
ls ldrb
|
||||
ls ldrsb
|
||||
ls ldrh
|
||||
ls ldrsh
|
||||
ls ldr
|
||||
1:
|
||||
ls strb
|
||||
ls strh
|
||||
ls str
|
||||
|
||||
pld [r5]
|
||||
pld [r5, #0x330]
|
||||
pld [r5, #-0x30]
|
||||
@ -402,8 +389,6 @@ ldst:
|
||||
ldrt r1, [r5]
|
||||
ldrt r1, [r5, #0x30]
|
||||
|
||||
.purgem ls
|
||||
|
||||
ldxstx:
|
||||
ldrexb r1, [r4]
|
||||
ldrexh r1, [r4]
|
||||
@ -454,8 +439,8 @@ tst_teq_cmp_cmn_mov_mvn:
|
||||
\opw r0, r0
|
||||
\ops r9, r0
|
||||
\opsw r0, r9
|
||||
\op r0, #129
|
||||
\op r5, #129
|
||||
\opw r0, #129
|
||||
\opw r5, #129
|
||||
.endm
|
||||
|
||||
mt tst tsts tst.w tsts.w
|
||||
|
Loading…
Reference in New Issue
Block a user