This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [binutils, Arm] Add support for conditional instructions in Armv8.1-M Mainline


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e39c1607a2df3a97bf7b70bef6de5b7a2db55eea

commit e39c1607a2df3a97bf7b70bef6de5b7a2db55eea
Author: Sudakshina Das <sudi.das@arm.com>
Date:   Tue May 21 18:15:13 2019 +0100

    [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  <sudi.das@arm.com>
    
    	* 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  <sudi.das@arm.com>
    
    	* 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 %<bitfield>c and %<bitfield>C.

Diff:
---
 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(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 34fee55..fc1fb65 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,21 @@
 2019-05-21  Sudakshina Das  <sudi.das@arm.com>
 
+	* 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  <sudi.das@arm.com>
+
 	* config/tc-arm.c (operand_parse_code): New entries for
 	OP_RRnpcsp_I32 (register or integer operands).
 	(do_mve_scalar_shift): New.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 8826119..b657828 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 0000000..d953f9a
--- /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 0000000..47eafcf
--- /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 0000000..a7d98ed
--- /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 0000000..171da37
--- /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 0000000..f192d5f
--- /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 e6950ac..c336a1a 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,5 +1,15 @@
 2019-05-21  Sudakshina Das  <sudi.das@arm.com>
 
+	* 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 %<bitfield>c and %<bitfield>C.
+
+2019-05-21  Sudakshina Das  <sudi.das@arm.com>
+
 	* 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,
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index ab99fb7..ad65ffa 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[] =
    %<bitfield>r		print as an ARM register
    %<bitfield>d		print the bitfield in decimal
    %<bitfield>A		print accumulate or not
+   %<bitfield>c		print bitfield as a condition code
+   %<bitfield>C		print bitfield as an inverted condition code
    %<bitfield>Q		print as a MVE Q register
    %<bitfield>F		print as a MVE S register
    %<bitfield>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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]