From 62b3e31101ef2dfb96ee4652d5145e722b335e31 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 24 Feb 2006 15:36:36 +0000 Subject: [PATCH] 2006-02-24 Paul Brook gas/ * config/arm/tc-arm.c (arm_ext_v6_notm, arm_ext_div, arm_ext_v7, arm_ext_v7a, arm_ext_v7r, arm_ext_v7m): New variables. (struct asm_barrier_opt): Define. (arm_v7m_psr_hsh, arm_barrier_opt_hsh): New variables. (parse_psr): Accept V7M psr names. (parse_barrier): New function. (enum operand_parse_code): Add OP_oBARRIER. (parse_operands): Implement OP_oBARRIER. (do_barrier): New function. (do_dbg, do_pli, do_t_barrier, do_t_dbg, do_t_div): New functions. (do_t_cpsi): Add V7M restrictions. (do_t_mrs, do_t_msr): Validate V7M variants. (md_assemble): Check for NULL variants. (v7m_psrs, barrier_opt_names): New tables. (insns): Add V7 instructions. Mark V6 instructions absent from V7M. (md_begin): Initialize arm_v7m_psr_hsh and arm_barrier_opt_hsh. (arm_cpu_option_table): Add Cortex-M3, R4 and A8. (arm_arch_option_table): Add armv7, armv7a, armv7r and armv7m. (struct cpu_arch_ver_table): Define. (cpu_arch_ver): New. (aeabi_set_public_attributes): Use cpu_arch_ver. Set Tag_CPU_arch_profile. * doc/c-arm.texi: Document new cpu and arch options. gas/testsuite/ * gas/arm/thumb32.d: Fix expected msr and mrs output. * gas/arm/arch7.d: New test. * gas/arm/arch7.s: New test. * gas/arm/arch7m-bad.l: New test. * gas/arm/arch7m-bad.d: New test. * gas/arm/arch7m-bad.s: New test. include/opcode/ * arm.h: Add V7 feature bits. opcodes/ * arm-dis.c (arm_opcodes): Add V7 instructions. (thumb32_opcodes): Ditto. Handle V7M MSR/MRS variants. (print_arm_address): New function. (print_insn_arm): Use it. Add 'P' and 'U' cases. (psr_name): New function. (print_insn_thumb32): Add 'U', 'C' and 'D' cases. --- gas/ChangeLog | 26 +++ gas/config/tc-arm.c | 337 +++++++++++++++++++++++++---- gas/doc/c-arm.texi | 7 + gas/testsuite/ChangeLog | 9 + gas/testsuite/gas/arm/arch7.d | 76 +++++++ gas/testsuite/gas/arm/arch7.s | 79 +++++++ gas/testsuite/gas/arm/arch7m-bad.d | 4 + gas/testsuite/gas/arm/arch7m-bad.l | 5 + gas/testsuite/gas/arm/arch7m-bad.s | 7 + gas/testsuite/gas/arm/thumb32.d | 20 +- include/opcode/ChangeLog | 4 + include/opcode/arm.h | 31 ++- opcodes/ChangeLog | 9 + opcodes/arm-dis.c | 277 +++++++++++++++++------- 14 files changed, 746 insertions(+), 145 deletions(-) create mode 100644 gas/testsuite/gas/arm/arch7.d create mode 100644 gas/testsuite/gas/arm/arch7.s create mode 100644 gas/testsuite/gas/arm/arch7m-bad.d create mode 100644 gas/testsuite/gas/arm/arch7m-bad.l create mode 100644 gas/testsuite/gas/arm/arch7m-bad.s diff --git a/gas/ChangeLog b/gas/ChangeLog index d6729151e85..307c531600d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,29 @@ +2006-02-24 Paul Brook + + * config/arm/tc-arm.c (arm_ext_v6_notm, arm_ext_div, arm_ext_v7, + arm_ext_v7a, arm_ext_v7r, arm_ext_v7m): New variables. + (struct asm_barrier_opt): Define. + (arm_v7m_psr_hsh, arm_barrier_opt_hsh): New variables. + (parse_psr): Accept V7M psr names. + (parse_barrier): New function. + (enum operand_parse_code): Add OP_oBARRIER. + (parse_operands): Implement OP_oBARRIER. + (do_barrier): New function. + (do_dbg, do_pli, do_t_barrier, do_t_dbg, do_t_div): New functions. + (do_t_cpsi): Add V7M restrictions. + (do_t_mrs, do_t_msr): Validate V7M variants. + (md_assemble): Check for NULL variants. + (v7m_psrs, barrier_opt_names): New tables. + (insns): Add V7 instructions. Mark V6 instructions absent from V7M. + (md_begin): Initialize arm_v7m_psr_hsh and arm_barrier_opt_hsh. + (arm_cpu_option_table): Add Cortex-M3, R4 and A8. + (arm_arch_option_table): Add armv7, armv7a, armv7r and armv7m. + (struct cpu_arch_ver_table): Define. + (cpu_arch_ver): New. + (aeabi_set_public_attributes): Use cpu_arch_ver. Set + Tag_CPU_arch_profile. + * doc/c-arm.texi: Document new cpu and arch options. + 2006-02-23 H.J. Lu * config/tc-ia64.c (operand_match): Handle IA64_OPND_IMMU5b. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 906f62a35a8..4d96af556be 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -182,6 +182,12 @@ static const arm_feature_set arm_ext_v6 = ARM_FEATURE (ARM_EXT_V6, 0); static const arm_feature_set arm_ext_v6k = ARM_FEATURE (ARM_EXT_V6K, 0); static const arm_feature_set arm_ext_v6z = ARM_FEATURE (ARM_EXT_V6Z, 0); static const arm_feature_set arm_ext_v6t2 = ARM_FEATURE (ARM_EXT_V6T2, 0); +static const arm_feature_set arm_ext_v6_notm = ARM_FEATURE (ARM_EXT_V6_NOTM, 0); +static const arm_feature_set arm_ext_div = ARM_FEATURE (ARM_EXT_DIV, 0); +static const arm_feature_set arm_ext_v7 = ARM_FEATURE (ARM_EXT_V7, 0); +static const arm_feature_set arm_ext_v7a = ARM_FEATURE (ARM_EXT_V7A, 0); +static const arm_feature_set arm_ext_v7r = ARM_FEATURE (ARM_EXT_V7R, 0); +static const arm_feature_set arm_ext_v7m = ARM_FEATURE (ARM_EXT_V7M, 0); static const arm_feature_set arm_arch_any = ARM_ANY; static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1); @@ -328,6 +334,12 @@ struct asm_psr unsigned long field; }; +struct asm_barrier_opt +{ + const char *template; + unsigned long value; +}; + /* The bit that distinguishes CPSR and SPSR. */ #define SPSR_BIT (1 << 22) @@ -561,8 +573,10 @@ static struct hash_control *arm_ops_hsh; static struct hash_control *arm_cond_hsh; static struct hash_control *arm_shift_hsh; static struct hash_control *arm_psr_hsh; +static struct hash_control *arm_v7m_psr_hsh; static struct hash_control *arm_reg_hsh; static struct hash_control *arm_reloc_hsh; +static struct hash_control *arm_barrier_opt_hsh; /* Stuff needed to resolve the label ambiguity As: @@ -3481,28 +3495,35 @@ parse_psr (char **str) { char *p; unsigned long psr_field; + const struct asm_psr *psr; + char *start; /* CPSR's and SPSR's can now be lowercase. This is just a convenience feature for ease of use and backwards compatibility. */ p = *str; - if (*p == 's' || *p == 'S') + if (strncasecmp (p, "SPSR", 4) == 0) psr_field = SPSR_BIT; - else if (*p == 'c' || *p == 'C') + else if (strncasecmp (p, "CPSR", 4) == 0) psr_field = 0; else - goto error; + { + start = p; + do + p++; + while (ISALNUM (*p) || *p == '_'); + + psr = hash_find_n (arm_v7m_psr_hsh, start, p - start); + if (!psr) + return FAIL; - p++; - if (strncasecmp (p, "PSR", 3) != 0) - goto error; - p += 3; + *str = p; + return psr->field; + } + p += 4; if (*p == '_') { /* A suffix follows. */ - const struct asm_psr *psr; - char *start; - p++; start = p; @@ -3653,6 +3674,26 @@ parse_cond (char **str) return c->value; } +/* Parse an option for a barrier instruction. Returns the encoding for the + option, or FAIL. */ +static int +parse_barrier (char **str) +{ + char *p, *q; + const struct asm_barrier_opt *o; + + p = q = *str; + while (ISALPHA (*q)) + q++; + + o = hash_find_n (arm_barrier_opt_hsh, p, q - p); + if (!o) + return FAIL; + + *str = q; + return o->value; +} + /* Parse the operands of a table branch instruction. Similar to a memory operand. */ static int @@ -3777,6 +3818,7 @@ enum operand_parse_code OP_oSHar, /* ASR immediate */ OP_oSHllar, /* LSL or ASR immediate */ OP_oROR, /* ROR 0/8/16/24 */ + OP_oBARRIER, /* Option argument for a barrier instruction. */ OP_FIRST_OPTIONAL = OP_oI7b }; @@ -3998,6 +4040,7 @@ parse_operands (char *str, const unsigned char *pattern) case OP_oROR: val = parse_ror (&str); break; case OP_PSR: val = parse_psr (&str); break; case OP_COND: val = parse_cond (&str); break; + case OP_oBARRIER:val = parse_barrier (&str); break; case OP_TB: po_misc_or_fail (parse_tb (&str)); @@ -4065,6 +4108,7 @@ parse_operands (char *str, const unsigned char *pattern) case OP_oROR: case OP_PSR: case OP_COND: + case OP_oBARRIER: case OP_REGLST: case OP_VRSLST: case OP_VRDLST: @@ -4585,6 +4629,20 @@ do_arit (void) encode_arm_shifter_operand (2); } +static void +do_barrier (void) +{ + if (inst.operands[0].present) + { + constraint ((inst.instruction & 0xf0) != 0x40 + && inst.operands[0].imm != 0xf, + "bad barrier type"); + inst.instruction |= inst.operands[0].imm; + } + else + inst.instruction |= 0xf; +} + static void do_bfc (void) { @@ -4813,6 +4871,12 @@ do_cpsi (void) inst.instruction |= inst.operands[1].imm; } +static void +do_dbg (void) +{ + inst.instruction |= inst.operands[0].imm; +} + static void do_it (void) { @@ -5184,6 +5248,22 @@ do_pld (void) encode_arm_addr_mode_2 (0, /*is_t=*/FALSE); } +/* ARMv7: PLI */ +static void +do_pli (void) +{ + constraint (!inst.operands[0].isreg, + _("'[' expected after PLI mnemonic")); + constraint (inst.operands[0].postind, + _("post-indexed expression used in preload instruction")); + constraint (inst.operands[0].writeback, + _("writeback used in preload instruction")); + constraint (!inst.operands[0].preind, + _("unindexed addressing used in preload instruction")); + encode_arm_addr_mode_2 (0, /*is_t=*/FALSE); + inst.instruction &= ~PRE_INDEX; +} + static void do_push_pop (void) { @@ -6444,6 +6524,20 @@ do_t_arit3c (void) } } +static void +do_t_barrier (void) +{ + if (inst.operands[0].present) + { + constraint ((inst.instruction & 0xf0) != 0x40 + && inst.operands[0].imm != 0xf, + "bad barrier type"); + inst.instruction |= inst.operands[0].imm; + } + else + inst.instruction |= 0xf; +} + static void do_t_bfc (void) { @@ -6618,7 +6712,8 @@ static void do_t_cpsi (void) { if (unified_syntax - && (inst.operands[1].present || inst.size_req == 4)) + && (inst.operands[1].present || inst.size_req == 4) + && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6_notm)) { unsigned int imod = (inst.instruction & 0x0030) >> 4; inst.instruction = 0xf3af8000; @@ -6629,7 +6724,11 @@ do_t_cpsi (void) } else { - constraint (inst.operands[1].present, + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1) + && (inst.operands[0].imm & 4), + _("selected processor does not support 'A' form " + "of this instruction")); + constraint (inst.operands[1].present || inst.size_req == 4, _("Thumb does not support the 2-argument " "form of this instruction")); inst.instruction |= inst.operands[0].imm; @@ -6664,6 +6763,22 @@ do_t_czb (void) inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH7; } +static void +do_t_dbg (void) +{ + inst.instruction |= inst.operands[0].imm; +} + +static void +do_t_div (void) +{ + if (!inst.operands[1].present) + inst.operands[1].reg = inst.operands[0].reg; + inst.instruction |= inst.operands[0].reg << 8; + inst.instruction |= inst.operands[1].reg << 16; + inst.instruction |= inst.operands[2].reg; +} + static void do_t_hint (void) { @@ -7211,21 +7326,53 @@ do_t_mvn_tst (void) static void do_t_mrs (void) { - /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */ - constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f)) - != (PSR_c|PSR_f), - _("'CPSR' or 'SPSR' expected")); + int flags; + flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT); + if (flags == 0) + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v7m), + _("selected processor does not support " + "requested special purpose register")); + } + else + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1), + _("selected processor does not support " + "requested special purpose register %x")); + /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */ + constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f), + _("'CPSR' or 'SPSR' expected")); + } + inst.instruction |= inst.operands[0].reg << 8; - inst.instruction |= (inst.operands[1].imm & SPSR_BIT) >> 2; + inst.instruction |= (flags & SPSR_BIT) >> 2; + inst.instruction |= inst.operands[1].imm & 0xff; } static void do_t_msr (void) { + int flags; + constraint (!inst.operands[1].isreg, _("Thumb encoding does not support an immediate here")); - inst.instruction |= (inst.operands[0].imm & SPSR_BIT) >> 2; - inst.instruction |= (inst.operands[0].imm & ~SPSR_BIT) >> 8; + flags = inst.operands[0].imm; + if (flags & ~0xff) + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1), + _("selected processor does not support " + "requested special purpose register")); + } + else + { + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v7m), + _("selected processor does not support " + "requested special purpose register")); + flags |= PSR_f; + } + inst.instruction |= (flags & SPSR_BIT) >> 2; + inst.instruction |= (flags & ~SPSR_BIT) >> 8; + inst.instruction |= (flags & 0xff); inst.instruction |= inst.operands[1].reg << 16; } @@ -8154,8 +8301,9 @@ md_assemble (char *str) if (!ARM_CPU_HAS_FEATURE (variant, arm_arch_t2)) ARM_CLEAR_FEATURE (variant, variant, fpu_any_hard); /* Check that this instruction is supported for this CPU. */ - if (thumb_mode == 1 - && !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant)) + if (!opcode->tvariant + || (thumb_mode == 1 + && !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant))) { as_bad (_("selected processor does not support `%s'"), str); return; @@ -8220,7 +8368,8 @@ md_assemble (char *str) else { /* Check that this instruction is supported for this CPU. */ - if (!ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant)) + if (!opcode->avariant || + !ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant)) { as_bad (_("selected processor does not support `%s'"), str); return; @@ -8526,6 +8675,25 @@ static const struct asm_psr psrs[] = {"cxsf", PSR_c | PSR_x | PSR_s | PSR_f}, }; +/* Table of V7M psr names. */ +static const struct asm_psr v7m_psrs[] = +{ + {"apsr", 0 }, + {"iapsr", 1 }, + {"eapsr", 2 }, + {"psr", 3 }, + {"ipsr", 5 }, + {"epsr", 6 }, + {"iepsr", 7 }, + {"msp", 8 }, + {"psp", 9 }, + {"primask", 16}, + {"basepri", 17}, + {"basepri_max", 18}, + {"faultmask", 19}, + {"control", 20} +}; + /* Table of all shift-in-operand names. */ static const struct asm_shift_name shift_names [] = { @@ -8575,6 +8743,14 @@ static const struct asm_cond conds[] = {"al", 0xe} }; +static struct asm_barrier_opt barrier_opt_names[] = +{ + { "sy", 0xf }, + { "un", 0x7 }, + { "st", 0xe }, + { "unst", 0x6 } +}; + /* Table of ARM-format instructions. */ /* Macros for gluing together operand strings. N.B. In all cases @@ -8971,10 +9147,17 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT &arm_ext_v6t2 - TUF(cps, 1020000, f3af8100, 1, (I31b), imm0, imm0), TCE(ldrex, 1900f9f, e8500f00, 2, (RRnpc, ADDR), ldrex, t_ldrex), TUF(mcrr2, c400000, fc400000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c), TUF(mrrc2, c500000, fc500000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c), + + TCE(ssat, 6a00010, f3000000, 4, (RRnpc, I32, RRnpc, oSHllar),ssat, t_ssat), + TCE(usat, 6e00010, f3800000, 4, (RRnpc, I31, RRnpc, oSHllar),usat, t_usat), + +/* ARM V6 not included in V7M (eg. integer SIMD). */ +#undef THUMB_VARIANT +#define THUMB_VARIANT &arm_ext_v6_notm + TUF(cps, 1020000, f3af8100, 1, (I31b), imm0, imm0), TCE(pkhbt, 6800010, eac00000, 4, (RRnpc, RRnpc, RRnpc, oSHll), pkhbt, t_pkhbt), TCE(pkhtb, 6800050, eac00020, 4, (RRnpc, RRnpc, RRnpc, oSHar), pkhtb, t_pkhtb), TCE(qadd16, 6200f10, fa90f010, 3, (RRnpc, RRnpc, RRnpc), rd_rn_rm, t_simd), @@ -9052,13 +9235,11 @@ static const struct asm_opcode insns[] = UF(srsib, 9cd0500, 1, (I31w), srs), UF(srsda, 84d0500, 1, (I31w), srs), TUF(srsdb, 94d0500, e800c000, 1, (I31w), srs, srs), - TCE(ssat, 6a00010, f3000000, 4, (RRnpc, I32, RRnpc, oSHllar),ssat, t_ssat), TCE(ssat16, 6a00f30, f3200000, 3, (RRnpc, I16, RRnpc), ssat16, t_ssat16), TCE(strex, 1800f90, e8400000, 3, (RRnpc, RRnpc, ADDR), strex, t_strex), TCE(umaal, 0400090, fbe00060, 4, (RRnpc, RRnpc, RRnpc, RRnpc),smlal, t_mlal), TCE(usad8, 780f010, fb70f000, 3, (RRnpc, RRnpc, RRnpc), smul, t_simd), TCE(usada8, 7800010, fb700000, 4, (RRnpc, RRnpc, RRnpc, RRnpc),smla, t_mla), - TCE(usat, 6e00010, f3800000, 4, (RRnpc, I31, RRnpc, oSHllar),usat, t_usat), TCE(usat16, 6e00f30, f3a00000, 3, (RRnpc, I15, RRnpc), usat16, t_usat16), #undef ARM_VARIANT @@ -9074,12 +9255,15 @@ static const struct asm_opcode insns[] = #define THUMB_VARIANT &arm_ext_v6t2 TCE(ldrexb, 1d00f9f, e8d00f4f, 2, (RRnpc, RRnpcb), rd_rn, rd_rn), TCE(ldrexh, 1f00f9f, e8d00f5f, 2, (RRnpc, RRnpcb), rd_rn, rd_rn), - TCE(ldrexd, 1b00f9f, e8d0007f, 3, (RRnpc, oRRnpc, RRnpcb), ldrexd, t_ldrexd), TCE(strexb, 1c00f90, e8c00f40, 3, (RRnpc, RRnpc, ADDR), strex, rm_rd_rn), TCE(strexh, 1e00f90, e8c00f50, 3, (RRnpc, RRnpc, ADDR), strex, rm_rd_rn), - TCE(strexd, 1a00f90, e8c00070, 4, (RRnpc, RRnpc, oRRnpc, RRnpcb), strexd, t_strexd), TUF(clrex, 57ff01f, f3bf8f2f, 0, (), noargs, noargs), +#undef THUMB_VARIANT +#define THUMB_VARIANT &arm_ext_v6_notm + TCE(ldrexd, 1b00f9f, e8d0007f, 3, (RRnpc, oRRnpc, RRnpcb), ldrexd, t_ldrexd), + TCE(strexd, 1a00f90, e8c00070, 4, (RRnpc, RRnpc, oRRnpc, RRnpcb), strexd, t_strexd), + #undef ARM_VARIANT #define ARM_VARIANT &arm_ext_v6z TCE(smc, 1600070, f7f08000, 1, (EXPi), smc, t_smc), @@ -9129,6 +9313,23 @@ static const struct asm_opcode insns[] = TCE(tbb, 0, e8d0f000, 1, (TB), 0, t_tb), TCE(tbh, 0, e8d0f010, 1, (TB), 0, t_tb), + /* Thumb-2 hardware division instructions (R and M profiles only). */ +#undef THUMB_VARIANT +#define THUMB_VARIANT &arm_ext_div + TCE(sdiv, 0, fb90f0f0, 3, (RR, oRR, RR), 0, t_div), + TCE(udiv, 0, fbb0f0f0, 3, (RR, oRR, RR), 0, t_div), + + /* ARM V7 instructions. */ +#undef ARM_VARIANT +#define ARM_VARIANT &arm_ext_v7 +#undef THUMB_VARIANT +#define THUMB_VARIANT &arm_ext_v7 + TUF(pli, 450f000, f910f000, 1, (ADDR), pli, t_pld), + TCE(dbg, 320f0f0, f3af80f0, 1, (I15), dbg, t_dbg), + TUF(dmb, 57ff050, f3bf8f50, 1, (oBARRIER), barrier, t_barrier), + TUF(dsb, 57ff040, f3bf8f40, 1, (oBARRIER), barrier, t_barrier), + TUF(isb, 57ff060, f3bf8f60, 1, (oBARRIER), barrier, t_barrier), + #undef ARM_VARIANT #define ARM_VARIANT &fpu_fpa_ext_v1 /* Core FPA instruction set (V1). */ cCE(wfs, e200110, 1, (RR), rd), @@ -12503,8 +12704,10 @@ md_begin (void) || (arm_cond_hsh = hash_new ()) == NULL || (arm_shift_hsh = hash_new ()) == NULL || (arm_psr_hsh = hash_new ()) == NULL + || (arm_v7m_psr_hsh = hash_new ()) == NULL || (arm_reg_hsh = hash_new ()) == NULL - || (arm_reloc_hsh = hash_new ()) == NULL) + || (arm_reloc_hsh = hash_new ()) == NULL + || (arm_barrier_opt_hsh = hash_new ()) == NULL) as_fatal (_("virtual memory exhausted")); for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++) @@ -12515,8 +12718,15 @@ md_begin (void) hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i)); for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++) hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i)); + for (i = 0; i < sizeof (v7m_psrs) / sizeof (struct asm_psr); i++) + hash_insert (arm_v7m_psr_hsh, v7m_psrs[i].template, (PTR) (v7m_psrs + i)); for (i = 0; i < sizeof (reg_names) / sizeof (struct reg_entry); i++) hash_insert (arm_reg_hsh, reg_names[i].name, (PTR) (reg_names + i)); + for (i = 0; + i < sizeof (barrier_opt_names) / sizeof (struct asm_barrier_opt); + i++) + hash_insert (arm_barrier_opt_hsh, barrier_opt_names[i].template, + (PTR) (barrier_opt_names + i)); #ifdef OBJ_ELF for (i = 0; i < sizeof (reloc_names) / sizeof (struct reloc_entry); i++) hash_insert (arm_reloc_hsh, reloc_names[i].name, (PTR) (reloc_names + i)); @@ -13028,6 +13238,9 @@ static const struct arm_cpu_option_table arm_cpus[] = {"arm1156t2f-s", ARM_ARCH_V6T2, FPU_ARCH_VFP_V2, NULL}, {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE, NULL}, {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2, NULL}, + {"cortex-a8", ARM_ARCH_V7A, FPU_ARCH_VFP_V2, NULL}, + {"cortex-r4", ARM_ARCH_V7R, FPU_NONE, NULL}, + {"cortex-m3", ARM_ARCH_V7M, FPU_NONE, NULL}, /* ??? XSCALE is really an architecture. */ {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL}, /* ??? iwmmxt is not a processor. */ @@ -13075,6 +13288,10 @@ static const struct arm_arch_option_table arm_archs[] = {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP}, {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP}, {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP}, + {"armv7", ARM_ARCH_V7, FPU_ARCH_VFP}, + {"armv7a", ARM_ARCH_V7A, FPU_ARCH_VFP}, + {"armv7r", ARM_ARCH_V7R, FPU_ARCH_VFP}, + {"armv7m", ARM_ARCH_V7M, FPU_ARCH_VFP}, {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP}, {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP}, {NULL, ARM_ARCH_NONE, ARM_ARCH_NONE} @@ -13474,37 +13691,56 @@ md_show_usage (FILE * fp) #ifdef OBJ_ELF +typedef struct +{ + int val; + arm_feature_set flags; +} cpu_arch_ver_table; + +/* Mapping from CPU features to EABI CPU arch values. Table must be sorted + least features first. */ +static const cpu_arch_ver_table cpu_arch_ver[] = +{ + {1, ARM_ARCH_V4}, + {2, ARM_ARCH_V4T}, + {3, ARM_ARCH_V5}, + {4, ARM_ARCH_V5TE}, + {5, ARM_ARCH_V5TEJ}, + {6, ARM_ARCH_V6}, + {7, ARM_ARCH_V6Z}, + {8, ARM_ARCH_V6K}, + {9, ARM_ARCH_V6T2}, + {10, ARM_ARCH_V7A}, + {10, ARM_ARCH_V7R}, + {10, ARM_ARCH_V7M}, + {0, ARM_ARCH_NONE} +}; + /* Set the public EABI object attributes. */ static void aeabi_set_public_attributes (void) { int arch; arm_feature_set flags; + arm_feature_set tmp; + const cpu_arch_ver_table *p; /* Choose the architecture based on the capabilities of the requested cpu (if any) and/or the instructions actually used. */ ARM_MERGE_FEATURE_SETS (flags, arm_arch_used, thumb_arch_used); ARM_MERGE_FEATURE_SETS (flags, flags, *mfpu_opt); ARM_MERGE_FEATURE_SETS (flags, flags, selected_cpu); - if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6t2)) - arch = 8; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6z)) - arch = 7; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6k)) - arch = 9; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6)) - arch = 6; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v5e)) - arch = 4; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v5) - || ARM_CPU_HAS_FEATURE (flags, arm_ext_v5t)) - arch = 3; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v4t)) - arch = 2; - else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v4)) - arch = 1; - else - arch = 0; + + tmp = flags; + arch = 0; + for (p = cpu_arch_ver; p->val; p++) + { + if (ARM_CPU_HAS_FEATURE (tmp, p->flags)) + { + arch = p->val; + ARM_CLEAR_FEATURE (tmp, tmp, p->flags); + } + } /* Tag_CPU_name. */ if (selected_cpu_name[0]) @@ -13524,6 +13760,13 @@ aeabi_set_public_attributes (void) } /* Tag_CPU_arch. */ elf32_arm_add_eabi_attr_int (stdoutput, 6, arch); + /* Tag_CPU_arch_profile. */ + if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a)) + elf32_arm_add_eabi_attr_int (stdoutput, 7, 'A'); + else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7r)) + elf32_arm_add_eabi_attr_int (stdoutput, 7, 'R'); + else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7m)) + elf32_arm_add_eabi_attr_int (stdoutput, 7, 'M'); /* Tag_ARM_ISA_use. */ if (ARM_CPU_HAS_FEATURE (arm_arch_used, arm_arch_full)) elf32_arm_add_eabi_attr_int (stdoutput, 8, 1); diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi index 6a6ceb61898..299dc42bacd 100644 --- a/gas/doc/c-arm.texi +++ b/gas/doc/c-arm.texi @@ -107,6 +107,9 @@ recognized: @code{arm1176jzf-s}, @code{mpcore}, @code{mpcorenovfp}, +@code{cortex-a8}, +@code{cortex-r4}, +@code{cortex-m3}, @code{ep9312} (ARM920 with Cirrus Maverick coprocessor), @code{i80200} (Intel XScale processor) @code{iwmmxt} (Intel(r) XScale processor with Wireless MMX(tm) technology coprocessor) @@ -151,6 +154,10 @@ names are recognized: @code{armv6k}, @code{armv6z}, @code{armv6zk}, +@code{armv7}, +@code{armv7a}, +@code{armv7r}, +@code{armv7m}, @code{iwmmxt} and @code{xscale}. diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 3e6d7433f31..5dde8f7c064 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2006-02-24 Paul Brook + + * gas/arm/thumb32.d: Fix expected msr and mrs output. + * gas/arm/arch7.d: New test. + * gas/arm/arch7.s: New test. + * gas/arm/arch7m-bad.l: New test. + * gas/arm/arch7m-bad.d: New test. + * gas/arm/arch7m-bad.s: New test. + 2006-02-23 H.J. Lu * gas/ia64/opc-i.s: Add tests for tf. diff --git a/gas/testsuite/gas/arm/arch7.d b/gas/testsuite/gas/arm/arch7.d new file mode 100644 index 00000000000..f6563408282 --- /dev/null +++ b/gas/testsuite/gas/arm/arch7.d @@ -0,0 +1,76 @@ +#name: ARM V7 instructions +#as: -march=armv7r +#objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section .text: +0+000 <[^>]*> f6d6f008 pli \[r6, r8\] +0+004 <[^>]*> f6d9f007 pli \[r9, r7\] +0+008 <[^>]*> f6d0f101 pli \[r0, r1, lsl #2\] +0+00c <[^>]*> f4d5f000 pli \[r5\] +0+010 <[^>]*> f4d5ffff pli \[r5, #4095\] +0+014 <[^>]*> f455ffff pli \[r5, #-4095\] +0+018 <[^>]*> e320f0f0 dbg #0 +0+01c <[^>]*> e320f0ff dbg #15 +0+020 <[^>]*> f57ff05f dmb sy +0+024 <[^>]*> f57ff05f dmb sy +0+028 <[^>]*> f57ff04f dsb sy +0+02c <[^>]*> f57ff04f dsb sy +0+030 <[^>]*> f57ff047 dsb un +0+034 <[^>]*> f57ff04e dsb st +0+038 <[^>]*> f57ff046 dsb unst +0+03c <[^>]*> f57ff06f isb sy +0+040 <[^>]*> f57ff06f isb sy +0+044 <[^>]*> f916 f008 pli \[r6, r8\] +0+048 <[^>]*> f919 f007 pli \[r9, r7\] +0+04c <[^>]*> f910 f021 pli \[r0, r1, lsl #2\] +0+050 <[^>]*> f995 f000 pli \[r5\] +0+054 <[^>]*> f995 ffff pli \[r5, #4095\] +0+058 <[^>]*> f915 fcff pli \[r5, #-255\] +0+05c <[^>]*> f99f ffff pli \[pc, #4095\] ; 0000105f <[^>]*> +0+060 <[^>]*> f91f ffff pli \[pc, #-4095\] ; fffff065 <[^>]*> +0+064 <[^>]*> f3af 80f0 dbg #0 +0+068 <[^>]*> f3af 80ff dbg #15 +0+06c <[^>]*> f3bf 8f5f dmb sy +0+070 <[^>]*> f3bf 8f5f dmb sy +0+074 <[^>]*> f3bf 8f4f dsb sy +0+078 <[^>]*> f3bf 8f4f dsb sy +0+07c <[^>]*> f3bf 8f47 dsb un +0+080 <[^>]*> f3bf 8f4e dsb st +0+084 <[^>]*> f3bf 8f46 dsb unst +0+088 <[^>]*> f3bf 8f6f isb sy +0+08c <[^>]*> f3bf 8f6f isb sy +0+090 <[^>]*> fb99 f6fc sdiv r6, r9, ip +0+094 <[^>]*> fb96 f9f3 sdiv r9, r6, r3 +0+098 <[^>]*> fbb6 f9f3 udiv r9, r6, r3 +0+09c <[^>]*> fbb9 f6fc udiv r6, r9, ip +# V7M APSR has the same encoding as V7A CPSR_f +0+0a0 <[^>]*> f3ef 8000 mrs r0, (CPSR|APSR) +0+0a4 <[^>]*> f3ef 8001 mrs r0, IAPSR +0+0a8 <[^>]*> f3ef 8002 mrs r0, EAPSR +0+0ac <[^>]*> f3ef 8003 mrs r0, PSR +0+0b0 <[^>]*> f3ef 8005 mrs r0, IPSR +0+0b4 <[^>]*> f3ef 8006 mrs r0, EPSR +0+0b8 <[^>]*> f3ef 8007 mrs r0, IEPSR +0+0bc <[^>]*> f3ef 8008 mrs r0, MSP +0+0c0 <[^>]*> f3ef 8009 mrs r0, PSP +0+0c4 <[^>]*> f3ef 8010 mrs r0, PRIMASK +0+0c8 <[^>]*> f3ef 8011 mrs r0, BASEPRI +0+0cc <[^>]*> f3ef 8012 mrs r0, BASEPRI_MASK +0+0d0 <[^>]*> f3ef 8013 mrs r0, FAULTMASK +0+0d4 <[^>]*> f3ef 8014 mrs r0, CONTROL +0+0d8 <[^>]*> f380 8800 msr (CPSR_f|APSR), r0 +0+0dc <[^>]*> f380 8801 msr IAPSR, r0 +0+0e0 <[^>]*> f380 8802 msr EAPSR, r0 +0+0e4 <[^>]*> f380 8803 msr PSR, r0 +0+0e8 <[^>]*> f380 8805 msr IPSR, r0 +0+0ec <[^>]*> f380 8806 msr EPSR, r0 +0+0f0 <[^>]*> f380 8807 msr IEPSR, r0 +0+0f4 <[^>]*> f380 8808 msr MSP, r0 +0+0f8 <[^>]*> f380 8809 msr PSP, r0 +0+0fc <[^>]*> f380 8810 msr PRIMASK, r0 +0+100 <[^>]*> f380 8811 msr BASEPRI, r0 +0+104 <[^>]*> f380 8812 msr BASEPRI_MASK, r0 +0+108 <[^>]*> f380 8813 msr FAULTMASK, r0 +0+10c <[^>]*> f380 8814 msr CONTROL, r0 diff --git a/gas/testsuite/gas/arm/arch7.s b/gas/testsuite/gas/arm/arch7.s new file mode 100644 index 00000000000..9b30aa27cb1 --- /dev/null +++ b/gas/testsuite/gas/arm/arch7.s @@ -0,0 +1,79 @@ + # ARMV7 instructions + .text + .arch armv7r +label1: + pli [r6, r8] + pli [r9, r7] + pli [r0, r1, lsl #2] + pli [r5] + pli [r5, #4095] + pli [r5, #-4095] + + dbg #0 + dbg #15 + dmb + dmb sy + dsb + dsb sy + dsb un + dsb st + dsb unst + isb + isb sy + .thumb + .thumb_func +label2: + pli [r6, r8] + pli [r9, r7] + pli [r0, r1, lsl #2] + pli [r5] + pli [r5, #4095] + pli [r5, #-255] + pli [pc, #4095] + pli [pc, #-4095] + + dbg #0 + dbg #15 + dmb + dmb sy + dsb + dsb sy + dsb un + dsb st + dsb unst + isb + isb sy + + sdiv r6, r9, r12 + sdiv r9, r6, r3 + udiv r9, r6, r3 + udiv r6, r9, r12 + .arch armv7m + mrs r0, apsr + mrs r0, iapsr + mrs r0, eapsr + mrs r0, psr + mrs r0, ipsr + mrs r0, epsr + mrs r0, iepsr + mrs r0, msp + mrs r0, psp + mrs r0, primask + mrs r0, basepri + mrs r0, basepri_max + mrs r0, faultmask + mrs r0, control + msr apsr, r0 + msr iapsr, r0 + msr eapsr, r0 + msr psr, r0 + msr ipsr, r0 + msr epsr, r0 + msr iepsr, r0 + msr msp, r0 + msr psp, r0 + msr primask, r0 + msr basepri, r0 + msr basepri_max, r0 + msr faultmask, r0 + msr control, r0 diff --git a/gas/testsuite/gas/arm/arch7m-bad.d b/gas/testsuite/gas/arm/arch7m-bad.d new file mode 100644 index 00000000000..b7a3336cb30 --- /dev/null +++ b/gas/testsuite/gas/arm/arch7m-bad.d @@ -0,0 +1,4 @@ +#name: Invalid V7M instructions +#as: -march=armv7m +#error-output: arch7m-bad.l + diff --git a/gas/testsuite/gas/arm/arch7m-bad.l b/gas/testsuite/gas/arm/arch7m-bad.l new file mode 100644 index 00000000000..c962dacdf03 --- /dev/null +++ b/gas/testsuite/gas/arm/arch7m-bad.l @@ -0,0 +1,5 @@ +[^:]*: Assembler messages: +[^:]*:5: Error: selected processor does not support 'A' form of this instruction -- `cpsie a' +[^:]*:6: Error: Thumb does not support the 2-argument form of this instruction -- `cpsie i,#0x10' +[^:]*:7: Error: selected processor does not support `cps #0x10' + diff --git a/gas/testsuite/gas/arm/arch7m-bad.s b/gas/testsuite/gas/arm/arch7m-bad.s new file mode 100644 index 00000000000..78ff86495e9 --- /dev/null +++ b/gas/testsuite/gas/arm/arch7m-bad.s @@ -0,0 +1,7 @@ + .text + .thumb + .thumb_func +label: + cpsie a + cpsie i, #0x10 + cps #0x10 diff --git a/gas/testsuite/gas/arm/thumb32.d b/gas/testsuite/gas/arm/thumb32.d index e811b14adac..0aac53a0cad 100644 --- a/gas/testsuite/gas/arm/thumb32.d +++ b/gas/testsuite/gas/arm/thumb32.d @@ -631,16 +631,16 @@ Disassembly of section .text: 0[0-9a-f]+ <[^>]+> f240 5000 movw r0, #1280 ; 0x500 0[0-9a-f]+ <[^>]+> f240 0081 movw r0, #129 ; 0x81 0[0-9a-f]+ <[^>]+> f64f 70ff movw r0, #65535 ; 0xffff -0[0-9a-f]+ <[^>]+> f3ef 8000 mrs r0, SPSR -0[0-9a-f]+ <[^>]+> f3ff 8000 mrs r0, CPSR -0[0-9a-f]+ <[^>]+> f3ef 8900 mrs r9, SPSR -0[0-9a-f]+ <[^>]+> f3ff 8900 mrs r9, CPSR -0[0-9a-f]+ <[^>]+> f380 8100 msr SPSR_c, r0 -0[0-9a-f]+ <[^>]+> f390 8100 msr CPSR_c, r0 -0[0-9a-f]+ <[^>]+> f389 8100 msr SPSR_c, r9 -0[0-9a-f]+ <[^>]+> f380 8200 msr SPSR_x, r0 -0[0-9a-f]+ <[^>]+> f380 8400 msr SPSR_s, r0 -0[0-9a-f]+ <[^>]+> f380 8800 msr SPSR_f, r0 +0[0-9a-f]+ <[^>]+> f3ef 8000 mrs r0, CPSR +0[0-9a-f]+ <[^>]+> f3ff 8000 mrs r0, SPSR +0[0-9a-f]+ <[^>]+> f3ef 8900 mrs r9, CPSR +0[0-9a-f]+ <[^>]+> f3ff 8900 mrs r9, SPSR +0[0-9a-f]+ <[^>]+> f380 8100 msr CPSR_c, r0 +0[0-9a-f]+ <[^>]+> f390 8100 msr SPSR_c, r0 +0[0-9a-f]+ <[^>]+> f389 8100 msr CPSR_c, r9 +0[0-9a-f]+ <[^>]+> f380 8200 msr CPSR_x, r0 +0[0-9a-f]+ <[^>]+> f380 8400 msr CPSR_s, r0 +0[0-9a-f]+ <[^>]+> f380 8800 msr CPSR_f, r0 0[0-9a-f]+ <[^>]+> fb00 f000 mul\.w r0, r0, r0 0[0-9a-f]+ <[^>]+> fb09 f000 mul\.w r0, r9, r0 0[0-9a-f]+ <[^>]+> fb00 f009 mul\.w r0, r0, r9 diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index fedd6387505..76b797834bf 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,7 @@ +2006-02-24 Paul Brook + + * arm.h: Add V7 feature bits. + 2006-02-23 H.J. Lu * ia64.h (ia64_opnd): Add IA64_OPND_IMMU5b. diff --git a/include/opcode/arm.h b/include/opcode/arm.h index 97312b63fb3..3260b2feaaa 100644 --- a/include/opcode/arm.h +++ b/include/opcode/arm.h @@ -35,6 +35,15 @@ #define ARM_EXT_V6K 0x00002000 /* ARM V6K. */ #define ARM_EXT_V6Z 0x00004000 /* ARM V6Z. */ #define ARM_EXT_V6T2 0x00008000 /* Thumb-2. */ +#define ARM_EXT_DIV 0x00010000 /* Integer division. */ +/* The 'M' in Arm V7M stands for Microcontroller. + On earlier architecture variants it stands for Multiply. */ +#define ARM_EXT_V5E_NOTM 0x00020000 /* Arm V5E but not Arm V7M. */ +#define ARM_EXT_V6_NOTM 0x00040000 /* Arm V6 but not Arm V7M. */ +#define ARM_EXT_V7 0x00080000 /* Arm V7. */ +#define ARM_EXT_V7A 0x00100000 /* Arm V7A. */ +#define ARM_EXT_V7R 0x00200000 /* Arm V7R. */ +#define ARM_EXT_V7M 0x00400000 /* Arm V7M. */ /* Co-processor space extensions. */ #define ARM_CEXT_XSCALE 0x00000001 /* Allow MIA etc. */ @@ -75,10 +84,18 @@ #define ARM_AEXT_V6K (ARM_AEXT_V6 | ARM_EXT_V6K) #define ARM_AEXT_V6Z (ARM_AEXT_V6 | ARM_EXT_V6Z) #define ARM_AEXT_V6ZK (ARM_AEXT_V6 | ARM_EXT_V6K | ARM_EXT_V6Z) -#define ARM_AEXT_V6T2 (ARM_AEXT_V6 | ARM_EXT_V6T2) -#define ARM_AEXT_V6KT2 (ARM_AEXT_V6 | ARM_EXT_V6T2 | ARM_EXT_V6K) -#define ARM_AEXT_V6ZT2 (ARM_AEXT_V6 | ARM_EXT_V6T2 | ARM_EXT_V6Z) -#define ARM_AEXT_V6ZKT2 (ARM_AEXT_V6 | ARM_EXT_V6T2 | ARM_EXT_V6K | ARM_EXT_V6Z) +#define ARM_AEXT_V6T2 (ARM_AEXT_V6 | ARM_EXT_V6T2 | ARM_EXT_V6_NOTM) +#define ARM_AEXT_V6KT2 (ARM_AEXT_V6T2 | ARM_EXT_V6K) +#define ARM_AEXT_V6ZT2 (ARM_AEXT_V6T2 | ARM_EXT_V6Z) +#define ARM_AEXT_V6ZKT2 (ARM_AEXT_V6T2 | ARM_EXT_V6K | ARM_EXT_V6Z) +#define ARM_AEXT_V7_ARM (ARM_AEXT_V6T2 | ARM_EXT_V7) +#define ARM_AEXT_V7A (ARM_AEXT_V7_ARM | ARM_EXT_V7A) +#define ARM_AEXT_V7R (ARM_AEXT_V7_ARM | ARM_EXT_V7R | ARM_EXT_DIV) +#define ARM_AEXT_NOTM \ + (ARM_AEXT_V4 | ARM_EXT_V5ExP | ARM_EXT_V5J | ARM_EXT_V6_NOTM) +#define ARM_AEXT_V7M \ + ((ARM_AEXT_V7_ARM | ARM_EXT_V7M | ARM_EXT_DIV) & ~(ARM_AEXT_NOTM)) +#define ARM_AEXT_V7 (ARM_AEXT_V7A & ARM_AEXT_V7R & ARM_AEXT_V7M) /* Processors with specific extensions in the co-processor space. */ #define ARM_ARCH_XSCALE ARM_FEATURE (ARM_AEXT_V5TE, ARM_CEXT_XSCALE) @@ -130,13 +147,17 @@ #define ARM_ARCH_V6KT2 ARM_FEATURE (ARM_AEXT_V6KT2, 0) #define ARM_ARCH_V6ZT2 ARM_FEATURE (ARM_AEXT_V6ZT2, 0) #define ARM_ARCH_V6ZKT2 ARM_FEATURE (ARM_AEXT_V6ZKT2, 0) +#define ARM_ARCH_V7 ARM_FEATURE (ARM_AEXT_V7, 0) +#define ARM_ARCH_V7A ARM_FEATURE (ARM_AEXT_V7A, 0) +#define ARM_ARCH_V7R ARM_FEATURE (ARM_AEXT_V7R, 0) +#define ARM_ARCH_V7M ARM_FEATURE (ARM_AEXT_V7M, 0) /* Some useful combinations: */ #define ARM_ARCH_NONE ARM_FEATURE (0, 0) #define FPU_NONE ARM_FEATURE (0, 0) #define ARM_ANY ARM_FEATURE (-1, 0) /* Any basic core. */ #define FPU_ANY_HARD ARM_FEATURE (0, FPU_FPA | FPU_VFP_HARD | FPU_MAVERICK) -#define ARM_ARCH_THUMB2 ARM_FEATURE (ARM_EXT_V6T2, 0) +#define ARM_ARCH_THUMB2 ARM_FEATURE (ARM_EXT_V6T2 | ARM_EXT_V7 | ARM_EXT_V7A | ARM_EXT_V7R | ARM_EXT_V7M | ARM_EXT_DIV, 0) /* There are too many feature bits to fit in a single word, so use a structure. For simplicity we put all core features in one word and diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index a8960dbaa61..6aad1942616 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,12 @@ +2006-02-24 Paul Brook + + * arm-dis.c (arm_opcodes): Add V7 instructions. + (thumb32_opcodes): Ditto. Handle V7M MSR/MRS variants. + (print_arm_address): New function. + (print_insn_arm): Use it. Add 'P' and 'U' cases. + (psr_name): New function. + (print_insn_thumb32): Add 'U', 'C' and 'D' cases. + 2006-02-23 H.J. Lu * ia64-opc-i.c (bXc): New. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index fb3cb77bc4a..b5167e9b6f2 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -402,6 +402,8 @@ static const struct opcode32 coprocessor_opcodes[] = %t print 't' iff bit 21 set and bit 24 clear %B print arm BLX(1) destination %C print the PSR sub type. + %U print barrier type. + %P print address for pli instruction. %r print as an ARM register %d print the bitfield in decimal @@ -428,6 +430,13 @@ static const struct opcode32 arm_opcodes[] = {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"}, {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"}, + /* V7 instructions. */ + {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"}, + {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"}, + {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"}, + {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"}, + {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"}, + /* ARM V6T2 instructions. */ {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"}, {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"}, @@ -827,6 +836,8 @@ static const struct opcode16 thumb_opcodes[] = %B print an unconditional branch offset %s print the shift field of an SSAT instruction %R print the rotation field of an SXT instruction + %U print barrier type. + %P print address for pli instruction. %d print bitfield in decimal %W print bitfield*4 in decimal @@ -847,6 +858,15 @@ static const struct opcode16 thumb_opcodes[] = makes heavy use of special-case bit patterns. */ static const struct opcode32 thumb32_opcodes[] = { + /* V7 instructions. */ + {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli\t%a"}, + {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg\t#%0-3d"}, + {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb\t%U"}, + {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb\t%U"}, + {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb\t%U"}, + {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv\t%8-11r, %16-19r, %0-3r"}, + /* Instructions defined in the basic V6T2 set. */ {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop.w"}, {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield.w"}, @@ -861,14 +881,14 @@ static const struct opcode32 thumb32_opcodes[] = {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj\t%16-19r"}, {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb\t%16-19r%21'!"}, {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia\t%16-19r%21'!"}, - {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff0ff, "mrs\t%8-11r, %20?CSPSR"}, + {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs\t%8-11r, %D"}, {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, 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"}, - {ARM_EXT_V6T2, 0xf3808000, 0xffe0f0ff, "msr\t%20?CSPSR_%8'c%9'x%10's%11'f, %16-19r"}, + {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr\t%C, %16-19r"}, {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex\t%12-15r, [%16-19r]"}, {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb\t%12-15r, [%16-19r]"}, {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb\t#%0-4d%21'!"}, @@ -1602,6 +1622,96 @@ print_insn_coprocessor (struct disassemble_info *info, long given, return FALSE; } +static void +print_arm_address (bfd_vma pc, struct disassemble_info *info, long given) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (((given & 0x000f0000) == 0x000f0000) + && ((given & 0x02000000) == 0)) + { + int offset = given & 0xfff; + + func (stream, "[pc"); + + if (given & 0x01000000) + { + if ((given & 0x00800000) == 0) + offset = - offset; + + /* Pre-indexed. */ + func (stream, ", #%d]", offset); + + offset += pc + 8; + + /* Cope with the possibility of write-back + being used. Probably a very dangerous thing + for the programmer to do, but who are we to + argue ? */ + if (given & 0x00200000) + func (stream, "!"); + } + else + { + /* Post indexed. */ + func (stream, "], #%d", offset); + + /* ie ignore the offset. */ + offset = pc + 8; + } + + func (stream, "\t; "); + info->print_address_func (offset, info); + } + else + { + func (stream, "[%s", + arm_regnames[(given >> 16) & 0xf]); + if ((given & 0x01000000) != 0) + { + if ((given & 0x02000000) == 0) + { + int offset = given & 0xfff; + if (offset) + func (stream, ", #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + } + else + { + func (stream, ", %s", + (((given & 0x00800000) == 0) + ? "-" : "")); + arm_decode_shift (given, func, stream); + } + + func (stream, "]%s", + ((given & 0x00200000) != 0) ? "!" : ""); + } + else + { + if ((given & 0x02000000) == 0) + { + int offset = given & 0xfff; + if (offset) + func (stream, "], #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + else + func (stream, "]"); + } + else + { + func (stream, "], %s", + (((given & 0x00800000) == 0) + ? "-" : "")); + arm_decode_shift (given, func, stream); + } + } + } +} + /* Print one ARM instruction from PC on INFO->STREAM. */ static void @@ -1642,88 +1752,13 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) break; case 'a': - if (((given & 0x000f0000) == 0x000f0000) - && ((given & 0x02000000) == 0)) - { - int offset = given & 0xfff; - - func (stream, "[pc"); - - if (given & 0x01000000) - { - if ((given & 0x00800000) == 0) - offset = - offset; - - /* Pre-indexed. */ - func (stream, ", #%d]", offset); - - offset += pc + 8; - - /* Cope with the possibility of write-back - being used. Probably a very dangerous thing - for the programmer to do, but who are we to - argue ? */ - if (given & 0x00200000) - func (stream, "!"); - } - else - { - /* Post indexed. */ - func (stream, "], #%d", offset); - - /* ie ignore the offset. */ - offset = pc + 8; - } - - func (stream, "\t; "); - info->print_address_func (offset, info); - } - else - { - func (stream, "[%s", - arm_regnames[(given >> 16) & 0xf]); - if ((given & 0x01000000) != 0) - { - if ((given & 0x02000000) == 0) - { - int offset = given & 0xfff; - if (offset) - func (stream, ", #%s%d", - (((given & 0x00800000) == 0) - ? "-" : ""), offset); - } - else - { - func (stream, ", %s", - (((given & 0x00800000) == 0) - ? "-" : "")); - arm_decode_shift (given, func, stream); - } + print_arm_address (pc, info, given); + break; - func (stream, "]%s", - ((given & 0x00200000) != 0) ? "!" : ""); - } - else - { - if ((given & 0x02000000) == 0) - { - int offset = given & 0xfff; - if (offset) - func (stream, "], #%s%d", - (((given & 0x00800000) == 0) - ? "-" : ""), offset); - else - func (stream, "]"); - } - else - { - func (stream, "], %s", - (((given & 0x00800000) == 0) - ? "-" : "")); - arm_decode_shift (given, func, stream); - } - } - } + case 'P': + /* Set P address bit and use normal address + printing routine. */ + print_arm_address (pc, info, given | (1 << 24)); break; case 's': @@ -1913,6 +1948,19 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) func (stream, "c"); break; + case 'U': + switch (given & 0xf) + { + case 0xf: func(stream, "sy"); break; + case 0x7: func(stream, "un"); break; + case 0xe: func(stream, "st"); break; + case 0x6: func(stream, "unst"); break; + default: + func(stream, "#%d", (int)given & 0xf); + break; + } + break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { @@ -2292,6 +2340,30 @@ print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given) abort (); } +/* Return the name of an V7M special register. */ +static const char * +psr_name (int regno) +{ + switch (regno) + { + case 0: return "APSR"; + case 1: return "IAPSR"; + case 2: return "EAPSR"; + case 3: return "PSR"; + case 5: return "IPSR"; + case 6: return "EPSR"; + case 7: return "IEPSR"; + case 8: return "MSP"; + case 9: return "PSP"; + case 16: return "PRIMASK"; + case 17: return "BASEPRI"; + case 18: return "BASEPRI_MASK"; + case 19: return "FAULTMASK"; + case 20: return "CONTROL"; + default: return ""; + } +} + /* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */ static void @@ -2638,6 +2710,45 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) } break; + case 'U': + switch (given & 0xf) + { + case 0xf: func(stream, "sy"); break; + case 0x7: func(stream, "un"); break; + case 0xe: func(stream, "st"); break; + case 0x6: func(stream, "unst"); break; + default: + func(stream, "#%d", (int)given & 0xf); + break; + } + break; + + case 'C': + if ((given & 0xff) == 0) + { + func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C'); + if (given & 0x800) + func (stream, "f"); + if (given & 0x400) + func (stream, "s"); + if (given & 0x200) + func (stream, "x"); + if (given & 0x100) + func (stream, "c"); + } + else + { + func (stream, psr_name (given & 0xff)); + } + break; + + case 'D': + if ((given & 0xff) == 0) + func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C'); + else + func (stream, psr_name (given & 0xff)); + break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { -- 2.30.2