diff options
author | Matthew Gretton-Dann <matthew.gretton-dann@arm.com> | 2012-08-24 07:57:19 +0000 |
---|---|---|
committer | Matthew Gretton-Dann <matthew.gretton-dann@arm.com> | 2012-08-24 07:57:19 +0000 |
commit | 5a01bb1d0f18ec1738106460009f622617c4a19c (patch) | |
tree | 045a00bd8045136f8d7e9aea59a142d92baa779b /gas/config | |
parent | dcbd0d713ca8b0433b0aaaecd956af1a7117015e (diff) | |
download | gdb-5a01bb1d0f18ec1738106460009f622617c4a19c.zip gdb-5a01bb1d0f18ec1738106460009f622617c4a19c.tar.gz gdb-5a01bb1d0f18ec1738106460009f622617c4a19c.tar.bz2 |
* gas/config/tc-arm.c (do_t_it): Fully initialise now_it.
(new_automatic_it_block): Likewise.
(handle_it_block): Record whether current instruction is
conditionally executed.
* gas/config/tc-arm.c (depr_insn_mask): New structure.
(depr_it_insns): New variable.
(it_fsm_post_encode): Warn on deprecated uses.
* gas/config/tc-arm.h (current_it): Add new fields.
* gas/testsuite/gas/arm/armv8-a-it-bad.d: New testcase.
* gas/testsuite/gas/arm/armv8-a-it-bad.l: Likewise.
* gas/testsuite/gas/arm/armv8-a-it-bad.s: Likewise.
* gas/testsuite/gas/arm/ldr-t-bad.s: Update testcase.
* gas/testsuite/gas/arm/ldr-t.d: Likewise.
* gas/testsuite/gas/arm/ldr-t.s: Likewise.
* gas/testsuite/gas/arm/neon-cond-bad-inc.s: Likewise.
* gas/testsuite/gas/arm/sp-pc-validations-bad-t: Likewise.
* gas/testsuite/gas/arm/vfp-fma-inc.s: Likewise.
* gas/testsuite/gas/arm/vfp-neon-syntax-inc.s: Likewise.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-arm.c | 84 | ||||
-rw-r--r-- | gas/config/tc-arm.h | 2 |
2 files changed, 82 insertions, 4 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 02e843d..d9cf3d3 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -10356,6 +10356,7 @@ do_t_it (void) set_it_insn_type (IT_INSN); now_it.mask = (inst.instruction & 0xf) | 0x10; now_it.cc = cond; + now_it.warn_deprecated = FALSE; /* If the condition is a negative condition, invert the mask. */ if ((cond & 0x1) == 0x0) @@ -10363,13 +10364,25 @@ do_t_it (void) unsigned int mask = inst.instruction & 0x000f; if ((mask & 0x7) == 0) - /* no conversion needed */; + { + /* No conversion needed. */ + now_it.block_length = 1; + } else if ((mask & 0x3) == 0) - mask ^= 0x8; + { + mask ^= 0x8; + now_it.block_length = 2; + } else if ((mask & 0x1) == 0) - mask ^= 0xC; + { + mask ^= 0xC; + now_it.block_length = 3; + } else - mask ^= 0xE; + { + mask ^= 0xE; + now_it.block_length = 4; + } inst.instruction &= 0xfff0; inst.instruction |= mask; @@ -16187,6 +16200,8 @@ new_automatic_it_block (int cond) now_it.block_length = 1; mapping_state (MAP_THUMB); now_it.insn = output_it_inst (cond, now_it.mask, NULL); + now_it.warn_deprecated = FALSE; + now_it.insn_cond = TRUE; } /* Close an automatic IT block. @@ -16294,6 +16309,7 @@ static int handle_it_state (void) { now_it.state_handled = 1; + now_it.insn_cond = FALSE; switch (now_it.state) { @@ -16371,6 +16387,7 @@ handle_it_state (void) } else { + now_it.insn_cond = TRUE; now_it_add_mask (inst.cond); } @@ -16382,6 +16399,7 @@ handle_it_state (void) case NEUTRAL_IT_INSN: now_it.block_length++; + now_it.insn_cond = TRUE; if (now_it.block_length > 4) force_automatic_it_block_close (); @@ -16404,6 +16422,7 @@ handle_it_state (void) now_it.mask <<= 1; now_it.mask &= 0x1f; is_last = (now_it.mask == 0x10); + now_it.insn_cond = TRUE; switch (inst.it_insn_type) { @@ -16448,6 +16467,25 @@ handle_it_state (void) return SUCCESS; } +struct depr_insn_mask +{ + unsigned long pattern; + unsigned long mask; + const char* description; +}; + +/* List of 16-bit instruction patterns deprecated in an IT block in + ARMv8. */ +static const struct depr_insn_mask depr_it_insns[] = { + { 0xc000, 0xc000, N_("Short branches, Undefined, SVC, LDM/STM") }, + { 0xb000, 0xb000, N_("Miscellaneous 16-bit instructions") }, + { 0xa000, 0xb800, N_("ADR") }, + { 0x4800, 0xf800, N_("Literal loads") }, + { 0x4478, 0xf478, N_("Hi-register ADD, MOV, CMP, BX, BLX using pc") }, + { 0x4487, 0xfc87, N_("Hi-register ADD, MOV, CMP using pc") }, + { 0, 0, NULL } +}; + static void it_fsm_post_encode (void) { @@ -16456,6 +16494,44 @@ it_fsm_post_encode (void) if (!now_it.state_handled) handle_it_state (); + if (now_it.insn_cond + && !now_it.warn_deprecated + && warn_on_deprecated + && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8)) + { + if (inst.instruction >= 0x10000) + { + as_warn (_("it blocks containing wide Thumb instructions are " + "deprecated in ARMv8")); + now_it.warn_deprecated = TRUE; + } + else + { + const struct depr_insn_mask *p = depr_it_insns; + + while (p->mask != 0) + { + if ((inst.instruction & p->mask) == p->pattern) + { + as_warn (_("it blocks containing 16-bit Thumb intsructions " + "of the following class are deprecated in ARMv8: " + "%s"), p->description); + now_it.warn_deprecated = TRUE; + break; + } + + ++p; + } + } + + if (now_it.block_length > 1) + { + as_warn (_("it blocks of more than one conditional instruction are " + "deprecated in ARMv8")); + now_it.warn_deprecated = TRUE; + } + } + is_last = (now_it.mask == 0x10); if (is_last) { diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h index 4425d75..da6469c 100644 --- a/gas/config/tc-arm.h +++ b/gas/config/tc-arm.h @@ -257,6 +257,8 @@ struct current_it int block_length; char *insn; int state_handled; + int warn_deprecated; + int insn_cond; }; #ifdef OBJ_ELF |