summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elfxx-riscv.c3
-rw-r--r--gas/config/tc-riscv.c18
-rw-r--r--gas/testsuite/gas/riscv/zicbop-fail.d3
-rw-r--r--gas/testsuite/gas/riscv/zicbop-fail.l4
-rw-r--r--gas/testsuite/gas/riscv/zicbop-fail.s4
-rw-r--r--gas/testsuite/gas/riscv/zicbop.d12
-rw-r--r--gas/testsuite/gas/riscv/zicbop.s4
-rw-r--r--include/opcode/riscv-opc.h7
-rw-r--r--include/opcode/riscv.h1
-rw-r--r--opcodes/riscv-dis.c4
-rw-r--r--opcodes/riscv-opc.c3
11 files changed, 63 insertions, 0 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 2915b74dd0f..185bab7d819 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -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:
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 9cc0abfda88..bb5f6e4aedd 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -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
index 00000000000..d734c7d4d15
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zicbop-fail.d
@@ -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
index 00000000000..4b5d5fc84fa
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zicbop-fail.l
@@ -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
index 00000000000..0353c5ff80a
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zicbop-fail.s
@@ -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
index 00000000000..056a8a501ff
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zicbop.d
@@ -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
index 00000000000..ffe2014be6f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zicbop.s
@@ -0,0 +1,4 @@
+target:
+ prefetch.i 0x20(x1)
+ prefetch.r -2048(x16)
+ prefetch.w +0x7e0(x31)
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 01cd3a4e9dd..1572c84f0be 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2029,6 +2029,13 @@
#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
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 048ab0a5d68..5462b5eceab 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -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. */
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 34724d4aec5..57b798d8e14 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -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);
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 00ee21d783f..6a288987358 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -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 },