RISC-V: Prefetch hint instructions and operand set
authorTsukasa OI <research_trasio@irq.a4lg.com>
Tue, 11 Jan 2022 10:14:02 +0000 (19:14 +0900)
committerNelson Chu <nelson.chu@sifive.com>
Fri, 18 Mar 2022 07:32:16 +0000 (15:32 +0800)
This commit adds 'Zicbop' hint instructions.

bfd/ChangeLog:

* elfxx-riscv.c (riscv_multi_subset_supports): Add handling for
new instruction class.

gas/ChangeLog:

* config/tc-riscv.c (riscv_ip): Add handling for new operand
type 'f' (32-byte aligned pseudo S-type immediate for prefetch
hints).
(validate_riscv_insn): Likewise.

include/ChangeLog:

* opcode/riscv-opc.h (MATCH_PREFETCH_I, MASK_PREFETCH_I,
MATCH_PREFETCH_R, MASK_PREFETCH_R, MATCH_PREFETCH_W,
MASK_PREFETCH_W): New macros.
* opcode/riscv.h (enum riscv_insn_class): Add new instruction
class INSN_CLASS_ZICBOP.

opcodes/ChangeLog:

* riscv-dis.c (print_insn_args): Add handling for new operand
type.
* riscv-opc.c (riscv_opcodes): Add prefetch hint instructions.

bfd/elfxx-riscv.c
gas/config/tc-riscv.c
gas/testsuite/gas/riscv/zicbop-fail.d [new file with mode: 0644]
gas/testsuite/gas/riscv/zicbop-fail.l [new file with mode: 0644]
gas/testsuite/gas/riscv/zicbop-fail.s [new file with mode: 0644]
gas/testsuite/gas/riscv/zicbop.d [new file with mode: 0644]
gas/testsuite/gas/riscv/zicbop.s [new file with mode: 0644]
include/opcode/riscv-opc.h
include/opcode/riscv.h
opcodes/riscv-dis.c
opcodes/riscv-opc.c

index 2915b74dd0f6e7f2a1a3860cdc29b39ac2b388a0..185bab7d8192aacb4b269f22a3de32fe1a3d71cf 100644 (file)
@@ -1172,6 +1172,7 @@ static struct riscv_supported_ext riscv_supported_std_ext[] =
 
 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
 {
+  {"zicbop",           ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
   {"zicsr",            ISA_SPEC_CLASS_20191213,        2, 0,  0 },
   {"zicsr",            ISA_SPEC_CLASS_20190608,        2, 0,  0 },
   {"zifencei",         ISA_SPEC_CLASS_20191213,        2, 0,  0 },
@@ -2316,6 +2317,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
     {
     case INSN_CLASS_I:
       return riscv_subset_supports (rps, "i");
+    case INSN_CLASS_ZICBOP:
+      return riscv_subset_supports (rps, "zicbop");
     case INSN_CLASS_ZICSR:
       return riscv_subset_supports (rps, "zicsr");
     case INSN_CLASS_ZIFENCEI:
index 9cc0abfda8811d8915dcc620afe17e4606b1c30c..bb5f6e4aedd6f4fb369365d398c7b28ec4d256bb 100644 (file)
@@ -1179,6 +1179,7 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
        case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
        case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break;
        case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break;
+       case 'f': /* Fall through.  */
        case 'q': used_bits |= ENCODE_STYPE_IMM (-1U); break;
        case 'u': used_bits |= ENCODE_UTYPE_IMM (-1U); break;
        case 'z': break; /* Zero immediate.  */
@@ -3191,6 +3192,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
              imm_expr->X_op = O_absent;
              continue;
 
+           case 'f': /* Prefetch offset, pseudo S-type but lower 5-bits zero.  */
+             if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
+               continue;
+             my_getExpression (imm_expr, asarg);
+             check_absolute_expr (ip, imm_expr, false);
+             if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
+                 || imm_expr->X_add_number >= (signed) RISCV_IMM_REACH / 2
+                 || imm_expr->X_add_number < -(signed) RISCV_IMM_REACH / 2)
+               as_bad (_("improper prefetch offset (%ld)"),
+                       (long) imm_expr->X_add_number);
+             ip->insn_opcode |=
+               ENCODE_STYPE_IMM ((unsigned) (imm_expr->X_add_number) &
+                                 ~ 0x1fU);
+             imm_expr->X_op = O_absent;
+             asarg = expr_end;
+             continue;
+
            default:
            unknown_riscv_ip_operand:
              as_fatal (_("internal: unknown argument type `%s'"),
diff --git a/gas/testsuite/gas/riscv/zicbop-fail.d b/gas/testsuite/gas/riscv/zicbop-fail.d
new file mode 100644 (file)
index 0000000..d734c7d
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv64g_zicbop
+#source: zicbop-fail.s
+#error_output: zicbop-fail.l
diff --git a/gas/testsuite/gas/riscv/zicbop-fail.l b/gas/testsuite/gas/riscv/zicbop-fail.l
new file mode 100644 (file)
index 0000000..4b5d5fc
--- /dev/null
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*: Error: improper prefetch offset \(2048\)
+.*: Error: improper prefetch offset \(-2080\)
+.*: Error: improper prefetch offset \(255\)
diff --git a/gas/testsuite/gas/riscv/zicbop-fail.s b/gas/testsuite/gas/riscv/zicbop-fail.s
new file mode 100644 (file)
index 0000000..0353c5f
--- /dev/null
@@ -0,0 +1,4 @@
+target:
+       prefetch.i      2048(x1)
+       prefetch.r      -0x820(x16)
+       prefetch.w      +0xff(x31)
diff --git a/gas/testsuite/gas/riscv/zicbop.d b/gas/testsuite/gas/riscv/zicbop.d
new file mode 100644 (file)
index 0000000..056a8a5
--- /dev/null
@@ -0,0 +1,12 @@
+#as: -march=rv64g_zicbop
+#source: zicbop.s
+#objdump: -dr
+
+.*:[   ]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[      ]+[0-9a-f]+:[   ]+0200e013[     ]+prefetch\.i[  ]+32\(ra\)
+[      ]+[0-9a-f]+:[   ]+80186013[     ]+prefetch\.r[  ]+-2048\(a6\)
+[      ]+[0-9a-f]+:[   ]+7e3fe013[     ]+prefetch\.w[  ]+2016\(t6\)
diff --git a/gas/testsuite/gas/riscv/zicbop.s b/gas/testsuite/gas/riscv/zicbop.s
new file mode 100644 (file)
index 0000000..ffe2014
--- /dev/null
@@ -0,0 +1,4 @@
+target:
+       prefetch.i      0x20(x1)
+       prefetch.r      -2048(x16)
+       prefetch.w      +0x7e0(x31)
index 01cd3a4e9dd047f7aa82b941dc8864b9d2212f22..1572c84f0be1c9c355e0248544a11b19837382af 100644 (file)
 #define MASK_HSV_W 0xfe007fff
 #define MATCH_HSV_D 0x6e004073
 #define MASK_HSV_D 0xfe007fff
+/* Zicbop hint instructions. */
+#define MATCH_PREFETCH_I 0x6013
+#define MASK_PREFETCH_I 0x1f07fff
+#define MATCH_PREFETCH_R 0x106013
+#define MASK_PREFETCH_R 0x1f07fff
+#define MATCH_PREFETCH_W 0x306013
+#define MASK_PREFETCH_W 0x1f07fff
 /* Unprivileged Counter/Timers CSR addresses.  */
 #define CSR_CYCLE 0xc00
 #define CSR_TIME 0xc01
index 048ab0a5d6836914eb1737373cd4ce8fe73b0607..5462b5eceabf7d9c5c20d6e9e93f54395cb43032 100644 (file)
@@ -388,6 +388,7 @@ enum riscv_insn_class
   INSN_CLASS_V,
   INSN_CLASS_ZVEF,
   INSN_CLASS_SVINVAL,
+  INSN_CLASS_ZICBOP,
 };
 
 /* This structure holds information for a particular instruction.  */
index 34724d4aec50d2f464e5e08b2fd4a8aa5ad5c115..57b798d8e14f6a80fd94e0ab985ae76b75e1c8be 100644 (file)
@@ -424,6 +424,10 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
          print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
          break;
 
+       case 'f':
+         print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
+         break;
+
        case 'a':
          info->target = EXTRACT_JTYPE_IMM (l) + pc;
          (*info->print_address_func) (info->target, info);
index 00ee21d783f1c97e3471fcf735b9d36f5070c694..6a288987358f159bab25c04c9b063c666dc9f659 100644 (file)
@@ -388,6 +388,9 @@ const struct riscv_opcode riscv_opcodes[] =
 {"lw",          0, INSN_CLASS_I, "d,o(s)",    MATCH_LW, MASK_LW, match_opcode, INSN_DREF|INSN_4_BYTE },
 {"lw",          0, INSN_CLASS_I, "d,A",       0, (int) M_LW, match_never, INSN_MACRO },
 {"not",         0, INSN_CLASS_I, "d,s",       MATCH_XORI|MASK_IMM, MASK_XORI|MASK_IMM, match_opcode, INSN_ALIAS },
+{"prefetch.i",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
+{"prefetch.r",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
+{"prefetch.w",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
 {"ori",         0, INSN_CLASS_I, "d,s,j",     MATCH_ORI, MASK_ORI, match_opcode, 0 },
 {"or",          0, INSN_CLASS_C, "Cs,Cw,Ct",  MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS },
 {"or",          0, INSN_CLASS_C, "Cs,Ct,Cw",  MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS },