]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: rcpc3: Define address operand fields and inserter/extractors
authorVictor Do Nascimento <victor.donascimento@arm.com>
Fri, 5 Jan 2024 17:27:04 +0000 (17:27 +0000)
committerVictor Do Nascimento <victor.donascimento@arm.com>
Mon, 15 Jan 2024 13:11:48 +0000 (13:11 +0000)
Beyond the need to encode any registers involved in data transfer and
the address base register for load/stores, it is necessary to specify
the data register addressing mode and whether the address register is
to be pre/post-indexed, whereby loads may be post-indexed and stores
pre-indexed with write-back.

The use of a single bit to specify both the indexing mode and indexing
value requires a novel function be written to accommodate this for
address operand insertion in assembly and another for extraction in
disassembly, along with the definition of two insn fields for use with
these instructions.

This therefore defines the following functions:

  - aarch64_ins_rcpc3_addr_opt_offset
  - aarch64_ins_rcpc3_addr_offset
  - aarch64_ext_rcpc3_addr_opt_offset
  - aarch64_ext_rcpc3_addr_offset

It extends the `do_special_{encoding|decoding}' functions and defines
two rcpc3 instruction fields:

  - FLD_opc2
  - FLD_rcpc3_size

include/opcode/aarch64.h
opcodes/aarch64-asm.c
opcodes/aarch64-asm.h
opcodes/aarch64-dis.c
opcodes/aarch64-dis.h
opcodes/aarch64-opc.c
opcodes/aarch64-opc.h

index 3c1f522b813f34081ed8b47feeb375a7f9371f9c..85e28d9d2876522a07f30761309058d1f232ad14 100644 (file)
@@ -1282,7 +1282,9 @@ extern const aarch64_opcode aarch64_opcode_table[];
 #define F_OPD_NARROW (1ULL << 33)
 /* For the instruction with size[22:23] field.  */
 #define F_OPD_SIZE (1ULL << 34)
-/* Next bit is 35.  */
+/* RCPC3 instruction has the field of 'size'.  */
+#define F_RCPC3_SIZE (1ULL << 35)
+/* Next bit is 36.  */
 
 /* Instruction constraints.  */
 /* This instruction has a predication constraint on the instruction at PC+4.  */
@@ -1350,7 +1352,7 @@ opcode_has_special_coder (const aarch64_opcode *opcode)
 {
   return (opcode->flags & (F_SF | F_LSE_SZ | F_SIZEQ | F_FPTYPE | F_SSIZE | F_T
          | F_GPRSIZE_IN_Q | F_LDS_SIZE | F_MISC | F_N | F_COND
-         | F_OPD_SIZE)) != 0;
+         | F_OPD_SIZE | F_RCPC3_SIZE)) != 0;
 }
 \f
 struct aarch64_name_value_pair
index 4d0b13e4c5aa33b8192a298990f8ce6ca3cd8ae8..565c4b10559d1800c39f118d225088da5c1c3e36 100644 (file)
@@ -702,6 +702,24 @@ aarch64_ins_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return true;
 }
 
+/* Encode the address operand for e.g.
+     stlur <Xt>, [<Xn|SP>{, <amount>}].  */
+bool
+aarch64_ins_rcpc3_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                              const aarch64_opnd_info *info, aarch64_insn *code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  /* Rn */
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+
+  /* simm9 */
+  int imm = info->addr.offset.imm;
+  insert_field (self->fields[1], code, imm, 0);
+
+  return true;
+}
+
 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!.  */
 bool
 aarch64_ins_addr_simm (const aarch64_operand *self,
@@ -736,6 +754,28 @@ aarch64_ins_addr_simm (const aarch64_operand *self,
   return true;
 }
 
+/* Encode the address operand, potentially offset by the load/store ammount,
+   e.g. LDIAPP <Xt>, <Xt2> [<Xn|SP>, #<simm>]
+   and  STILP  <Xt>, <Xt2> [<Xn|SP>], #<simm>.*/
+bool
+aarch64_ins_rcpc3_addr_opt_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                                  const aarch64_opnd_info *info,
+                                  aarch64_insn *code,
+                                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int imm;
+
+  /* Rn */
+  insert_field (FLD_Rn, code, info->addr.base_regno, 0);
+  /* simm */
+  imm = info->addr.offset.imm;
+  if (!imm)
+    insert_field (FLD_opc2, code, 1, 0);
+
+  return true;
+}
+
 /* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}].  */
 bool
 aarch64_ins_addr_simm10 (const aarch64_operand *self,
@@ -1943,6 +1983,22 @@ do_special_encoding (struct aarch64_inst *inst)
        ? 1 : 0;
       insert_field (FLD_lse_sz, &inst->value, value, 0);
     }
+  if (inst->opcode->flags & F_RCPC3_SIZE)
+    {
+      switch (inst->operands[0].qualifier)
+       {
+       case AARCH64_OPND_QLF_W: value = 2; break;
+       case AARCH64_OPND_QLF_X: value = 3; break;
+       case AARCH64_OPND_QLF_S_B: value = 0; break;
+       case AARCH64_OPND_QLF_S_H: value = 1; break;
+       case AARCH64_OPND_QLF_S_S: value = 2; break;
+       case AARCH64_OPND_QLF_S_D: value = 3; break;
+       case AARCH64_OPND_QLF_S_Q: value = 0; break;
+       default: return;
+       }
+      insert_field (FLD_rcpc3_size, &inst->value, value, 0);
+    }
+
   if (inst->opcode->flags & F_SIZEQ)
     encode_sizeq (inst);
   if (inst->opcode->flags & F_FPTYPE)
index e48bf0db8a86149155e325923f6644bb90410ccb..c6dde1c4d1b16f63665e12d0f9217481d8cbfe3b 100644 (file)
@@ -115,6 +115,8 @@ AARCH64_DECL_OPD_INSERTER (ins_imm_rotate2);
 AARCH64_DECL_OPD_INSERTER (ins_x0_to_x30);
 AARCH64_DECL_OPD_INSERTER (ins_simple_index);
 AARCH64_DECL_OPD_INSERTER (ins_plain_shrimm);
+AARCH64_DECL_OPD_INSERTER (ins_rcpc3_addr_opt_offset);
+AARCH64_DECL_OPD_INSERTER (ins_rcpc3_addr_offset);
 
 #undef AARCH64_DECL_OPD_INSERTER
 
index 2896a119f353e4f737ab70ffd7701597b1223989..f63b74706f6da606d3df848bd722e5c2ae3f3ecb 100644 (file)
@@ -1032,6 +1032,70 @@ aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return true;
 }
 
+/* Decode the address operand for rcpc3 instructions with optional load/store
+   datasize offset, e.g. STILPP <Xs>, <Xt>, [<Xn|SP>{,#-16}]! and
+   LIDAP <Xs>, <Xt>, [<Xn|SP>]{,#-16}.  */
+bool
+aarch64_ext_rcpc3_addr_opt_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                                  aarch64_opnd_info *info,
+                                  aarch64_insn code,
+                                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                                  aarch64_operand_error *err ATTRIBUTE_UNUSED)
+{
+  info->addr.base_regno = extract_field (FLD_Rn, code, 0);
+  if (!extract_field (FLD_opc2, code, 0))
+    {
+      info->addr.writeback = 1;
+
+      enum aarch64_opnd type;
+      for (int i = 0; i < AARCH64_MAX_OPND_NUM; i++)
+       {
+         aarch64_opnd_info opnd = info[i];
+         type = opnd.type;
+         if (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS)
+           break;
+       }
+
+      assert (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS);
+      int offset = calc_ldst_datasize (inst->operands);
+
+      switch (type)
+       {
+       case AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB:
+       case AARCH64_OPND_RCPC3_ADDR_PREIND_WB:
+         info->addr.offset.imm = -offset;
+         info->addr.preind = 1;
+         break;
+       case AARCH64_OPND_RCPC3_ADDR_OPT_POSTIND:
+       case AARCH64_OPND_RCPC3_ADDR_POSTIND:
+         info->addr.offset.imm = offset;
+         info->addr.postind = 1;
+         break;
+       default:
+         return false;
+       }
+    }
+  return true;
+}
+
+bool
+aarch64_ext_rcpc3_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                              aarch64_opnd_info *info,
+                              aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->qualifier = get_expected_qualifier (inst, info->idx);
+
+  /* Rn */
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+
+  /* simm9 */
+  aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]);
+  info->addr.offset.imm = sign_extend (imm, 8);
+  return true;
+}
+
 /* Decode the address operand for e.g.
      stlur <Xt>, [<Xn|SP>{, <amount>}].  */
 bool
@@ -2579,6 +2643,26 @@ do_special_decoding (aarch64_inst *inst)
       value = extract_field (FLD_lse_sz, inst->value, 0);
       inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
     }
+  /* rcpc3 'size' field.  */
+  if (inst->opcode->flags & F_RCPC3_SIZE)
+    {
+      value = extract_field (FLD_rcpc3_size, inst->value, 0);
+      for (int i = 0;
+          aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS;
+          i++)
+       {
+         if (aarch64_operands[inst->operands[i].type].op_class
+             == AARCH64_OPND_CLASS_INT_REG)
+           inst->operands[i].qualifier = get_greg_qualifier_from_value (value & 1);
+         else if (aarch64_operands[inst->operands[i].type].op_class
+             == AARCH64_OPND_CLASS_FP_REG)
+           {
+             value += (extract_field (FLD_opc1, inst->value, 0) << 2);
+             inst->operands[i].qualifier = get_sreg_qualifier_from_value (value);
+           }
+       }
+    }
+
   /* size:Q fields.  */
   if (inst->opcode->flags & F_SIZEQ)
     return decode_sizeq (inst);
index 48bebfea1e146e71d5fcae67c6558a35fe198e3f..6ed6776b679050ca6581b6a0f9534037989db889 100644 (file)
@@ -140,6 +140,9 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_x0_to_x30);
 AARCH64_DECL_OPD_EXTRACTOR (ext_simple_index);
 AARCH64_DECL_OPD_EXTRACTOR (ext_plain_shrimm);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist_zt);
+AARCH64_DECL_OPD_EXTRACTOR (ext_rcpc3_addr_opt_offset);
+AARCH64_DECL_OPD_EXTRACTOR (ext_rcpc3_addr_offset);
+
 
 #undef AARCH64_DECL_OPD_EXTRACTOR
 
index 091df2c54f3fcc614c74cb7b20e633a482183bbe..9a72d30268f0cbe66af44819a9a2a6f9f5867443 100644 (file)
@@ -410,6 +410,8 @@ const aarch64_field fields[] =
     {  6,  2 }, /* ZAn_2: name of the 2bit encoded ZA tile.  */
     {  5,  3 }, /* ZAn_3: name of the 3bit encoded ZA tile.  */
     {  6,  1 }, /* ZAn: name of the bit encoded ZA tile.  */
+    { 12,  4 },        /* opc2: in rcpc3 ld/st inst deciding the pre/post-index.  */
+    { 30,  2 },        /* rcpc3_size: in rcpc3 ld/st, field controls Rt/Rt2 width.  */
 };
 
 enum aarch64_operand_class
index 587775152e3ef26cb3d09e138eda2791b95cb5d9..4e781f000cc38c12058530e5851b08083d42af52 100644 (file)
@@ -216,7 +216,9 @@ enum aarch64_field_kind
   FLD_ol,
   FLD_ZAn_2,
   FLD_ZAn_3,
-  FLD_ZAn
+  FLD_ZAn,
+  FLD_opc2,
+  FLD_rcpc3_size,
 };
 
 /* Field description.  */