From e39c1607a2df3a97bf7b70bef6de5b7a2db55eea Mon Sep 17 00:00:00 2001 From: Sudakshina Das Date: Tue, 21 May 2019 18:15:13 +0100 Subject: [PATCH] [binutils, Arm] Add support for conditional instructions in Armv8.1-M Mainline This patch adds the following instructions which are part of the Armv8.1-M Mainline: CINC CINV CNEG CSINC CSINV CSNEG CSET CSETM CSEL gas/ChangeLog: 2019-05-21 Sudakshina Das * config/tc-arm.c (TOGGLE_BIT): New. (T16_32_TAB): New entries for cinc, cinv, cneg, csinc, csinv, csneg, cset, csetm and csel. (operand_parse_code): New OP_RR_ZR. (parse_operand): Handle case for OP_RR_ZR. (do_t_cond): New. (insns): New instructions for cinc, cinv, cneg, csinc, csinv, csneg, cset, csetm, csel. * testsuite/gas/arm/armv8_1-m-cond-bad.d: New test. * testsuite/gas/arm/armv8_1-m-cond-bad.l: New test. * testsuite/gas/arm/armv8_1-m-cond-bad.s: New test. * testsuite/gas/arm/armv8_1-m-cond.d: New test. * testsuite/gas/arm/armv8_1-m-cond.s: New test. opcodes/ChangeLog: 2019-05-21 Sudakshina Das * arm-dis.c (enum mve_instructions): New enum for csinc, csinv, csneg, csel, cset, csetm, cinv, cinv and cneg. (mve_opcodes): New instructions as above. (is_mve_encoding_conflict): Add cases for csinc, csinv, csneg and csel. (print_insn_mve): Accept new %c and %C. --- gas/ChangeLog | 16 ++++ gas/config/tc-arm.c | 82 +++++++++++++++++++- gas/testsuite/gas/arm/armv8_1-m-cond-bad.d | 4 + gas/testsuite/gas/arm/armv8_1-m-cond-bad.l | 8 ++ gas/testsuite/gas/arm/armv8_1-m-cond-bad.s | 15 ++++ gas/testsuite/gas/arm/armv8_1-m-cond.d | 21 +++++ gas/testsuite/gas/arm/armv8_1-m-cond.s | 17 +++++ opcodes/ChangeLog | 10 +++ opcodes/arm-dis.c | 89 ++++++++++++++++++++++ 9 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 gas/testsuite/gas/arm/armv8_1-m-cond-bad.d create mode 100644 gas/testsuite/gas/arm/armv8_1-m-cond-bad.l create mode 100644 gas/testsuite/gas/arm/armv8_1-m-cond-bad.s create mode 100644 gas/testsuite/gas/arm/armv8_1-m-cond.d create mode 100644 gas/testsuite/gas/arm/armv8_1-m-cond.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 34fee55530c..fc1fb65e29b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2019-05-21 Sudakshina Das + + * config/tc-arm.c (TOGGLE_BIT): New. + (T16_32_TAB): New entries for cinc, cinv, cneg, csinc, + csinv, csneg, cset, csetm and csel. + (operand_parse_code): New OP_RR_ZR. + (parse_operand): Handle case for OP_RR_ZR. + (do_t_cond): New. + (insns): New instructions for cinc, cinv, cneg, csinc, + csinv, csneg, cset, csetm, csel. + * testsuite/gas/arm/armv8_1-m-cond-bad.d: New test. + * testsuite/gas/arm/armv8_1-m-cond-bad.l: New test. + * testsuite/gas/arm/armv8_1-m-cond-bad.s: New test. + * testsuite/gas/arm/armv8_1-m-cond.d: New test. + * testsuite/gas/arm/armv8_1-m-cond.s: New test. + 2019-05-21 Sudakshina Das * config/tc-arm.c (operand_parse_code): New entries for diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 8826119f409..b657828c20e 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -1009,6 +1009,9 @@ static void it_fsm_post_encode (void); } \ while (0) +/* Toggle value[pos]. */ +#define TOGGLE_BIT(value, pos) (value ^ (1 << pos)) + /* Pure syntax. */ /* This array holds the chars that always start a comment. If the @@ -6930,6 +6933,7 @@ enum operand_parse_code OP_RRe, /* ARM register, only even numbered. */ OP_RRo, /* ARM register, only odd numbered, not r13 or r15. */ OP_RRnpcsp_I32, /* ARM register (no BadReg) or literal 1 .. 32 */ + OP_RR_ZR, /* ARM register or ZR but no PC */ OP_REGLST, /* ARM register list */ OP_CLRMLST, /* CLRM register list */ @@ -7793,6 +7797,8 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) case OP_oRMQRZ: po_reg_or_goto (REG_TYPE_MQ, try_rr_zr); break; + + case OP_RR_ZR: try_rr_zr: po_reg_or_goto (REG_TYPE_RN, ZR); break; @@ -7880,6 +7886,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) case OP_RMQRZ: case OP_oRMQRZ: + case OP_RR_ZR: if (!inst.operands[i].iszr && inst.operands[i].reg == REG_PC) inst.error = BAD_PC; break; @@ -11107,7 +11114,7 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d) inst.error = _("instruction does not accept unindexed addressing"); } -/* Table of Thumb instructions which exist in both 16- and 32-bit +/* Table of Thumb instructions which exist in 16- and/or 32-bit 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 @@ -11136,11 +11143,20 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d) X(_bflx, 0000, f070e001), \ X(_bic, 4380, ea200000), \ X(_bics, 4380, ea300000), \ + X(_cinc, 0000, ea509000), \ + X(_cinv, 0000, ea50a000), \ X(_cmn, 42c0, eb100f00), \ X(_cmp, 2800, ebb00f00), \ + X(_cneg, 0000, ea50b000), \ X(_cpsie, b660, f3af8400), \ X(_cpsid, b670, f3af8600), \ X(_cpy, 4600, ea4f0000), \ + X(_csel, 0000, ea508000), \ + X(_cset, 0000, ea5f900f), \ + X(_csetm, 0000, ea5fa00f), \ + X(_csinc, 0000, ea509000), \ + X(_csinv, 0000, ea50a000), \ + X(_csneg, 0000, ea50b000), \ X(_dec_sp,80dd, f1ad0d00), \ X(_dls, 0000, f040e001), \ X(_dlstp, 0000, f000e001), \ @@ -11955,6 +11971,60 @@ do_t_clz (void) inst.instruction |= Rm; } +/* For the Armv8.1-M conditional instructions. */ +static void +do_t_cond (void) +{ + unsigned Rd, Rn, Rm; + signed int cond; + + constraint (inst.cond != COND_ALWAYS, BAD_COND); + + Rd = inst.operands[0].reg; + switch (inst.instruction) + { + case T_MNEM_csinc: + case T_MNEM_csinv: + case T_MNEM_csneg: + case T_MNEM_csel: + Rn = inst.operands[1].reg; + Rm = inst.operands[2].reg; + cond = inst.operands[3].imm; + constraint (Rn == REG_SP, BAD_SP); + constraint (Rm == REG_SP, BAD_SP); + break; + + case T_MNEM_cinc: + case T_MNEM_cinv: + case T_MNEM_cneg: + Rn = inst.operands[1].reg; + cond = inst.operands[2].imm; + /* Invert the last bit to invert the cond. */ + cond = TOGGLE_BIT (cond, 0); + constraint (Rn == REG_SP, BAD_SP); + Rm = Rn; + break; + + case T_MNEM_csetm: + case T_MNEM_cset: + cond = inst.operands[1].imm; + /* Invert the last bit to invert the cond. */ + cond = TOGGLE_BIT (cond, 0); + Rn = REG_PC; + Rm = REG_PC; + break; + + default: abort (); + } + + set_pred_insn_type (OUTSIDE_PRED_INSN); + inst.instruction = THUMB_OP32 (inst.instruction); + inst.instruction |= Rd << 8; + inst.instruction |= Rn << 16; + inst.instruction |= Rm; + inst.instruction |= cond << 4; +} + static void do_t_csdb (void) { @@ -25157,6 +25227,16 @@ static const struct asm_opcode insns[] = /* Armv8.1-M Mainline instructions. */ #undef THUMB_VARIANT #define THUMB_VARIANT & arm_ext_v8_1m_main + toU("cinc", _cinc, 3, (RRnpcsp, RR_ZR, COND), t_cond), + toU("cinv", _cinv, 3, (RRnpcsp, RR_ZR, COND), t_cond), + toU("cneg", _cneg, 3, (RRnpcsp, RR_ZR, COND), t_cond), + toU("csel", _csel, 4, (RRnpcsp, RR_ZR, RR_ZR, COND), t_cond), + toU("csetm", _csetm, 2, (RRnpcsp, COND), t_cond), + toU("cset", _cset, 2, (RRnpcsp, COND), t_cond), + toU("csinc", _csinc, 4, (RRnpcsp, RR_ZR, RR_ZR, COND), t_cond), + toU("csinv", _csinv, 4, (RRnpcsp, RR_ZR, RR_ZR, COND), t_cond), + toU("csneg", _csneg, 4, (RRnpcsp, RR_ZR, RR_ZR, COND), t_cond), + toC("bf", _bf, 2, (EXPs, EXPs), t_branch_future), toU("bfcsel", _bfcsel, 4, (EXPs, EXPs, EXPs, COND), t_branch_future), toC("bfx", _bfx, 2, (EXPs, RRnpcsp), t_branch_future), diff --git a/gas/testsuite/gas/arm/armv8_1-m-cond-bad.d b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.d new file mode 100644 index 00000000000..d953f9a0cd6 --- /dev/null +++ b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.d @@ -0,0 +1,4 @@ +#name: Invalid Armv8.1-M Mainline conditional instructions +#source: armv8_1-m-cond-bad.s +#as: -march=armv8.1-m.main +#error_output: armv8_1-m-cond-bad.l diff --git a/gas/testsuite/gas/arm/armv8_1-m-cond-bad.l b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.l new file mode 100644 index 00000000000..47eafcf79a7 --- /dev/null +++ b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.l @@ -0,0 +1,8 @@ +.*: Assembler messages: +.*: Error: condition required -- `cset r4,r2,ne' +.*: Error: r13 not allowed here -- `csetm sp,ne' +.*: Error: r15 not allowed here -- `cinc r3,pc,lt' +.*: Error: r15 not allowed here -- `cinv pc,r2,lt' +.*: Error: r13 not allowed here -- `cneg r3,sp,lt' +.*: Error: instruction not allowed in IT block -- `csinc r3,r2,r4,lt' +.*: Error: instruction cannot be conditional -- `csnegne r3,r2,r4,lt' diff --git a/gas/testsuite/gas/arm/armv8_1-m-cond-bad.s b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.s new file mode 100644 index 00000000000..a7d98edb3d3 --- /dev/null +++ b/gas/testsuite/gas/arm/armv8_1-m-cond-bad.s @@ -0,0 +1,15 @@ + .syntax unified + .text + +foo: + cset r4, r2, ne + csetm sp, ne + cinc r3, pc, lt + cinv pc, r2, lt + cneg r3, sp, lt + it eq + csinc r3, r2, r4, lt + csinv r3, r4, r4, lt + it ne + csnegne r3, r2, r4, lt + csinv r3, r4, r4, lt diff --git a/gas/testsuite/gas/arm/armv8_1-m-cond.d b/gas/testsuite/gas/arm/armv8_1-m-cond.d new file mode 100644 index 00000000000..171da374a5b --- /dev/null +++ b/gas/testsuite/gas/arm/armv8_1-m-cond.d @@ -0,0 +1,21 @@ +#name: Valid Armv8.1-M Mainline conditional instructions +#source: armv8_1-m-cond.s +#as: -march=armv8.1-m.main +#objdump: -dr --prefix-addresses --show-raw-insn -marmv8.1-m.main + +.*: +file format .*arm.* + +Disassembly of section .text: +0[0-9a-f]+ <[^>]+> ea5f 940f cset r4, ne +0[0-9a-f]+ <[^>]+> ea5f a40f csetm r4, ne +0[0-9a-f]+ <[^>]+> ea52 93a2 cinc r3, r2, lt +0[0-9a-f]+ <[^>]+> ea52 a3a2 cinv r3, r2, lt +0[0-9a-f]+ <[^>]+> ea52 b3a2 cneg r3, r2, lt +0[0-9a-f]+ <[^>]+> ea52 93b4 csinc r3, r2, r4, lt +0[0-9a-f]+ <[^>]+> ea54 93b4 cinc r3, r4, ge +0[0-9a-f]+ <[^>]+> ea5f 93bf cset r3, ge +0[0-9a-f]+ <[^>]+> ea52 a3b4 csinv r3, r2, r4, lt +0[0-9a-f]+ <[^>]+> ea54 a3b4 cinv r3, r4, ge +0[0-9a-f]+ <[^>]+> ea5f a3bf csetm r3, ge +0[0-9a-f]+ <[^>]+> ea52 b3b4 csneg r3, r2, r4, lt +0[0-9a-f]+ <[^>]+> ea54 b3b4 cneg r3, r4, ge diff --git a/gas/testsuite/gas/arm/armv8_1-m-cond.s b/gas/testsuite/gas/arm/armv8_1-m-cond.s new file mode 100644 index 00000000000..f192d5f879c --- /dev/null +++ b/gas/testsuite/gas/arm/armv8_1-m-cond.s @@ -0,0 +1,17 @@ + .syntax unified + .text + +foo: + cset r4, ne + csetm r4, ne + cinc r3, r2, lt + cinv r3, r2, lt + cneg r3, r2, lt + csinc r3, r2, r4, lt + csinc r3, r4, r4, lt + csinc r3, zr, zr, lt + csinv r3, r2, r4, lt + csinv r3, r4, r4, lt + csinv r3, zr, zr, lt + csneg r3, r2, r4, lt + csneg r3, r4, r4, lt diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index e6950acc17d..c336a1a6a15 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,13 @@ +2019-05-21 Sudakshina Das + + * arm-dis.c (enum mve_instructions): New enum + for csinc, csinv, csneg, csel, cset, csetm, cinv, cinv + and cneg. + (mve_opcodes): New instructions as above. + (is_mve_encoding_conflict): Add cases for csinc, csinv, + csneg and csel. + (print_insn_mve): Accept new %c and %C. + 2019-05-21 Sudakshina Das * arm-dis.c (emun mve_instructions): Updated for new instructions. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index ab99fb71872..ad65ffa99ad 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -281,6 +281,15 @@ enum mve_instructions MVE_SRSHR, MVE_SQSHLL, MVE_SQSHL, + MVE_CINC, + MVE_CINV, + MVE_CNEG, + MVE_CSINC, + MVE_CSINV, + MVE_CSET, + MVE_CSETM, + MVE_CSNEG, + MVE_CSEL, MVE_NONE }; @@ -2060,6 +2069,8 @@ static const struct opcode32 neon_opcodes[] = %r print as an ARM register %d print the bitfield in decimal %A print accumulate or not + %c print bitfield as a condition code + %C print bitfield as an inverted condition code %Q print as a MVE Q register %F print as a MVE S register %Z as %<>r but r15 is ZR instead of PC and r13 is @@ -3400,6 +3411,51 @@ static const struct mopcode32 mve_opcodes[] = 0xea500f1f, 0xfff08f3f, "urshr%c\t%16-19S, %j"}, + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSINC, + 0xea509000, 0xfff0f000, + "csinc\t%8-11S, %16-19Z, %0-3Z, %4-7c"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSINV, + 0xea50a000, 0xfff0f000, + "csinv\t%8-11S, %16-19Z, %0-3Z, %4-7c"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSET, + 0xea5f900f, 0xfffff00f, + "cset\t%8-11S, %4-7C"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSETM, + 0xea5fa00f, 0xfffff00f, + "csetm\t%8-11S, %4-7C"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSEL, + 0xea508000, 0xfff0f000, + "csel\t%8-11S, %16-19Z, %0-3Z, %4-7c"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CSNEG, + 0xea50b000, 0xfff0f000, + "csneg\t%8-11S, %16-19Z, %0-3Z, %4-7c"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CINC, + 0xea509000, 0xfff0f000, + "cinc\t%8-11S, %16-19Z, %4-7C"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CINV, + 0xea50a000, 0xfff0f000, + "cinv\t%8-11S, %16-19Z, %4-7C"}, + + {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN), + MVE_CNEG, + 0xea50b000, 0xfff0f000, + "cneg\t%8-11S, %16-19Z, %4-7C"}, + {ARM_FEATURE_CORE_LOW (0), MVE_NONE, 0x00000000, 0x00000000, 0} @@ -5653,6 +5709,30 @@ is_mve_encoding_conflict (unsigned long given, else return FALSE; + case MVE_CSINC: + case MVE_CSINV: + { + unsigned long rm, rn; + rm = arm_decode_field (given, 0, 3); + rn = arm_decode_field (given, 16, 19); + /* CSET/CSETM. */ + if (rm == 0xf && rn == 0xf) + return TRUE; + /* CINC/CINV. */ + else if (rn == rm && rn != 0xf) + return TRUE; + } + /* Fall through. */ + case MVE_CSEL: + case MVE_CSNEG: + if (arm_decode_field (given, 0, 3) == 0xd) + return TRUE; + /* CNEG. */ + else if (matched_insn == MVE_CSNEG) + if (arm_decode_field (given, 0, 3) == arm_decode_field (given, 16, 19)) + return TRUE; + return FALSE; + default: case MVE_VADD_FP_T1: case MVE_VADD_FP_T2: @@ -9264,6 +9344,15 @@ print_insn_mve (struct disassemble_info *info, long given) func (stream, "%s", arm_regnames[value]); break; + case 'c': + func (stream, "%s", arm_conditional[value]); + break; + + case 'C': + value ^= 1; + func (stream, "%s", arm_conditional[value]); + break; + case 'S': if (value == 13 || value == 15) is_unpredictable = TRUE; -- 2.30.2