[PATCH 1/1] RISC-V: Support ".option [no]exact" assembler directives
Tsukasa OI
research_trasio@irq.a4lg.com
Fri May 16 02:31:04 GMT 2025
From: Tsukasa OI <research_trasio@irq.a4lg.com>
This commit adds two assembler directives: ".option exact" and
".option noexact" (enable/disable the exact mode) as discussed in
<https://github.com/riscv-non-isa/riscv-asm-manual/pull/122> and
already implemented in LLVM.
When the exact mode is enabled,
1. Linker relaxations are turned off,
2. Instruction aliases that will change the encoding from the
(likely non-alias) instruction with the same name are disabled
(e.g. "addi" will never turn into "c.addi" even if optimizable) and
3. Assembler relaxation of branch instructions are disabled
(e.g. "blt" with a long offset will not turn into "bge + j").
The main purpose of this mode is to emit desired machine code as the
user writes, assuming the user knows constraints of their code. So,
macros like "li" (known to be expanded into possibly complex sequences)
are not guaranteed to be fully aware of this mode.
Currently, interactions between ".option relax/norelax" and
".option exact/noexact" are designed to be LLVM-compatible (i.e.
".option exact/noexact" imply ".option norelax/relax", respectively)
but considered flaky and strongly discouraged from using both.
cf. <https://github.com/llvm/llvm-project/pull/122483>
gas/ChangeLog:
* config/tc-riscv.c (struct riscv_set_options): Add exact option.
(RELAX_BRANCH_ENCODE): Encode exact option.
(RELAX_BRANCH_EXACT): New predicate macro.
(relaxed_branch_length): Handle exact mode cases.
(append_insn): Pass exact option to RELAX_BRANCH_ENCODE.
(riscv_ip): Skip instructions that would change the encoding
when the exact mode is enabled.
(s_riscv_option): Parse ".option exact" and ".option noexact"
assembler directives.
* doc/c-riscv.texi: Document new assembler directives.
* testsuite/gas/riscv/exact.s: Test exact mode basics.
* testsuite/gas/riscv/exact.d: Ditto.
* testsuite/gas/riscv/exact-branch-local.s: Test conditional
branches and unconditional jumps relative to a local symbol.
* testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto.
* testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto.
* testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto.
* testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto.
* testsuite/gas/riscv/exact-branch-extern.s: Test conditional
branches and unconditional jumps relative to an external symbol.
* testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto.
* testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto.
* testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact
mode to test various configurations and instructions.
* testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto.
* testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto.
include/ChangeLog:
* opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases
to reject on the exact mode.
opcodes/ChangeLog:
* riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all
instructions that should be rejected on the exact mode.
---
gas/config/tc-riscv.c | 39 +++-
gas/doc/c-riscv.texi | 13 ++
.../gas/riscv/exact-branch-extern-exact.d | 32 ++++
.../gas/riscv/exact-branch-extern-noexact.d | 50 +++++
gas/testsuite/gas/riscv/exact-branch-extern.s | 40 ++++
.../gas/riscv/exact-branch-local-exact-fail.d | 3 +
.../gas/riscv/exact-branch-local-exact-fail.l | 43 +++++
.../gas/riscv/exact-branch-local-exact-ok.d | 75 ++++++++
.../gas/riscv/exact-branch-local-noexact.d | 149 +++++++++++++++
gas/testsuite/gas/riscv/exact-branch-local.s | 138 ++++++++++++++
gas/testsuite/gas/riscv/exact.d | 15 ++
gas/testsuite/gas/riscv/exact.s | 11 ++
.../gas/riscv/no-relax-branch-offset-fail.l | 5 +-
.../gas/riscv/no-relax-branch-offset-fail.s | 11 +-
include/opcode/riscv.h | 6 +
opcodes/riscv-opc.c | 178 +++++++++---------
16 files changed, 705 insertions(+), 103 deletions(-)
create mode 100644 gas/testsuite/gas/riscv/exact-branch-extern-exact.d
create mode 100644 gas/testsuite/gas/riscv/exact-branch-extern-noexact.d
create mode 100644 gas/testsuite/gas/riscv/exact-branch-extern.s
create mode 100644 gas/testsuite/gas/riscv/exact-branch-local-exact-fail.d
create mode 100644 gas/testsuite/gas/riscv/exact-branch-local-exact-fail.l
create mode 100644 gas/testsuite/gas/riscv/exact-branch-local-exact-ok.d
create mode 100644 gas/testsuite/gas/riscv/exact-branch-local-noexact.d
create mode 100644 gas/testsuite/gas/riscv/exact-branch-local.s
create mode 100644 gas/testsuite/gas/riscv/exact.d
create mode 100644 gas/testsuite/gas/riscv/exact.s
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index a35288e55cb1..0844b49ae1d1 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -268,6 +268,7 @@ struct riscv_set_options
int pic; /* Generate position-independent code. */
int rvc; /* Generate RVC code. */
int relax; /* Emit relocs the linker is allowed to relax. */
+ int exact; /* Emit instructions without compression or relaxation. */
int arch_attr; /* Emit architecture and privileged elf attributes. */
int csr_check; /* Enable the CSR checking. */
};
@@ -277,6 +278,7 @@ static struct riscv_set_options riscv_opts =
0, /* pic */
0, /* rvc */
1, /* relax */
+ 0, /* exact */
DEFAULT_RISCV_ATTR, /* arch_attr */
0, /* csr_check */
};
@@ -469,16 +471,18 @@ static bool explicit_priv_attr = false;
static char *expr_parse_end;
/* Macros for encoding relaxation state for RVC branches and far jumps. */
-#define RELAX_BRANCH_ENCODE(uncond, rvc, length) \
+#define RELAX_BRANCH_ENCODE(uncond, rvc, length, exact) \
((relax_substateT) \
(0xc0000000 \
| ((uncond) ? 1 : 0) \
| ((rvc) ? 2 : 0) \
- | ((length) << 2)))
+ | ((length) << 2) \
+ | ((exact) << 6)))
#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
#define RELAX_BRANCH_LENGTH(i) (((i) >> 2) & 0xF)
#define RELAX_BRANCH_RVC(i) (((i) & 2) != 0)
#define RELAX_BRANCH_UNCOND(i) (((i) & 1) != 0)
+#define RELAX_BRANCH_EXACT(i) (((i) & 0x40) != 0)
/* Is the given value a sign-extended 32-bit value? */
#define IS_SEXT_32BIT_NUM(x) \
@@ -808,22 +812,25 @@ add_relaxed_insn (struct riscv_cl_insn *insn, int max_chars, int var,
static unsigned
relaxed_branch_length (fragS *fragp, asection *sec, int update)
{
- int jump, rvc, length = 8;
+ int jump, rvc, exact, length = 8;
if (!fragp)
return length;
jump = RELAX_BRANCH_UNCOND (fragp->fr_subtype);
rvc = RELAX_BRANCH_RVC (fragp->fr_subtype);
+ exact = RELAX_BRANCH_EXACT (fragp->fr_subtype);
length = RELAX_BRANCH_LENGTH (fragp->fr_subtype);
/* Assume jumps are in range; the linker will catch any that aren't. */
length = jump ? 4 : 8;
- if (fragp->fr_symbol != NULL
- && S_IS_DEFINED (fragp->fr_symbol)
- && !S_IS_WEAK (fragp->fr_symbol)
- && sec == S_GET_SEGMENT (fragp->fr_symbol))
+ if (exact)
+ length = rvc ? 2 : 4;
+ else if (fragp->fr_symbol != NULL
+ && S_IS_DEFINED (fragp->fr_symbol)
+ && !S_IS_WEAK (fragp->fr_symbol)
+ && sec == S_GET_SEGMENT (fragp->fr_symbol))
{
offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
bfd_vma rvc_range = jump ? RVC_JUMP_REACH : RVC_BRANCH_REACH;
@@ -838,7 +845,7 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
}
if (update)
- fragp->fr_subtype = RELAX_BRANCH_ENCODE (jump, rvc, length);
+ fragp->fr_subtype = RELAX_BRANCH_ENCODE (jump, rvc, length, exact);
return length;
}
@@ -1990,7 +1997,8 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
}
add_relaxed_insn (ip, worst_case, best_case,
- RELAX_BRANCH_ENCODE (j, best_case == 2, worst_case),
+ RELAX_BRANCH_ENCODE (j, best_case == 2, worst_case,
+ riscv_opts.exact),
address_expr->X_add_symbol,
address_expr->X_add_number);
return;
@@ -2870,6 +2878,9 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
if ((insn->xlen_requirement != 0) && (xlen != insn->xlen_requirement))
continue;
+ if (riscv_opts.exact && (insn->pinfo & INSN_NON_EXACT))
+ continue;
+
if (!riscv_multi_subset_supports (&riscv_rps_as, insn->insn_class))
{
error.missing_ext = riscv_multi_subset_supports_ext (&riscv_rps_as,
@@ -5084,6 +5095,16 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
riscv_opts.relax = true;
else if (strcmp (name, "norelax") == 0)
riscv_opts.relax = false;
+ else if (strcmp (name, "exact") == 0)
+ {
+ riscv_opts.exact = true;
+ riscv_opts.relax = false;
+ }
+ else if (strcmp (name, "noexact") == 0)
+ {
+ riscv_opts.exact = false;
+ riscv_opts.relax = true;
+ }
else if (strcmp (name, "csr-check") == 0)
riscv_opts.csr_check = true;
else if (strcmp (name, "no-csr-check") == 0)
diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
index 28ccfb26b4b0..974414eb3c89 100644
--- a/gas/doc/c-riscv.texi
+++ b/gas/doc/c-riscv.texi
@@ -210,6 +210,19 @@ Enables or disables relaxation. The RISC-V assembler and linker
opportunistically relax some code sequences, but sometimes this behavior is not
desirable.
+@item exact
+@itemx noexact
+Enables or disables exact mode. Not only the exact mode disables linker
+relaxations, it also disables automatic instruction compression and the branch
+relaxation (both optionally change instruction encodings and/or instruction
+count). This mode is useful in some cases where the instruction sequences, as
+exactly written, are expected to be emitted.
+
+Note that, in the current implementation, @samp{.option exact} implies
+@samp{.option norelax} and @samp{.option noexact} implies @samp{.option relax}.
+Due to their flaky interactions, it is strongly discouraged to use both
+@samp{.option relax/norelax} and @samp{.option exact/noexact} in the same scope.
+
@item csr-check
@itemx no-csr-check
Enables or disables the CSR checking.
diff --git a/gas/testsuite/gas/riscv/exact-branch-extern-exact.d b/gas/testsuite/gas/riscv/exact-branch-extern-exact.d
new file mode 100644
index 000000000000..71224fc42336
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-extern-exact.d
@@ -0,0 +1,32 @@
+#as: -march=rv32ic --defsym exact_mode=1
+#source: exact-branch-extern.s
+#objdump: -drw -Mno-aliases
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[ ]+[0-9a-f]+:[ ]+00b50063[ ]+beq[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+feb51ee3[ ]+bne[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+feb54ce3[ ]+blt[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+feb55ae3[ ]+bge[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+feb568e3[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+feb576e3[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+d565[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_RVC_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+f17d[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_RVC_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fea5c2e3[ ]+blt[ ]+a1,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fea5d0e3[ ]+bge[ ]+a1,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fca5eee3[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fca5fce3[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fc050ae3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fc0518e3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fc0546e3[ ]+blt[ ]+a0,zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fca044e3[ ]+blt[ ]+zero,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fca052e3[ ]+bge[ ]+zero,a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+fc0550e3[ ]+bge[ ]+a0,zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_BRANCH[ ]+ext
+[ ]+[0-9a-f]+:[ ]+0001[ ]+.*
+[ ]+[0-9a-f]+:[ ]+fbbff56f[ ]+jal[ ]+a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+bf5d[ ]+c\.j[ ]+[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_RVC_JUMP[ ]+ext
+[ ]+[0-9a-f]+:[ ]+3f55[ ]+c\.jal[ ]+[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_RVC_JUMP[ ]+ext
diff --git a/gas/testsuite/gas/riscv/exact-branch-extern-noexact.d b/gas/testsuite/gas/riscv/exact-branch-extern-noexact.d
new file mode 100644
index 000000000000..0c17b482380a
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-extern-noexact.d
@@ -0,0 +1,50 @@
+#as: -march=rv32ic
+#source: exact-branch-extern.s
+#objdump: -drw -Mno-aliases
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[ ]+[0-9a-f]+:[ ]+00b51463[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffdff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00b50463[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ff5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00b55463[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fedff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00b54463[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fe5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00b57463[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fddff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00b56463[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fd5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00051463[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fcdff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00050463[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fc5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a5d463[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fbdff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a5c463[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fb5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a5f463[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fadff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a5e463[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+fa5ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00051463[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f9dff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00050463[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f95ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00055463[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f8dff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a05463[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f85ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00a04463[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f7dff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+00054463[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f75ff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+0001[ ]+.*
+[ ]+[0-9a-f]+:[ ]+f6fff56f[ ]+jal[ ]+a0,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+f6bff06f[ ]+jal[ ]+zero,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
+[ ]+[0-9a-f]+:[ ]+f67ff0ef[ ]+jal[ ]+ra,[0-9a-f]+.*[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+ext
diff --git a/gas/testsuite/gas/riscv/exact-branch-extern.s b/gas/testsuite/gas/riscv/exact-branch-extern.s
new file mode 100644
index 000000000000..04d05fdd42dd
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-extern.s
@@ -0,0 +1,40 @@
+.ifdef exact_mode
+ .option exact
+.else
+ .option noexact
+.endif
+ .extern ext
+
+ ## Conditional Branches
+
+ # Basic instructions
+ beq a0, a1, ext
+ bne a0, a1, ext
+ blt a0, a1, ext
+ bge a0, a1, ext
+ bltu a0, a1, ext
+ bgeu a0, a1, ext
+
+ # Compressed instructions
+ c.beqz a0, ext
+ c.bnez a0, ext
+
+ # Aliases
+ bgt a0, a1, ext
+ ble a0, a1, ext
+ bgtu a0, a1, ext
+ bleu a0, a1, ext
+ beqz a0, ext
+ bnez a0, ext
+ bltz a0, ext
+ bgtz a0, ext
+ blez a0, ext
+ bgez a0, ext
+
+ c.nop
+
+ ## Unconditional Jumps (normal and compressed)
+
+ jal a0, ext
+ c.j ext
+ c.jal ext # RV32C only
diff --git a/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.d b/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.d
new file mode 100644
index 000000000000..cdf9203574af
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.d
@@ -0,0 +1,3 @@
+#as: -march=rv32ic --defsym exact_mode=1 --defsym long_branch=1
+#source: exact-branch-local.s
+#error_output: exact-branch-local-exact-fail.l
diff --git a/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.l b/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.l
new file mode 100644
index 000000000000..5b07fcac1eb9
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-local-exact-fail.l
@@ -0,0 +1,43 @@
+.*Assembler messages:
+.*:93: Error: invalid B-type offset \(\+4096\)
+.*:94: Error: invalid B-type offset \(-4098\)
+.*:95: Error: invalid B-type offset \(\+4096\)
+.*:96: Error: invalid B-type offset \(-4098\)
+.*:97: Error: invalid B-type offset \(\+4096\)
+.*:98: Error: invalid B-type offset \(-4098\)
+.*:99: Error: invalid B-type offset \(\+4096\)
+.*:100: Error: invalid B-type offset \(-4098\)
+.*:101: Error: invalid B-type offset \(\+4096\)
+.*:102: Error: invalid B-type offset \(-4098\)
+.*:103: Error: invalid B-type offset \(\+4096\)
+.*:104: Error: invalid B-type offset \(-4098\)
+.*:105: Error: invalid B-type offset \(\+4096\)
+.*:106: Error: invalid B-type offset \(-4098\)
+.*:107: Error: invalid B-type offset \(\+4096\)
+.*:108: Error: invalid B-type offset \(-4098\)
+.*:109: Error: invalid B-type offset \(\+4096\)
+.*:110: Error: invalid B-type offset \(-4098\)
+.*:111: Error: invalid B-type offset \(\+4096\)
+.*:112: Error: invalid B-type offset \(-4098\)
+.*:113: Error: invalid B-type offset \(\+4096\)
+.*:114: Error: invalid B-type offset \(-4098\)
+.*:115: Error: invalid B-type offset \(\+4096\)
+.*:116: Error: invalid B-type offset \(-4098\)
+.*:117: Error: invalid B-type offset \(\+4096\)
+.*:118: Error: invalid B-type offset \(-4098\)
+.*:119: Error: invalid B-type offset \(\+4096\)
+.*:120: Error: invalid B-type offset \(-4098\)
+.*:121: Error: invalid B-type offset \(\+4096\)
+.*:122: Error: invalid B-type offset \(-4098\)
+.*:123: Error: invalid B-type offset \(\+4096\)
+.*:124: Error: invalid B-type offset \(-4098\)
+.*:128: Error: invalid CB-type offset \(\+256\)
+.*:129: Error: invalid CB-type offset \(-258\)
+.*:130: Error: invalid CB-type offset \(\+256\)
+.*:131: Error: invalid CB-type offset \(-258\)
+.*:132: Error: invalid J-type offset \(\+1048576\)
+.*:133: Error: invalid J-type offset \(-1048578\)
+.*:134: Error: invalid CJ-type offset \(\+2048\)
+.*:135: Error: invalid CJ-type offset \(-2050\)
+.*:136: Error: invalid CJ-type offset \(\+2048\)
+.*:137: Error: invalid CJ-type offset \(-2050\)
diff --git a/gas/testsuite/gas/riscv/exact-branch-local-exact-ok.d b/gas/testsuite/gas/riscv/exact-branch-local-exact-ok.d
new file mode 100644
index 000000000000..c7f1c6e74f6c
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-local-exact-ok.d
@@ -0,0 +1,75 @@
+#as: -march=rv32ic --defsym exact_mode=1
+#source: exact-branch-local.s
+#objdump: -d -Mno-aliases
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[ ]+[0-9a-f]+:[ ]+00b50063[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b51063[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b54063[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b55063[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b56063[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b57063[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5c063[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5d063[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5e063[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5f063[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00054063[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a04063[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a05063[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00055063[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+0e050f63[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f00500e3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+0e051f63[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f00510e3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e050fe3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e051fe3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb50fe3[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b50063[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb51fe3[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b51063[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb54fe3[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b54063[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb55fe3[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b55063[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb56fe3[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b56063[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb57fe3[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b57063[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5cfe3[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5c063[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5dfe3[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5d063[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5efe3[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5e063[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5ffe3[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5f063[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e050fe3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e051fe3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e054fe3[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80054063[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea04fe3[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a04063[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea05fe3[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a05063[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e055fe3[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80055063[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+0000056f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+a001[ ]+c\.j[ ]+[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+2001[ ]+c\.jal[ ]+[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ffff56f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+8000056f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+affd[ ]+c\.j[ ]+[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+b001[ ]+c\.j[ ]+[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+2ffd[ ]+c\.jal[ ]+[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+3001[ ]+c\.jal[ ]+[0-9a-f]+.*
diff --git a/gas/testsuite/gas/riscv/exact-branch-local-noexact.d b/gas/testsuite/gas/riscv/exact-branch-local-noexact.d
new file mode 100644
index 000000000000..a10af28b67e9
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-local-noexact.d
@@ -0,0 +1,149 @@
+#as: -march=rv32ic --defsym long_branch=1
+#source: exact-branch-local.s
+#objdump: -d -Mno-aliases
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[ ]+[0-9a-f]+:[ ]+00b50063[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b51063[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b54063[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b55063[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b56063[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b57063[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5c063[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5d063[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5e063[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5f063[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+c101[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+e101[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00054063[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a04063[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a05063[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00055063[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+cd7d[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+d101[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ed7d[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+f101[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e050fe3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e051fe3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb50fe3[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b50063[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb51fe3[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b51063[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb54fe3[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b54063[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb55fe3[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b55063[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb56fe3[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b56063[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7eb57fe3[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80b57063[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5cfe3[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5c063[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5dfe3[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5d063[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5efe3[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5e063[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea5ffe3[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a5f063[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e050fe3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e051fe3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e054fe3[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80054063[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea04fe3[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a04063[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ea05fe3[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80a05063[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7e055fe3[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+80055063[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+0000056f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+a001[ ]+c\.j[ ]+.*
+[ ]+[0-9a-f]+:[ ]+2001[ ]+c\.jal[ ]+.*
+[ ]+[0-9a-f]+:[ ]+7ffff56f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+8000056f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+affd[ ]+c\.j[ ]+.*
+[ ]+[0-9a-f]+:[ ]+b001[ ]+c\.j[ ]+.*
+[ ]+[0-9a-f]+:[ ]+2ffd[ ]+c\.jal[ ]+.*
+[ ]+[0-9a-f]+:[ ]+3001[ ]+c\.jal[ ]+.*
+[ ]+[0-9a-f]+:[ ]+00b51463[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b51463[ ]+bne[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b50463[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b50463[ ]+beq[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b55463[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b55463[ ]+bge[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b54463[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b54463[ ]+blt[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b57463[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b57463[ ]+bgeu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b56463[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00b56463[ ]+bltu[ ]+a0,a1,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5d463[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5d463[ ]+bge[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5c463[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5c463[ ]+blt[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5f463[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5f463[ ]+bgeu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5e463[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a5e463[ ]+bltu[ ]+a1,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+e119[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ff0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+e119[ ]+c\.bnez[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffdfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+c119[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ff0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+c119[ ]+c\.beqz[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffdfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00055463[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00055463[ ]+bge[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a05463[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a05463[ ]+bge[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a04463[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00a04463[ ]+blt[ ]+zero,a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00054463[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7fd0006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+00054463[ ]+blt[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffbfe06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+10050063[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ee050fe3[ ]+beq[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+10051063[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ee051fe3[ ]+bne[ ]+a0,zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+8000056f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+7ffff56f[ ]+jal[ ]+a0,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+0010006f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffeff06f[ ]+jal[ ]+zero,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+001000ef[ ]+jal[ ]+ra,[0-9a-f]+.*
+[ ]+[0-9a-f]+:[ ]+ffeff0ef[ ]+jal[ ]+ra,[0-9a-f]+.*
diff --git a/gas/testsuite/gas/riscv/exact-branch-local.s b/gas/testsuite/gas/riscv/exact-branch-local.s
new file mode 100644
index 000000000000..5aeba3620258
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact-branch-local.s
@@ -0,0 +1,138 @@
+.ifdef exact_mode
+ .option exact
+.else
+ .option noexact
+.endif
+
+ ## Conditional Branches
+
+ # Zero offset.
+ beq a0, a1, .
+ bne a0, a1, .
+ blt a0, a1, .
+ bge a0, a1, .
+ bltu a0, a1, .
+ bgeu a0, a1, .
+
+ # Zero offset (aliases).
+ bgt a0, a1, .
+ ble a0, a1, .
+ bgtu a0, a1, .
+ bleu a0, a1, .
+ beqz a0, .
+ bnez a0, .
+ bltz a0, .
+ bgtz a0, .
+ blez a0, .
+ bgez a0, .
+
+ # Offsets that c.b{ne,eq}z can represent.
+ beqz a0, .+0x0fe
+ beqz a0, .-0x100
+ bnez a0, .+0x0fe
+ bnez a0, .-0x100
+
+ # Offsets that c.b{ne,eq}z cannot represent but single b{ne,eq}z can.
+ beqz a0, .+0x0ffe
+ beqz a0, .-0x1000
+ bnez a0, .+0x0ffe
+ bnez a0, .-0x1000
+
+ # Offsets that single conditional branch instruction can represent.
+ beq a0, a1, .+0x0ffe
+ beq a0, a1, .-0x1000
+ bne a0, a1, .+0x0ffe
+ bne a0, a1, .-0x1000
+ blt a0, a1, .+0x0ffe
+ blt a0, a1, .-0x1000
+ bge a0, a1, .+0x0ffe
+ bge a0, a1, .-0x1000
+ bltu a0, a1, .+0x0ffe
+ bltu a0, a1, .-0x1000
+ bgeu a0, a1, .+0x0ffe
+ bgeu a0, a1, .-0x1000
+ bgt a0, a1, .+0x0ffe
+ bgt a0, a1, .-0x1000
+ ble a0, a1, .+0x0ffe
+ ble a0, a1, .-0x1000
+ bgtu a0, a1, .+0x0ffe
+ bgtu a0, a1, .-0x1000
+ bleu a0, a1, .+0x0ffe
+ bleu a0, a1, .-0x1000
+ beqz a0, .+0x0ffe
+ beqz a0, .-0x1000
+ bnez a0, .+0x0ffe
+ bnez a0, .-0x1000
+ bltz a0, .+0x0ffe
+ bltz a0, .-0x1000
+ bgtz a0, .+0x0ffe
+ bgtz a0, .-0x1000
+ blez a0, .+0x0ffe
+ blez a0, .-0x1000
+ bgez a0, .+0x0ffe
+ bgez a0, .-0x1000
+
+ ## Unconditional Jumps (normal and compressed)
+
+ # Zero offset.
+ jal a0, .
+ c.j .
+ c.jal . # RV32C only
+
+ # Offsets that single jump instruction can represent.
+ jal a0, .+0x0ffffe
+ jal a0, .-0x100000
+ c.j .+0x7fe
+ c.j .-0x800
+ c.jal .+0x7fe # RV32C only
+ c.jal .-0x800 # RV32C only
+
+.ifdef long_branch
+ # Offsets that single conditional branch instruction cannot represent.
+ # (should fail on the exact mode)
+ beq a0, a1, .+0x0ffe+2
+ beq a0, a1, .-0x1000-2
+ bne a0, a1, .+0x0ffe+2
+ bne a0, a1, .-0x1000-2
+ blt a0, a1, .+0x0ffe+2
+ blt a0, a1, .-0x1000-2
+ bge a0, a1, .+0x0ffe+2
+ bge a0, a1, .-0x1000-2
+ bltu a0, a1, .+0x0ffe+2
+ bltu a0, a1, .-0x1000-2
+ bgeu a0, a1, .+0x0ffe+2
+ bgeu a0, a1, .-0x1000-2
+ bgt a0, a1, .+0x0ffe+2
+ bgt a0, a1, .-0x1000-2
+ ble a0, a1, .+0x0ffe+2
+ ble a0, a1, .-0x1000-2
+ bgtu a0, a1, .+0x0ffe+2
+ bgtu a0, a1, .-0x1000-2
+ bleu a0, a1, .+0x0ffe+2
+ bleu a0, a1, .-0x1000-2
+ beqz a0, .+0x0ffe+2
+ beqz a0, .-0x1000-2
+ bnez a0, .+0x0ffe+2
+ bnez a0, .-0x1000-2
+ bltz a0, .+0x0ffe+2
+ bltz a0, .-0x1000-2
+ bgtz a0, .+0x0ffe+2
+ bgtz a0, .-0x1000-2
+ blez a0, .+0x0ffe+2
+ blez a0, .-0x1000-2
+ bgez a0, .+0x0ffe+2
+ bgez a0, .-0x1000-2
+
+ # Offsets that single instruction cannot represent.
+ # Fail on the exact mode, either fallback or linker error on the non-exact mode.
+ c.beqz a0, .+0x0fe+2
+ c.beqz a0, .-0x100-2
+ c.bnez a0, .+0x0fe+2
+ c.bnez a0, .-0x100-2
+ jal a0, .+0x0ffffe+2 # results in a linker error on the non-exact mode
+ jal a0, .-0x100000-2 # results in a linker error on the non-exact mode
+ c.j .+0x7fe+2
+ c.j .-0x800-2
+ c.jal .+0x7fe+2 # RV32C only
+ c.jal .-0x800-2 # RV32C only
+.endif
diff --git a/gas/testsuite/gas/riscv/exact.d b/gas/testsuite/gas/riscv/exact.d
new file mode 100644
index 000000000000..3af23035800e
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact.d
@@ -0,0 +1,15 @@
+#as: -march=rv32ic
+#objdump: -d -Mno-aliases
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[ ]+0:[ ]+4108[ ]+c\.lw[ ]+a0,0\(a0\)
+[ ]+2:[ ]+4108[ ]+c\.lw[ ]+a0,0\(a0\)
+[ ]+4:[ ]+00052503[ ]+lw[ ]+a0,0\(a0\)
+[ ]+8:[ ]+4108[ ]+c\.lw[ ]+a0,0\(a0\)
+[ ]+a:[ ]+4108[ ]+c\.lw[ ]+a0,0\(a0\)
+[ ]+c:[ ]+4108[ ]+c\.lw[ ]+a0,0\(a0\)
diff --git a/gas/testsuite/gas/riscv/exact.s b/gas/testsuite/gas/riscv/exact.s
new file mode 100644
index 000000000000..89f828ebdb1f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/exact.s
@@ -0,0 +1,11 @@
+ # noexact by default.
+ lw a0, 0(a0)
+ c.lw a0, 0(a0)
+
+ .option exact
+ lw a0, 0(a0)
+ c.lw a0, 0(a0)
+
+ .option noexact
+ lw a0, 0(a0)
+ c.lw a0, 0(a0)
diff --git a/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.l b/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.l
index 8f6b5c955915..1e2dfc51dc94 100644
--- a/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.l
+++ b/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.l
@@ -5,4 +5,7 @@
.*:10: Error: invalid J-type offset \(-1048578\)
.*:14: Error: invalid J-type offset \(\+1048576\)
.*:17: Error: invalid J-type offset \(-1048578\)
-.*:20: Error: invalid CJ-type offset \(\+1\)
+.*:20: Error: invalid J-type offset \(\+7\)
+.*:21: Error: invalid B-type offset \(\+5\)
+.*:22: Error: invalid CJ-type offset \(\+3\)
+.*:23: Error: invalid CB-type offset \(\+1\)
diff --git a/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.s b/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.s
index 98a0978e7fc3..4e8ac3bd78ad 100644
--- a/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.s
+++ b/gas/testsuite/gas/riscv/no-relax-branch-offset-fail.s
@@ -1,10 +1,10 @@
- .option norelax
+ .option exact
# Relative to the current instruction.
j .+0x0ffffe+2
j .-0x100000-2
- # Relative to local labels (make sure that all instructions except "c.j" occupy 4-bytes).
+ # Relative to local labels (all instructions except "c.*" occupy 4-bytes).
j 1f+0x0ffffe-4+2
1:
j 2f-0x100000-4-2
@@ -16,5 +16,8 @@
lui t0, 0x2abcd
j 4b-0x100000+4-2
- # Jump to odd address (violates instruction alignment).
- c.j .+1
+ # Jump or branch to odd address (violates instruction alignment).
+ j .+7
+ bnez a0, .+5
+ c.j .+3
+ c.bnez a0, .+1
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 7fca806b643e..c8ff00e94b99 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -675,6 +675,12 @@ struct riscv_opcode
#define INSN_8_BYTE 0x00000040
#define INSN_16_BYTE 0x00000050
+/* Instruction is prohibited in the exact mode.
+
+ In the exact mode, regular aliases (with INSN_ALIAS) are allowed if
+ the instruction is neither compressed (one-by-one) nor relaxed. */
+#define INSN_NON_EXACT 0x00000080
+
/* Instruction is actually a macro. It should be ignored by the
disassembler, and requires special treatment by the assembler. */
#define INSN_MACRO 0xffffffff
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index f17d284ca6d9..83d931c74ecd 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -464,13 +464,13 @@ const struct riscv_opcode riscv_opcodes[] =
{"prefetch.i", 0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
{"prefetch.r", 0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
{"prefetch.w", 0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
-{"ntl.p1", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_P1, MASK_C_NTL_P1, match_opcode, INSN_ALIAS },
+{"ntl.p1", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_P1, MASK_C_NTL_P1, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"ntl.p1", 0, INSN_CLASS_ZIHINTNTL, "", MATCH_NTL_P1, MASK_NTL_P1, match_opcode, 0 },
-{"ntl.pall", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_PALL, MASK_C_NTL_PALL, match_opcode, INSN_ALIAS },
+{"ntl.pall", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_PALL, MASK_C_NTL_PALL, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"ntl.pall", 0, INSN_CLASS_ZIHINTNTL, "", MATCH_NTL_PALL, MASK_NTL_PALL, match_opcode, 0 },
-{"ntl.s1", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_S1, MASK_C_NTL_S1, match_opcode, INSN_ALIAS },
+{"ntl.s1", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_S1, MASK_C_NTL_S1, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"ntl.s1", 0, INSN_CLASS_ZIHINTNTL, "", MATCH_NTL_S1, MASK_NTL_S1, match_opcode, 0 },
-{"ntl.all", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_ALL, MASK_C_NTL_ALL, match_opcode, INSN_ALIAS },
+{"ntl.all", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_ALL, MASK_C_NTL_ALL, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"ntl.all", 0, INSN_CLASS_ZIHINTNTL, "", MATCH_NTL_ALL, MASK_NTL_ALL, match_opcode, 0 },
{"c.ntl.p1", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_P1, MASK_C_NTL_P1, match_opcode, 0 },
{"c.ntl.pall", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_PALL, MASK_C_NTL_PALL, match_opcode, 0 },
@@ -481,17 +481,17 @@ const struct riscv_opcode riscv_opcodes[] =
/* Basic RVI instructions and aliases. */
{"unimp", 0, INSN_CLASS_C, "", 0, 0xffffU, match_opcode, INSN_ALIAS },
{"unimp", 0, INSN_CLASS_I, "", MATCH_CSRRW|(CSR_CYCLE << OP_SH_CSR), 0xffffffffU, match_opcode, 0 }, /* csrw cycle, x0 */
-{"ebreak", 0, INSN_CLASS_C, "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
+{"ebreak", 0, INSN_CLASS_C, "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"ebreak", 0, INSN_CLASS_I, "", MATCH_EBREAK, MASK_EBREAK, match_opcode, 0 },
-{"sbreak", 0, INSN_CLASS_C, "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
+{"sbreak", 0, INSN_CLASS_C, "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sbreak", 0, INSN_CLASS_I, "", MATCH_EBREAK, MASK_EBREAK, match_opcode, INSN_ALIAS },
-{"ret", 0, INSN_CLASS_C, "", MATCH_C_JR|(X_RA << OP_SH_RD), MASK_C_JR|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH },
+{"ret", 0, INSN_CLASS_C, "", MATCH_C_JR|(X_RA << OP_SH_RD), MASK_C_JR|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH|INSN_NON_EXACT },
{"ret", 0, INSN_CLASS_I, "", MATCH_JALR|(X_RA << OP_SH_RS1), MASK_JALR|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS|INSN_BRANCH },
-{"jr", 0, INSN_CLASS_C, "d", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, INSN_ALIAS|INSN_BRANCH },
+{"jr", 0, INSN_CLASS_C, "d", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, INSN_ALIAS|INSN_BRANCH|INSN_NON_EXACT },
{"jr", 0, INSN_CLASS_I, "s", MATCH_JALR, MASK_JALR|MASK_RD|MASK_IMM, match_opcode, INSN_ALIAS|INSN_BRANCH },
{"jr", 0, INSN_CLASS_I, "o(s)", MATCH_JALR, MASK_JALR|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH },
{"jr", 0, INSN_CLASS_I, "s,j", MATCH_JALR, MASK_JALR|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH },
-{"jalr", 0, INSN_CLASS_C, "d", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, INSN_ALIAS|INSN_JSR },
+{"jalr", 0, INSN_CLASS_C, "d", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, INSN_ALIAS|INSN_JSR|INSN_NON_EXACT },
{"jalr", 0, INSN_CLASS_I, "s", MATCH_JALR|(X_RA << OP_SH_RD), MASK_JALR|MASK_RD|MASK_IMM, match_opcode, INSN_ALIAS|INSN_JSR },
{"jalr", 0, INSN_CLASS_I, "o(s)", MATCH_JALR|(X_RA << OP_SH_RD), MASK_JALR|MASK_RD, match_opcode, INSN_ALIAS|INSN_JSR },
{"jalr", 0, INSN_CLASS_I, "s,j", MATCH_JALR|(X_RA << OP_SH_RD), MASK_JALR|MASK_RD, match_opcode, INSN_ALIAS|INSN_JSR },
@@ -499,9 +499,9 @@ const struct riscv_opcode riscv_opcodes[] =
{"jalr", 0, INSN_CLASS_I, "d,o(s)", MATCH_JALR, MASK_JALR, match_opcode, INSN_JSR },
{"jalr", 0, INSN_CLASS_I, "d,s,1", MATCH_JALR, MASK_JALR|MASK_IMM, match_opcode, INSN_JSR },
{"jalr", 0, INSN_CLASS_I, "d,s,j", MATCH_JALR, MASK_JALR, match_opcode, INSN_JSR },
-{"j", 0, INSN_CLASS_C, "Ca", MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS|INSN_BRANCH },
+{"j", 0, INSN_CLASS_C, "Ca", MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS|INSN_BRANCH|INSN_NON_EXACT },
{"j", 0, INSN_CLASS_I, "a", MATCH_JAL, MASK_JAL|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH },
-{"jal", 32, INSN_CLASS_C, "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS|INSN_JSR },
+{"jal", 32, INSN_CLASS_C, "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS|INSN_JSR|INSN_NON_EXACT },
{"jal", 0, INSN_CLASS_I, "a", MATCH_JAL|(X_RA << OP_SH_RD), MASK_JAL|MASK_RD, match_opcode, INSN_ALIAS|INSN_JSR },
{"jal", 0, INSN_CLASS_I, "d,a", MATCH_JAL, MASK_JAL, match_opcode, INSN_JSR },
{"call", 0, INSN_CLASS_I, "d,c", (X_T1 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO },
@@ -509,31 +509,31 @@ const struct riscv_opcode riscv_opcodes[] =
{"tail", 0, INSN_CLASS_ZICFILP, "c", (X_T2 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO },
{"tail", 0, INSN_CLASS_I, "c", (X_T1 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO },
{"jump", 0, INSN_CLASS_I, "c,s", 0, (int) M_CALL, match_rs1_nonzero, INSN_MACRO },
-{"nop", 0, INSN_CLASS_C, "", MATCH_C_ADDI, 0xffff, match_opcode, INSN_ALIAS },
+{"nop", 0, INSN_CLASS_C, "", MATCH_C_ADDI, 0xffff, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"nop", 0, INSN_CLASS_I, "", MATCH_ADDI, MASK_ADDI|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS },
-{"lui", 0, INSN_CLASS_C, "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
+{"lui", 0, INSN_CLASS_C, "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS | INSN_NON_EXACT },
{"lui", 0, INSN_CLASS_I, "d,u", MATCH_LUI, MASK_LUI, match_opcode, 0 },
-{"li", 0, INSN_CLASS_C, "d,Cv", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
-{"li", 0, INSN_CLASS_C, "d,Co", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
+{"li", 0, INSN_CLASS_C, "d,Cv", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS | INSN_NON_EXACT },
+{"li", 0, INSN_CLASS_C, "d,Co", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
{"li", 0, INSN_CLASS_I, "d,j", MATCH_ADDI, MASK_ADDI|MASK_RS1, match_opcode, INSN_ALIAS }, /* addi */
{"li", 0, INSN_CLASS_I, "d,I", 0, (int) M_LI, NULL, INSN_MACRO },
-{"mv", 0, INSN_CLASS_C, "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
+{"mv", 0, INSN_CLASS_C, "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
{"mv", 0, INSN_CLASS_I, "d,s", MATCH_ADDI, MASK_ADDI|MASK_IMM, match_opcode, INSN_ALIAS },
-{"move", 0, INSN_CLASS_C, "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
+{"move", 0, INSN_CLASS_C, "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
{"move", 0, INSN_CLASS_I, "d,s", MATCH_ADDI, MASK_ADDI|MASK_IMM, match_opcode, INSN_ALIAS },
-{"zext.b", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS },
+{"zext.b", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"zext.b", 0, INSN_CLASS_I, "d,s", MATCH_ANDI|ENCODE_ITYPE_IMM (255), MASK_ANDI | MASK_IMM, match_opcode, INSN_ALIAS },
-{"andi", 0, INSN_CLASS_ZCB, "Cs,Cw,Wcf",MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS },
-{"andi", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
+{"andi", 0, INSN_CLASS_ZCB, "Cs,Cw,Wcf",MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"andi", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"andi", 0, INSN_CLASS_I, "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, 0 },
-{"and", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
-{"and", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
-{"and", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
+{"and", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"and", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"and", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"and", 0, INSN_CLASS_I, "d,s,t", MATCH_AND, MASK_AND, match_opcode, 0 },
{"and", 0, INSN_CLASS_I, "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS },
-{"beqz", 0, INSN_CLASS_C, "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
+{"beqz", 0, INSN_CLASS_C, "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH|INSN_NON_EXACT },
{"beqz", 0, INSN_CLASS_I, "s,p", MATCH_BEQ, MASK_BEQ|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
-{"beq", 0, INSN_CLASS_C, "Cs,Cz,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
+{"beq", 0, INSN_CLASS_C, "Cs,Cz,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH|INSN_NON_EXACT },
{"beq", 0, INSN_CLASS_I, "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, INSN_CONDBRANCH },
{"blez", 0, INSN_CLASS_I, "t,p", MATCH_BGE, MASK_BGE|MASK_RS1, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bgez", 0, INSN_CLASS_I, "s,p", MATCH_BGE, MASK_BGE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
@@ -547,23 +547,23 @@ const struct riscv_opcode riscv_opcodes[] =
{"bltu", 0, INSN_CLASS_I, "s,t,p", MATCH_BLTU, MASK_BLTU, match_opcode, INSN_CONDBRANCH },
{"bgt", 0, INSN_CLASS_I, "t,s,p", MATCH_BLT, MASK_BLT, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bgtu", 0, INSN_CLASS_I, "t,s,p", MATCH_BLTU, MASK_BLTU, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
-{"bnez", 0, INSN_CLASS_C, "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
+{"bnez", 0, INSN_CLASS_C, "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH|INSN_NON_EXACT },
{"bnez", 0, INSN_CLASS_I, "s,p", MATCH_BNE, MASK_BNE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
-{"bne", 0, INSN_CLASS_C, "Cs,Cz,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
+{"bne", 0, INSN_CLASS_C, "Cs,Cz,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH|INSN_NON_EXACT },
{"bne", 0, INSN_CLASS_I, "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, INSN_CONDBRANCH },
-{"addi", 0, INSN_CLASS_C, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
-{"addi", 0, INSN_CLASS_C, "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
-{"addi", 0, INSN_CLASS_C, "d,CU,z", MATCH_C_NOP, MASK_C_ADDI|MASK_RVC_IMM, match_c_nop, INSN_ALIAS },
-{"addi", 0, INSN_CLASS_C, "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS },
-{"addi", 0, INSN_CLASS_C, "d,Cz,Co", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
-{"addi", 0, INSN_CLASS_C, "d,CV,z", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
+{"addi", 0, INSN_CLASS_C, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS | INSN_NON_EXACT },
+{"addi", 0, INSN_CLASS_C, "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
+{"addi", 0, INSN_CLASS_C, "d,CU,z", MATCH_C_NOP, MASK_C_ADDI|MASK_RVC_IMM, match_c_nop, INSN_ALIAS | INSN_NON_EXACT },
+{"addi", 0, INSN_CLASS_C, "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS | INSN_NON_EXACT },
+{"addi", 0, INSN_CLASS_C, "d,Cz,Co", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
+{"addi", 0, INSN_CLASS_C, "d,CV,z", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
{"addi", 0, INSN_CLASS_I, "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, 0 },
-{"add", 0, INSN_CLASS_C, "d,CU,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
-{"add", 0, INSN_CLASS_C, "d,CV,CU", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
-{"add", 0, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
-{"add", 0, INSN_CLASS_C, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
-{"add", 0, INSN_CLASS_C, "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS },
-{"add", 0, INSN_CLASS_C, "d,Cz,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
+{"add", 0, INSN_CLASS_C, "d,CU,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
+{"add", 0, INSN_CLASS_C, "d,CV,CU", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
+{"add", 0, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
+{"add", 0, INSN_CLASS_C, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS | INSN_NON_EXACT },
+{"add", 0, INSN_CLASS_C, "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS | INSN_NON_EXACT },
+{"add", 0, INSN_CLASS_C, "d,Cz,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS | INSN_NON_EXACT },
{"add", 0, INSN_CLASS_I, "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, 0 },
{"add", 0, INSN_CLASS_I, "d,s,t,1", MATCH_ADD, MASK_ADD, match_opcode, 0 },
{"add", 0, INSN_CLASS_I, "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS },
@@ -577,44 +577,44 @@ const struct riscv_opcode riscv_opcodes[] =
{"mips.ehb", 0, INSN_CLASS_XMIPSEXECTL, "", MATCH_MIPS_EHB, MASK_MIPS_EHB, match_opcode, 0 },
{"mips.ihb", 0, INSN_CLASS_XMIPSEXECTL, "", MATCH_MIPS_IHB, MASK_MIPS_IHB, match_opcode, 0 },
{"mips.pause", 0, INSN_CLASS_XMIPSEXECTL, "", MATCH_MIPS_PAUSE, MASK_MIPS_PAUSE, match_opcode, 0 },
-{"slli", 0, INSN_CLASS_C, "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_slli_as_c_slli, INSN_ALIAS },
+{"slli", 0, INSN_CLASS_C, "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_slli_as_c_slli, INSN_ALIAS | INSN_NON_EXACT },
{"slli", 0, INSN_CLASS_I, "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, 0 },
-{"sll", 0, INSN_CLASS_C, "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_slli_as_c_slli, INSN_ALIAS },
+{"sll", 0, INSN_CLASS_C, "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_slli_as_c_slli, INSN_ALIAS | INSN_NON_EXACT },
{"sll", 0, INSN_CLASS_I, "d,s,t", MATCH_SLL, MASK_SLL, match_opcode, 0 },
{"sll", 0, INSN_CLASS_I, "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, INSN_ALIAS },
-{"srli", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_srxi_as_c_srxi, INSN_ALIAS },
+{"srli", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_srxi_as_c_srxi, INSN_ALIAS | INSN_NON_EXACT },
{"srli", 0, INSN_CLASS_I, "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, 0 },
-{"srl", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_srxi_as_c_srxi, INSN_ALIAS },
+{"srl", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_srxi_as_c_srxi, INSN_ALIAS | INSN_NON_EXACT },
{"srl", 0, INSN_CLASS_I, "d,s,t", MATCH_SRL, MASK_SRL, match_opcode, 0 },
{"srl", 0, INSN_CLASS_I, "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, INSN_ALIAS },
-{"srai", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_srxi_as_c_srxi, INSN_ALIAS },
+{"srai", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_srxi_as_c_srxi, INSN_ALIAS | INSN_NON_EXACT },
{"srai", 0, INSN_CLASS_I, "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, 0 },
-{"sra", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_srxi_as_c_srxi, INSN_ALIAS },
+{"sra", 0, INSN_CLASS_C, "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_srxi_as_c_srxi, INSN_ALIAS | INSN_NON_EXACT },
{"sra", 0, INSN_CLASS_I, "d,s,t", MATCH_SRA, MASK_SRA, match_opcode, 0 },
{"sra", 0, INSN_CLASS_I, "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, INSN_ALIAS },
-{"sub", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, INSN_ALIAS },
+{"sub", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sub", 0, INSN_CLASS_I, "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, 0 },
{"lb", 0, INSN_CLASS_I, "d,o(s)", MATCH_LB, MASK_LB, match_opcode, INSN_DREF|INSN_1_BYTE },
{"lb", 0, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"lbu", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_LBU, MASK_C_LBU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_1_BYTE },
+{"lbu", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_LBU, MASK_C_LBU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_1_BYTE|INSN_NON_EXACT },
{"lbu", 0, INSN_CLASS_I, "d,o(s)", MATCH_LBU, MASK_LBU, match_opcode, INSN_DREF|INSN_1_BYTE },
{"lbu", 0, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"lh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LH, MASK_C_LH, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
+{"lh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LH, MASK_C_LH, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE|INSN_NON_EXACT },
{"lh", 0, INSN_CLASS_I, "d,o(s)", MATCH_LH, MASK_LH, match_opcode, INSN_DREF|INSN_2_BYTE },
{"lh", 0, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"lhu", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LHU, MASK_C_LHU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
+{"lhu", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LHU, MASK_C_LHU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE|INSN_NON_EXACT },
{"lhu", 0, INSN_CLASS_I, "d,o(s)", MATCH_LHU, MASK_LHU, match_opcode, INSN_DREF|INSN_2_BYTE },
{"lhu", 0, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"lw", 0, INSN_CLASS_C, "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
-{"lw", 0, INSN_CLASS_C, "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
+{"lw", 0, INSN_CLASS_C, "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
+{"lw", 0, INSN_CLASS_C, "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
{"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_Lx, match_rd_nonzero, INSN_MACRO },
-{"not", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_NOT, MASK_C_NOT, match_opcode, INSN_ALIAS },
+{"not", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_NOT, MASK_C_NOT, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"not", 0, INSN_CLASS_I, "d,s", MATCH_XORI|MASK_IMM, MASK_XORI|MASK_IMM, match_opcode, INSN_ALIAS },
{"ori", 0, INSN_CLASS_I, "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, 0 },
{"or", 0, INSN_CLASS_I, "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, INSN_ALIAS },
-{"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 },
+{"or", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"or", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"or", 0, INSN_CLASS_I, "d,s,t", MATCH_OR, MASK_OR, match_opcode, 0 },
/* Zicfilp instructions. */
@@ -633,14 +633,14 @@ const struct riscv_opcode riscv_opcodes[] =
{"sltu", 0, INSN_CLASS_I, "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, INSN_ALIAS },
{"sgt", 0, INSN_CLASS_I, "d,t,s", MATCH_SLT, MASK_SLT, match_opcode, INSN_ALIAS },
{"sgtu", 0, INSN_CLASS_I, "d,t,s", MATCH_SLTU, MASK_SLTU, match_opcode, INSN_ALIAS },
-{"sb", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_SB, MASK_C_SB, match_opcode, INSN_DREF|INSN_1_BYTE|INSN_ALIAS },
+{"sb", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_SB, MASK_C_SB, match_opcode, INSN_DREF|INSN_1_BYTE|INSN_ALIAS|INSN_NON_EXACT },
{"sb", 0, INSN_CLASS_I, "t,q(s)", MATCH_SB, MASK_SB, match_opcode, INSN_DREF|INSN_1_BYTE },
{"sb", 0, INSN_CLASS_I, "t,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
-{"sh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_SH, MASK_C_SH, match_opcode, INSN_DREF|INSN_2_BYTE|INSN_ALIAS },
+{"sh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_SH, MASK_C_SH, match_opcode, INSN_DREF|INSN_2_BYTE|INSN_ALIAS|INSN_NON_EXACT },
{"sh", 0, INSN_CLASS_I, "t,q(s)", MATCH_SH, MASK_SH, match_opcode, INSN_DREF|INSN_2_BYTE },
{"sh", 0, INSN_CLASS_I, "t,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
-{"sw", 0, INSN_CLASS_C, "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
-{"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_C, "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
+{"sw", 0, INSN_CLASS_C, "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
{"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_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
{"fence", 0, INSN_CLASS_I, "", MATCH_FENCE|MASK_PRED|MASK_SUCC, MASK_FENCE|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS },
@@ -657,34 +657,34 @@ const struct riscv_opcode riscv_opcodes[] =
{"scall", 0, INSN_CLASS_I, "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
{"xori", 0, INSN_CLASS_I, "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, 0 },
{"xor", 0, INSN_CLASS_I, "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, INSN_ALIAS },
-{"xor", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
-{"xor", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
+{"xor", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"xor", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"xor", 0, INSN_CLASS_I, "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, 0 },
{"lwu", 64, INSN_CLASS_I, "d,o(s)", MATCH_LWU, MASK_LWU, match_opcode, INSN_DREF|INSN_4_BYTE },
{"lwu", 64, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"ld", 64, INSN_CLASS_C, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"ld", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"ld", 64, INSN_CLASS_C, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"ld", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"ld", 64, INSN_CLASS_I, "d,o(s)", MATCH_LD, MASK_LD, match_opcode, INSN_DREF|INSN_8_BYTE },
{"ld", 64, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
-{"ld", 32, INSN_CLASS_ZCLSD, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_even_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"ld", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"ld", 32, INSN_CLASS_ZCLSD, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_even_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"ld", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"ld", 32, INSN_CLASS_ZILSD, "d,o(s)", MATCH_LD, MASK_LD, match_rd_even, INSN_DREF|INSN_8_BYTE },
{"ld", 32, INSN_CLASS_ZILSD, "d,A", 0, (int) M_Lx, match_rd_even_nonzero, INSN_MACRO },
-{"sd", 64, INSN_CLASS_C, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"sd", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"sd", 64, INSN_CLASS_C, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"sd", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"sd", 64, INSN_CLASS_I, "t,q(s)", MATCH_SD, MASK_SD, match_opcode, INSN_DREF|INSN_8_BYTE },
{"sd", 64, INSN_CLASS_I, "t,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
-{"sd", 32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_crs2_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"sd", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"sd", 32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_crs2_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"sd", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"sd", 32, INSN_CLASS_ZILSD, "t,q(s)", MATCH_SD, MASK_SD, match_rs2_even, INSN_DREF|INSN_8_BYTE },
{"sd", 32, INSN_CLASS_ZILSD, "t,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero_rs2_even, INSN_MACRO },
-{"sext.w", 64, INSN_CLASS_C, "d,CU", MATCH_C_ADDIW, MASK_C_ADDIW|MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
+{"sext.w", 64, INSN_CLASS_C, "d,CU", MATCH_C_ADDIW, MASK_C_ADDIW|MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
{"sext.w", 64, INSN_CLASS_I, "d,s", MATCH_ADDIW, MASK_ADDIW|MASK_IMM, match_opcode, INSN_ALIAS },
-{"addiw", 64, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
+{"addiw", 64, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
{"addiw", 64, INSN_CLASS_I, "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, 0 },
-{"addw", 64, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
-{"addw", 64, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
-{"addw", 64, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
+{"addw", 64, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"addw", 64, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
+{"addw", 64, INSN_CLASS_C, "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS | INSN_NON_EXACT },
{"addw", 64, INSN_CLASS_I, "d,s,t", MATCH_ADDW, MASK_ADDW, match_opcode, 0 },
{"addw", 64, INSN_CLASS_I, "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, INSN_ALIAS },
{"negw", 64, INSN_CLASS_I, "d,t", MATCH_SUBW, MASK_SUBW|MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0 */
@@ -697,7 +697,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"sraiw", 64, INSN_CLASS_I, "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, 0 },
{"sraw", 64, INSN_CLASS_I, "d,s,t", MATCH_SRAW, MASK_SRAW, match_opcode, 0 },
{"sraw", 64, INSN_CLASS_I, "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, INSN_ALIAS },
-{"subw", 64, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_SUBW, MASK_C_SUBW, match_opcode, INSN_ALIAS },
+{"subw", 64, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_SUBW, MASK_C_SUBW, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"subw", 64, INSN_CLASS_I, "d,s,t", MATCH_SUBW, MASK_SUBW, match_opcode, 0 },
/* Atomic memory operation instruction subset. */
@@ -891,7 +891,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"amocas.q.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_AQRL, MASK_AMOCAS_Q|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_16_BYTE },
/* Multiply/Divide instruction subset. */
-{"mul", 0, INSN_CLASS_ZCB_AND_ZMMUL, "Cs,Cw,Ct", MATCH_C_MUL, MASK_C_MUL, match_opcode, INSN_ALIAS },
+{"mul", 0, INSN_CLASS_ZCB_AND_ZMMUL, "Cs,Cw,Ct", MATCH_C_MUL, MASK_C_MUL, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"mul", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MUL, MASK_MUL, match_opcode, 0 },
{"mulh", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MULH, MASK_MULH, match_opcode, 0 },
{"mulhu", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MULHU, MASK_MULHU, match_opcode, 0 },
@@ -993,12 +993,12 @@ const struct riscv_opcode riscv_opcodes[] =
{"fsflags", 0, INSN_CLASS_F_INX, "d,s", MATCH_FSFLAGS, MASK_FSFLAGS, match_opcode, INSN_ALIAS },
{"fsflagsi", 0, INSN_CLASS_F_INX, "d,Z", MATCH_FSFLAGSI, MASK_FSFLAGSI, match_opcode, INSN_ALIAS },
{"fsflagsi", 0, INSN_CLASS_F_INX, "Z", MATCH_FSFLAGSI, MASK_FSFLAGSI|MASK_RD, match_opcode, INSN_ALIAS },
-{"flw", 32, INSN_CLASS_F_AND_C, "D,Cm(Cc)", MATCH_C_FLWSP, MASK_C_FLWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
-{"flw", 32, INSN_CLASS_F_AND_C, "CD,Ck(Cs)", MATCH_C_FLW, MASK_C_FLW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
+{"flw", 32, INSN_CLASS_F_AND_C, "D,Cm(Cc)", MATCH_C_FLWSP, MASK_C_FLWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
+{"flw", 32, INSN_CLASS_F_AND_C, "CD,Ck(Cs)", MATCH_C_FLW, MASK_C_FLW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
{"flw", 0, INSN_CLASS_F, "D,o(s)", MATCH_FLW, MASK_FLW, match_opcode, INSN_DREF|INSN_4_BYTE },
{"flw", 0, INSN_CLASS_F, "D,A,s", 0, (int) M_FLx, match_rs1_nonzero, INSN_MACRO },
-{"fsw", 32, INSN_CLASS_F_AND_C, "CT,CM(Cc)", MATCH_C_FSWSP, MASK_C_FSWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
-{"fsw", 32, INSN_CLASS_F_AND_C, "CD,Ck(Cs)", MATCH_C_FSW, MASK_C_FSW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
+{"fsw", 32, INSN_CLASS_F_AND_C, "CT,CM(Cc)", MATCH_C_FSWSP, MASK_C_FSWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
+{"fsw", 32, INSN_CLASS_F_AND_C, "CD,Ck(Cs)", MATCH_C_FSW, MASK_C_FSW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE|INSN_NON_EXACT },
{"fsw", 0, INSN_CLASS_F, "T,q(s)", MATCH_FSW, MASK_FSW, match_opcode, INSN_DREF|INSN_4_BYTE },
{"fsw", 0, INSN_CLASS_F, "T,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
{"fmv.x.w", 0, INSN_CLASS_F, "d,S", MATCH_FMV_X_S, MASK_FMV_X_S, match_opcode, 0 },
@@ -1055,12 +1055,12 @@ const struct riscv_opcode riscv_opcodes[] =
{"fcvt.s.lu", 64, INSN_CLASS_F_INX, "D,s,m", MATCH_FCVT_S_LU, MASK_FCVT_S_LU, match_opcode, 0 },
/* Double-precision floating-point instruction subset. */
-{"fld", 0, INSN_CLASS_D_AND_C, "D,Cn(Cc)", MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"fld", 0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"fld", 0, INSN_CLASS_D_AND_C, "D,Cn(Cc)", MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"fld", 0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"fld", 0, INSN_CLASS_D, "D,o(s)", MATCH_FLD, MASK_FLD, match_opcode, INSN_DREF|INSN_8_BYTE },
{"fld", 0, INSN_CLASS_D, "D,A,s", 0, (int) M_FLx, match_rs1_nonzero, INSN_MACRO },
-{"fsd", 0, INSN_CLASS_D_AND_C, "CT,CN(Cc)", MATCH_C_FSDSP, MASK_C_FSDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
-{"fsd", 0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FSD, MASK_C_FSD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
+{"fsd", 0, INSN_CLASS_D_AND_C, "CT,CN(Cc)", MATCH_C_FSDSP, MASK_C_FSDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
+{"fsd", 0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FSD, MASK_C_FSD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE|INSN_NON_EXACT },
{"fsd", 0, INSN_CLASS_D, "T,q(s)", MATCH_FSD, MASK_FSD, match_opcode, INSN_DREF|INSN_8_BYTE },
{"fsd", 0, INSN_CLASS_D, "T,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
{"fmv.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJ_D, MASK_FSGNJ_D, match_rs1_eq_rs2, INSN_ALIAS },
@@ -1237,9 +1237,9 @@ const struct riscv_opcode riscv_opcodes[] =
{"czero.nez", 0, INSN_CLASS_ZICOND, "d,s,t", MATCH_CZERO_NEZ, MASK_CZERO_NEZ, match_opcode, 0 },
/* Zicfiss instructions. */
-{"sspush", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPUSH, MASK_C_SSPUSH, match_rd_x1x5_opcode, INSN_ALIAS },
+{"sspush", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPUSH, MASK_C_SSPUSH, match_rd_x1x5_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sspush", 0, INSN_CLASS_ZICFISS, "t", MATCH_SSPUSH, MASK_SSPUSH, match_rs2_x1x5_opcode, 0 },
-{"sspopchk", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPOPCHK, MASK_C_SSPOPCHK, match_rd_x1x5_opcode, INSN_ALIAS },
+{"sspopchk", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPOPCHK, MASK_C_SSPOPCHK, match_rd_x1x5_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sspopchk", 0, INSN_CLASS_ZICFISS, "s", MATCH_SSPOPCHK, MASK_SSPOPCHK, match_rs1_x1x5_opcode, 0 },
{"c.sspush", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPUSH, MASK_C_SSPUSH, match_rd_x1x5_opcode, 0 },
{"c.sspopchk", 0, INSN_CLASS_ZICFISS_AND_ZCMOP, "d", MATCH_C_SSPOPCHK, MASK_C_SSPOPCHK, match_rd_x1x5_opcode, 0 },
@@ -1350,13 +1350,13 @@ const struct riscv_opcode riscv_opcodes[] =
{"max", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MAX, MASK_MAX, match_opcode, 0 },
{"minu", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MINU, MASK_MINU, match_opcode, 0 },
{"maxu", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MAXU, MASK_MAXU, match_opcode, 0 },
-{"sext.b", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_B, MASK_C_SEXT_B, match_opcode, INSN_ALIAS },
+{"sext.b", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_B, MASK_C_SEXT_B, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sext.b", 0, INSN_CLASS_ZBB, "d,s", MATCH_SEXT_B, MASK_SEXT_B, match_opcode, 0 },
{"sext.b", 0, INSN_CLASS_I, "d,s", 0, (int) M_SEXTB, NULL, INSN_MACRO },
-{"sext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_H, MASK_C_SEXT_H, match_opcode, INSN_ALIAS },
+{"sext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_H, MASK_C_SEXT_H, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"sext.h", 0, INSN_CLASS_ZBB, "d,s", MATCH_SEXT_H, MASK_SEXT_H, match_opcode, 0 },
{"sext.h", 0, INSN_CLASS_I, "d,s", 0, (int) M_EXTH, NULL, INSN_MACRO },
-{"zext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_ZEXT_H, MASK_C_ZEXT_H, match_opcode, INSN_ALIAS },
+{"zext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_ZEXT_H, MASK_C_ZEXT_H, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"zext.h", 32, INSN_CLASS_ZBB_OR_ZBKB, "d,s", MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, 0 },
{"zext.h", 64, INSN_CLASS_ZBB_OR_ZBKB, "d,s", MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, 0 },
{"zext.h", 0, INSN_CLASS_I, "d,s", 0, (int) M_EXTH, NULL, INSN_MACRO },
@@ -1392,7 +1392,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"sh1add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH1ADD_UW, MASK_SH1ADD_UW, match_opcode, 0 },
{"sh2add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH2ADD_UW, MASK_SH2ADD_UW, match_opcode, 0 },
{"sh3add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH3ADD_UW, MASK_SH3ADD_UW, match_opcode, 0 },
-{"zext.w", 64, INSN_CLASS_ZCB_AND_ZBA, "Cs,Cw", MATCH_C_ZEXT_W, MASK_C_ZEXT_W, match_opcode, INSN_ALIAS },
+{"zext.w", 64, INSN_CLASS_ZCB_AND_ZBA, "Cs,Cw", MATCH_C_ZEXT_W, MASK_C_ZEXT_W, match_opcode, INSN_ALIAS | INSN_NON_EXACT },
{"zext.w", 64, INSN_CLASS_ZBA, "d,s", MATCH_ADD_UW, MASK_ADD_UW | MASK_RS2, match_opcode, INSN_ALIAS },
{"zext.w", 64, INSN_CLASS_I, "d,s", 0, (int) M_ZEXTW, NULL, INSN_MACRO },
{"add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_ADD_UW, MASK_ADD_UW, match_opcode, 0 },
--
2.43.0
More information about the Binutils
mailing list