From 2cf451c653352e6f5d1769f36a2a48f1d5820ae1 Mon Sep 17 00:00:00 2001 Message-Id: <2cf451c653352e6f5d1769f36a2a48f1d5820ae1.1645771895.git.research_trasio@irq.a4lg.com> From: Tsukasa OI Date: Tue, 11 Jan 2022 19:14:02 +0900 Subject: [PATCH 1/2] RISC-V: Prefetch hint instructions and operand set This commit adds 'Zicbop' hint instructions and testcases. bfd/ChangeLog: * elfxx-riscv.c (riscv_supported_std_z_ext): Add 'Zicbop' standard 'Z' extension. (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. * testsuite/gas/riscv/zicbop-fail.d: New testcase for invalid prefetch hint instructions. * testsuite/gas/riscv/zicbop-fail.l: Likewise. * testsuite/gas/riscv/zicbop-fail.s: Likewise. * testsuite/gas/riscv/zicbop.d: New testcase for prefetch hint instructions. * testsuite/gas/riscv/zicbop.s: 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 | 3 +++ gas/config/tc-riscv.c | 18 ++++++++++++++++++ gas/testsuite/gas/riscv/zicbop-fail.d | 3 +++ gas/testsuite/gas/riscv/zicbop-fail.l | 4 ++++ gas/testsuite/gas/riscv/zicbop-fail.s | 4 ++++ gas/testsuite/gas/riscv/zicbop.d | 12 ++++++++++++ gas/testsuite/gas/riscv/zicbop.s | 4 ++++ include/opcode/riscv-opc.h | 7 +++++++ include/opcode/riscv.h | 1 + opcodes/riscv-dis.c | 4 ++++ opcodes/riscv-opc.c | 3 +++ 11 files changed, 63 insertions(+) create mode 100644 gas/testsuite/gas/riscv/zicbop-fail.d create mode 100644 gas/testsuite/gas/riscv/zicbop-fail.l create mode 100644 gas/testsuite/gas/riscv/zicbop-fail.s create mode 100644 gas/testsuite/gas/riscv/zicbop.d create mode 100644 gas/testsuite/gas/riscv/zicbop.s diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index d74e7a584eb..83cd90d006a 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 }, @@ -2319,6 +2320,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 322e0f070ba..966d08ced82 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1180,6 +1180,7 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length) case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break; case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break; case 'q': used_bits |= ENCODE_STYPE_IMM (-1U); break; + case 'f': used_bits |= ENCODE_STYPE_IMM (-1U); break; case 'u': used_bits |= ENCODE_UTYPE_IMM (-1U); break; case 'z': break; /* Zero immediate. */ case '[': break; /* Unused operand. */ @@ -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 : +[ ]+[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 2da0f7cf0a4..bd200d736e5 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 }, -- 2.32.0