diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 2a6e7186c2a..16909a93b9c 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1335,6 +1335,7 @@ static struct riscv_supported_ext riscv_supported_std_ext[] = {"b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"+", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {NULL, 0, 0, 0, 0} }; @@ -1618,7 +1619,7 @@ riscv_recognized_prefixed_ext (const char *ext) } /* Canonical order for single letter extensions. */ -static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh"; +static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh+"; /* Array is used to compare the orders of standard extensions quickly. */ static int riscv_ext_order[26] = {0}; @@ -1788,6 +1789,7 @@ riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec, table = riscv_supported_std_ext; } + int i = 0; while (table != NULL && table[i].name != NULL) { @@ -1938,7 +1940,7 @@ riscv_parse_extensions (riscv_parse_subset_t *rps, const char *p) { /* First letter must start with i, e or g. */ - if (*p != 'e' && *p != 'i' && *p != 'g') + if (*p != 'e' && *p != 'i' && *p != 'g' && *p != '+') { rps->error_handler (_("%s: first ISA extension must be `e', `i' or `g'"), @@ -2569,6 +2571,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps, { case INSN_CLASS_I: return riscv_subset_supports (rps, "i"); + case INSN_CLASS_OTBN: + return riscv_subset_supports (rps, "+"); case INSN_CLASS_ZICBOM: return riscv_subset_supports (rps, "zicbom"); case INSN_CLASS_ZICBOP: @@ -2854,6 +2858,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps, { case INSN_CLASS_I: return "i"; + case INSN_CLASS_OTBN: + return "+"; case INSN_CLASS_ZICBOM: return "zicbom"; case INSN_CLASS_ZICBOP: diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index a77e153fb44..e4d325eb038 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -68,6 +68,7 @@ enum riscv_csr_class CSR_CLASS_NONE, CSR_CLASS_I, + CSR_CLASS_OTBN, /* OTBN */ CSR_CLASS_I_32, /* rv32 only */ CSR_CLASS_F, /* f-ext only */ CSR_CLASS_ZKR, /* zkr only */ @@ -171,6 +172,9 @@ static const char *file_arch_str = NULL; static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_NONE; static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE; +/* Global flag indicating whether we are compiling OTBN code. */ +static bool riscv_arch_is_otbn = false; + static unsigned xlen = 0; /* The width of an x-register. */ static unsigned abi_xlen = 0; /* The width of a pointer in the ABI. */ static bool rve_abi = false; @@ -371,6 +375,8 @@ riscv_set_arch (const char *s) riscv_set_arch_str (&file_arch_str); riscv_set_arch_str (&riscv_rps_as.subset_list->arch_str); + riscv_arch_is_otbn = strcmp(s, "rv32+") == 0; + riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c") || riscv_subset_supports (&riscv_rps_as, "zca")); @@ -957,6 +963,9 @@ opcode_name_lookup (char **s) enum reg_class { RCLASS_GPR, + RCLASS_WDR, + RCLASS_WDR_Q, + RCLASS_WDR_H, RCLASS_FPR, RCLASS_VECR, RCLASS_VECM, @@ -1062,6 +1071,9 @@ riscv_csr_address (const char *csr_name, need_check_version = true; extension = "i"; break; + case CSR_CLASS_OTBN: + extension = "+"; + break; case CSR_CLASS_H_32: is_rv32_only = true; /* Fall through. */ @@ -1570,6 +1582,89 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length) goto unknown_validate_operand; } break; /* end RVV */ + + /* + * OTBN + */ + + case '+': + switch (*++oparg) { + case 'a': + USE_BITS(OP_MASK_BN_WRD, OP_SH_BN_WRD); + break; + case 'h': + USE_BITS(OP_MASK_BN_WRD, OP_SH_BN_WRD); + USE_BITS(OP_MASK_BN_MULQACC_SO_DH, OP_SH_BN_MULQACC_SO_DH); + break; + case 'b': + USE_BITS(OP_MASK_BN_WRS1, OP_SH_BN_WRS1); + break; + case 'c': + USE_BITS(OP_MASK_BN_WRS2, OP_SH_BN_WRS2); + break; + case 's': + USE_BITS(OP_MASK_BN_WRS2, OP_SH_BN_WRS2); + USE_BITS(OP_MASK_BN_SHIFT_TYPE, OP_SH_BN_SHIFT_TYPE); + USE_BITS(OP_MASK_BN_SHIFT_AMOUNT, OP_SH_BN_SHIFT_AMOUNT); + break; + case 't': + USE_BITS(OP_MASK_BN_WRS2, OP_SH_BN_WRS2); + USE_BITS(OP_MASK_BN_RSHI_IMM0, OP_SH_BN_RSHI_IMM0); + USE_BITS(OP_MASK_BN_RSHI_IMM1, OP_SH_BN_RSHI_IMM1); + break; + case 'e': + USE_BITS(OP_MASK_BN_WRS2, OP_SH_BN_WRS2); + USE_BITS(OP_MASK_BN_Q2, OP_SH_BN_Q2); + break; + case 'f': + USE_BITS(OP_MASK_BN_WRS1, OP_SH_BN_WRS1); + USE_BITS(OP_MASK_BN_Q1, OP_SH_BN_Q1); + break; + case '>': + USE_BITS(OP_MASK_BN_ACC_SH, OP_SH_BN_ACC_SH); + break; + case 'i': + USE_BITS(OP_MASK_BN_WRS2, OP_SH_BN_WRS2); + USE_BITS(OP_MASK_BN_GRD_INC, OP_SH_BN_GRD_INC); + break; + case 'j': + USE_BITS(OP_MASK_BN_WRS1, OP_SH_BN_WRS1); + USE_BITS(OP_MASK_BN_GRS_INC, OP_SH_BN_GRS_INC); + break; + case 'k': + USE_BITS(OP_MASK_BN_WRS1, OP_SH_BN_WRS1); + USE_BITS(OP_MASK_BN_INC1, OP_SH_BN_INC1); + break; + case 'o': + USE_BITS(OP_MASK_BN_OFF0, OP_SH_BN_OFF0); + USE_BITS(OP_MASK_BN_OFF1, OP_SH_BN_OFF1); + break; + case 'B': + USE_BITS(OP_MASK_LOOP_SZ, OP_SH_LOOP_SZ); + break; + case 'J': + USE_BITS(OP_MASK_LOOP_ITS0, OP_SH_LOOP_ITS0); + USE_BITS(OP_MASK_LOOP_ITS1, OP_SH_LOOP_ITS1); + break; + case 'C': + USE_BITS(OP_MASK_CSR, OP_SH_CSR); + break; + case 'E': + USE_BITS(OP_MASK_BN_WSR, OP_SH_BN_WSR); + break; + case 'I': + USE_BITS(OP_MASK_BN_IMM, OP_SH_BN_IMM); + break; + case 'F': + USE_BITS(OP_MASK_BN_FLAG_GROUP, OP_SH_BN_FLAG_GROUP); + break; + case 'Z': + USE_BITS(OP_MASK_BN_FLAG_SEL, OP_SH_BN_FLAG_SEL); + USE_BITS(OP_MASK_BN_FLAG_GROUP, OP_SH_BN_FLAG_GROUP); + break; + } + break; /* end OTBN */ + case ',': break; case '(': break; case ')': break; @@ -1907,6 +2002,9 @@ md_begin (void) hash_reg_names (RCLASS_FPR, riscv_fpr_names_abi, NFPR); hash_reg_names (RCLASS_VECR, riscv_vecr_names_numeric, NVECR); hash_reg_names (RCLASS_VECM, riscv_vecm_names_numeric, NVECM); + hash_reg_names(RCLASS_WDR, riscv_wdr_names_numeric, NWDR); + hash_reg_names(RCLASS_WDR_Q, riscv_wdr_q_names_numeric, NWDRQ); + hash_reg_names(RCLASS_WDR_H, riscv_wdr_h_names_numeric, NWDRH); /* Add "fp" as an alias for "s0". */ hash_reg_name (RCLASS_GPR, "fp", 8); @@ -2187,8 +2285,10 @@ pcrel_access (int destreg, int tempreg, expressionS *ep, ep2.X_add_symbol = make_internal_label (); ep2.X_add_number = 0; - macro_build (ep, "auipc", "d,u", tempreg, hi_reloc); - macro_build (&ep2, lo_insn, lo_pattern, destreg, tempreg, lo_reloc); + /* Cannot use the `auipc` instruction for the `la` macro in OTBN code. */ + macro_build(ep, riscv_arch_is_otbn ? "lui" : "auipc", "d,u,", tempreg, + hi_reloc); + macro_build(&ep2, lo_insn, lo_pattern, destreg, tempreg, lo_reloc); } static void @@ -2841,6 +2941,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, error.missing_ext = NULL; /* Indicate we are assembling instruction with CSR. */ bool insn_with_csr = false; + bool insn_bn_gpr_inc = false; /* Parse the name of the instruction. Terminate the string if whitespace is found so that str_hash_find only sees the name part of the string. */ @@ -3425,10 +3526,260 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, } break; /* end RVV */ + /* + * OTBN + */ + + case '+': + switch (*++oparg) { + case 'a': + case 'b': + case 'c': + if (!reg_lookup(&asarg, RCLASS_WDR, ®no)) { + break; + } + if (*oparg == 'a') { + INSERT_OPERAND(BN_WRD, *ip, regno); + } else if (*oparg == 'b') { + INSERT_OPERAND(BN_WRS1, *ip, regno); + } else { + INSERT_OPERAND(BN_WRS2, *ip, regno); + } + continue; + case 'e': + case 'f': + if (!reg_lookup(&asarg, RCLASS_WDR_Q, ®no)) { + break; + } + if (*oparg == 'e') { + INSERT_OPERAND(BN_WRS1, *ip, regno >> 2); + INSERT_OPERAND(BN_Q1, *ip, regno & 0x3); + } else { + INSERT_OPERAND(BN_WRS2, *ip, regno >> 2); + INSERT_OPERAND(BN_Q2, *ip, regno & 0x3); + } + continue; + case 'h': { + if (!reg_lookup(&asarg, RCLASS_WDR_H, ®no)) { + break; + } + INSERT_OPERAND(BN_WRD, *ip, regno >> 1); + INSERT_OPERAND(BN_MULQACC_SO_DH, *ip, regno & 0x1); + continue; + } + + case 's': + if (!reg_lookup(&asarg, RCLASS_WDR, ®no)) { + break; + } + INSERT_OPERAND(RS2, *ip, regno); + + unsigned long shift_type = 0; + bool has_shift = false; + if ((*asarg == '>') && (*(asarg + 1) == '>')) { + asarg += 2; + shift_type = 1; + has_shift = true; + } else if ((*asarg == '<') && (*(asarg + 1) == '<')) { + asarg += 2; + has_shift = true; + } + INSERT_OPERAND(SHIFT_TYPE, *ip, shift_type); + + if (has_shift) { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, false); + unsigned long shift_amount = imm_expr->X_add_number; + if ((shift_amount & 0x7) != 0 || shift_amount > 248) { + as_bad(_("improper shift amount (%" PRIu64 ")"), shift_amount); + } + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + INSERT_OPERAND(SHIFT_AMOUNT, *ip, shift_amount >> 3); + } + continue; + + case 't': { + if (!reg_lookup(&asarg, RCLASS_WDR, ®no)) { + break; + } + INSERT_OPERAND(BN_WRS2, *ip, regno); + + if ((*asarg == '>') && (*(asarg + 1) == '>')) { + asarg += 2; + + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, false); + unsigned long shift_amount = imm_expr->X_add_number; + if (shift_amount > 255) { + as_bad(_("improper shift amount (%" PRIu64 ")"), shift_amount); + } + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + INSERT_OPERAND(BN_RSHI_IMM0, *ip, shift_amount & 0x1); + INSERT_OPERAND(BN_RSHI_IMM1, *ip, shift_amount >> 1); + continue; + } + break; + } + + case '>': { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, false); + long int imm = imm_expr->X_add_number; + + if ((imm < 0) || (imm > 192) || ((imm & 0x3f) != 0)) { + as_bad(_("improper shift amount (%" PRIi64 ")"), imm); + } + + INSERT_OPERAND(BN_ACC_SH, *ip, imm >> 6); + + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + continue; + } + + case 'i': + case 'j': + case 'k': + if (!reg_lookup(&asarg, RCLASS_GPR, ®no)) { + break; + } + + bool gpr_inc = false; + if ((*asarg == '+') && (*(asarg + 1) == '+')) { + if (insn_bn_gpr_inc) { + as_bad("both gpr increments cannot be specified together"); + break; + } + asarg += 2; + gpr_inc = true; + } + + if (*oparg == 'i') { + INSERT_OPERAND(BN_WRS2, *ip, regno); + INSERT_OPERAND(BN_GRD_INC, *ip, gpr_inc); + insn_bn_gpr_inc = gpr_inc; + } else if (*oparg == 'j') { + INSERT_OPERAND(BN_WRS1, *ip, regno); + INSERT_OPERAND(BN_GRS_INC, *ip, gpr_inc); + insn_bn_gpr_inc = false; + } else { + INSERT_OPERAND(BN_WRS1, *ip, regno); + INSERT_OPERAND(BN_INC1, *ip, gpr_inc); + insn_bn_gpr_inc = false; + } + continue; + case 'o': + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, false); + int off = imm_expr->X_add_number; + if (((off & 0x1f) != 0) || (off < -16384) || (off > 16352)) { + as_bad(_("improper offset amount (%" PRIu64 ")"), + imm_expr->X_add_number); + break; + } + INSERT_OPERAND(OFF0, *ip, off >> 5); + INSERT_OPERAND(OFF1, *ip, (off >> 5) >> 7); + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + continue; + case 'I': { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, true); + unsigned long imm = imm_expr->X_add_number; + if (imm > 1024) + as_bad(_("improper CSR address (%" PRIu64 ")"), imm); + INSERT_OPERAND(BN_IMM, *ip, imm); + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + continue; + } + + case 'B': { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, true); + unsigned long sz = imm_expr->X_add_number; + if (sz < 1 || sz > 4096) + as_bad(_("improper loop body size (%" PRIu64 ")"), sz); + + INSERT_OPERAND(LOOP_SZ, *ip, sz - 1); + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + continue; + } + case 'J': { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, true); + unsigned long its = imm_expr->X_add_number; + if (its > 1023) + as_bad(_("improper loop iteration number (%" PRIu64 ")"), its); + + INSERT_OPERAND(LOOP_ITS0, *ip, its & 0x1f); + INSERT_OPERAND(LOOP_ITS1, *ip, (its >> 5) & 0x1f); + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + continue; + } + + case 'C': + insn_with_csr = true; + if (reg_lookup(&asarg, RCLASS_CSR, ®no)) { + INSERT_OPERAND(CSR, *ip, regno); + } else { + my_getExpression(imm_expr, asarg); + check_absolute_expr(ip, imm_expr, true); + if ((unsigned long)imm_expr->X_add_number > 0xfff) + as_bad(_("improper CSR address (%" PRIu64 ")"), + imm_expr->X_add_number); + INSERT_OPERAND(CSR, *ip, imm_expr->X_add_number); + imm_expr->X_op = O_absent; + asarg = expr_parse_end; + } + continue; + + case 'E': { + if (!arg_lookup(&asarg, riscv_otbn_wsr, ARRAY_SIZE(riscv_otbn_wsr), + ®no)) { + as_bad("unknown wsr"); + break; + } + INSERT_OPERAND(BN_WSR, *ip, regno); + } + continue; + + case 'F': + // The flag group operand is optional. + if (*asarg == '\0') { + continue; + } + if (!arg_lookup(&asarg, riscv_otbn_fg, ARRAY_SIZE(riscv_otbn_fg), + ®no)) { + as_bad("flag group must be either FG0 or FG1"); + break; + } + INSERT_OPERAND(FLAG_GROUP, *ip, regno); + continue; + + case 'Z': + if (!arg_lookup(&asarg, riscv_otbn_sel_fg, + ARRAY_SIZE(riscv_otbn_sel_fg), ®no)) { + as_bad("unknown selection bit"); + break; + } + INSERT_OPERAND(BN_FLAG_SEL, *ip, regno & 0x3); + INSERT_OPERAND(BN_FLAG_GROUP, *ip, (regno >> 2) & 0x1); + continue; + } + break; /* end OTBN */ + case ',': if (*asarg++ == *oparg) continue; asarg--; + // Allow for optional trailing operands. + if (*asarg == '\0') + continue; break; case '(': @@ -4815,13 +5166,15 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) case BFD_RELOC_RISCV_PCREL_HI20: /* Record and evaluate the pcrel_hi relocation with local symbol. Fill in a tentative value to improve objdump readability for -mrelax, - and set fx_done for -mno-relax. */ - if (fixP->fx_addsy - && S_IS_LOCAL (fixP->fx_addsy) - && S_GET_SEGMENT (fixP->fx_addsy) == seg) + and set fx_done for -mno-relax. + If we are compiling OTBN code, do not add the offset to the PC. */ + if (fixP->fx_addsy && + ((S_IS_LOCAL(fixP->fx_addsy) && S_GET_SEGMENT(fixP->fx_addsy) == seg) + || riscv_arch_is_otbn)) { - bfd_vma target = S_GET_VALUE (fixP->fx_addsy) + *valP; - bfd_vma value = target - md_pcrel_from (fixP); + bfd_vma target = S_GET_VALUE(fixP->fx_addsy) + *valP; + bfd_vma value = + riscv_arch_is_otbn ? target : target - md_pcrel_from(fixP); /* Record PCREL_HI20. */ if (!riscv_record_pcrel_fixup (riscv_pcrel_hi_fixup_hash, @@ -4844,19 +5197,20 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) case BFD_RELOC_RISCV_PCREL_LO12_I: /* Resolve the pcrel_lo relocation with local symbol. Fill in a tentative value to improve objdump readability for -mrelax, - and set fx_done for -mno-relax. */ + and set fx_done for -mno-relax. + If we are compiling OTBN code, do not add the offset to the PC. */ { bfd_vma location_pcrel_hi = S_GET_VALUE (fixP->fx_addsy) + *valP; riscv_pcrel_hi_fixup search = {(const asection *) seg, location_pcrel_hi, 0, 0}; riscv_pcrel_hi_fixup *entry = htab_find (riscv_pcrel_hi_fixup_hash, &search); - if (entry && entry->symbol - && S_IS_LOCAL (entry->symbol) - && S_GET_SEGMENT (entry->symbol) == seg) + if (entry && entry->symbol && + ((S_IS_LOCAL(entry->symbol) && S_GET_SEGMENT(entry->symbol) == seg) || + riscv_arch_is_otbn)) { - bfd_vma target = entry->target; - bfd_vma value = target - entry->address; + bfd_vma target = entry->target; + bfd_vma value = riscv_arch_is_otbn ? target : target - entry->address; if (fixP->fx_r_type == BFD_RELOC_RISCV_PCREL_LO12_S) bfd_putl32 (bfd_getl32 (buf) | ENCODE_STYPE_IMM (value), buf); else diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index 9a5256b8dd2..eeb83e9d5e3 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -21,6 +21,73 @@ #ifndef RISCV_ENCODING_H #define RISCV_ENCODING_H /* Instruction opcode macros. */ + +/* + * OTBN-only instructions. + */ + +#define MATCH_LOOP 0x7b +#define MASK_LOOP 0x7fff +#define MATCH_LOOPI 0x107b +#define MASK_LOOPI 0x707f +/* OTBN bignum. */ +#define MATCH_BN_ADD 0x2b +#define MASK_BN_ADD 0x707f +#define MATCH_BN_ADDC 0x202b +#define MASK_BN_ADDC 0x707f +#define MATCH_BN_ADDI 0x402b +#define MASK_BN_ADDI 0x4000707f +#define MATCH_BN_ADDM 0x502b +#define MASK_BN_ADDM 0xfe00707f +#define MATCH_BN_MULQACC 0x3b +#define MASK_BN_MULQACC 0xe0001fff +#define MATCH_BN_MULQACC_Z 0x103b +#define MASK_BN_MULQACC_Z 0xe0001fff +#define MATCH_BN_MULQACC_WO 0x2000003b +#define MASK_BN_MULQACC_WO 0x6000107f +#define MATCH_BN_MULQACC_WO_Z 0x2000103b +#define MASK_BN_MULQACC_WO_Z 0x6000107f +#define MATCH_BN_MULQACC_SO 0x4000003b +#define MASK_BN_MULQACC_SO 0x4000107f +#define MATCH_BN_MULQACC_SO_Z 0x4000103b +#define MASK_BN_MULQACC_SO_Z 0x4000107f +#define MATCH_BN_SUB 0x102b +#define MASK_BN_SUB 0x707f +#define MATCH_BN_SUBB 0x302b +#define MASK_BN_SUBB 0x707f +#define MATCH_BN_SUBI 0x4000402b +#define MASK_BN_SUBI 0x4000707f +#define MATCH_BN_SUBM 0x4000502b +#define MASK_BN_SUBM 0xfe00707f +#define MATCH_BN_AND 0x0000207b +#define MASK_BN_AND 0x707f +#define MATCH_BN_OR 0x0000407b +#define MASK_BN_OR 0x707f +#define MATCH_BN_NOT 0x0000507b +#define MASK_BN_NOT 0xff07f +#define MATCH_BN_XOR 0x0000607b +#define MASK_BN_XOR 0x707f +#define MATCH_BN_RSHI 0x307b +#define MASK_BN_RSHI 0x307f +#define MATCH_BN_SEL 0xb +#define MASK_BN_SEL 0x7800707f +#define MATCH_BN_CMP 0x0000100b +#define MASK_BN_CMP 0x7fff +#define MATCH_BN_CMPB 0x0000300b +#define MASK_BN_CMPB 0x7fff +#define MATCH_BN_LID 0x400b +#define MASK_BN_LID 0x707f +#define MATCH_BN_SID 0x500b +#define MASK_BN_SID 0x707f +#define MATCH_BN_MOV 0x0000600b +#define MASK_BN_MOV 0xfff0707f +#define MATCH_BN_MOVR 0x8000600b +#define MASK_BN_MOVR 0xfe007d7f +#define MATCH_BN_WSRR 0x700b +#define MASK_BN_WSRR 0xf00ff07f +#define MATCH_BN_WSRW 0x8000700b +#define MASK_BN_WSRW 0xf0007fff + #define MATCH_SLLI_RV32 0x1013 #define MASK_SLLI_RV32 0xfe00707f #define MATCH_SRLI_RV32 0x5013 @@ -3786,6 +3853,21 @@ #define MASK_SFVFNRCLIPXUFQF 0xfe00707f #define MATCH_SFVFNRCLIPXFQF 0x8e00505b #define MASK_SFVFNRCLIPXFQF 0xfe00707f +/* OTBN CSRs */ +#define CSR_FG0 0x7c0 +#define CSR_FG1 0x7c1 +#define CSR_FLAGS 0x7c8 +#define CSR_MOD0 0x7d0 +#define CSR_MOD1 0x7d1 +#define CSR_MOD2 0x7d2 +#define CSR_MOD3 0x7d3 +#define CSR_MOD4 0x7d4 +#define CSR_MOD5 0x7d5 +#define CSR_MOD6 0x7d6 +#define CSR_MOD7 0x7d7 +#define CSR_RND_PREFETCH 0x7d8 +#define CSR_RND 0xfc0 +#define CSR_URND 0xfc1 /* Unprivileged Counter/Timers CSR addresses. */ #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 @@ -5090,6 +5172,21 @@ DECLARE_INSN(xperm_w, MATCH_XPERM_W, MASK_XPERM_W) #endif /* DECLARE_INSN */ #ifdef DECLARE_CSR +DECLARE_CSR(FG0, CSR_FG0, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(FG1, CSR_FG1, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(FLAGS, CSR_FLAGS, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD0, CSR_MOD0, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD1, CSR_MOD1, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD2, CSR_MOD2, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD3, CSR_MOD3, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD4, CSR_MOD4, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD5, CSR_MOD5, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD6, CSR_MOD6, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(MOD7, CSR_MOD7, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(RND_PREFETCH, CSR_RND_PREFETCH, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(RND, CSR_RND, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +DECLARE_CSR(URND, CSR_URND, CSR_CLASS_OTBN, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) + /* Unprivileged Counter/Timers CSRs. */ DECLARE_CSR(cycle, CSR_CYCLE, CSR_CLASS_I, PRIV_SPEC_CLASS_1P10, PRIV_SPEC_CLASS_DRAFT) DECLARE_CSR(time, CSR_TIME, CSR_CLASS_I, PRIV_SPEC_CLASS_1P10, PRIV_SPEC_CLASS_DRAFT) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 5b703fe09e6..099b8f587fd 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -268,6 +268,70 @@ static inline unsigned int riscv_insn_length (insn_t insn) /* RV fields. */ +/* OTBN operand masks. */ +#define OP_MASK_SHIFT_TYPE 0x1 +#define OP_SH_SHIFT_TYPE 30 +#define OP_MASK_SHIFT_AMOUNT 0x1f +#define OP_SH_SHIFT_AMOUNT 25 +#define OP_MASK_FLAG_GROUP 0x1 +#define OP_SH_FLAG_GROUP 31 +#define OP_MASK_INCD 0x1 +#define OP_SH_INCD 7 +#define OP_MASK_INC1 0x1 +#define OP_SH_INC1 8 +#define OP_MASK_OFF0 0x7f +#define OP_SH_OFF0 25 +#define OP_MASK_OFF1 0x7 +#define OP_SH_OFF1 9 +#define OP_MASK_BN_WRS2 0x1f +#define OP_SH_BN_WRS2 20 +#define OP_MASK_BN_WRS1 0x1f +#define OP_SH_BN_WRS1 15 +#define OP_MASK_BN_WRD 0x1f +#define OP_SH_BN_WRD 7 +#define OP_MASK_BN_Q2 0x3 +#define OP_SH_BN_Q2 27 +#define OP_MASK_BN_Q1 0x3 +#define OP_SH_BN_Q1 25 +#define OP_MASK_BN_ACC_SH 0x3 +#define OP_SH_BN_ACC_SH 13 +#define OP_MASK_BN_GRD_INC 0x1 +#define OP_SH_BN_GRD_INC 7 +#define OP_MASK_BN_GRS_INC 0x1 +#define OP_SH_BN_GRS_INC 9 +#define OP_MASK_BN_INCD 0x1 +#define OP_SH_BN_INCD 7 +#define OP_MASK_BN_INC1 0x1 +#define OP_SH_BN_INC1 8 +#define OP_MASK_BN_OFF0 0x7f +#define OP_SH_BN_OFF0 25 +#define OP_MASK_BN_OFF1 0x7 +#define OP_SH_BN_OFF1 9 +#define OP_MASK_BN_SHIFT_TYPE 0x1 +#define OP_SH_BN_SHIFT_TYPE 30 +#define OP_MASK_BN_SHIFT_AMOUNT 0x1f +#define OP_SH_BN_SHIFT_AMOUNT 25 +#define OP_MASK_BN_FLAG_GROUP 0x1 +#define OP_SH_BN_FLAG_GROUP 31 +#define OP_MASK_BN_FLAG_SEL 0x3 +#define OP_SH_BN_FLAG_SEL 25 +#define OP_MASK_BN_RSHI_IMM0 0x1 +#define OP_SH_BN_RSHI_IMM0 14 +#define OP_MASK_BN_RSHI_IMM1 0x7f +#define OP_SH_BN_RSHI_IMM1 25 +#define OP_MASK_BN_IMM 0x3ff +#define OP_SH_BN_IMM 20 +#define OP_MASK_BN_MULQACC_SO_DH 0x1 +#define OP_SH_BN_MULQACC_SO_DH 29 +#define OP_MASK_BN_WSR 0xff +#define OP_SH_BN_WSR 20 +#define OP_MASK_LOOP_SZ 0xfff +#define OP_SH_LOOP_SZ 20 +#define OP_MASK_LOOP_ITS0 0x1f +#define OP_SH_LOOP_ITS0 7 +#define OP_MASK_LOOP_ITS1 0x1f +#define OP_SH_LOOP_ITS1 15 + #define OP_MASK_OP 0x7f #define OP_SH_OP 0 #define OP_MASK_RS2 0x1f @@ -404,6 +468,9 @@ static inline unsigned int riscv_insn_length (insn_t insn) #define NGPR 32 #define NFPR 32 +#define NWDR 32 +#define NWDRQ 128 +#define NWDRH 64 /* These fake label defines are use by both the assembler, and libopcodes. The assembler uses this when it needs to generate a fake @@ -456,6 +523,7 @@ enum riscv_insn_class INSN_CLASS_NONE, INSN_CLASS_I, + INSN_CLASS_OTBN, INSN_CLASS_C, INSN_CLASS_M, INSN_CLASS_F, @@ -670,12 +738,18 @@ enum riscv_seg_mstate MAP_INSN, /* Instructions. */ }; -#define NRC (4 + 1) /* Max characters in register names, incl nul. */ +#define NRC (5 + 1) /* Max characters in register names, incl nul. */ extern const char riscv_gpr_names_numeric[NGPR][NRC]; extern const char riscv_gpr_names_abi[NGPR][NRC]; extern const char riscv_fpr_names_numeric[NFPR][NRC]; extern const char riscv_fpr_names_abi[NFPR][NRC]; +extern const char riscv_wdr_names_numeric[NWDR][NRC]; +extern const char riscv_wdr_q_names_numeric[NWDRQ][NRC]; +extern const char riscv_wdr_h_names_numeric[NWDRH][NRC]; +extern const char * const riscv_otbn_fg[2]; +extern const char * const riscv_otbn_wsr[8]; +extern const char * const riscv_otbn_sel_fg[12]; extern const char * const riscv_rm[8]; extern const char * const riscv_pred_succ[16]; extern const char riscv_vecr_names_numeric[NVECR][NRC]; diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 193109f4c00..3e6c80c6da8 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -58,6 +58,104 @@ const char riscv_fpr_names_abi[NFPR][NRC] = "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11" }; +const char riscv_wdr_names_numeric[NWDR][NRC] = +{ + "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", + "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", + "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", + "w24", "w25", "w26", "w27", "w28", "w29", "w30", "w31" +}; + +const char riscv_wdr_q_names_numeric[NWDRQ][NRC] = +{ + "w0.0", "w0.1", "w0.2", "w0.3", + "w1.0", "w1.1", "w1.2", "w1.3", + "w2.0", "w2.1", "w2.2", "w2.3", + "w3.0", "w3.1", "w3.2", "w3.3", + "w4.0", "w4.1", "w4.2", "w4.3", + "w5.0", "w5.1", "w5.2", "w5.3", + "w6.0", "w6.1", "w6.2", "w6.3", + "w7.0", "w7.1", "w7.2", "w7.3", + "w8.0", "w8.1", "w8.2", "w8.3", + "w9.0", "w9.1", "w9.2", "w9.3", + "w10.0", "w10.1", "w10.2", "w10.3", + "w11.0", "w11.1", "w11.2", "w11.3", + "w12.0", "w12.1", "w12.2", "w12.3", + "w13.0", "w13.1", "w13.2", "w13.3", + "w14.0", "w14.1", "w14.2", "w14.3", + "w15.0", "w15.1", "w15.2", "w15.3", + "w16.0", "w16.1", "w16.2", "w16.3", + "w17.0", "w17.1", "w17.2", "w17.3", + "w18.0", "w18.1", "w18.2", "w18.3", + "w19.0", "w19.1", "w19.2", "w19.3", + "w20.0", "w20.1", "w20.2", "w20.3", + "w21.0", "w21.1", "w21.2", "w21.3", + "w22.0", "w22.1", "w22.2", "w22.3", + "w23.0", "w23.1", "w23.2", "w23.3", + "w24.0", "w24.1", "w24.2", "w24.3", + "w25.0", "w25.1", "w25.2", "w25.3", + "w26.0", "w26.1", "w26.2", "w26.3", + "w27.0", "w27.1", "w27.2", "w27.3", + "w28.0", "w28.1", "w28.2", "w28.3", + "w29.0", "w29.1", "w29.2", "w29.3", + "w30.0", "w30.1", "w30.2", "w30.3", + "w31.0", "w31.1", "w31.2", "w31.3" +}; + +const char riscv_wdr_h_names_numeric[NWDRH][NRC] = +{ + "w0.L", "w0.U", + "w1.L", "w1.U", + "w2.L", "w2.U", + "w3.L", "w3.U", + "w4.L", "w4.U", + "w5.L", "w5.U", + "w6.L", "w6.U", + "w7.L", "w7.U", + "w8.L", "w8.U", + "w9.L", "w9.U", + "w10.L", "w10.U", + "w11.L", "w11.U", + "w12.L", "w12.U", + "w13.L", "w13.U", + "w14.L", "w14.U", + "w15.L", "w15.U", + "w16.L", "w16.U", + "w17.L", "w17.U", + "w18.L", "w18.U", + "w19.L", "w19.U", + "w20.L", "w20.U", + "w21.L", "w21.U", + "w22.L", "w22.U", + "w23.L", "w23.U", + "w24.L", "w24.U", + "w25.L", "w25.U", + "w26.L", "w26.U", + "w27.L", "w27.U", + "w28.L", "w28.U", + "w29.L", "w29.U", + "w30.L", "w30.U", + "w31.L", "w31.U" +}; + +/* OTBN flag groups. */ +const char * const riscv_otbn_fg[2] = { + "FG0", "FG1" +}; + +/* OTBN WSRs */ +const char * const riscv_otbn_wsr[8] = { + "MOD", "RND", "URND", "ACC", + "KEY_S0_L", "KEY_S0_H", "KEY_S1_L", "KEY_S1_H", +}; + +const char * const riscv_otbn_sel_fg[12] = { + "C", "M", "L", "Z", + "FG1.C", "FG1.M", "FG1.L", "FG1.Z", + "FG0.C", "FG0.M", "FG0.L", "FG0.Z" +}; + + /* Rounding modes. */ const char * const riscv_rm[8] = { @@ -437,15 +535,50 @@ const struct riscv_opcode riscv_opcodes[] = {"c.ntl.all", 0, INSN_CLASS_ZIHINTNTL_AND_C, "", MATCH_C_NTL_ALL, MASK_C_NTL_ALL, match_opcode, 0 }, {"pause", 0, INSN_CLASS_ZIHINTPAUSE, "", MATCH_PAUSE, MASK_PAUSE, match_opcode, 0 }, +/* OTBN-only instructions */ +{"bn.add", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_ADD, MASK_BN_ADD, match_opcode, 0 }, +{"bn.addc", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_ADDC, MASK_BN_ADDC, match_opcode, 0 }, +{"bn.addi", 0, INSN_CLASS_OTBN, "+a,+b,+I,+F", MATCH_BN_ADDI, MASK_BN_ADDI, match_opcode, 0 }, +{"bn.addm", 0, INSN_CLASS_OTBN, "+a,+b,+c", MATCH_BN_ADDM, MASK_BN_ADDM, match_opcode, 0 }, +{"bn.mulqacc", 0, INSN_CLASS_OTBN, "+e,+f,+>", MATCH_BN_MULQACC, MASK_BN_MULQACC, match_opcode, 0 }, +{"bn.mulqacc.z", 0, INSN_CLASS_OTBN, "+e,+f,+>", MATCH_BN_MULQACC_Z, MASK_BN_MULQACC_Z, match_opcode, 0 }, +{"bn.mulqacc.wo", 0, INSN_CLASS_OTBN, "+a,+e,+f,+>,+F", MATCH_BN_MULQACC_WO, MASK_BN_MULQACC_WO, match_opcode, 0 }, +{"bn.mulqacc.wo.z", 0, INSN_CLASS_OTBN, "+a,+e,+f,+>,+F", MATCH_BN_MULQACC_WO_Z, MASK_BN_MULQACC_WO_Z, match_opcode, 0 }, +{"bn.mulqacc.so", 0, INSN_CLASS_OTBN, "+h,+e,+f,+>,+F", MATCH_BN_MULQACC_SO, MASK_BN_MULQACC_SO, match_opcode, 0 }, +{"bn.mulqacc.so.z", 0, INSN_CLASS_OTBN, "+h,+e,+f,+>,+F", MATCH_BN_MULQACC_SO_Z, MASK_BN_MULQACC_SO_Z, match_opcode, 0 }, +{"bn.sub", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_SUB, MASK_BN_SUB, match_opcode, 0 }, +{"bn.subb", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_SUBB, MASK_BN_SUBB, match_opcode, 0 }, +{"bn.subi", 0, INSN_CLASS_OTBN, "+a,+b,+I,+F", MATCH_BN_SUBI, MASK_BN_SUBI, match_opcode, 0 }, +{"bn.subm", 0, INSN_CLASS_OTBN, "+a,+b,+c", MATCH_BN_SUBM, MASK_BN_SUBM, match_opcode, 0 }, +{"bn.and", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_AND, MASK_BN_AND, match_opcode, 0 }, +{"bn.or" , 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_OR, MASK_BN_OR, match_opcode, 0 }, +{"bn.not" , 0, INSN_CLASS_OTBN, "+a,+s,+F", MATCH_BN_NOT, MASK_BN_NOT, match_opcode, 0 }, +{"bn.xor", 0, INSN_CLASS_OTBN, "+a,+b,+s,+F", MATCH_BN_XOR, MASK_BN_XOR, match_opcode, 0 }, +{"bn.rshi", 0, INSN_CLASS_OTBN, "+a,+b,+t", MATCH_BN_RSHI, MASK_BN_RSHI, match_opcode, 0 }, +{"bn.sel", 0, INSN_CLASS_OTBN, "+a,+b,+c,+Z", MATCH_BN_SEL, MASK_BN_SEL, match_opcode, 0 }, +{"bn.cmp" , 0, INSN_CLASS_OTBN, "+b,+s,+F", MATCH_BN_CMP, MASK_BN_CMP, match_opcode, 0 }, +{"bn.cmpb" , 0, INSN_CLASS_OTBN, "+b,+s,+F", MATCH_BN_CMPB, MASK_BN_CMPB, match_opcode, 0 }, +{"bn.lid", 0, INSN_CLASS_OTBN, "+i,+o(+k)", MATCH_BN_LID, MASK_BN_LID, match_opcode, 0 }, +{"bn.sid", 0, INSN_CLASS_OTBN, "+i,+o(+k)", MATCH_BN_SID, MASK_BN_SID, match_opcode, 0 }, +{"bn.mov", 0, INSN_CLASS_OTBN, "+a,+b", MATCH_BN_MOV, MASK_BN_MOV, match_opcode, 0 }, +{"bn.movr", 0, INSN_CLASS_OTBN, "+i,+j", MATCH_BN_MOVR, MASK_BN_MOVR, match_opcode, 0 }, +{"bn.wsrr", 0, INSN_CLASS_OTBN, "+a,+E", MATCH_BN_WSRR, MASK_BN_WSRR, match_opcode, 0 }, +{"bn.wsrw", 0, INSN_CLASS_OTBN, "+E,+b", MATCH_BN_WSRW, MASK_BN_WSRW, match_opcode, 0 }, + +{"loop", 0, INSN_CLASS_OTBN, "s,+B", MATCH_LOOP, MASK_LOOP, match_opcode, 0 }, +{"loopi", 0, INSN_CLASS_OTBN, "+J,+B", MATCH_LOOPI, MASK_LOOPI, match_opcode, 0 }, + /* 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 */ +{"unimp", 0, INSN_CLASS_OTBN, "", 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_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_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_I, "", MATCH_JALR|(X_RA << OP_SH_RS1), MASK_JALR|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS|INSN_BRANCH }, +{"ret", 0, INSN_CLASS_OTBN, "", 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_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 }, @@ -458,11 +591,13 @@ 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 }, +{"jalr", 0, INSN_CLASS_OTBN, "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_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", 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 }, +{"jal", 0, INSN_CLASS_OTBN, "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 }, {"call", 0, INSN_CLASS_I, "c", (X_RA << OP_SH_RS1)|(X_RA << OP_SH_RD), (int) M_CALL, NULL, INSN_MACRO }, {"tail", 0, INSN_CLASS_ZICFILP, "c", (X_T2 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO }, @@ -470,12 +605,15 @@ const struct riscv_opcode riscv_opcodes[] = {"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_I, "", MATCH_ADDI, MASK_ADDI|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS }, +{"nop", 0, INSN_CLASS_OTBN, "", 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_I, "d,u", MATCH_LUI, MASK_LUI, match_opcode, 0 }, +{"lui", 0, INSN_CLASS_OTBN, "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_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 }, +{"li", 0, INSN_CLASS_OTBN, "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_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 }, @@ -485,15 +623,18 @@ const struct riscv_opcode riscv_opcodes[] = {"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_I, "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, 0 }, +{"andi", 0, INSN_CLASS_OTBN, "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_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 }, +{"and", 0, INSN_CLASS_OTBN, "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_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_I, "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, INSN_CONDBRANCH }, +{"beq", 0, INSN_CLASS_OTBN, "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 }, {"bge", 0, INSN_CLASS_I, "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_CONDBRANCH }, @@ -510,6 +651,7 @@ const struct riscv_opcode riscv_opcodes[] = {"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_I, "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, INSN_CONDBRANCH }, +{"bne", 0, INSN_CLASS_OTBN, "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 }, @@ -517,6 +659,7 @@ const struct riscv_opcode riscv_opcodes[] = {"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_I, "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, 0 }, +{"addi", 0, INSN_CLASS_OTBN, "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 }, @@ -526,7 +669,9 @@ const struct riscv_opcode riscv_opcodes[] = {"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 }, +{"add", 0, INSN_CLASS_OTBN, "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, 0 }, {"la", 0, INSN_CLASS_I, "d,B", 0, (int) M_LA, match_rd_nonzero, INSN_MACRO }, +{"la", 0, INSN_CLASS_OTBN, "d,B", 0, (int) M_LA, match_rd_nonzero, INSN_MACRO }, {"lla", 0, INSN_CLASS_I, "d,B", 0, (int) M_LLA, NULL, INSN_MACRO }, {"lga", 0, INSN_CLASS_I, "d,B", 0, (int) M_LGA, match_rd_nonzero, INSN_MACRO }, {"la.tls.gd", 0, INSN_CLASS_I, "d,A", 0, (int) M_LA_TLS_GD, NULL, INSN_MACRO }, @@ -534,21 +679,28 @@ const struct riscv_opcode riscv_opcodes[] = {"neg", 0, INSN_CLASS_I, "d,t", MATCH_SUB, MASK_SUB|MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 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_I, "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, 0 }, +{"slli", 0, INSN_CLASS_OTBN, "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_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 }, +{"sll", 0, INSN_CLASS_I, "d,s,t", MATCH_SLL, MASK_SLL, match_opcode, 0 }, {"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_I, "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, 0 }, +{"srli", 0, INSN_CLASS_OTBN, "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_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 }, +{"srl", 0, INSN_CLASS_I, "d,s,t", MATCH_SRL, MASK_SRL, match_opcode, 0 }, {"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_I, "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, 0 }, +{"srai", 0, INSN_CLASS_OTBN, "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_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 }, +{"sra", 0, INSN_CLASS_I, "d,s,t", MATCH_SRA, MASK_SRA, match_opcode, 0 }, {"sub", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, INSN_ALIAS }, {"sub", 0, INSN_CLASS_I, "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, 0 }, +{"sub", 0, INSN_CLASS_OTBN, "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 }, @@ -564,13 +716,16 @@ const struct riscv_opcode riscv_opcodes[] = {"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_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 }, +{"lw", 0, INSN_CLASS_OTBN, "d,o(s)", MATCH_LW, MASK_LW, match_opcode, INSN_DREF|INSN_4_BYTE }, {"not", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_NOT, MASK_C_NOT, match_opcode, INSN_ALIAS }, {"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 }, +{"ori", 0, INSN_CLASS_OTBN, "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_I, "d,s,t", MATCH_OR, MASK_OR, match_opcode, 0 }, +{"or", 0, INSN_CLASS_OTBN, "d,s,t", MATCH_OR, MASK_OR, match_opcode, 0 }, /* Zicfilp instructions. */ {"lpad", 0, INSN_CLASS_ZICFILP, "u", MATCH_LPAD, MASK_LPAD, match_opcode, 0 }, @@ -597,6 +752,7 @@ const struct riscv_opcode riscv_opcodes[] = {"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_I, "t,q(s)", MATCH_SW, MASK_SW, match_opcode, INSN_DREF|INSN_4_BYTE }, +{"sw", 0, INSN_CLASS_OTBN, "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 }, {"fence", 0, INSN_CLASS_I, "P,Q", MATCH_FENCE, MASK_FENCE|MASK_RD|MASK_RS1|(MASK_IMM & ~MASK_PRED & ~MASK_SUCC), match_opcode, 0 }, @@ -609,12 +765,15 @@ const struct riscv_opcode riscv_opcodes[] = {"rdinstreth", 32, INSN_CLASS_I, "d", MATCH_RDINSTRETH, MASK_RDINSTRETH, match_opcode, INSN_ALIAS }, {"rdtimeh", 32, INSN_CLASS_I, "d", MATCH_RDTIMEH, MASK_RDTIMEH, match_opcode, INSN_ALIAS }, {"ecall", 0, INSN_CLASS_I, "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 }, +{"ecall", 0, INSN_CLASS_OTBN, "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 }, {"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 }, +{"xori", 0, INSN_CLASS_OTBN, "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_I, "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, 0 }, +{"xor", 0, INSN_CLASS_OTBN, "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 }, @@ -2278,9 +2437,11 @@ const struct riscv_opcode riscv_opcodes[] = {"csrc", 0, INSN_CLASS_ZICSR, "E,Z", MATCH_CSRRCI, MASK_CSRRCI|MASK_RD, match_opcode, INSN_ALIAS }, {"csrrwi", 0, INSN_CLASS_ZICSR, "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, 0 }, {"csrrw", 0, INSN_CLASS_ZICSR, "d,E,s", MATCH_CSRRW, MASK_CSRRW, match_opcode, 0 }, +{"csrrw", 0, INSN_CLASS_OTBN, "d,+C,s",MATCH_CSRRW, MASK_CSRRW, match_opcode, 0 }, {"csrrw", 0, INSN_CLASS_ZICSR, "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, INSN_ALIAS }, {"csrrsi", 0, INSN_CLASS_ZICSR, "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, 0 }, {"csrrs", 0, INSN_CLASS_ZICSR, "d,E,s", MATCH_CSRRS, MASK_CSRRS, match_opcode, 0 }, +{"csrrs", 0, INSN_CLASS_OTBN, "d,+C,s", MATCH_CSRRS, MASK_CSRRS, match_opcode, 0 }, {"csrrs", 0, INSN_CLASS_ZICSR, "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, INSN_ALIAS }, {"csrrci", 0, INSN_CLASS_ZICSR, "d,E,Z", MATCH_CSRRCI, MASK_CSRRCI, match_opcode, 0 }, {"csrrc", 0, INSN_CLASS_ZICSR, "d,E,s", MATCH_CSRRC, MASK_CSRRC, match_opcode, 0 },