From 23d00a419fe67801afc02a87f7ab9c5374b0238e Mon Sep 17 00:00:00 2001 From: Sudakshina Das Date: Tue, 21 May 2019 18:11:08 +0100 Subject: [PATCH] [binutils, Arm] Add support for shift instructions in MVE This patch adds the following instructions which are part of Armv8.1-M MVE: ASRL (imm) ASRL (reg) LSLL (imm) LSLL (reg) LSRL SQRSHRL SRQSHR SQSHLL SQSHL SRSHRL SRSHR UQRSHLL UQRSHL UQSHLL UQSHL URSHLL URSHL *** gas/ChangeLog *** 2019-05-21 Sudakshina Das * config/tc-arm.c (operand_parse_code): New entries for OP_RRnpcsp_I32 (register or integer operands). (do_mve_scalar_shift): New. (insns): New instructions for asrl, lsll, lsrl, sqrshrl, sqrshr, sqshl sqshll, srshr, srshrl, uqrshll, uqrshl, uqshll, uqshl, urshrl and urshr. * testsuite/gas/arm/mve-shift.d: New. * testsuite/gas/arm/mve-shift.s: New. * testsuite/gas/arm/mve-shift-bad.d: New. * testsuite/gas/arm/mve-shift-bad.s: New. * testsuite/gas/arm/mve-shift-bad.l: New. *** opcodes/ChangeLog *** 2019-05-21 Sudakshina Das * arm-dis.c (emun mve_instructions): Updated for new instructions. (mve_opcodes): New instructions for asrl, lsll, lsrl, sqrshrl, sqrshr, sqshl, sqshll, srshr, srshrl, uqrshll, uqrshl, uqshll, uqshl, urshrl and urshr. (is_mve_okay_in_it): Add new instructions to TRUE list. (is_mve_unpredictable): Add cases for UNPRED_R13 and UNPRED_R15. (print_insn_mve): Updated to accept new %j, %m and %n patterns. --- gas/ChangeLog | 13 ++ gas/config/tc-arm.c | 50 +++++++ gas/testsuite/gas/arm/mve-shift-bad.d | 4 + gas/testsuite/gas/arm/mve-shift-bad.l | 12 ++ gas/testsuite/gas/arm/mve-shift-bad.s | 15 +++ gas/testsuite/gas/arm/mve-shift.d | 27 ++++ gas/testsuite/gas/arm/mve-shift.s | 21 +++ opcodes/ChangeLog | 11 ++ opcodes/arm-dis.c | 183 ++++++++++++++++++++++++++ 9 files changed, 336 insertions(+) create mode 100644 gas/testsuite/gas/arm/mve-shift-bad.d create mode 100644 gas/testsuite/gas/arm/mve-shift-bad.l create mode 100644 gas/testsuite/gas/arm/mve-shift-bad.s create mode 100644 gas/testsuite/gas/arm/mve-shift.d create mode 100644 gas/testsuite/gas/arm/mve-shift.s diff --git a/gas/ChangeLog b/gas/ChangeLog index f25c2dc2ba8..34fee55530c 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2019-05-21 Sudakshina Das + + * config/tc-arm.c (operand_parse_code): New entries for + OP_RRnpcsp_I32 (register or integer operands). + (do_mve_scalar_shift): New. + (insns): New instructions for asrl, lsll, lsrl, sqrshrl, sqrshr, sqshl + sqshll, srshr, srshrl, uqrshll, uqrshl, uqshll, uqshl, urshrl and urshr. + * testsuite/gas/arm/mve-shift.d: New. + * testsuite/gas/arm/mve-shift.s: New. + * testsuite/gas/arm/mve-shift-bad.d: New. + * testsuite/gas/arm/mve-shift-bad.s: New. + * testsuite/gas/arm/mve-shift-bad.l: New. + 2019-05-21 Faraz Shahbazker * testsuite/gas/mips/r6-branch-constraints.s: Rename to ... diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 136df3340d3..8826119f409 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -7559,6 +7559,9 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) case OP_RRnpc_I0: po_reg_or_goto (REG_TYPE_RN, I0); break; I0: po_imm_or_fail (0, 0, FALSE); break; + case OP_RRnpcsp_I32: po_reg_or_goto (REG_TYPE_RN, I32); break; + I32: po_imm_or_fail (1, 32, FALSE); break; + case OP_RF_IF: po_reg_or_goto (REG_TYPE_FN, IF); break; IF: if (!is_immediate_prefix (*str)) @@ -7818,6 +7821,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) case OP_oRRnpcsp: case OP_RRnpcsp: + case OP_RRnpcsp_I32: if (inst.operands[i].isreg) { if (inst.operands[i].reg == REG_PC) @@ -14123,6 +14127,37 @@ v8_1_loop_reloc (int is_le) } } +/* For shifts in MVE. */ +static void +do_mve_scalar_shift (void) +{ + if (!inst.operands[2].present) + { + inst.operands[2] = inst.operands[1]; + inst.operands[1].reg = 0xf; + } + + inst.instruction |= inst.operands[0].reg << 16; + inst.instruction |= inst.operands[1].reg << 8; + + if (inst.operands[2].isreg) + { + /* Assuming Rm is already checked not to be 11x1. */ + constraint (inst.operands[2].reg == inst.operands[0].reg, BAD_OVERLAP); + constraint (inst.operands[2].reg == inst.operands[1].reg, BAD_OVERLAP); + inst.instruction |= inst.operands[2].reg << 12; + } + else + { + /* Assuming imm is already checked as [1,32]. */ + unsigned int value = inst.operands[2].imm; + inst.instruction |= (value & 0x1c) << 10; + inst.instruction |= (value & 0x03) << 6; + /* Change last 4 bits from 0xd to 0xf. */ + inst.instruction |= 0x2; + } +} + /* MVE instruction encoder helpers. */ #define M_MNEM_vabav 0xee800f01 #define M_MNEM_vmladav 0xeef00e00 @@ -25137,6 +25172,21 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT & mve_ext + ToC("lsll", ea50010d, 3, (RRe, RRo, RRnpcsp_I32), mve_scalar_shift), + ToC("lsrl", ea50011f, 3, (RRe, RRo, I32), mve_scalar_shift), + ToC("asrl", ea50012d, 3, (RRe, RRo, RRnpcsp_I32), mve_scalar_shift), + ToC("uqrshll", ea51010d, 3, (RRe, RRo, RRnpcsp), mve_scalar_shift), + ToC("sqrshrl", ea51012d, 3, (RRe, RRo, RRnpcsp), mve_scalar_shift), + ToC("uqshll", ea51010f, 3, (RRe, RRo, I32), mve_scalar_shift), + ToC("urshrl", ea51011f, 3, (RRe, RRo, I32), mve_scalar_shift), + ToC("srshrl", ea51012f, 3, (RRe, RRo, I32), mve_scalar_shift), + ToC("sqshll", ea51013f, 3, (RRe, RRo, I32), mve_scalar_shift), + ToC("uqrshl", ea500f0d, 2, (RRnpcsp, RRnpcsp), mve_scalar_shift), + ToC("sqrshr", ea500f2d, 2, (RRnpcsp, RRnpcsp), mve_scalar_shift), + ToC("uqshl", ea500f0f, 2, (RRnpcsp, I32), mve_scalar_shift), + ToC("urshr", ea500f1f, 2, (RRnpcsp, I32), mve_scalar_shift), + ToC("srshr", ea500f2f, 2, (RRnpcsp, I32), mve_scalar_shift), + ToC("sqshl", ea500f3f, 2, (RRnpcsp, I32), mve_scalar_shift), ToC("vpt", ee410f00, 3, (COND, RMQ, RMQRZ), mve_vpt), ToC("vptt", ee018f00, 3, (COND, RMQ, RMQRZ), mve_vpt), diff --git a/gas/testsuite/gas/arm/mve-shift-bad.d b/gas/testsuite/gas/arm/mve-shift-bad.d new file mode 100644 index 00000000000..f3aea254020 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-shift-bad.d @@ -0,0 +1,4 @@ +#name: Invalid MVE shift instructions +#source: mve-shift-bad.s +#as: -march=armv8.1-m.main+mve +#error_output: mve-shift-bad.l diff --git a/gas/testsuite/gas/arm/mve-shift-bad.l b/gas/testsuite/gas/arm/mve-shift-bad.l new file mode 100644 index 00000000000..5e7bfeda997 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-shift-bad.l @@ -0,0 +1,12 @@ +.*: Assembler messages: +.*: immediate value out of range -- `asrl r2,r3,#0' +.*: immediate value out of range -- `asrl r2,r3,#33' +.*: Error: Odd register not allowed here -- `asrl r1,r3,r5' +.*: Error: Even register not allowed here -- `lsll r2,r4,#5' +.*: Error: r15 not allowed here -- `lsll r2,r15,r5' +.*: Warning: instruction is UNPREDICTABLE with SP operand +.*: Error: registers may not be the same -- `sqrshrl r2,r3,r3' +.*: Error: registers may not be the same -- `sqrshr r2,r2' +.*: Error: registers may not be the same -- `uqrshll r2,r3,r2' +.*: Error: thumb conditional instruction should be in IT block -- `uqshlgt r2,#32' +.*: Error: constant expression required -- `urshrlle r2,r3,r5' diff --git a/gas/testsuite/gas/arm/mve-shift-bad.s b/gas/testsuite/gas/arm/mve-shift-bad.s new file mode 100644 index 00000000000..7b38359a7df --- /dev/null +++ b/gas/testsuite/gas/arm/mve-shift-bad.s @@ -0,0 +1,15 @@ + .syntax unified + .text + +foo: + asrl r2, r3, #0 + asrl r2, r3, #33 + asrl r1, r3, r5 + lsll r2, r4, #5 + lsll r2, r15, r5 + lsrl r2, r13, #5 + sqrshrl r2, r3, r3 + sqrshr r2, r2 + uqrshll r2, r3, r2 + uqshlgt r2, #32 + urshrlle r2, r3, r5 diff --git a/gas/testsuite/gas/arm/mve-shift.d b/gas/testsuite/gas/arm/mve-shift.d new file mode 100644 index 00000000000..be5cd4682f5 --- /dev/null +++ b/gas/testsuite/gas/arm/mve-shift.d @@ -0,0 +1,27 @@ +#name: Valid MVE shift instructions +#source: mve-shift.s +#as: -march=armv8.1-m.main+mve +#objdump: -dr --prefix-addresses --show-raw-insn -marmv8.1-m.main + +.*: +file format .*arm.* + +Disassembly of section .text: +0[0-9a-f]+ <[^>]+> ea52 136f asrl r2, r3, #5 +0[0-9a-f]+ <[^>]+> ea52 532d asrl r2, r3, r5 +0[0-9a-f]+ <[^>]+> ea52 134f lsll r2, r3, #5 +0[0-9a-f]+ <[^>]+> ea52 530d lsll r2, r3, r5 +0[0-9a-f]+ <[^>]+> ea52 135f lsrl r2, r3, #5 +0[0-9a-f]+ <[^>]+> ea53 532d sqrshrl r2, r3, r5 +0[0-9a-f]+ <[^>]+> ea52 5f2d sqrshr r2, r5 +0[0-9a-f]+ <[^>]+> ea53 137f sqshll r2, r3, #5 +0[0-9a-f]+ <[^>]+> ea52 1f7f sqshl r2, #5 +0[0-9a-f]+ <[^>]+> ea53 73ef srshrl r2, r3, #31 +0[0-9a-f]+ <[^>]+> ea52 7fef srshr r2, #31 +0[0-9a-f]+ <[^>]+> ea53 530d uqrshll r2, r3, r5 +0[0-9a-f]+ <[^>]+> ea52 5f0d uqrshl r2, r5 +0[0-9a-f]+ <[^>]+> ea53 73cf uqshll r2, r3, #31 +0[0-9a-f]+ <[^>]+> bfce itee gt +0[0-9a-f]+ <[^>]+> ea52 0f0f uqshlgt r2, #32 +0[0-9a-f]+ <[^>]+> ea53 031f urshrlle r2, r3, #32 +0[0-9a-f]+ <[^>]+> ea52 0f1f urshrle r2, #32 +#... diff --git a/gas/testsuite/gas/arm/mve-shift.s b/gas/testsuite/gas/arm/mve-shift.s new file mode 100644 index 00000000000..267e3fbb9ac --- /dev/null +++ b/gas/testsuite/gas/arm/mve-shift.s @@ -0,0 +1,21 @@ + .syntax unified + .text +foo: + asrl r2, r3, #5 + asrl r2, r3, r5 + lsll r2, r3, #5 + lsll r2, r3, r5 + lsrl r2, r3, #5 + sqrshrl r2, r3, r5 + sqrshr r2, r5 + sqshll r2, r3, #5 + sqshl r2, #5 + srshrl r2, r3, #31 + srshr r2, #31 + uqrshll r2, r3, r5 + uqrshl r2, r5 + uqshll r2, r3, #31 + itee gt + uqshlgt r2, #32 + urshrlle r2, r3, #32 + urshrle r2, #32 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 7f061c28d30..e6950acc17d 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,14 @@ +2019-05-21 Sudakshina Das + + * arm-dis.c (emun mve_instructions): Updated for new instructions. + (mve_opcodes): New instructions for asrl, lsll, lsrl, sqrshrl, + sqrshr, sqshl, sqshll, srshr, srshrl, uqrshll, uqrshl, uqshll, + uqshl, urshrl and urshr. + (is_mve_okay_in_it): Add new instructions to TRUE list. + (is_mve_unpredictable): Add cases for UNPRED_R13 and UNPRED_R15. + (print_insn_mve): Updated to accept new %j, + %m and %n patterns. + 2019-05-21 Faraz Shahbazker * mips-opc.c (mips_builtin_opcodes): Change source register diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 096b5715cab..ab99fb71872 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -264,6 +264,23 @@ enum mve_instructions MVE_VREV16, MVE_VREV32, MVE_VREV64, + MVE_LSLL, + MVE_LSLLI, + MVE_LSRL, + MVE_ASRL, + MVE_ASRLI, + MVE_SQRSHRL, + MVE_SQRSHR, + MVE_UQRSHL, + MVE_UQRSHLL, + MVE_UQSHL, + MVE_UQSHLL, + MVE_URSHRL, + MVE_URSHR, + MVE_SRSHRL, + MVE_SRSHR, + MVE_SQSHLL, + MVE_SQSHL, MVE_NONE }; @@ -2026,6 +2043,7 @@ static const struct opcode32 neon_opcodes[] = %d print addr mode of MVE vldr[bhw] and vstr[bhw] %u print 'U' (unsigned) or 'S' for various mve instructions %i print MVE predicate(s) for vpt and vpst + %j print a 5-bit immediate from hw2[14:12,7:6] %m print rounding mode for vcvt and vrint %n print vector comparison code for predicated instruction %s print size for various vcvt instructions @@ -2046,6 +2064,8 @@ static const struct opcode32 neon_opcodes[] = %F print as a MVE S register %Z as %<>r but r15 is ZR instead of PC and r13 is UNPREDICTABLE + + %S as %<>r but r15 or r13 is UNPREDICTABLE %s print size for vector predicate & non VMOV instructions %I print carry flag or not %i print immediate for vstr/vldr reg +/- imm @@ -3295,6 +3315,91 @@ static const struct mopcode32 mve_opcodes[] = 0xee011f40, 0xff811f70, "vsub%v.i%20-21s\t%13-15,22Q, %17-19,7Q, %0-3r"}, + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_ASRLI, + 0xea50012f, 0xfff1813f, + "asrl%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_ASRL, + 0xea50012d, 0xfff101ff, + "asrl%c\t%17-19l, %9-11h, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_LSLLI, + 0xea50010f, 0xfff1813f, + "lsll%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_LSLL, + 0xea50010d, 0xfff101ff, + "lsll%c\t%17-19l, %9-11h, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_LSRL, + 0xea50011f, 0xfff1813f, + "lsrl%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SQRSHRL, + 0xea51012d, 0xfff101ff, + "sqrshrl%c\t%17-19l, %9-11h, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SQRSHR, + 0xea500f2d, 0xfff00fff, + "sqrshr%c\t%16-19S, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SQSHLL, + 0xea51013f, 0xfff1813f, + "sqshll%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SQSHL, + 0xea500f3f, 0xfff08f3f, + "sqshl%c\t%16-19S, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SRSHRL, + 0xea51012f, 0xfff1813f, + "srshrl%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_SRSHR, + 0xea500f2f, 0xfff08f3f, + "srshr%c\t%16-19S, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_UQRSHLL, + 0xea51010d, 0xfff101ff, + "uqrshll%c\t%17-19l, %9-11h, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_UQRSHL, + 0xea500f0d, 0xfff00fff, + "uqrshl%c\t%16-19S, %12-15S"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_UQSHLL, + 0xea51010f, 0xfff1813f, + "uqshll%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_UQSHL, + 0xea500f0f, 0xfff08f3f, + "uqshl%c\t%16-19S, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_URSHRL, + 0xea51011f, 0xfff1813f, + "urshrl%c\t%17-19l, %9-11h, %j"}, + + {ARM_FEATURE_COPROC (FPU_MVE), + MVE_URSHR, + 0xea500f1f, 0xfff08f3f, + "urshr%c\t%16-19S, %j"}, + {ARM_FEATURE_CORE_LOW (0), MVE_NONE, 0x00000000, 0x00000000, 0} @@ -5169,6 +5274,23 @@ is_mve_okay_in_it (enum mve_instructions matched_insn) case MVE_VMOV2_VEC_LANE_TO_GP: case MVE_VMOV2_GP_TO_VEC_LANE: case MVE_VMOV_VEC_LANE_TO_GP: + case MVE_LSLL: + case MVE_LSLLI: + case MVE_LSRL: + case MVE_ASRL: + case MVE_ASRLI: + case MVE_SQRSHRL: + case MVE_SQRSHR: + case MVE_UQRSHL: + case MVE_UQRSHLL: + case MVE_UQSHL: + case MVE_UQSHLL: + case MVE_URSHRL: + case MVE_URSHR: + case MVE_SRSHRL: + case MVE_SRSHR: + case MVE_SQSHLL: + case MVE_SQSHL: return TRUE; default: return FALSE; @@ -5515,6 +5637,22 @@ is_mve_encoding_conflict (unsigned long given, else return FALSE; + case MVE_ASRLI: + case MVE_ASRL: + case MVE_LSLLI: + case MVE_LSLL: + case MVE_LSRL: + case MVE_SQRSHRL: + case MVE_SQSHLL: + case MVE_SRSHRL: + case MVE_UQRSHLL: + case MVE_UQSHLL: + case MVE_URSHRL: + if (arm_decode_field (given, 9, 11) == 0x7) + return TRUE; + else + return FALSE; + default: case MVE_VADD_FP_T1: case MVE_VADD_FP_T2: @@ -6490,6 +6628,34 @@ is_mve_unpredictable (unsigned long given, enum mve_instructions matched_insn, return FALSE; } + case MVE_LSLL: + case MVE_LSLLI: + case MVE_LSRL: + case MVE_ASRL: + case MVE_ASRLI: + case MVE_UQSHLL: + case MVE_UQRSHLL: + case MVE_URSHRL: + case MVE_SRSHRL: + case MVE_SQSHLL: + case MVE_SQRSHRL: + { + unsigned long gpr = arm_decode_field (given, 9, 11); + gpr = ((gpr << 1) | 1); + if (gpr == 0xd) + { + *unpredictable_code = UNPRED_R13; + return TRUE; + } + else if (gpr == 0xf) + { + *unpredictable_code = UNPRED_R15; + return TRUE; + } + + return FALSE; + } + default: return FALSE; } @@ -8983,6 +9149,15 @@ print_insn_mve (struct disassemble_info *info, long given) } break; + case 'j': + { + unsigned int imm5 = 0; + imm5 |= arm_decode_field (given, 6, 7); + imm5 |= (arm_decode_field (given, 12, 14) << 2); + func (stream, "#%u", (imm5 == 0) ? 32 : imm5); + } + break; + case 'n': print_vec_condition (info, given, insn->mve_op); break; @@ -9088,6 +9263,14 @@ print_insn_mve (struct disassemble_info *info, long given) else func (stream, "%s", arm_regnames[value]); break; + + case 'S': + if (value == 13 || value == 15) + is_unpredictable = TRUE; + else + func (stream, "%s", arm_regnames[value]); + break; + case 's': print_mve_size (info, value, -- 2.30.2