From 43422a711448c15339d5bbbe00593b590593ac9f Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Wed, 6 Jul 2022 12:06:01 +0900 Subject: [PATCH] RISC-V: Non-standard encodings of fence (disasm) This commit adds disassembler support for non-standard encodings of the fence instruction. Despite that those fields are reserved in many cases, base implementation shall ignore and handle with fm=0000. gas/ChangeLog: * config/tc-riscv.c (validate_riscv_insn): Add ignored fm field. (riscv_ip): Add ignored fm field. * testsuite/gas/riscv/fence-dis-nonstd.s: New disasm test. * testsuite/gas/riscv/fence-dis-nonstd.d: Likewise. include/ChangeLog: * opcode/riscv.h (OP_MASK_FM, OP_SH_FM): New. opcodes/ChangeLog: * riscv-dis.c (print_insn_args): Add ignored fm field. Print "none" on fence pred/succ operand value 0b0000. (arg_print): Add default value argument. * riscv-opc.c (riscv_opcodes): Reorder fence.tso so that reserved fence instruction entry is matched at the end. Ignore reserved bit positions. --- gas/config/tc-riscv.c | 3 +++ gas/testsuite/gas/riscv/fence-dis-nonstd.d | 21 +++++++++++++++++++++ gas/testsuite/gas/riscv/fence-dis-nonstd.s | 22 ++++++++++++++++++++++ include/opcode/riscv.h | 2 ++ opcodes/riscv-dis.c | 14 ++++++++------ opcodes/riscv-opc.c | 4 ++-- 6 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 gas/testsuite/gas/riscv/fence-dis-nonstd.d create mode 100644 gas/testsuite/gas/riscv/fence-dis-nonstd.s diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 88d8298fbf2..bbfdcde69d0 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1415,6 +1415,8 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length) case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break; case 's': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break; case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break; + /* fence: fm field. */ + case 'f': USE_BITS (OP_MASK_FM, OP_SH_FM); break; default: goto unknown_validate_operand; } @@ -3534,6 +3536,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, case 'd': /* Ignored RD. */ case 's': /* Ignored RS1. */ case 'j': /* Ignored immediate (I-type). */ + case 'f': /* Ignored fence fm field. */ break; default: goto unknown_riscv_ip_operand; diff --git a/gas/testsuite/gas/riscv/fence-dis-nonstd.d b/gas/testsuite/gas/riscv/fence-dis-nonstd.d new file mode 100644 index 00000000000..5960bd2d99c --- /dev/null +++ b/gas/testsuite/gas/riscv/fence-dis-nonstd.d @@ -0,0 +1,21 @@ +#as: -march=rv32i +#source: fence-dis-nonstd.s +#objdump: -dr + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+0ff0000f[ ]+fence +[ ]+[0-9a-f]+:[ ]+8330000f[ ]+fence\.tso +[ ]+[0-9a-f]+:[ ]+0ff0000f[ ]+fence +[ ]+[0-9a-f]+:[ ]+8330000f[ ]+fence\.tso +[ ]+[0-9a-f]+:[ ]+0100000f[ ]+fence[ ]+w,none +[ ]+[0-9a-f]+:[ ]+0cf00f8f[ ]+fence[ ]+io,iorw +[ ]+[0-9a-f]+:[ ]+0fcf800f[ ]+fence[ ]+iorw,io +[ ]+[0-9a-f]+:[ ]+83300f8f[ ]+fence\.tso +[ ]+[0-9a-f]+:[ ]+833f800f[ ]+fence\.tso +[ ]+[0-9a-f]+:[ ]+8ff0000f[ ]+fence[ ]+iorw,iorw +[ ]+[0-9a-f]+:[ ]+1330000f[ ]+fence[ ]+rw,rw diff --git a/gas/testsuite/gas/riscv/fence-dis-nonstd.s b/gas/testsuite/gas/riscv/fence-dis-nonstd.s new file mode 100644 index 00000000000..7f2433ec77c --- /dev/null +++ b/gas/testsuite/gas/riscv/fence-dis-nonstd.s @@ -0,0 +1,22 @@ +target: + fence + fence.tso + # Standard encodings of fence and fence.tso + .insn i MISC_MEM, 0, x0, x0, 0x0ff + .insn i MISC_MEM, 0, x0, x0, 0x833-0x1000 + # Standard encoding of pause + .insn i MISC_MEM, 0, x0, x0, 0x010 + # Non-standard encodings (regular, either RD or RS1 are non-zero) + # Ignore unused bit fields. + .insn i MISC_MEM, 0, x31, x0, 0x0cf + .insn i MISC_MEM, 0, x0, x31, 0x0fc + # Non-standard encodings (TSO, either RD or RS1 are non-zero) + # Ignore unused bit fields for fence.tso. + .insn i MISC_MEM, 0, x31, x0, 0x833-0x1000 + .insn i MISC_MEM, 0, x0, x31, 0x833-0x1000 + # Non-standard encoding (TSO, pred and succ are not defined) + # Since fm+pred+succ is not defined, fallback to regular fence. + .insn i MISC_MEM, 0, x0, x0, 0x8ff-0x1000 + # Non-standard encoding (fm is reserved) + # Fallback to regular fence. + .insn i MISC_MEM, 0, x0, x0, 0x133 diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index c3cbde600cb..3053215e34d 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -240,6 +240,8 @@ static inline unsigned int riscv_insn_length (insn_t insn) #define OP_SH_AQ 26 #define OP_MASK_RL 0x1 #define OP_SH_RL 25 +#define OP_MASK_FM 0xfU +#define OP_SH_FM 28 #define OP_MASK_CSR 0xfffU #define OP_SH_CSR 20 diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index cf5d639f7fd..cc239c8625f 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -178,9 +178,11 @@ parse_riscv_dis_options (const char *opts_in) static void arg_print (struct disassemble_info *info, unsigned long val, - const char* const* array, size_t size) + const char *const *array, size_t size, const char *default_val) { - const char *s = val >= size || array[val] == NULL ? "unknown" : array[val]; + const char *s = val >= size || array[val] == NULL + ? (default_val == NULL ? "unknown" : default_val) + : array[val]; (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", s); } @@ -441,17 +443,17 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 'm': arg_print (info, EXTRACT_OPERAND (RM, l), - riscv_rm, ARRAY_SIZE (riscv_rm)); + riscv_rm, ARRAY_SIZE (riscv_rm), NULL); break; case 'P': arg_print (info, EXTRACT_OPERAND (PRED, l), - riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); + riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ), "none"); break; case 'Q': arg_print (info, EXTRACT_OPERAND (SUCC, l), - riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); + riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ), "none"); break; case 'o': @@ -608,7 +610,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info break; print (info->stream, dis_style_text, ","); arg_print (info, EXTRACT_OPERAND (RM, l), riscv_rm, - ARRAY_SIZE (riscv_rm)); + ARRAY_SIZE (riscv_rm), NULL); break; default: goto undefined_modifier; diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 477480bf7ae..c1a0e042ea8 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -464,10 +464,10 @@ const struct riscv_opcode riscv_opcodes[] = {"sw", 0, INSN_CLASS_C, "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE }, {"sw", 0, INSN_CLASS_I, "t,q(s)", MATCH_SW, MASK_SW, match_opcode, INSN_DREF|INSN_4_BYTE }, {"sw", 0, INSN_CLASS_I, "t,A,s", 0, (int) M_SW, match_never, INSN_MACRO }, +{"fence.tso", 0, INSN_CLASS_I, "\\ds", MATCH_FENCE_TSO, MASK_FENCE_TSO, match_opcode, 0 }, {"fence", 0, INSN_CLASS_I, "", MATCH_FENCE|MASK_PRED|MASK_SUCC, MASK_FENCE|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS }, -{"fence", 0, INSN_CLASS_I, "P,Q", MATCH_FENCE, MASK_FENCE|MASK_RD|MASK_RS1|(MASK_IMM & ~MASK_PRED & ~MASK_SUCC), match_opcode, 0 }, +{"fence", 0, INSN_CLASS_I, "P,Q\\dsf", MATCH_FENCE, MASK_FENCE, match_opcode, 0 }, {"fence.i", 0, INSN_CLASS_ZIFENCEI, "\\dsj", MATCH_FENCE_I, MASK_FENCE_I, match_opcode, 0 }, -{"fence.tso", 0, INSN_CLASS_I, "", MATCH_FENCE_TSO, MASK_FENCE_TSO|MASK_RD|MASK_RS1, match_opcode, 0 }, {"rdcycle", 0, INSN_CLASS_I, "d", MATCH_RDCYCLE, MASK_RDCYCLE, match_opcode, INSN_ALIAS }, {"rdinstret", 0, INSN_CLASS_I, "d", MATCH_RDINSTRET, MASK_RDINSTRET, match_opcode, INSN_ALIAS }, {"rdtime", 0, INSN_CLASS_I, "d", MATCH_RDTIME, MASK_RDTIME, match_opcode, INSN_ALIAS },