aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-05-25 16:11:08 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-05-27 12:30:13 -0700
commit164ad4affd15511dfa12f1394aade4adba3c3cb8 (patch)
tree7038b3c6c5d05dd7f08c9d0e701557f776bb4cc7 /binutils
parent24565255e250769a2aa7203872d693eb9083d272 (diff)
downloadriscv-gnu-toolchain-164ad4affd15511dfa12f1394aade4adba3c3cb8.zip
riscv-gnu-toolchain-164ad4affd15511dfa12f1394aade4adba3c3cb8.tar.gz
riscv-gnu-toolchain-164ad4affd15511dfa12f1394aade4adba3c3cb8.tar.bz2
binutils: complete implementation of RVC v1.7 draft
Diffstat (limited to 'binutils')
-rw-r--r--binutils/gas/config/tc-riscv.c275
-rw-r--r--binutils/include/opcode/riscv-opc.h133
-rw-r--r--binutils/include/opcode/riscv.h51
-rw-r--r--binutils/opcodes/riscv-dis.c49
-rw-r--r--binutils/opcodes/riscv-opc.c195
5 files changed, 486 insertions, 217 deletions
diff --git a/binutils/gas/config/tc-riscv.c b/binutils/gas/config/tc-riscv.c
index cdc0a51..0faad26 100644
--- a/binutils/gas/config/tc-riscv.c
+++ b/binutils/gas/config/tc-riscv.c
@@ -60,6 +60,8 @@ bfd_boolean rv64 = TRUE; /* RV64 (true) or RV32 (false) */
#define LOAD_ADDRESS_INSN (rv64 ? "ld" : "lw")
#define ADD32_INSN (rv64 ? "addiw" : "addi")
+unsigned elf_flags = 0;
+
/* This is the set of options which the .option pseudo-op may modify. */
struct riscv_set_options
@@ -128,6 +130,7 @@ riscv_set_arch (const char* arg)
FIXME: Version numbers are not supported yet. */
const char* subsets = "IMAFDC";
+ const char* extension = NULL;
const char* p;
int rvc = 0;
@@ -173,6 +176,12 @@ riscv_set_arch (const char* arg)
while (ISLOWER(*q));
*q = 0;
+ if (extension)
+ as_bad ("only one eXtension is supported (found %s and %s)",
+ extension, subset);
+ extension = subset;
+ EF_SET_RISCV_EXT (elf_flags, riscv_elf_name_to_flag (subset));
+
riscv_add_subset (subset);
p += strlen (subset);
free (subset);
@@ -224,13 +233,6 @@ const char EXP_CHARS[] = "eE";
/* or 0d1.2345e12 */
const char FLT_CHARS[] = "rRsSfFdDxXpP";
-/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
- changed in read.c . Ideally it shouldn't have to know about it at all,
- but nothing is ideal around here.
- */
-
-static char *insn_error;
-
#define RELAX_BRANCH_ENCODE(uncond, rvc, length) \
((relax_substateT) \
(0xc0000000 \
@@ -551,15 +553,26 @@ validate_riscv_insn (const struct riscv_opcode *opc)
{
case 'd': USE_BITS (OP_MASK_CRDS, OP_SH_CRDS); break;
case 's': USE_BITS (OP_MASK_CRS1S, OP_SH_CRS1S); break;
- case 'S': USE_BITS (OP_MASK_CRS1, OP_SH_CRS1); break;
+ case 't': USE_BITS (OP_MASK_CRS2S, OP_SH_CRS2S); break;
+ case 'w': break; /* RS1S, constrained to equal RD */
+ case 'x': break; /* RS1S, constrained to equal RD */
+ case 'D': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
+ case 'T': USE_BITS (OP_MASK_CRS2, OP_SH_CRS2); break;
+ case 'V': USE_BITS (OP_MASK_CRS2, OP_SH_CRS2); break;
case 'c': break; /* RS1, constrained to equal sp */
case 'U': break; /* RS2, constrained to equal RD */
+ case '<': used_bits |= ENCODE_RVC_IMM(-1U); break;
case '>': used_bits |= ENCODE_RVC_IMM(-1U); break;
+ case 'i': used_bits |= ENCODE_RVC_SIMM3(-1U); break;
case 'j': used_bits |= ENCODE_RVC_IMM(-1U); break;
case 'k': used_bits |= ENCODE_RVC_LW_IMM(-1U); break;
case 'l': used_bits |= ENCODE_RVC_LD_IMM(-1U); break;
case 'm': used_bits |= ENCODE_RVC_LWSP_IMM(-1U); break;
case 'n': used_bits |= ENCODE_RVC_LDSP_IMM(-1U); break;
+ case 'K': used_bits |= ENCODE_RVC_ADDI4SPN_IMM(-1U); break;
+ case 'L': used_bits |= ENCODE_RVC_ADDI16SP_IMM(-1U); break;
+ case 'M': used_bits |= ENCODE_RVC_SWSP_IMM(-1U); break;
+ case 'N': used_bits |= ENCODE_RVC_SDSP_IMM(-1U); break;
case 'u': used_bits |= ENCODE_RVC_IMM(-1U); break;
case 'v': used_bits |= ENCODE_RVC_IMM(-1U); break;
case 'a': used_bits |= ENCODE_RVC_J_IMM(-1U); break;
@@ -638,12 +651,6 @@ md_begin (void)
{
const char *name = riscv_opcodes[i].name;
- if (!riscv_subset_supports(riscv_opcodes[i].subset))
- {
- i++;
- continue;
- }
-
retval = hash_insert (op_hash, name, (void *) &riscv_opcodes[i]);
if (retval != NULL)
@@ -1219,78 +1226,40 @@ my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
side effect, it sets the global variable imm_reloc to the type of
relocation to do if one of the operands is an address expression. */
-static void
+static const char *
riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
bfd_reloc_code_real_type *imm_reloc)
{
char *s;
const char *args;
char c = 0;
- struct riscv_opcode *insn;
+ struct riscv_opcode *insn, *end = &riscv_opcodes[NUMOPCODES];
char *argsStart;
unsigned int regno;
char save_c = 0;
int argnum;
const struct percent_op_match *p;
+ const char *error = "unrecognized opcode";
- insn_error = NULL;
-
- /* If the instruction contains a '.', we first try to match an instruction
- including the '.'. Then we try again without the '.'. */
- insn = NULL;
- for (s = str; *s != '\0' && !ISSPACE (*s); ++s)
- continue;
-
- /* If we stopped on whitespace, then replace the whitespace with null for
- the call to hash_find. Save the character we replaced just in case we
- have to re-parse the instruction. */
- if (ISSPACE (*s))
- {
- save_c = *s;
- *s++ = '\0';
- }
+ /* Parse the name of the instruction. Terminate the string if whitespace
+ is found so that hash_find only sees the name part of the string. */
+ for (s = str; *s != '\0'; ++s)
+ if (ISSPACE (*s))
+ {
+ save_c = *s;
+ *s++ = '\0';
+ break;
+ }
insn = (struct riscv_opcode *) hash_find (op_hash, str);
- /* If we didn't find the instruction in the opcode table, try again, but
- this time with just the instruction up to, but not including the
- first '.'. */
- if (insn == NULL)
- {
- /* Restore the character we overwrite above (if any). */
- if (save_c)
- *(--s) = save_c;
-
- /* Scan up to the first '.' or whitespace. */
- for (s = str;
- *s != '\0' && *s != '.' && !ISSPACE (*s);
- ++s)
- continue;
-
- /* If we did not find a '.', then we can quit now. */
- if (*s != '.')
- {
- insn_error = "unrecognized opcode";
- return;
- }
-
- /* Lookup the instruction in the hash table. */
- *s++ = '\0';
- if ((insn = (struct riscv_opcode *) hash_find (op_hash, str)) == NULL)
- {
- insn_error = "unrecognized opcode";
- return;
- }
- }
-
argsStart = s;
- for (;;)
+ for ( ; insn && insn < end && strcmp (insn->name, str) == 0; insn++)
{
- bfd_boolean ok;
- gas_assert (strcmp (insn->name, str) == 0);
+ if (!riscv_subset_supports (insn->subset))
+ continue;
create_insn (ip, insn);
- insn_error = NULL;
argnum = 1;
imm_expr->X_op = O_absent;
@@ -1308,7 +1277,10 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
&& !riscv_opts.rvc)
break;
if (*s == '\0')
- return;
+ {
+ error = NULL;
+ goto out;
+ }
break;
/* Xcustom */
case '^':
@@ -1375,50 +1347,42 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
s = expr_end;
continue;
case 'd':
- ok = reg_lookup( &s, RCLASS_VEC_GPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VRD, *ip, regno );
continue;
case 's':
- ok = reg_lookup( &s, RCLASS_VEC_GPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VRS, *ip, regno );
continue;
case 't':
- ok = reg_lookup( &s, RCLASS_VEC_GPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VRT, *ip, regno );
continue;
case 'r':
- ok = reg_lookup( &s, RCLASS_VEC_GPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VRR, *ip, regno );
continue;
case 'D':
- ok = reg_lookup( &s, RCLASS_VEC_FPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VFD, *ip, regno );
continue;
case 'S':
- ok = reg_lookup( &s, RCLASS_VEC_FPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VFS, *ip, regno );
continue;
case 'T':
- ok = reg_lookup( &s, RCLASS_VEC_FPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VFT, *ip, regno );
continue;
case 'R':
- ok = reg_lookup( &s, RCLASS_VEC_FPR, &regno );
- if ( !ok )
+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
as_bad( _( "Invalid vector register" ) );
INSERT_OPERAND( VFR, *ip, regno );
continue;
@@ -1440,16 +1404,42 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
break;
INSERT_OPERAND (CRS1S, *ip, regno % 8);
continue;
- case 'S': /* RS1 */
- if (!reg_lookup (&s, RCLASS_GPR, &regno))
+ case 'w': /* RS1 x8-x15, constrained to equal RD x8-x15 */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
+ || EXTRACT_OPERAND (CRS1S, *ip) + 8 != regno)
+ break;
+ continue;
+ case 't': /* RS2 x8-x15 */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
+ || !(regno >= 8 && regno <= 15))
+ break;
+ INSERT_OPERAND (CRS2S, *ip, regno % 8);
+ continue;
+ case 'x': /* RS2 x8-x15, constrained to equal RD x8-x15 */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
+ || EXTRACT_OPERAND (CRS2S, *ip) + 8 != regno)
+ break;
+ continue;
+ case 'D': /* RD, nonzero */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno) || regno == 0)
break;
- INSERT_OPERAND (CRS1, *ip, regno);
+ INSERT_OPERAND (RD, *ip, regno);
continue;
- case 'U': /* RS2, constrained to equal RD */
+ case 'U': /* RS1, constrained to equal RD */
if (!reg_lookup (&s, RCLASS_GPR, &regno)
|| EXTRACT_OPERAND (RD, *ip) != regno)
break;
continue;
+ case 'T': /* RS2, nonzero */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno) || regno == 0)
+ break;
+ INSERT_OPERAND (CRS2, *ip, regno);
+ continue;
+ case 'V': /* RS2 */
+ if (!reg_lookup (&s, RCLASS_GPR, &regno))
+ break;
+ INSERT_OPERAND (CRS2, *ip, regno);
+ continue;
case 'c': /* RS1, constrained to equal sp */
if (!reg_lookup (&s, RCLASS_GPR, &regno)
|| regno != X_SP)
@@ -1458,16 +1448,35 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
case '>':
if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
|| imm_expr->X_op != O_constant
- || !VALID_RVC_IMM (imm_expr->X_add_number - 32))
+ || imm_expr->X_add_number <= 0
+ || imm_expr->X_add_number >= 64)
break;
ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
rvc_imm_done:
s = expr_end;
imm_expr->X_op = O_absent;
continue;
+ case '<':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_RVC_IMM (imm_expr->X_add_number)
+ || imm_expr->X_add_number <= 0
+ || imm_expr->X_add_number >= 32)
+ break;
+ ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case 'i':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || imm_expr->X_add_number == 0
+ || !VALID_RVC_SIMM3 (imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_RVC_SIMM3 (imm_expr->X_add_number);
+ goto rvc_imm_done;
case 'j':
if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
|| imm_expr->X_op != O_constant
+ || imm_expr->X_add_number == 0
|| !VALID_RVC_IMM (imm_expr->X_add_number))
break;
ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
@@ -1500,13 +1509,41 @@ rvc_imm_done:
break;
ip->insn_opcode |= ENCODE_RVC_LDSP_IMM (imm_expr->X_add_number);
goto rvc_imm_done;
+ case 'K':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_RVC_ADDI4SPN_IMM (imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_RVC_ADDI4SPN_IMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case 'L':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_RVC_ADDI16SP_IMM (imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_RVC_ADDI16SP_IMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case 'M':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_RVC_SWSP_IMM (imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_RVC_SWSP_IMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case 'N':
+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_RVC_SDSP_IMM (imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_RVC_SDSP_IMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
case 'u':
p = percent_op_utype;
if (my_getSmallExpression (imm_expr, imm_reloc, s, p))
break;
rvc_lui:
if (imm_expr->X_op != O_constant
- || imm_expr->X_add_number < 0
+ || imm_expr->X_add_number <= 0
|| imm_expr->X_add_number >= RISCV_BIGIMM_REACH
|| (imm_expr->X_add_number >= RISCV_RVC_IMM_REACH/2
&& imm_expr->X_add_number <
@@ -1581,8 +1618,7 @@ rvc_lui:
continue;
case 'E': /* Control register. */
- ok = reg_lookup (&s, RCLASS_CSR, &regno);
- if (ok)
+ if (reg_lookup (&s, RCLASS_CSR, &regno))
INSERT_OPERAND (CSR, *ip, regno);
else
{
@@ -1620,8 +1656,7 @@ rvc_lui:
case 'd': /* destination register */
case 's': /* source register */
case 't': /* target register */
- ok = reg_lookup (&s, RCLASS_GPR, &regno);
- if (ok)
+ if (reg_lookup (&s, RCLASS_GPR, &regno))
{
c = *args;
if (*s == ' ')
@@ -1682,7 +1717,7 @@ rvc_lui:
my_getExpression (imm_expr, s);
if (imm_expr->X_op != O_big
&& imm_expr->X_op != O_constant)
- insn_error = _("absolute expression required");
+ break;
normalize_constant_expr (imm_expr);
s = expr_end;
continue;
@@ -1777,20 +1812,16 @@ jump:
}
break;
}
- /* Args don't match. */
- if (insn + 1 < &riscv_opcodes[NUMOPCODES] &&
- !strcmp (insn->name, insn[1].name))
- {
- ++insn;
- s = argsStart;
- insn_error = _("illegal operands");
- continue;
- }
- if (save_c)
- *(--argsStart) = save_c;
- insn_error = _("illegal operands");
- return;
+ s = argsStart;
+ error = _("illegal operands");
}
+
+out:
+ /* Restore the character we might have clobbered above. */
+ if (save_c)
+ *(argsStart - 1) = save_c;
+
+ return error;
}
void
@@ -1800,11 +1831,11 @@ md_assemble (char *str)
expressionS imm_expr;
bfd_reloc_code_real_type imm_reloc = BFD_RELOC_UNUSED;
- riscv_ip (str, &insn, &imm_expr, &imm_reloc);
+ const char *error = riscv_ip (str, &insn, &imm_expr, &imm_reloc);
- if (insn_error)
+ if (error)
{
- as_bad ("%s `%s'", insn_error, str);
+ as_bad ("%s `%s'", error, str);
return;
}
@@ -2268,10 +2299,16 @@ md_convert_frag_branch (fragS *fragp)
rs1 = 8 + ((insn >> OP_SH_CRS1S) & OP_MASK_CRS1S);
if ((insn & MASK_C_J) == MATCH_C_J)
insn = MATCH_JAL;
+ else if ((insn & MASK_C_JAL) == MATCH_C_JAL)
+ insn = MATCH_JAL | (X_RA << OP_SH_RD);
else if ((insn & MASK_C_BEQZ) == MATCH_C_BEQZ)
insn = MATCH_BEQ | (rs1 << OP_SH_RS1);
else if ((insn & MASK_C_BNEZ) == MATCH_C_BNEZ)
insn = MATCH_BNE | (rs1 << OP_SH_RS1);
+ else if ((insn & MASK_C_BLTZ) == MATCH_C_BLTZ)
+ insn = MATCH_BLT | (rs1 << OP_SH_RS1);
+ else if ((insn & MASK_C_BGEZ) == MATCH_C_BGEZ)
+ insn = MATCH_BGE | (rs1 << OP_SH_RS1);
else
abort ();
bfd_putl32 (insn, buf);
@@ -2380,21 +2417,7 @@ tc_riscv_regname_to_dw2regnum (char *regname)
void
riscv_elf_final_processing (void)
{
- struct riscv_subset* s;
-
- unsigned int Xlen = 0;
- for (s = riscv_subsets; s != NULL; s = s->next)
- if (s->name[0] == 'X')
- Xlen += strlen(s->name);
-
- char extension[Xlen];
- extension[0] = 0;
- for (s = riscv_subsets; s != NULL; s = s->next)
- if (s->name[0] == 'X')
- strcat(extension, s->name);
-
- EF_SET_RISCV_EXT(elf_elfheader (stdoutput)->e_flags,
- riscv_elf_name_to_flag (extension));
+ elf_elfheader (stdoutput)->e_flags |= elf_flags;
}
/* Pseudo-op table. */
diff --git a/binutils/include/opcode/riscv-opc.h b/binutils/include/opcode/riscv-opc.h
index e0ab6a2..a479406 100644
--- a/binutils/include/opcode/riscv-opc.h
+++ b/binutils/include/opcode/riscv-opc.h
@@ -63,48 +63,106 @@
#define MASK_BLTU 0x707f
#define MATCH_BNE 0x1063
#define MASK_BNE 0x707f
-#define MATCH_C_ADD 0x6000
+#define MATCH_C_ADD 0x1000
#define MASK_C_ADD 0xf003
-#define MATCH_C_ADDI 0x8000
+#define MATCH_C_ADD3 0xa000
+#define MASK_C_ADD3 0xe063
+#define MATCH_C_ADDI 0xc002
#define MASK_C_ADDI 0xe003
-#define MATCH_C_ADDI4 0xa000
-#define MASK_C_ADDI4 0xe003
-#define MATCH_C_ADDIW 0xe000
+#define MATCH_C_ADDI16SP 0xc002
+#define MASK_C_ADDI16SP 0xef83
+#define MATCH_C_ADDI4SPN 0xa001
+#define MASK_C_ADDI4SPN 0xe003
+#define MATCH_C_ADDIN 0x8001
+#define MASK_C_ADDIN 0xe063
+#define MATCH_C_ADDIW 0xe002
#define MASK_C_ADDIW 0xe003
-#define MATCH_C_ADDW 0x7000
+#define MATCH_C_ADDW 0x9000
#define MASK_C_ADDW 0xf003
-#define MATCH_C_BEQZ 0x2002
+#define MATCH_C_AND3 0xa060
+#define MASK_C_AND3 0xe063
+#define MATCH_C_ANDI 0xe002
+#define MASK_C_ANDI 0xe003
+#define MATCH_C_ANDIN 0x8061
+#define MASK_C_ANDIN 0xe063
+#define MATCH_C_BEQZ 0x4002
#define MASK_C_BEQZ 0xe003
+#define MATCH_C_BGEZ 0xe001
+#define MASK_C_BGEZ 0xe003
+#define MATCH_C_BLTZ 0x6001
+#define MASK_C_BLTZ 0xe003
#define MATCH_C_BNEZ 0x6002
#define MASK_C_BNEZ 0xe003
-#define MATCH_C_J 0xa002
+#define MATCH_C_EBREAK 0x1000
+#define MASK_C_EBREAK 0xffff
+#define MATCH_C_J 0x2
#define MASK_C_J 0xe003
-#define MATCH_C_JALR 0x5000
-#define MASK_C_JALR 0xf003
-#define MATCH_C_LD 0x2001
+#define MATCH_C_JAL 0x2002
+#define MASK_C_JAL 0xe003
+#define MATCH_C_JALR 0xa002
+#define MASK_C_JALR 0xf07f
+#define MATCH_C_JR 0x8002
+#define MASK_C_JR 0xf07f
+#define MATCH_C_LD 0xe000
#define MASK_C_LD 0xe003
-#define MATCH_C_LDSP 0xc001
+#define MATCH_C_LDSP 0xe001
#define MASK_C_LDSP 0xe003
-#define MATCH_C_LI 0x0
+#define MATCH_C_LI 0x8002
#define MASK_C_LI 0xe003
-#define MATCH_C_LUI 0x2000
+#define MATCH_C_LUI 0xa002
#define MASK_C_LUI 0xe003
-#define MATCH_C_LW 0x1
+#define MATCH_C_LW 0xc000
#define MASK_C_LW 0xe003
-#define MATCH_C_LWSP 0x8001
+#define MATCH_C_LWSP 0xc001
#define MASK_C_LWSP 0xe003
-#define MATCH_C_MV 0x4000
+#define MATCH_C_MV 0x0
#define MASK_C_MV 0xf003
-#define MATCH_C_SD 0x6001
+#define MATCH_C_OR3 0xa040
+#define MASK_C_OR3 0xe063
+#define MATCH_C_ORIN 0x8041
+#define MASK_C_ORIN 0xe063
+#define MATCH_C_SD 0x6000
#define MASK_C_SD 0xe003
-#define MATCH_C_SDSP 0xe001
+#define MATCH_C_SDSP 0x6001
#define MASK_C_SDSP 0xe003
-#define MATCH_C_SLLI 0xc000
+#define MATCH_C_SLL 0x6400
+#define MASK_C_SLL 0xfc63
+#define MATCH_C_SLLI 0x1
#define MASK_C_SLLI 0xe003
-#define MATCH_C_SW 0x4001
+#define MATCH_C_SLLIW 0x8001
+#define MASK_C_SLLIW 0xe003
+#define MATCH_C_SLLR 0x6c00
+#define MASK_C_SLLR 0xfc63
+#define MATCH_C_SLT 0x6440
+#define MASK_C_SLT 0xfc63
+#define MATCH_C_SLTR 0x6c40
+#define MASK_C_SLTR 0xfc63
+#define MATCH_C_SLTU 0x6460
+#define MASK_C_SLTU 0xfc63
+#define MATCH_C_SLTUR 0x6c60
+#define MASK_C_SLTUR 0xfc63
+#define MATCH_C_SRA 0x6020
+#define MASK_C_SRA 0xfc63
+#define MATCH_C_SRAI 0x2000
+#define MASK_C_SRAI 0xe003
+#define MATCH_C_SRL 0x6420
+#define MASK_C_SRL 0xfc63
+#define MATCH_C_SRLI 0x2001
+#define MASK_C_SRLI 0xe003
+#define MATCH_C_SRLR 0x6c20
+#define MASK_C_SRLR 0xfc63
+#define MATCH_C_SUB 0x8000
+#define MASK_C_SUB 0xf003
+#define MATCH_C_SUB3 0xa020
+#define MASK_C_SUB3 0xe063
+#define MATCH_C_SW 0x4000
#define MASK_C_SW 0xe003
-#define MATCH_C_SWSP 0xa001
+#define MATCH_C_SWSP 0x4001
#define MASK_C_SWSP 0xe003
+#define MATCH_C_XOR 0x6000
+#define MASK_C_XOR 0xfc63
+#define MATCH_C_XORIN 0x8021
+#define MASK_C_XORIN 0xe063
#define MATCH_CSRRC 0x3073
#define MASK_CSRRC 0x707f
#define MATCH_CSRRCI 0x7073
@@ -807,14 +865,25 @@ DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
+DECLARE_INSN(c_add3, MATCH_C_ADD3, MASK_C_ADD3)
DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
-DECLARE_INSN(c_addi4, MATCH_C_ADDI4, MASK_C_ADDI4)
+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
+DECLARE_INSN(c_addin, MATCH_C_ADDIN, MASK_C_ADDIN)
DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
+DECLARE_INSN(c_and3, MATCH_C_AND3, MASK_C_AND3)
+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
+DECLARE_INSN(c_andin, MATCH_C_ANDIN, MASK_C_ANDIN)
DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
+DECLARE_INSN(c_bgez, MATCH_C_BGEZ, MASK_C_BGEZ)
+DECLARE_INSN(c_bltz, MATCH_C_BLTZ, MASK_C_BLTZ)
DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
@@ -822,11 +891,29 @@ DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
+DECLARE_INSN(c_or3, MATCH_C_OR3, MASK_C_OR3)
+DECLARE_INSN(c_orin, MATCH_C_ORIN, MASK_C_ORIN)
DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
+DECLARE_INSN(c_sll, MATCH_C_SLL, MASK_C_SLL)
DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
+DECLARE_INSN(c_slliw, MATCH_C_SLLIW, MASK_C_SLLIW)
+DECLARE_INSN(c_sllr, MATCH_C_SLLR, MASK_C_SLLR)
+DECLARE_INSN(c_slt, MATCH_C_SLT, MASK_C_SLT)
+DECLARE_INSN(c_sltr, MATCH_C_SLTR, MASK_C_SLTR)
+DECLARE_INSN(c_sltu, MATCH_C_SLTU, MASK_C_SLTU)
+DECLARE_INSN(c_sltur, MATCH_C_SLTUR, MASK_C_SLTUR)
+DECLARE_INSN(c_sra, MATCH_C_SRA, MASK_C_SRA)
+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
+DECLARE_INSN(c_srl, MATCH_C_SRL, MASK_C_SRL)
+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
+DECLARE_INSN(c_srlr, MATCH_C_SRLR, MASK_C_SRLR)
+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
+DECLARE_INSN(c_sub3, MATCH_C_SUB3, MASK_C_SUB3)
DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
+DECLARE_INSN(c_xorin, MATCH_C_XORIN, MASK_C_XORIN)
DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
diff --git a/binutils/include/opcode/riscv.h b/binutils/include/opcode/riscv.h
index 1ce9955..25fa7cd 100644
--- a/binutils/include/opcode/riscv.h
+++ b/binutils/include/opcode/riscv.h
@@ -28,12 +28,14 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, US
/* RVC fields */
-#define OP_MASK_CRS1 0x1f
-#define OP_SH_CRS1 2
+#define OP_MASK_CRS2 0x1f
+#define OP_SH_CRS2 2
#define OP_MASK_CRS1S 0x7
-#define OP_SH_CRS1S 2
+#define OP_SH_CRS1S 7
+#define OP_MASK_CRS2S 0x7
+#define OP_SH_CRS2S 2
#define OP_MASK_CRDS 0x7
-#define OP_SH_CRDS 7
+#define OP_SH_CRDS 10
static const char rvc_rs1_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 7 };
#define rvc_rd_regmap rvc_rs1_regmap
@@ -85,18 +87,28 @@ static const char* const riscv_pred_succ[16] = {
((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
#define EXTRACT_RVC_IMM(x) \
(RV_X(x, 2, 5) | (-RV_X(x, 12, 1) << 5))
+#define EXTRACT_RVC_SIMM3(x) \
+ (RV_X(x, 10, 2) | (-RV_X(x, 12, 1) << 2))
+#define EXTRACT_RVC_ADDI4SPN_IMM(x) \
+ ((RV_X(x, 6, 1) << 2) | (RV_X(x, 5, 1) << 3) | (RV_X(x, 11, 2) << 4) | (RV_X(x, 7, 4) << 6))
+#define EXTRACT_RVC_ADDI16SP_IMM(x) \
+ ((RV_X(x, 6, 1) << 4) | (RV_X(x, 5, 1) << 5) | (RV_X(x, 2, 3) << 6) | (-RV_X(x, 12, 1) << 9))
#define EXTRACT_RVC_LW_IMM(x) \
- ((RV_X(x, 11, 1) << 2) | (RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 10, 1) << 6))
+ ((RV_X(x, 6, 1) << 2) | (RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 1) << 6))
#define EXTRACT_RVC_LD_IMM(x) \
- ((RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 10, 2) << 6))
+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 6))
#define EXTRACT_RVC_LWSP_IMM(x) \
((RV_X(x, 4, 3) << 2) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 2) << 6))
#define EXTRACT_RVC_LDSP_IMM(x) \
((RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 3) << 6))
+#define EXTRACT_RVC_SWSP_IMM(x) \
+ ((RV_X(x, 9, 4) << 2) | (RV_X(x, 7, 2) << 6))
+#define EXTRACT_RVC_SDSP_IMM(x) \
+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 7, 3) << 6))
#define EXTRACT_RVC_B_IMM(x) \
- ((RV_X(x, 7, 1) << 1) | (RV_X(x, 11, 1) << 2) | (RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 10, 1) << 6) | (RV_X(x, 8, 1) << 7) | (-RV_X(x, 9, 1) << 8))
+ ((RV_X(x, 3, 4) << 1) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 10, 2) << 6) | (-RV_X(x, 12, 1) << 8))
#define EXTRACT_RVC_J_IMM(x) \
- ((RV_X(x, 7, 1) << 1) | (RV_X(x, 11, 1) << 2) | (RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 10, 1) << 6) | (RV_X(x, 8, 2) << 7) | (RV_X(x, 2, 2) << 9) | (-RV_X(x, 4, 1) << 11))
+ ((RV_X(x, 3, 4) << 1) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 7, 5) << 6) | (-RV_X(x, 12, 1) << 11))
#define ENCODE_ITYPE_IMM(x) \
(RV_X(x, 0, 12) << 20)
@@ -110,18 +122,28 @@ static const char* const riscv_pred_succ[16] = {
((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
#define ENCODE_RVC_IMM(x) \
((RV_X(x, 0, 5) << 2) | (RV_X(x, 5, 1) << 12))
+#define ENCODE_RVC_SIMM3(x) \
+ (RV_X(x, 0, 3) << 10)
+#define ENCODE_RVC_ADDI4SPN_IMM(x) \
+ ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 1) << 5) | (RV_X(x, 4, 2) << 11) | (RV_X(x, 6, 4) << 7))
+#define ENCODE_RVC_ADDI16SP_IMM(x) \
+ ((RV_X(x, 4, 1) << 6) | (RV_X(x, 5, 1) << 5) | (RV_X(x, 6, 3) << 2) | (RV_X(x, 9, 1) << 12))
#define ENCODE_RVC_LW_IMM(x) \
- ((RV_X(x, 2, 1) << 11) | (RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 1) << 10))
+ ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 1) << 5))
#define ENCODE_RVC_LD_IMM(x) \
- ((RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 2) << 10))
+ ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 2) << 5))
#define ENCODE_RVC_LWSP_IMM(x) \
((RV_X(x, 2, 3) << 4) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 2) << 2))
#define ENCODE_RVC_LDSP_IMM(x) \
((RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 3) << 2))
+#define ENCODE_RVC_SWSP_IMM(x) \
+ ((RV_X(x, 2, 4) << 9) | (RV_X(x, 6, 2) << 7))
+#define ENCODE_RVC_SDSP_IMM(x) \
+ ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 3) << 7))
#define ENCODE_RVC_B_IMM(x) \
- ((RV_X(x, 1, 1) << 7) | (RV_X(x, 2, 1) << 11) | (RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 1) << 10) | (RV_X(x, 7, 2) << 8))
+ ((RV_X(x, 1, 4) << 3) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 3) << 10))
#define ENCODE_RVC_J_IMM(x) \
- ((RV_X(x, 1, 1) << 7) | (RV_X(x, 2, 1) << 11) | (RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 1) << 10) | (RV_X(x, 7, 2) << 8) | (RV_X(x, 9, 3) << 2))
+ ((RV_X(x, 1, 4) << 3) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 6) << 7))
#define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
@@ -129,10 +151,15 @@ static const char* const riscv_pred_succ[16] = {
#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x))
#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x))
#define VALID_RVC_IMM(x) (EXTRACT_RVC_IMM(ENCODE_RVC_IMM(x)) == (x))
+#define VALID_RVC_SIMM3(x) (EXTRACT_RVC_SIMM3(ENCODE_RVC_SIMM3(x)) == (x))
+#define VALID_RVC_ADDI4SPN_IMM(x) (EXTRACT_RVC_ADDI4SPN_IMM(ENCODE_RVC_ADDI4SPN_IMM(x)) == (x))
+#define VALID_RVC_ADDI16SP_IMM(x) (EXTRACT_RVC_ADDI16SP_IMM(ENCODE_RVC_ADDI16SP_IMM(x)) == (x))
#define VALID_RVC_LW_IMM(x) (EXTRACT_RVC_LW_IMM(ENCODE_RVC_LW_IMM(x)) == (x))
#define VALID_RVC_LD_IMM(x) (EXTRACT_RVC_LD_IMM(ENCODE_RVC_LD_IMM(x)) == (x))
#define VALID_RVC_LWSP_IMM(x) (EXTRACT_RVC_LWSP_IMM(ENCODE_RVC_LWSP_IMM(x)) == (x))
#define VALID_RVC_LDSP_IMM(x) (EXTRACT_RVC_LDSP_IMM(ENCODE_RVC_LDSP_IMM(x)) == (x))
+#define VALID_RVC_SWSP_IMM(x) (EXTRACT_RVC_SWSP_IMM(ENCODE_RVC_SWSP_IMM(x)) == (x))
+#define VALID_RVC_SDSP_IMM(x) (EXTRACT_RVC_SDSP_IMM(ENCODE_RVC_SDSP_IMM(x)) == (x))
#define VALID_RVC_B_IMM(x) (EXTRACT_RVC_B_IMM(ENCODE_RVC_B_IMM(x)) == (x))
#define VALID_RVC_J_IMM(x) (EXTRACT_RVC_J_IMM(ENCODE_RVC_J_IMM(x)) == (x))
diff --git a/binutils/opcodes/riscv-dis.c b/binutils/opcodes/riscv-dis.c
index a1fd06e..d42c39d 100644
--- a/binutils/opcodes/riscv-dis.c
+++ b/binutils/opcodes/riscv-dis.c
@@ -30,7 +30,7 @@
#include "elf/riscv.h"
#include <stdint.h>
-#include <assert.h>
+#include <ctype.h>
struct riscv_private_data
{
@@ -223,20 +223,30 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
riscv_gpr_names[((l >> OP_SH_CRDS) & OP_MASK_CRDS) + 8]);
break;
case 's': /* RS1 x8-x15 */
+ case 'w': /* RS1 x8-x15 */
print (info->stream, "%s",
riscv_gpr_names[((l >> OP_SH_CRS1S) & OP_MASK_CRS1S) + 8]);
break;
- case 'S': /* RS1 */
+ case 't': /* RS2 x8-x15 */
+ case 'x': /* RS2 x8-x15 */
print (info->stream, "%s",
- riscv_gpr_names[(l >> OP_SH_CRS1) & OP_MASK_CRS1]);
+ riscv_gpr_names[((l >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8]);
+ break;
+ case 'U': /* RS1, constrained to equal RD */
+ case 'D': /* RS1 or RD, nonzero */
+ print (info->stream, "%s", riscv_gpr_names[rd]);
break;
case 'c': /* RS1, constrained to equal sp */
print (info->stream, "%s", riscv_gpr_names[X_SP]);
continue;
- case 'U': /* RS2, constrained to equal RD */
- case 'T': /* RS2 */
- print (info->stream, "%s", riscv_gpr_names[rd]);
+ case 'T': /* RS2, nonzero */
+ case 'V': /* RS2 */
+ print (info->stream, "%s",
+ riscv_gpr_names[(l >> OP_SH_CRS2) & OP_MASK_CRS2]);
continue;
+ case 'i':
+ print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
+ break;
case 'j':
print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
break;
@@ -252,6 +262,18 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case 'n':
print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
break;
+ case 'K':
+ print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
+ break;
+ case 'L':
+ print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
+ break;
+ case 'M':
+ print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
+ break;
+ case 'N':
+ print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
+ break;
case 'p':
info->target = EXTRACT_RVC_B_IMM (l) + pc;
(*info->print_address_func) (info->target, info);
@@ -267,6 +289,9 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case '>':
print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
break;
+ case '<':
+ print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
+ break;
}
break;
@@ -279,6 +304,9 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
break;
case '0':
+ /* Only print constant 0 if it is the last argument */
+ if (!d[1])
+ print (info->stream, "0");
break;
case 'b':
@@ -418,7 +446,7 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
static const char *extension = NULL;
static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
struct riscv_private_data *pd;
- int insnlen;
+ int xlen, insnlen;
#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : 0x7f))
@@ -454,6 +482,10 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
else
pd = info->private_data;
+ xlen = 32;
+ if (elf_elfheader (info->section->owner)->e_ident[EI_CLASS] == ELFCLASS64)
+ xlen = 64;
+
insnlen = riscv_insn_length (word);
info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
@@ -473,7 +505,8 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
{
if ((op->match_func) (op, word)
&& !(no_aliases && (op->pinfo & INSN_ALIAS))
- && !(op->subset[0] == 'X' && strcmp(op->subset, extension)))
+ && !(op->subset[0] == 'X' && strcmp(op->subset, extension))
+ && !(isdigit(op->subset[0]) && atoi(op->subset) != xlen))
{
(*info->fprintf_func) (info->stream, "%s", op->name);
print_insn_args (op->args, word, memaddr, info);
diff --git a/binutils/opcodes/riscv-opc.c b/binutils/opcodes/riscv-opc.c
index 6872e54..5324d4f 100644
--- a/binutils/opcodes/riscv-opc.c
+++ b/binutils/opcodes/riscv-opc.c
@@ -94,8 +94,8 @@ const char * const riscv_vec_fpr_names[32] =
#define MASK_RS1 (OP_MASK_RS1 << OP_SH_RS1)
#define MASK_RS2 (OP_MASK_RS2 << OP_SH_RS2)
#define MASK_RD (OP_MASK_RD << OP_SH_RD)
-#define MASK_CRS1 (OP_MASK_CRS1 << OP_SH_CRS1)
#define MASK_IMM ENCODE_ITYPE_IMM(-1U)
+#define MASK_RVC_IMM ENCODE_RVC_IMM(-1U)
#define MASK_UIMM ENCODE_UTYPE_IMM(-1U)
#define MASK_RM (OP_MASK_RM << OP_SH_RM)
#define MASK_PRED (OP_MASK_PRED << OP_SH_PRED)
@@ -121,52 +121,91 @@ static int match_rs1_eq_rs2(const struct riscv_opcode *op, insn_t insn)
((insn & MASK_RS1) >> OP_SH_RS1) == ((insn & MASK_RS2) >> OP_SH_RS2);
}
+static int match_rd_nonzero(const struct riscv_opcode *op, insn_t insn)
+{
+ return match_opcode(op, insn) && ((insn & MASK_RD) != 0);
+}
+
const struct riscv_opcode riscv_builtin_opcodes[] =
{
/* name, isa, operands, match, mask, match_func, pinfo */
{"unimp", "C", "", 0, 0xffffU, match_opcode, 0 },
{"unimp", "I", "", MATCH_CSRRW | (CSR_CYCLE << OP_SH_CSR), 0xffffffffU, match_opcode, 0 }, /* csrw cycle, x0 */
-{"sbreak", "C", "", MATCH_C_LI | ENCODE_RVC_IMM(-32U), MASK_C_LI | MASK_RD | ENCODE_RVC_IMM(-1U), match_opcode, 0 },
-{"sbreak", "I", "", MATCH_SBREAK, MASK_SBREAK, match_opcode, 0 },
-{"nop", "C", "", MATCH_C_MV, MASK_C_MV | MASK_RD | MASK_CRS1, match_opcode, 0 },
+{"ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
+{"ebreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, 0 },
+{"sbreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
+{"sbreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, INSN_ALIAS },
+{"ret", "C", "", MATCH_C_JR | (X_RA << OP_SH_RD), MASK_C_JR | MASK_RD, match_opcode, INSN_ALIAS },
+{"ret", "I", "", MATCH_JALR | (X_RA << OP_SH_RS1), MASK_JALR | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jr", "C", "CD", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, INSN_ALIAS },
+{"jr", "I", "s", MATCH_JALR, MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jr", "I", "s,j", MATCH_JALR, MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jalr", "C", "CD", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, INSN_ALIAS },
+{"jalr", "I", "s", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jalr", "I", "s,j", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jalr", "I", "d,s", MATCH_JALR, MASK_JALR | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"jalr", "I", "d,s,j", MATCH_JALR, MASK_JALR, match_opcode, WR_xd|RD_xs1 },
+{"j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS },
+{"j", "I", "a", MATCH_JAL, MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS },
+{"jal", "C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS },
+{"jal", "I", "a", MATCH_JAL | (X_RA << OP_SH_RD), MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS|WR_xd },
+{"jal", "I", "d,a", MATCH_JAL, MASK_JAL, match_opcode, WR_xd },
+{"call", "I", "c", (X_T0 << OP_SH_RS1) | (X_RA << OP_SH_RD), (int) M_CALL, match_never, INSN_MACRO },
+{"tail", "I", "c", (X_T0 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
+{"jump", "I", "c,s", 0, (int) M_CALL, match_never, INSN_MACRO },
+{"nop", "C", "", MATCH_C_ADDI16SP, 0xffff, match_opcode, INSN_ALIAS },
{"nop", "I", "", MATCH_ADDI, MASK_ADDI | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
-{"lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_opcode, 0 },
+{"lui", "C", "CD,Cu", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, INSN_ALIAS },
{"lui", "I", "d,u", MATCH_LUI, MASK_LUI, match_opcode, WR_xd },
-{"li", "C", "d,Cv", MATCH_C_LUI, MASK_C_LUI, match_opcode, INSN_ALIAS },
-{"li", "C", "d,Cj", MATCH_C_LI, MASK_C_LI, match_opcode, 0 },
+{"li", "C", "CD,Cv", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, INSN_ALIAS },
+{"li", "C", "CD,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
+{"li", "C", "CD,0", MATCH_C_MV, MASK_C_MV | (OP_MASK_CRS2 << OP_SH_CRS2), match_rd_nonzero, INSN_ALIAS },
{"li", "I", "d,j", MATCH_ADDI, MASK_ADDI | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd }, /* addi */
{"li", "I", "d,I", 0, (int) M_LI, match_never, INSN_MACRO },
-{"mv", "C", "d,CS", MATCH_C_MV, MASK_C_MV, match_opcode, 0 },
+{"mv", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, INSN_ALIAS },
{"mv", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"move", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, INSN_ALIAS },
{"move", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"andi", "32C", "CD,CU,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, INSN_ALIAS },
+{"andi", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, INSN_ALIAS },
{"andi", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, WR_xd|RD_xs1 },
+{"and", "C", "Cd,Cs,Ct", MATCH_C_AND3, MASK_C_AND3, match_opcode, INSN_ALIAS },
+{"and", "32C", "CD,CU,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, INSN_ALIAS },
+{"and", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, INSN_ALIAS },
{"and", "I", "d,s,t", MATCH_AND, MASK_AND, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"and", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, 0 },
+{"beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS },
{"beqz", "I", "s,p", MATCH_BEQ, MASK_BEQ | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
{"beq", "I", "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, RD_xs1|RD_xs2 },
{"blez", "I", "t,p", MATCH_BGE, MASK_BGE | MASK_RS1, match_opcode, INSN_ALIAS|RD_xs2 },
+{"bgez", "32C", "Cs,Cp", MATCH_C_BGEZ, MASK_C_BGEZ, match_opcode, INSN_ALIAS },
{"bgez", "I", "s,p", MATCH_BGE, MASK_BGE | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
{"ble", "I", "t,s,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
{"bleu", "I", "t,s,p", MATCH_BGEU, MASK_BGEU, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
{"bge", "I", "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, RD_xs1|RD_xs2 },
{"bgeu", "I", "s,t,p", MATCH_BGEU, MASK_BGEU, match_opcode, RD_xs1|RD_xs2 },
+{"bltz", "32C", "Cs,Cp", MATCH_C_BLTZ, MASK_C_BLTZ, match_opcode, INSN_ALIAS },
{"bltz", "I", "s,p", MATCH_BLT, MASK_BLT | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
{"bgtz", "I", "t,p", MATCH_BLT, MASK_BLT | MASK_RS1, match_opcode, INSN_ALIAS|RD_xs2 },
{"blt", "I", "s,t,p", MATCH_BLT, MASK_BLT, match_opcode, RD_xs1|RD_xs2 },
{"bltu", "I", "s,t,p", MATCH_BLTU, MASK_BLTU, match_opcode, RD_xs1|RD_xs2 },
{"bgt", "I", "t,s,p", MATCH_BLT, MASK_BLT, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
{"bgtu", "I", "t,s,p", MATCH_BLTU, MASK_BLTU, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
-{"bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, 0 },
+{"bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS },
{"bnez", "I", "s,p", MATCH_BNE, MASK_BNE | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
{"bne", "I", "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, RD_xs1|RD_xs2 },
-{"addi", "C", "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_opcode, 0 },
-{"addi", "C", "d,CU,Cm", MATCH_C_ADDI4, MASK_C_ADDI4, match_opcode, 0 },
+{"addi", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
+{"addi", "C", "CD,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
+{"addi", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
+{"addi", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, INSN_ALIAS },
{"addi", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, WR_xd|RD_xs1 },
-{"add", "C", "d,CU,CS", MATCH_C_ADD, MASK_C_ADD, match_opcode, 0 },
-{"add", "C", "d,CS,CU", MATCH_C_ADD, MASK_C_ADD, match_opcode, 0 },
-{"add", "C", "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_opcode, 0 },
-{"add", "C", "d,CU,Cm", MATCH_C_ADDI4, MASK_C_ADDI4, match_opcode, 0 },
+{"add", "C", "CD,CU,CT", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, INSN_ALIAS },
+{"add", "C", "CD,CT,CU", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, INSN_ALIAS },
+{"add", "C", "CD,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
+{"add", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
+{"add", "C", "Cd,Cs,Ct", MATCH_C_ADD3, MASK_C_ADD3, match_opcode, INSN_ALIAS },
+{"add", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
+{"add", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, INSN_ALIAS },
{"add", "I", "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"add", "I", "d,s,t,0",MATCH_ADD, MASK_ADD, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"add", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
@@ -175,36 +214,29 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"la.tls.gd", "I", "d,A", 0, (int) M_LA_TLS_GD, match_never, INSN_MACRO },
{"la.tls.ie", "I", "d,A", 0, (int) M_LA_TLS_IE, match_never, INSN_MACRO },
{"neg", "I", "d,t", MATCH_SUB, MASK_SUB | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 }, /* sub 0 */
-{"slli", "C", "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_opcode, 0 },
+{"slli", "C", "CD,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
{"slli", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, WR_xd|RD_xs1 },
-{"sll", "C", "d,CU,Cj", MATCH_C_SLLI, MASK_C_SLLI, match_opcode, 0 },
+{"sll", "C", "CD,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
+{"sll", "32C", "Cs,Cw,Ct", MATCH_C_SLL, MASK_C_SLL, match_opcode, INSN_ALIAS },
+{"sll", "32C", "Ct,Cs,Cx", MATCH_C_SLLR, MASK_C_SLLR, match_opcode, INSN_ALIAS },
{"sll", "I", "d,s,t", MATCH_SLL, MASK_SLL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"sll", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"srli", "C", "CD,CU,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
{"srli", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, WR_xd|RD_xs1 },
+{"srl", "C", "CD,CU,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
+{"srl", "32C", "Cs,Cw,Ct", MATCH_C_SRL, MASK_C_SRL, match_opcode, INSN_ALIAS },
+{"srl", "32C", "Ct,Cs,Cx", MATCH_C_SRLR, MASK_C_SRLR, match_opcode, INSN_ALIAS },
{"srl", "I", "d,s,t", MATCH_SRL, MASK_SRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"srl", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"srai", "C", "CD,CU,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
{"srai", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, WR_xd|RD_xs1 },
+{"sra", "C", "CD,CU,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
+{"sra", "32C", "Cs,Cw,Ct", MATCH_C_SRA, MASK_C_SRA, match_opcode, INSN_ALIAS },
{"sra", "I", "d,s,t", MATCH_SRA, MASK_SRA, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"sra", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"sub", "C", "CD,CU,CT", MATCH_C_SUB, MASK_C_SUB, match_rd_nonzero, INSN_ALIAS },
+{"sub", "C", "Cd,Cs,Ct", MATCH_C_SUB3, MASK_C_SUB3, match_opcode, INSN_ALIAS },
{"sub", "I", "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, WR_xd|RD_xs1|RD_xs2 },
-{"ret", "C", "", MATCH_C_JALR | (X_RA << OP_SH_CRS1), MASK_C_JALR | MASK_RD | MASK_CRS1, match_opcode, INSN_ALIAS },
-{"ret", "I", "", MATCH_JALR | (X_RA << OP_SH_RS1), MASK_JALR | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, 0 },
-{"j", "I", "a", MATCH_JAL, MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS },
-{"jal", "I", "a", MATCH_JAL | (X_RA << OP_SH_RD), MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS|WR_xd },
-{"jal", "I", "d,a", MATCH_JAL, MASK_JAL, match_opcode, WR_xd },
-{"call", "I", "c", (X_T0 << OP_SH_RS1) | (X_RA << OP_SH_RD), (int) M_CALL, match_never, INSN_MACRO },
-{"tail", "I", "c", (X_T0 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
-{"jump", "I", "c,s", 0, (int) M_CALL, match_never, INSN_MACRO },
-{"jr", "C", "CS", MATCH_C_JALR, MASK_C_JALR | MASK_RD, match_opcode, INSN_ALIAS },
-{"jr", "I", "s", MATCH_JALR, MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"jr", "I", "s,j", MATCH_JALR, MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"jalr", "C", "CS", MATCH_C_JALR | (X_RA << OP_SH_RD), MASK_C_JALR | MASK_RD, match_opcode, 0 },
-{"jalr", "C", "d,CS", MATCH_C_JALR, MASK_C_JALR, match_opcode, 0 },
-{"jalr", "I", "s", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"jalr", "I", "s,j", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"jalr", "I", "d,s", MATCH_JALR, MASK_JALR | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"jalr", "I", "d,s,j", MATCH_JALR, MASK_JALR, match_opcode, WR_xd|RD_xs1 },
{"lb", "I", "d,o(s)", MATCH_LB, MASK_LB, match_opcode, WR_xd|RD_xs1 },
{"lb", "I", "d,A", 0, (int) M_LB, match_never, INSN_MACRO },
{"lbu", "I", "d,o(s)", MATCH_LBU, MASK_LBU, match_opcode, WR_xd|RD_xs1 },
@@ -213,12 +245,15 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"lh", "I", "d,A", 0, (int) M_LH, match_never, INSN_MACRO },
{"lhu", "I", "d,o(s)", MATCH_LHU, MASK_LHU, match_opcode, WR_xd|RD_xs1 },
{"lhu", "I", "d,A", 0, (int) M_LHU, match_never, INSN_MACRO },
-{"lw", "C", "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_opcode, WR_xd|RD_xs1 },
-{"lw", "C", "Cd,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, WR_xd|RD_xs1 },
+{"lw", "C", "CD,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS },
+{"lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS },
{"lw", "I", "d,o(s)", MATCH_LW, MASK_LW, match_opcode, WR_xd|RD_xs1 },
{"lw", "I", "d,A", 0, (int) M_LW, match_never, INSN_MACRO },
{"not", "I", "d,s", MATCH_XORI | MASK_IMM, MASK_XORI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"ori", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, INSN_ALIAS },
{"ori", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, WR_xd|RD_xs1 },
+{"or", "C", "Cd,Cs,Ct", MATCH_C_OR3, MASK_C_OR3, match_opcode, INSN_ALIAS },
+{"or", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, INSN_ALIAS },
{"or", "I", "d,s,t", MATCH_OR, MASK_OR, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"or", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"auipc", "I", "d,u", MATCH_AUIPC, MASK_AUIPC, match_opcode, WR_xd },
@@ -227,9 +262,13 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"sltz", "I", "d,s", MATCH_SLT, MASK_SLT | MASK_RS2, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"sgtz", "I", "d,t", MATCH_SLT, MASK_SLT | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 },
{"slti", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
+{"slt", "32C", "Cs,Cw,Ct", MATCH_C_SLT, MASK_C_SLT, match_opcode, INSN_ALIAS },
+{"slt", "32C", "Ct,Cs,Cx", MATCH_C_SLTR, MASK_C_SLTR, match_opcode, INSN_ALIAS },
{"slt", "I", "d,s,t", MATCH_SLT, MASK_SLT, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"slt", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, WR_xd|RD_xs1 },
{"sltiu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, WR_xd|RD_xs1 },
+{"sltu", "32C", "Cs,Cw,Ct", MATCH_C_SLTU, MASK_C_SLTU, match_opcode, INSN_ALIAS },
+{"sltu", "32C", "Ct,Cs,Cx", MATCH_C_SLTUR, MASK_C_SLTUR, match_opcode, INSN_ALIAS },
{"sltu", "I", "d,s,t", MATCH_SLTU, MASK_SLTU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"sltu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"sgt", "I", "d,t,s", MATCH_SLT, MASK_SLT, match_opcode, INSN_ALIAS|WR_xd|RD_xs1|RD_xs2 },
@@ -238,8 +277,8 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"sb", "I", "t,A,s", 0, (int) M_SB, match_never, INSN_MACRO },
{"sh", "I", "t,q(s)", MATCH_SH, MASK_SH, match_opcode, RD_xs1|RD_xs2 },
{"sh", "I", "t,A,s", 0, (int) M_SH, match_never, INSN_MACRO },
-{"sw", "C", "d,Cm(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, WR_xd|RD_xs1 },
-{"sw", "C", "Cd,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, WR_xd|RD_xs1 },
+{"sw", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS },
+{"sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, INSN_ALIAS },
{"sw", "I", "t,q(s)", MATCH_SW, MASK_SW, match_opcode, RD_xs1|RD_xs2 },
{"sw", "I", "t,A,s", 0, (int) M_SW, match_never, INSN_MACRO },
{"fence", "I", "", MATCH_FENCE | MASK_PRED | MASK_SUCC, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
@@ -253,29 +292,36 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"rdtimeh", "32I", "d", MATCH_RDTIMEH, MASK_RDTIMEH, match_opcode, WR_xd },
{"ecall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
{"scall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
+{"xori", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, INSN_ALIAS },
{"xori", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, WR_xd|RD_xs1 },
+{"xor", "32C", "Cs,Cw,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
+{"xor", "32C", "Cs,Ct,Cw", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
+{"xor", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, INSN_ALIAS },
{"xor", "I", "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"xor", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"lwu", "64I", "d,o(s)", MATCH_LWU, MASK_LWU, match_opcode, WR_xd|RD_xs1 },
{"lwu", "64I", "d,A", 0, (int) M_LWU, match_never, INSN_MACRO },
-{"ld", "64C", "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_opcode, WR_xd|RD_xs1 },
-{"ld", "64C", "Cd,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, WR_xd|RD_xs1 },
+{"ld", "64C", "CD,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS },
+{"ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS },
{"ld", "64I", "d,o(s)", MATCH_LD, MASK_LD, match_opcode, WR_xd|RD_xs1 },
{"ld", "64I", "d,A", 0, (int) M_LD, match_never, INSN_MACRO },
-{"sd", "64C", "d,Cn(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, WR_xd|RD_xs1 },
-{"sd", "64C", "Cd,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, WR_xd|RD_xs1 },
+{"sd", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS },
+{"sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS },
{"sd", "64I", "t,q(s)", MATCH_SD, MASK_SD, match_opcode, RD_xs1|RD_xs2 },
{"sd", "64I", "t,A,s", 0, (int) M_SD, match_never, INSN_MACRO },
+{"sext.w", "64C", "CD,CU", MATCH_C_ADDIW, MASK_C_ADDIW | MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
{"sext.w", "64I", "d,s", MATCH_ADDIW, MASK_ADDIW | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
-{"addiw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_opcode, 0 },
+{"addiw", "64C", "CD,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
{"addiw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, WR_xd|RD_xs1 },
-{"addw", "64C", "d,CU,CS", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, 0 },
-{"addw", "64C", "d,CS,CU", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, 0 },
-{"addw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_opcode, 0 },
+{"addw", "64C", "CD,CU,CT", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, INSN_ALIAS },
+{"addw", "64C", "CD,CT,CU", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, INSN_ALIAS },
+{"addw", "64C", "CD,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
{"addw", "64I", "d,s,t", MATCH_ADDW, MASK_ADDW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"addw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"negw", "64I", "d,t", MATCH_SUBW, MASK_SUBW | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 }, /* sub 0 */
+{"slliw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, INSN_ALIAS },
{"slliw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, WR_xd|RD_xs1 },
+{"sllw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, INSN_ALIAS },
{"sllw", "64I", "d,s,t", MATCH_SLLW, MASK_SLLW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
{"sllw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"srliw", "64I", "d,s,<", MATCH_SRLIW, MASK_SRLIW, match_opcode, WR_xd|RD_xs1 },
@@ -286,6 +332,59 @@ const struct riscv_opcode riscv_builtin_opcodes[] =
{"sraw", "64I", "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
{"subw", "64I", "d,s,t", MATCH_SUBW, MASK_SUBW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
+/* Compressed instructions */
+{"c.ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, 0 },
+{"c.jr", "C", "CD", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, 0 },
+{"c.jalr", "C", "CD", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, 0 },
+{"c.j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, 0 },
+{"c.jal", "C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, 0 },
+{"c.beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, 0 },
+{"c.bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, 0 },
+{"c.lwsp", "C", "CD,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, 0 },
+{"c.lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, 0 },
+{"c.swsp", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, 0 },
+{"c.sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, 0 },
+{"c.nop", "C", "", MATCH_C_ADDI16SP, 0xffff, match_opcode, 0 },
+{"c.mv", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, 0 },
+{"c.lui", "C", "CD,Cu", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, 0 },
+{"c.li", "C", "CD,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, 0 },
+{"c.addi4spn","C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, 0 },
+{"c.addi16sp","C", "Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, 0 },
+{"c.addi", "C", "CD,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, 0 },
+{"c.add", "C", "CD,CT", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, 0 },
+{"c.sub", "C", "CD,CT", MATCH_C_SUB, MASK_C_SUB, match_rd_nonzero, 0 },
+{"c.add3", "C", "Cd,Cs,Ct", MATCH_C_ADD3, MASK_C_ADD3, match_opcode, 0 },
+{"c.sub3", "C", "Cd,Cs,Ct", MATCH_C_SUB3, MASK_C_SUB3, match_opcode, 0 },
+{"c.and3", "C", "Cd,Cs,Ct", MATCH_C_AND3, MASK_C_AND3, match_opcode, 0 },
+{"c.or3", "C", "Cd,Cs,Ct", MATCH_C_OR3, MASK_C_OR3, match_opcode, 0 },
+{"c.slli", "C", "CD,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, 0 },
+{"c.srli", "C", "CD,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, 0 },
+{"c.srai", "C", "CD,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, 0 },
+{"c.slliw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, 0 },
+{"c.addiw", "64C", "CD,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, 0 },
+{"c.addw", "64C", "CD,CT", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, 0 },
+{"c.ldsp", "64C", "CD,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, 0 },
+{"c.ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, 0 },
+{"c.sdsp", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, 0 },
+{"c.sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, 0 },
+{"c.xor", "32C", "Cs,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, 0 },
+{"c.sra", "32C", "Cs,Ct", MATCH_C_SRA, MASK_C_SRA, match_opcode, 0 },
+{"c.sll", "32C", "Cs,Ct", MATCH_C_SLL, MASK_C_SLL, match_opcode, 0 },
+{"c.srl", "32C", "Cs,Ct", MATCH_C_SRL, MASK_C_SRL, match_opcode, 0 },
+{"c.slt", "32C", "Cs,Ct", MATCH_C_SLT, MASK_C_SLT, match_opcode, 0 },
+{"c.sltu", "32C", "Cs,Ct", MATCH_C_SLTU, MASK_C_SLTU, match_opcode, 0 },
+{"c.sllr", "32C", "Ct,Cs", MATCH_C_SLLR, MASK_C_SLLR, match_opcode, 0 },
+{"c.srlr", "32C", "Ct,Cs", MATCH_C_SRLR, MASK_C_SRLR, match_opcode, 0 },
+{"c.sltr", "32C", "Ct,Cs", MATCH_C_SLTR, MASK_C_SLTR, match_opcode, 0 },
+{"c.sltur", "32C", "Ct,Cs", MATCH_C_SLTUR, MASK_C_SLTUR, match_opcode, 0 },
+{"c.addin", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, 0 },
+{"c.xorin", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, 0 },
+{"c.orin", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, 0 },
+{"c.andin", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, 0 },
+{"c.andi", "32C", "CD,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, 0 },
+{"c.bltz", "32C", "Cs,Cp", MATCH_C_BLTZ, MASK_C_BLTZ, match_opcode, 0 },
+{"c.bgez", "32C", "Cs,Cp", MATCH_C_BGEZ, MASK_C_BGEZ, match_opcode, 0 },
+
/* Atomic memory operation instruction subset */
{"lr.w", "A", "d,0(s)", MATCH_LR_W, MASK_LR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
{"sc.w", "A", "d,t,0(s)", MATCH_SC_W, MASK_SC_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },