X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=545b7ec7a39c9e8bdc0f92a4e98af251090dab6d;hb=6530b175a1051db81806d031b8ab2937744ff57b;hp=9222aff21e470ea7e454b9f7758be7b92a842061;hpb=7465e07a575987962b4f1ade6656d5dfbe8fa78e;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 9222aff21e..545b7ec7a3 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -622,6 +622,14 @@ struct asm_opcode #define T2_OPCODE_MASK 0xfe1fffff #define T2_DATA_OP_SHIFT 21 +#define A_COND_MASK 0xf0000000 +#define A_PUSH_POP_OP_MASK 0x0fff0000 + +/* Opcodes for pushing/poping registers to/from the stack. */ +#define A1_OPCODE_PUSH 0x092d0000 +#define A2_OPCODE_PUSH 0x052d0004 +#define A2_OPCODE_POP 0x049d0004 + /* Codes to distinguish the arithmetic instructions. */ #define OPCODE_AND 0 #define OPCODE_EOR 1 @@ -7795,11 +7803,21 @@ do_it (void) } } +/* If there is only one register in the register list, + then return its register number. Otherwise return -1. */ +static int +only_one_reg_in_list (int range) +{ + int i = ffs (range) - 1; + return (i > 15 || range != (1 << i)) ? -1 : i; +} + static void -do_ldmstm (void) +encode_ldmstm(int from_push_pop_mnem) { int base_reg = inst.operands[0].reg; int range = inst.operands[1].imm; + int one_reg; inst.instruction |= base_reg << 16; inst.instruction |= range; @@ -7832,6 +7850,23 @@ do_ldmstm (void) as_warn (_("if writeback register is in list, it must be the lowest reg in the list")); } } + + /* If PUSH/POP has only one register, then use the A2 encoding. */ + one_reg = only_one_reg_in_list (range); + if (from_push_pop_mnem && one_reg >= 0) + { + int is_push = (inst.instruction & A_PUSH_POP_OP_MASK) == A1_OPCODE_PUSH; + + inst.instruction &= A_COND_MASK; + inst.instruction |= is_push ? A2_OPCODE_PUSH : A2_OPCODE_POP; + inst.instruction |= one_reg << 12; + } +} + +static void +do_ldmstm (void) +{ + encode_ldmstm (/*from_push_pop_mnem=*/FALSE); } /* ARMv5TE load-consecutive (argument parse) @@ -8333,7 +8368,7 @@ do_push_pop (void) inst.operands[0].isreg = 1; inst.operands[0].writeback = 1; inst.operands[0].reg = REG_SP; - do_ldmstm (); + encode_ldmstm (/*from_push_pop_mnem=*/TRUE); } /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the @@ -23060,6 +23095,7 @@ static const struct arm_cpu_option_table arm_cpus[] = ARM_CPU_OPT ("cortex-m3", ARM_ARCH_V7M, FPU_NONE, "Cortex-M3"), ARM_CPU_OPT ("cortex-m1", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M1"), ARM_CPU_OPT ("cortex-m0", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M0"), + ARM_CPU_OPT ("cortex-m0plus", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M0+"), /* ??? XSCALE is really an architecture. */ ARM_CPU_OPT ("xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL), /* ??? iwmmxt is not a processor. */