/* RISC-V opcode list
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2018 Free Software Foundation, Inc.
Contributed by Andrew Waterman (andrew@sifive.com).
Based on MIPS target.
return match_rd_nonzero (op, insn) && ((insn & MASK_CRS2) != 0);
}
+/* We don't allow mv zero,X to become a c.mv hint, so we need a separate
+ matching function for this. */
+
+static int
+match_c_add_with_hint (const struct riscv_opcode *op, insn_t insn)
+{
+ return match_opcode (op, insn) && ((insn & MASK_CRS2) != 0);
+}
+
+static int
+match_c_nop (const struct riscv_opcode *op, insn_t insn)
+{
+ return (match_opcode (op, insn)
+ && (((insn & MASK_RD) >> OP_SH_RD) == 0));
+}
+
+static int
+match_c_addi16sp (const struct riscv_opcode *op, insn_t insn)
+{
+ return (match_opcode (op, insn)
+ && (((insn & MASK_RD) >> OP_SH_RD) == 2)
+ && EXTRACT_RVC_ADDI16SP_IMM (insn) != 0);
+}
+
static int
match_c_lui (const struct riscv_opcode *op, insn_t insn)
{
- return match_rd_nonzero (op, insn) && (((insn & MASK_RD) >> OP_SH_RD) != 2);
+ return (match_rd_nonzero (op, insn)
+ && (((insn & MASK_RD) >> OP_SH_RD) != 2)
+ && EXTRACT_RVC_LUI_IMM (insn) != 0);
+}
+
+/* We don't allow lui zero,X to become a c.lui hint, so we need a separate
+ matching function for this. */
+
+static int
+match_c_lui_with_hint (const struct riscv_opcode *op, insn_t insn)
+{
+ return (match_opcode (op, insn)
+ && (((insn & MASK_RD) >> OP_SH_RD) != 2)
+ && EXTRACT_RVC_LUI_IMM (insn) != 0);
+}
+
+static int
+match_c_addi4spn (const struct riscv_opcode *op, insn_t insn)
+{
+ return match_opcode (op, insn) && EXTRACT_RVC_ADDI4SPN_IMM (insn) != 0;
}
const struct riscv_opcode riscv_opcodes[] =
{"lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
{"lui", "I", "d,u", MATCH_LUI, MASK_LUI, match_opcode, 0 },
{"li", "C", "d,Cv", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
-{"li", "C", "d,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
-{"li", "C", "d,0", MATCH_C_LI, MASK_C_LI | MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
+{"li", "C", "d,Co", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
{"li", "I", "d,j", MATCH_ADDI, MASK_ADDI | MASK_RS1, match_opcode, INSN_ALIAS }, /* addi */
{"li", "I", "d,I", 0, (int) M_LI, match_never, INSN_MACRO },
{"mv", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
{"mv", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS },
{"move", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
{"move", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS },
-{"andi", "C", "Cs,Cw,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
+{"andi", "C", "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
{"andi", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, 0 },
{"and", "C", "Cs,Cw,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
{"and", "C", "Cs,Ct,Cw", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
-{"and", "C", "Cs,Cw,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
+{"and", "C", "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
{"and", "I", "d,s,t", MATCH_AND, MASK_AND, match_opcode, 0 },
{"and", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS },
{"beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS },
{"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 },
{"bne", "I", "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, 0 },
-{"addi", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
+{"addi", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
{"addi", "C", "d,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", "C", "d,CU,z", MATCH_C_NOP, MASK_C_ADDI | MASK_RVC_IMM, match_c_nop, INSN_ALIAS },
+{"addi", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS },
{"addi", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, 0 },
{"add", "C", "d,CU,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
{"add", "C", "d,CV,CU", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
-{"add", "C", "d,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", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
+{"add", "C", "d,CU,Co", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
+{"add", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
+{"add", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS },
{"add", "I", "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, 0 },
+/* This is used for TLS, where the fourth arg is %tprel_add, to get a reloc
+ applied to an add instruction, for relaxation to use. */
{"add", "I", "d,s,t,0",MATCH_ADD, MASK_ADD, match_opcode, 0 },
{"add", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS },
{"la", "I", "d,A", 0, (int) M_LA, match_never, INSN_MACRO },
{"sd", "64I", "t,A,s", 0, (int) M_SD, match_never, INSN_MACRO },
{"sext.w", "64C", "d,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 },
-{"addiw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
+{"addiw", "64C", "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
{"addiw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, 0 },
{"addw", "64C", "Cs,Cw,Ct", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
{"addw", "64C", "Cs,Ct,Cw", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
-{"addw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
+{"addw", "64C", "d,CU,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
{"addw", "64I", "d,s,t", MATCH_ADDW, MASK_ADDW, match_opcode, 0 },
{"addw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, INSN_ALIAS },
{"negw", "64I", "d,t", MATCH_SUBW, MASK_SUBW | MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0 */
{"frrm", "F", "d", MATCH_FRRM, MASK_FRRM, match_opcode, 0 },
{"fsrm", "F", "s", MATCH_FSRM, MASK_FSRM | MASK_RD, match_opcode, 0 },
{"fsrm", "F", "d,s", MATCH_FSRM, MASK_FSRM, match_opcode, 0 },
+{"fsrmi", "F", "d,Z", MATCH_FSRMI, MASK_FSRMI, match_opcode, 0 },
+{"fsrmi", "F", "Z", MATCH_FSRMI, MASK_FSRMI | MASK_RD, match_opcode, 0 },
{"frflags", "F", "d", MATCH_FRFLAGS, MASK_FRFLAGS, match_opcode, 0 },
{"fsflags", "F", "s", MATCH_FSFLAGS, MASK_FSFLAGS | MASK_RD, match_opcode, 0 },
{"fsflags", "F", "d,s", MATCH_FSFLAGS, MASK_FSFLAGS, match_opcode, 0 },
+{"fsflagsi", "F", "d,Z", MATCH_FSFLAGSI, MASK_FSFLAGSI, match_opcode, 0 },
+{"fsflagsi", "F", "Z", MATCH_FSFLAGSI, MASK_FSFLAGSI | MASK_RD, match_opcode, 0 },
{"flw", "32C", "D,Cm(Cc)", MATCH_C_FLWSP, MASK_C_FLWSP, match_opcode, INSN_ALIAS },
{"flw", "32C", "CD,Ck(Cs)", MATCH_C_FLW, MASK_C_FLW, match_opcode, INSN_ALIAS },
{"flw", "F", "D,o(s)", MATCH_FLW, MASK_FLW, 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_ADDI, 0xffff, match_opcode, INSN_ALIAS },
-{"c.mv", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, 0 },
-{"c.lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, 0 },
-{"c.li", "C", "d,Co", 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", "d,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_opcode, 0 },
-{"c.add", "C", "d,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add, 0 },
+{"c.nop", "C", "Cj", MATCH_C_ADDI, MASK_C_ADDI | MASK_RD, match_opcode, INSN_ALIAS },
+{"c.mv", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add_with_hint, 0 },
+{"c.lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui_with_hint, 0 },
+{"c.li", "C", "d,Co", MATCH_C_LI, MASK_C_LI, match_opcode, 0 },
+{"c.addi4spn","C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, 0 },
+{"c.addi16sp","C", "Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, 0 },
+{"c.addi", "C", "d,Co", MATCH_C_ADDI, MASK_C_ADDI, match_opcode, 0 },
+{"c.add", "C", "d,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add_with_hint, 0 },
{"c.sub", "C", "Cs,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, 0 },
{"c.and", "C", "Cs,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, 0 },
{"c.or", "C", "Cs,Ct", MATCH_C_OR, MASK_C_OR, match_opcode, 0 },
{"c.xor", "C", "Cs,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, 0 },
-{"c.slli", "C", "d,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, 0 },
+{"c.slli", "C", "d,C>", MATCH_C_SLLI, MASK_C_SLLI, match_opcode, 0 },
{"c.srli", "C", "Cs,C>", MATCH_C_SRLI, MASK_C_SRLI, match_opcode, 0 },
{"c.srai", "C", "Cs,C>", MATCH_C_SRAI, MASK_C_SRAI, match_opcode, 0 },
{"c.andi", "C", "Cs,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, 0 },
/* Terminate the list. */
{0, 0, 0, 0, 0, 0, 0}
};
+
+/* Instruction format for .insn directive. */
+const struct riscv_opcode riscv_insn_types[] =
+{
+/* name, isa, operands, match, mask, match_func, pinfo. */
+{"r", "I", "O4,F3,F7,d,s,t", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,D,s,t", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,d,S,t", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,D,S,t", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,d,s,T", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,D,s,T", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,d,S,T", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F7,D,S,T", 0, 0, match_opcode, 0 },
+
+{"r", "I", "O4,F3,F2,d,s,t,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,s,t,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,S,t,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,S,t,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,s,T,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,s,T,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,S,T,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,S,T,r", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,s,t,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,s,t,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,S,t,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,S,t,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,s,T,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,s,T,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,d,S,T,R", 0, 0, match_opcode, 0 },
+{"r", "I", "O4,F3,F2,D,S,T,R", 0, 0, match_opcode, 0 },
+
+{"i", "I", "O4,F3,d,s,j", 0, 0, match_opcode, 0 },
+{"i", "I", "O4,F3,D,s,j", 0, 0, match_opcode, 0 },
+{"i", "I", "O4,F3,d,S,j", 0, 0, match_opcode, 0 },
+{"i", "I", "O4,F3,D,S,j", 0, 0, match_opcode, 0 },
+
+{"i", "I", "O4,F3,d,o(s)", 0, 0, match_opcode, 0 },
+{"i", "I", "O4,F3,D,o(s)", 0, 0, match_opcode, 0 },
+
+{"s", "I", "O4,F3,d,o(s)", 0, 0, match_opcode, 0 },
+{"s", "I", "O4,F3,D,o(s)", 0, 0, match_opcode, 0 },
+
+{"sb", "I", "O4,F3,s,t,p", 0, 0, match_opcode, 0 },
+{"sb", "I", "O4,F3,S,t,p", 0, 0, match_opcode, 0 },
+{"sb", "I", "O4,F3,s,T,p", 0, 0, match_opcode, 0 },
+{"sb", "I", "O4,F3,S,T,p", 0, 0, match_opcode, 0 },
+
+{"sb", "I", "O4,F3,t,q(s)", 0, 0, match_opcode, 0 },
+{"sb", "I", "O4,F3,T,q(s)", 0, 0, match_opcode, 0 },
+
+{"u", "I", "O4,d,u", 0, 0, match_opcode, 0 },
+{"u", "I", "O4,D,u", 0, 0, match_opcode, 0 },
+
+{"uj", "I", "O4,d,a", 0, 0, match_opcode, 0 },
+{"uj", "I", "O4,D,a", 0, 0, match_opcode, 0 },
+
+{"cr", "C", "O2,CF4,d,CV", 0, 0, match_opcode, 0 },
+{"cr", "C", "O2,CF4,D,CV", 0, 0, match_opcode, 0 },
+{"cr", "C", "O2,CF4,d,CT", 0, 0, match_opcode, 0 },
+{"cr", "C", "O2,CF4,D,CT", 0, 0, match_opcode, 0 },
+
+{"ci", "C", "O2,CF3,d,Co", 0, 0, match_opcode, 0 },
+{"ci", "C", "O2,CF3,D,Co", 0, 0, match_opcode, 0 },
+
+{"ciw", "C", "O2,CF3,Ct,C8", 0, 0, match_opcode, 0 },
+{"ciw", "C", "O2,CF3,CD,C8", 0, 0, match_opcode, 0 },
+
+{"cb", "C", "O2,CF3,Cs,Cp", 0, 0, match_opcode, 0 },
+{"cb", "C", "O2,CF3,CS,Cp", 0, 0, match_opcode, 0 },
+
+{"cj", "C", "O2,CF3,Ca", 0, 0, match_opcode, 0 },
+/* Terminate the list. */
+{0, 0, 0, 0, 0, 0, 0}
+};