]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[Morello] Branch and return instructions
authorSiddhesh Poyarekar <siddesh.poyarekar@arm.com>
Fri, 11 Sep 2020 03:48:06 +0000 (09:18 +0530)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:53:20 +0000 (15:53 -0700)
- BLR, BLRR, BLRS, BR, BRR, BRS, BX.
- RET, RETR, RETS.

Disassembly note: RET with capability is always disassembled with the
register name even if it is the default register, i.e. C30.  This is
to make it visually simpler to differentiate between the A64 and
Morello RET instructions.

gas/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* config/tc-aarch64.c (process_omitted_operand): Identify Can.
(parse_operands): Add CST_REG, Cam_SP
and A64C_IMMV4.
* testsuite/gas/aarch64/morello_insn.s: Add tests.
* testsuite/gas/aarch64/morello_insn.d: Likewise.
* testsuite/gas/aarch64/morello_insn-c64.d: Likewise.

include/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* opcode/aarch64.h (aarch64_opnd): Add CST_REG, Cam_SP
and A64C_IMMV4.
(aarch64_insn_class): Add br_sealed.

opcodes/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* aarch64-dis.c (aarch64_ext_a64c_immv): New function.
(aarch64_ext_regno): Set PRESENT flag for A64 RET.
* aarch64-dis.h (aarch64_ext_a64c_immv): New function.
* aarch64-opc.c (operand_general_constraint_met_p): Add
A64C_IMMV4.  Remove ATTRIBUTE_UNUSED.  Reject A64 RET without
operand when in C64.
(aarch64_match_operands_constraint): Remove ATTRIBUTE_UNUSED.
(aarch64_print_operand): Add A64C_IMMV4, Cam_SP and CST_REG.
* aarch64-tbl.h (QL1_A64C_CA, QL3_A64C_CA_CA_CA): New macros.
(aarch64_opcode_table): New instructions.
(AARCH64_OPERANDS): New operands.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc-2.c: Regenerate.

12 files changed:
gas/ChangeLog
gas/config/tc-aarch64.c
gas/testsuite/gas/aarch64/morello_insn-c64.d
gas/testsuite/gas/aarch64/morello_insn.d
gas/testsuite/gas/aarch64/morello_insn.s
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-dis.c
opcodes/aarch64-dis.h
opcodes/aarch64-opc.c
opcodes/aarch64-tbl.h

index b2ac69d5d881765437e61d733660df5f13ac6d90..5404bc99d7e189047e45e568ec3f6b313074063f 100644 (file)
@@ -1,3 +1,12 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * config/tc-aarch64.c (process_omitted_operand): Identify Can.
+       (parse_operands): Add CST_REG, Cam_SP
+       and A64C_IMMV4.
+       * testsuite/gas/aarch64/morello_insn.s: Add tests.
+       * testsuite/gas/aarch64/morello_insn.d: Likewise.
+       * testsuite/gas/aarch64/morello_insn-c64.d: Likewise.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * config/tc-aarch64.c (parse_operands): Add A64C_IMM8.
index acff6fcbc1931fea3c0a9c16eed84c92e1e0d607..38732f78f8b3031e5c56fb44380fe6996cd08c24 100644 (file)
@@ -5998,6 +5998,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
 
   switch (type)
     {
+    case AARCH64_OPND_Can:
     case AARCH64_OPND_Rd:
     case AARCH64_OPND_Rn:
     case AARCH64_OPND_Rm:
@@ -6654,6 +6655,20 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          info->qualifier = AARCH64_OPND_QLF_CA;
          break;
 
+       case AARCH64_OPND_A64C_CST_REG:
+         po_reg_or_fail (REG_TYPE_CA_N);
+         if (val != 29
+             && (opcode->iclass == br_sealed))
+           {
+             set_fatal_syntax_error
+               (_(N_ ("Capability register c29 expected")));
+             goto failure;
+           }
+         info->reg.regno = val;
+         info->qualifier = AARCH64_OPND_QLF_CA;
+         break;
+
+       case AARCH64_OPND_Cam_SP:
        case AARCH64_OPND_Can_SP:
        case AARCH64_OPND_Cad_SP:
          po_reg_or_fail (REG_TYPE_CA_N_SP);
@@ -6775,6 +6790,16 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          info->imm.value = val;
          break;
 
+       case AARCH64_OPND_A64C_IMMV4:
+         po_imm_nc_or_fail ();
+         if (val != 4)
+           {
+             set_fatal_syntax_error (_("immediate #4 expected"));
+             goto failure;
+           }
+         info->imm.value = 4;
+         break;
+
        case AARCH64_OPND_IMM0:
          po_imm_nc_or_fail ();
          if (val != 0)
index adab33ec2eb08b9fe410a2259ba1acd04392c2ba..ec8f54de1fedfdee7b5701df3e1fa9cec84f5600 100644 (file)
@@ -8,6 +8,17 @@
 Disassembly of section \.text:
 
 .* <.text>:
+.*:    c2c273e0        bx      #4
+.*:    c2c253c0        ret     c30
+.*:    c2c23280        blr     c20
+.*:    c2c23283        blrr    c20
+.*:    c2c23282        blrs    c20
+.*:    c2c21280        br      c20
+.*:    c2c21283        brr     c20
+.*:    c2c21282        brs     c20
+.*:    c2c25280        ret     c20
+.*:    c2c25283        retr    c20
+.*:    c2c25282        rets    c20
 .*:    c2c1d26b        mov     c11, c19
 .*:    c2c1d26b        mov     c11, c19
 .*:    c2c1d3eb        mov     c11, csp
@@ -77,6 +88,9 @@ Disassembly of section \.text:
 .*:    c2d92be7        bicflgs c7, csp, x25
 .*:    c2d928df        bicflgs csp, c6, x25
 .*:    c2d92bff        bicflgs csp, csp, x25
+.*:    c2c4a440        blrs    c29, c2, c4
+.*:    c2c48440        brs     c29, c2, c4
+.*:    c2c4c440        rets    c29, c2, c4
 .*:    c2a4e131        add     c17, c9, x4, sxtx
 .*:    c2a4f131        add     c17, c9, x4, sxtx #4
 .*:    c2a4d131        add     c17, c9, w4, sxtw #4
index aff1b3de897e5ec40d6ba96b2d1db2da962bb0a2..7ad902602732f3032a33f67e9d1feb3c0e5829b2 100644 (file)
@@ -7,6 +7,17 @@
 Disassembly of section \.text:
 
 .* <.text>:
+.*:    c2c273e0        bx      #4
+.*:    d65f03c0        ret
+.*:    c2c23280        blr     c20
+.*:    c2c23283        blrr    c20
+.*:    c2c23282        blrs    c20
+.*:    c2c21280        br      c20
+.*:    c2c21283        brr     c20
+.*:    c2c21282        brs     c20
+.*:    c2c25280        ret     c20
+.*:    c2c25283        retr    c20
+.*:    c2c25282        rets    c20
 .*:    c2c1d26b        mov     c11, c19
 .*:    c2c1d26b        mov     c11, c19
 .*:    c2c1d3eb        mov     c11, csp
@@ -76,6 +87,9 @@ Disassembly of section \.text:
 .*:    c2d92be7        bicflgs c7, csp, x25
 .*:    c2d928df        bicflgs csp, c6, x25
 .*:    c2d92bff        bicflgs csp, csp, x25
+.*:    c2c4a440        blrs    c29, c2, c4
+.*:    c2c48440        brs     c29, c2, c4
+.*:    c2c4c440        rets    c29, c2, c4
 .*:    c2a4e131        add     c17, c9, x4, sxtx
 .*:    c2a4f131        add     c17, c9, x4, sxtx #4
 .*:    c2a4d131        add     c17, c9, w4, sxtw #4
index d0af5e2af4f3e6068c794d24dc881565307d0ac7..bff8d4dab16f5a007d6c01d4881f598ea01905f1 100644 (file)
@@ -1,3 +1,17 @@
+// Zero/one operands
+
+bx #4
+ret
+
+// Single operand (n)
+
+       .macro morello_jump cn
+         .irp op, blr, blrr, blrs, br, brr, brs, ret, retr, rets
+           \op    \cn
+         .endr
+       .endm
+morello_jump c20
+
 // Two operands (dn).
 
        .macro morello_cspcsp cdsp, cnsp
@@ -53,6 +67,13 @@ morello_cspcspx c7, csp, x25
 morello_cspcspx csp, c6, x25
 morello_cspcspx csp, csp, x25
 
+       .macro morello_jump_sealed cn, cm
+         .irp op, blrs, brs, rets
+           \op   c29, \cn, \cm
+         .endr
+       .endm
+morello_jump_sealed c2, c4
+
 // Four operands (dnmi)
 
        .macro morello_add_scalar cspd, cspn, rm
index 675b28d9782d0ccf84d53219c4feb89b4dafa814..5a04de89041172345704d9cce29b9e9f860017e2 100644 (file)
@@ -1,3 +1,9 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * opcode/aarch64.h (aarch64_opnd): Add CST_REG, Cam_SP
+       and A64C_IMMV4.
+       (aarch64_insn_class): Add br_sealed.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * opcode/aarch64.h (aarch64_opnd): Add A64C_IMM8.
index bd865bc6b25b3f4ebfac1be068609ac562dd53fd..ab4cb09f54787effb55d92c2bd3e58c20390310e 100644 (file)
@@ -514,7 +514,11 @@ enum aarch64_opnd
   AARCH64_OPND_Cad_SP,          /* Capability register or Cap SP as
                                   destination.  */
   AARCH64_OPND_Can_SP,         /* Capability register or Cap SP as source. */
+  AARCH64_OPND_Cam_SP,         /* Capability register or Cap SP as source. */
   AARCH64_OPND_A64C_Rm_EXT,    /* Integer Xm extended.  */
+  AARCH64_OPND_A64C_IMMV4,     /* Immediate value #4 for BX.  */
+  AARCH64_OPND_A64C_CST_REG,   /* Constant capability register c29 for
+                                  BRS/BLRS.  */
   AARCH64_OPND_A64C_AIMM,      /* Add immediate for A64C ADD/SUB.  */
   AARCH64_OPND_A64C_IMM8,      /* IMM8 for BICFLGS.  */
 };
@@ -712,6 +716,7 @@ enum aarch64_insn_class
   dotproduct,
   bfloat16,
   a64c,
+  br_sealed,
 };
 
 /* Opcode enumerators.  */
index 5a2896b74d1efbecf211f01b39453169d3c92f82..41226c50d4fea1dba7acdc345bfe7e0f6bd24a26 100644 (file)
@@ -1,3 +1,20 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * aarch64-dis.c (aarch64_ext_a64c_immv): New function.
+       (aarch64_ext_regno): Set PRESENT flag for A64 RET.
+       * aarch64-dis.h (aarch64_ext_a64c_immv): New function.
+       * aarch64-opc.c (operand_general_constraint_met_p): Add
+       A64C_IMMV4.  Remove ATTRIBUTE_UNUSED.  Reject A64 RET without
+       operand when in C64.
+       (aarch64_match_operands_constraint): Remove ATTRIBUTE_UNUSED.
+       (aarch64_print_operand): Add A64C_IMMV4, Cam_SP and CST_REG.
+       * aarch64-tbl.h (QL1_A64C_CA, QL3_A64C_CA_CA_CA): New macros.
+       (aarch64_opcode_table): New instructions.
+       (AARCH64_OPERANDS): New operands.
+       * aarch64-asm-2.c: Regenerate.
+       * aarch64-dis-2.c: Regenerate.
+       * aarch64-opc-2.c: Regenerate.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * aarch64-opc.c (fields): Add a64c_imm8.
index 96e6b8533bb82dcbe37208277c00aa5dc8f1ff66..3f02c02ce5a94b731d4a5633b3266ec6f95933ba 100644 (file)
@@ -278,6 +278,10 @@ aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
   if (aarch64_get_operand_class (info->type) == AARCH64_OPND_CLASS_CAP_REG)
     info->qualifier = AARCH64_OPND_QLF_CA;
 
+  /* Allow disassembly of A64 RET when encountered in C64 code.  */
+  if (inst->opcode->iclass == branch_reg)
+    info->present = 1;
+
   return true;
 }
 
@@ -698,6 +702,29 @@ aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
   return true;
 }
 
+/* Set immediate value #4 when decoding for e.g. BX.  */
+bool
+aarch64_ext_a64c_immv (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                     aarch64_opnd_info *info,
+                     const aarch64_insn code ATTRIBUTE_UNUSED,
+                     const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                     aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  if (info->type == AARCH64_OPND_A64C_IMMV4)
+    {
+      info->imm.value = 4;
+      return true;
+    }
+  if (info->type == AARCH64_OPND_A64C_CST_REG
+      && (inst->opcode->iclass == br_sealed))
+    {
+      info->reg.regno = 29;
+      return true;
+    }
+
+  return false;
+}
+
 /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}.  */
 bool
 aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
index 8508b1b0c6bba802610d346749c9d0b0dc16ee3a..551c5369fa3b91e913a9d28290ce740f9770e5f0 100644 (file)
@@ -132,6 +132,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_imm_rotate1);
 AARCH64_DECL_OPD_EXTRACTOR (ext_imm_rotate2);
 AARCH64_DECL_OPD_EXTRACTOR (ext_x0_to_x30);
 AARCH64_DECL_OPD_EXTRACTOR (ext_a64c_aimm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_a64c_immv);
 
 #undef AARCH64_DECL_OPD_EXTRACTOR
 
index b23da806ed6e2cbb9b3d2817cb0b888a4a6f0517..365345c1db17d8848b624c45c28259686bc2332e 100644 (file)
@@ -1476,7 +1476,8 @@ set_other_error (aarch64_operand_error *mismatch_detail, int idx,
    represent an error.  */
 
 static int
-operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
+operand_general_constraint_met_p (aarch64_feature_set features,
+                                 const aarch64_opnd_info *opnds, int idx,
                                  enum aarch64_opnd type,
                                  const aarch64_opcode *opcode,
                                  aarch64_operand_error *mismatch_detail)
@@ -1545,6 +1546,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        default:
          break;
        }
+      /* Reject A64 RET with default operand when in C64 mode.  */
+      if (opcode->iclass == branch_reg
+         && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64)
+         && !opnd->present)
+       {
+         set_other_error (mismatch_detail, idx,
+                          _("capability register expected"));
+         return 0;
+       }
       break;
 
     case AARCH64_OPND_CLASS_SVE_REG:
@@ -2269,6 +2279,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          }
          break;
 
+       case AARCH64_OPND_A64C_IMMV4:
+         if (opnd->imm.value != 4)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("immediate #4 expected"));
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_IMM0:
        case AARCH64_OPND_FPIMM0:
          if (opnd->imm.value != 0)
@@ -2762,8 +2781,8 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
    Un-determined operand qualifiers may get established during the process.  */
 
 int
-aarch64_match_operands_constraint (aarch64_feature_set features
-                                  ATTRIBUTE_UNUSED, aarch64_inst *inst,
+aarch64_match_operands_constraint (aarch64_feature_set features,
+                                  aarch64_inst *inst,
                                   aarch64_operand_error *mismatch_detail)
 {
   int i;
@@ -2853,7 +2872,7 @@ aarch64_match_operands_constraint (aarch64_feature_set features
          DEBUG_TRACE ("skip the incomplete operand %d", i);
          continue;
        }
-      if (operand_general_constraint_met_p (inst->operands, i, type,
+      if (operand_general_constraint_met_p (features, inst->operands, i, type,
                                            inst->opcode,
                                            mismatch_detail) == 0)
        {
@@ -3514,6 +3533,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
       break;
 
+    case AARCH64_OPND_A64C_IMMV4:
     case AARCH64_OPND_A64C_IMM8:
     case AARCH64_OPND_IDX:
     case AARCH64_OPND_MASK:
@@ -3978,9 +3998,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_Cad_SP:
     case AARCH64_OPND_Can_SP:
+    case AARCH64_OPND_Cam_SP:
       snprintf (buf, size, "%s", get_cap_reg_name (opnd->reg.regno, 1));
       break;
 
+    case AARCH64_OPND_A64C_CST_REG:
     case AARCH64_OPND_Cat:
     case AARCH64_OPND_Cat2:
     case AARCH64_OPND_Can:
index bba48c1cd553eee9941c5b90e2e0ae8fb7e116cc..813111c4afff2e33b428b348023f8a7b40069183 100644 (file)
   QLF3(V_4S, V_8H, S_H),       \
 }
 
+#define QL1_A64C_CA            \
+{                              \
+  QLF1(CA),                    \
+}
+
 #define QL2_A64C_CA_CA         \
 {                              \
   QLF2(CA, CA),                        \
   QLF3(CA, CA, X),             \
 }
 
+#define QL3_A64C_CA_CA_CA      \
+{                              \
+  QLF3(CA, CA, CA),            \
+}
 \f
 /* Opcode table.  */
 
@@ -4043,6 +4052,19 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   A64C_INSN ("sub", 0x02800000, 0xff800000, a64c, 0, OP3 (Cad_SP, Can_SP, A64C_AIMM), QL3_A64C_CA_CA_NIL, 0),
   A64C_INSN ("bicflgs", 0xc2e00000, 0xffe01c00, a64c, 0, OP3 (Cad_SP, Can_SP, A64C_IMM8), QL3_A64C_CA_CA_NIL, 0),
   A64C_INSN ("bicflgs", 0xc2c02800, 0xffe0fc00, a64c, 0, OP3 (Cad_SP, Can_SP, Rm), QL3_A64C_CA_CA_X, 0),
+  A64C_INSN ("blr", 0xc2c23000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("blrr", 0xc2c23003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("blrs", 0xc2c23002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("blrs", 0xc2c0a400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0),
+  A64C_INSN ("br", 0xc2c21000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("brr", 0xc2c21003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("brs", 0xc2c21002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("brs", 0xc2c08400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0),
+  A64C_INSN ("bx", 0xc2c273e0, 0xffffffff, a64c, 0, OP1 (A64C_IMMV4), {}, 0),
+  A64C_INSN ("ret", 0xc2c25000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, F_OPD0_OPT | F_DEFAULT (30)),
+  A64C_INSN ("retr", 0xc2c25003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("rets", 0xc2c25002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0),
+  A64C_INSN ("rets", 0xc2c0c400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0),
   /* TME Instructions.  */
   _TME_INSN ("tstart", 0xd5233060, 0xffffffe0, 0, 0, OP1 (Rd), QL_I1X, 0),
   _TME_INSN ("tcommit", 0xd503307f, 0xffffffff, 0, 0, OP0 (), {}, 0),
@@ -5969,8 +5991,13 @@ const struct aarch64_opcode aarch64_opcode_table[] =
       "a Capability register or a capability stack pointer register")  \
     Y(CAP_REG, regno, "Can_SP", OPD_F_MAYBE_CSP, F(FLD_Can),           \
       "a Capability register or a capability stack pointer register")  \
+    Y(CAP_REG, regno, "Cam_SP", OPD_F_MAYBE_CSP, F(FLD_Cam),           \
+      "a Capability register or a capability stack pointer register")  \
     Y(MODIFIED_REG, reg_extended, "A64C_Rm_EXT", 0, F(),               \
       "an integer register with extension")                            \
+    X(IMMEDIATE, 0, ext_a64c_immv, "A64C_IMMV4", 0, F(), "4")          \
+    X(CAP_REG, 0, ext_a64c_immv, "A64C_CST_REG", 0, F(),               \
+      "capability register c29")                                       \
     X(IMMEDIATE, ins_aimm, ext_a64c_aimm, "A64C_AIMM", 0,              \
       F(FLD_a64c_shift_ai,FLD_imm12),                                  \
       "a 12-bit unsigned immediate with optional left shift of 12 bits")\