This patch supports Zcmt[1] instruction 'cm.jt' and 'cm.jalt'.
Add new CSR jvt for tablejump using. Since 'cm.jt' and 'cm.jalt'
have the same instructiong encoding, use 'match_cm_jt' and 'match_cm_jalt'
check the 'zcmt_index' field to distinguish them.
[1] https://github.com/riscvarchive/riscv-code-size-reduction/releases
Co-Authored by: Charlie Keaney <charlie.keaney@embecosm.com>
Co-Authored by: Mary Bennett <mary.bennett@embecosm.com>
Co-Authored by: Nandni Jamnadas <nandni.jamnadas@embecosm.com>
Co-Authored by: Sinan Lin <sinan.lin@linux.alibaba.com>
Co-Authored by: Simon Cook <simon.cook@embecosm.com>
Co-Authored by: Shihua Liao <shihua@iscas.ac.cn>
Co-Authored by: Yulong Shi <yulong@iscas.ac.cn>
bfd/ChangeLog:
* elfxx-riscv.c (riscv_multi_subset_supports): New extension.
(riscv_multi_subset_supports_ext): Ditto.
gas/ChangeLog:
* config/tc-riscv.c (enum riscv_csr_class): New CSR.
(riscv_csr_address): Ditto.
(validate_riscv_insn): New operand.
(riscv_ip): Ditto.
* testsuite/gas/riscv/csr-version-1p10.d: New CSR.
* testsuite/gas/riscv/csr-version-1p10.l: Ditto.
* testsuite/gas/riscv/csr-version-1p11.d: Ditto.
* testsuite/gas/riscv/csr-version-1p11.l: Ditto.
* testsuite/gas/riscv/csr-version-1p12.d: Ditto.
* testsuite/gas/riscv/csr-version-1p12.l: Ditto.
* testsuite/gas/riscv/csr.s: Ditto.
* testsuite/gas/riscv/march-help.l: New extension.
* testsuite/gas/riscv/zcmt-fail.d: New test.
* testsuite/gas/riscv/zcmt-fail.l: New test.
* testsuite/gas/riscv/zcmt-fail.s: New test.
* testsuite/gas/riscv/zcmt.d: New test.
* testsuite/gas/riscv/zcmt.s: New test.
include/ChangeLog:
* opcode/riscv-opc.h (MATCH_CM_JT): New opcode.
(MASK_CM_JT): New mask.
(MATCH_CM_JALT): New opcode.
(MASK_CM_JALT): New mask.
(CSR_JVT): New CSR.
(DECLARE_INSN): New declaration.
(DECLARE_CSR): Ditto.
* opcode/riscv.h (EXTRACT_ZCMT_INDEX): New marco.
(ENCODE_ZCMT_INDEX): Ditto.
(enum riscv_insn_class): New class.
opcodes/ChangeLog:
* riscv-dis.c (print_insn_args): New operand.
* riscv-opc.c (match_cm_jt): New function.
(match_cm_jalt): Ditto.
{"zcf", "+f,+zca", check_implicit_always},
{"zcmp", "+zca", check_implicit_always},
{"zcmop", "+zca", check_implicit_always},
+ {"zcmt", "+zca,+zicsr", check_implicit_always},
{"shcounterenw", "+h", check_implicit_always},
{"shgatpa", "+h", check_implicit_always},
{"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcmop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zcmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{NULL, 0, 0, 0, 0}
};
return riscv_subset_supports (rps, "zcmop");
case INSN_CLASS_ZCMP:
return riscv_subset_supports (rps, "zcmp");
+ case INSN_CLASS_ZCMT:
+ return riscv_subset_supports (rps, "zcmt");
case INSN_CLASS_SVINVAL:
return riscv_subset_supports (rps, "svinval");
case INSN_CLASS_H:
return "zcmop";
case INSN_CLASS_ZCMP:
return "zcmp";
+ case INSN_CLASS_ZCMT:
+ return "zcmt";
case INSN_CLASS_SVINVAL:
return "svinval";
case INSN_CLASS_H:
CSR_CLASS_I_32, /* rv32 only */
CSR_CLASS_F, /* f-ext only */
CSR_CLASS_ZKR, /* zkr only */
+ CSR_CLASS_ZCMT, /* zcmt only */
CSR_CLASS_V, /* rvv only */
CSR_CLASS_DEBUG, /* debug CSR */
CSR_CLASS_H, /* hypervisor */
case CSR_CLASS_ZKR:
extension = "zkr";
break;
+ case CSR_CLASS_ZCMT:
+ extension = "zcmt";
+ break;
case CSR_CLASS_V:
extension = "zve32x";
break;
case 'p': used_bits |= ENCODE_ZCMP_SPIMM (-1U); break;
/* Register list operand for cm.push and cm.pop. */
case 'r': USE_BITS (OP_MASK_REG_LIST, OP_SH_REG_LIST); break;
+ /* Table jump used by cm.jt or cm.jalt. */
+ case 'i':
+ case 'I': used_bits |= ENCODE_ZCMT_INDEX (-1U); break;
case 'f': break;
default:
goto unknown_validate_operand;
break;
INSERT_OPERAND (SREG2, *ip, regno % 8);
continue;
+ case 'I': /* index operand of cm.jt. The range is from 0 to 31. */
+ my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+ if (imm_expr->X_op != O_constant
+ || imm_expr->X_add_number < 0
+ || imm_expr->X_add_number > 31)
+ {
+ as_bad ("bad index value for cm.jt, range: [0, 31]");
+ break;
+ }
+ ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case 'i': /* index operand of cm.jalt. The range is from 32 to 255. */
+ my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+ if (imm_expr->X_op != O_constant
+ || imm_expr->X_add_number < 32
+ || imm_expr->X_add_number > 255)
+ {
+ as_bad ("bad index value for cm.jalt, range: [32, 255]");
+ break;
+ }
+ ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+ goto rvc_imm_done;
default:
goto unknown_riscv_ip_operand;
}
[ ]+[0-9a-f]+:[ ]+c2159073[ ]+csrw[ ]+vtype,a1
[ ]+[0-9a-f]+:[ ]+c2202573[ ]+csrr[ ]+a0,vlenb
[ ]+[0-9a-f]+:[ ]+c2259073[ ]+csrw[ ]+vlenb,a1
+[ ]+[0-9a-f]+:[ ]+01702573[ ]+csrr[ ]+a0,jvt
+[ ]+[0-9a-f]+:[ ]+01759073[ ]+csrw[ ]+jvt,a1
.*Info: macro .*
.*Warning: read-only CSR is written `csrw vlenb,a1'
.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
[ ]+[0-9a-f]+:[ ]+c2159073[ ]+csrw[ ]+vtype,a1
[ ]+[0-9a-f]+:[ ]+c2202573[ ]+csrr[ ]+a0,vlenb
[ ]+[0-9a-f]+:[ ]+c2259073[ ]+csrw[ ]+vlenb,a1
+[ ]+[0-9a-f]+:[ ]+01702573[ ]+csrr[ ]+a0,jvt
+[ ]+[0-9a-f]+:[ ]+01759073[ ]+csrw[ ]+jvt,a1
.*Info: macro .*
.*Warning: read-only CSR is written `csrw vlenb,a1'
.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
[ ]+[0-9a-f]+:[ ]+c2159073[ ]+csrw[ ]+vtype,a1
[ ]+[0-9a-f]+:[ ]+c2202573[ ]+csrr[ ]+a0,vlenb
[ ]+[0-9a-f]+:[ ]+c2259073[ ]+csrw[ ]+vlenb,a1
+[ ]+[0-9a-f]+:[ ]+01702573[ ]+csrr[ ]+a0,jvt
+[ ]+[0-9a-f]+:[ ]+01759073[ ]+csrw[ ]+jvt,a1
.*Info: macro .*
.*Warning: read-only CSR is written `csrw vlenb,a1'
.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
csr vl
csr vtype
csr vlenb
+
+ # Zcmt
+ csr jvt
zcd 1.0
zcmop 1.0
zcmp 1.0
+ zcmt 1.0
shcounterenw 1.0
shgatpa 1.0
shtvala 1.0
--- /dev/null
+#as: -march=rv64i_zcmt
+#source: zcmt-fail.s
+#error_output: zcmt-fail.l
--- /dev/null
+.*: Assembler messages:
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt -1'
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt 256'
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt x0'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt -1'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt 256'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt x0'
--- /dev/null
+target:
+ cm.jt -1
+ cm.jt 256
+ cm.jt x0
+ cm.jalt -1
+ cm.jalt 256
+ cm.jalt x0
--- /dev/null
+#as: -march=rv32i_zcmt
+#source: zcmt.s
+#objdump: -dr -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ ]*[0-9a-f]+:[ ]+a002[ ]+cm.jt[ ]+0
+[ ]*[0-9a-f]+:[ ]+a07e[ ]+cm.jt[ ]+31
+[ ]*[0-9a-f]+:[ ]+a102[ ]+cm.jalt[ ]+64
+[ ]*[0-9a-f]+:[ ]+a3fe[ ]+cm.jalt[ ]+255
--- /dev/null
+target:
+ cm.jt 0
+ cm.jt 31
+ cm.jalt 64
+ cm.jalt 255
#define MASK_CM_MVA01S 0xfc63
#define MATCH_CM_MVSA01 0xac22
#define MASK_CM_MVSA01 0xfc63
+/* Zcmt instructions. */
+#define MATCH_CM_JT 0xa002
+#define MASK_CM_JT 0xfc03
+#define MATCH_CM_JALT 0xa002
+#define MASK_CM_JALT 0xfc03
/* Svinval instruction. */
#define MATCH_SINVAL_VMA 0x16000073
#define MASK_SINVAL_VMA 0xfe007fff
#define CSR_MSCONTEXT 0x7aa
/* Unprivileged Scalar Crypto CSR addresses. */
#define CSR_SEED 0x015
+/* Unprivileged Zcmt CSR addresses. */
+#define CSR_JVT 0x017
/* Unprivileged Vector CSR addresses. */
#define CSR_VSTART 0x008
#define CSR_VXSAT 0x009
DECLARE_INSN(cm_popretz, MATCH_CM_POPRETZ, MASK_CM_POPRETZ)
DECLARE_INSN(cm_mvsa01, MATCH_CM_MVSA01, MASK_CM_MVSA01)
DECLARE_INSN(cm_mva01s, MATCH_CM_MVA01S, MASK_CM_MVA01S)
+/* Zcmt instructions. */
+DECLARE_INSN(cm_jt, MATCH_CM_JT, MASK_CM_JT)
+DECLARE_INSN(cm_jalt, MATCH_CM_JALT, MASK_CM_JALT)
/* Vendor-specific (T-Head) XTheadBa instructions. */
DECLARE_INSN(th_addsl, MATCH_TH_ADDSL, MASK_TH_ADDSL)
/* Vendor-specific (T-Head) XTheadBb instructions. */
DECLARE_CSR(mscontext, CSR_MSCONTEXT, CSR_CLASS_DEBUG, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
/* Unprivileged Scalar Crypto CSRs. */
DECLARE_CSR(seed, CSR_SEED, CSR_CLASS_ZKR, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
+/* Unprivileged Zcmt CSRs. */
+DECLARE_CSR(jvt, CSR_JVT, CSR_CLASS_ZCMT, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
/* Unprivileged Vector CSRs. */
DECLARE_CSR(vstart, CSR_VSTART, CSR_CLASS_V, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
DECLARE_CSR(vxsat, CSR_VXSAT, CSR_CLASS_V, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
(RV_X(x, 5, 1) << 1)
#define EXTRACT_ZCMP_SPIMM(x) \
(RV_X(x, 2, 2) << 4)
+#define EXTRACT_ZCMT_INDEX(x) \
+ (RV_X(x, 2, 8))
/* Vendor-specific (CORE-V) extract macros. */
#define EXTRACT_CV_IS2_UIMM5(x) \
(RV_X(x, 20, 5))
(RV_X(x, 1, 1) << 5)
#define ENCODE_ZCMP_SPIMM(x) \
(RV_X(x, 4, 2) << 2)
+#define ENCODE_ZCMT_INDEX(x) \
+ (RV_X(x, 0, 8) << 2)
/* Vendor-specific (CORE-V) encode macros. */
#define ENCODE_CV_IS2_UIMM5(x) \
(RV_X(x, 0, 5) << 20)
INSN_CLASS_ZCB_AND_ZMMUL,
INSN_CLASS_ZCMOP,
INSN_CLASS_ZCMP,
+ INSN_CLASS_ZCMT,
INSN_CLASS_SVINVAL,
INSN_CLASS_ZICBOM,
INSN_CLASS_ZICBOP,
print (info->stream, dis_style_immediate, "%d",
riscv_get_spimm (l));
break;
+ case 'i':
+ case 'I':
+ print (info->stream, dis_style_address_offset,
+ "%lu", EXTRACT_ZCMT_INDEX (l));
+ break;
default:
goto undefined_modifier;
}
&& (EXTRACT_OPERAND (SREG1, insn) != EXTRACT_OPERAND (SREG2, insn));
}
+/* This is used for cm.jt. This requires index operand to be less than 32. */
+
+static int
+match_cm_jt (const struct riscv_opcode *op, insn_t insn)
+{
+ return match_opcode (op, insn)
+ && EXTRACT_ZCMT_INDEX (insn) < 32;
+}
+
+/* This is used for cm.jalt. This requires index operand to be in 32 to 255. */
+
+static int
+match_cm_jalt (const struct riscv_opcode *op, insn_t insn)
+{
+ return match_opcode (op, insn)
+ && EXTRACT_ZCMT_INDEX (insn) >= 32
+ && EXTRACT_ZCMT_INDEX (insn) < 256;
+}
+
/* The order of overloaded instructions matters. Label arguments and
register arguments look the same. Instructions that can have either
for arguments must apear in the correct order in this table for the
{"cm.mva01s", 0, INSN_CLASS_ZCMP, "Wc1,Wc2", MATCH_CM_MVA01S, MASK_CM_MVA01S, match_opcode, 0 },
{"cm.mvsa01", 0, INSN_CLASS_ZCMP, "Wc1,Wc2", MATCH_CM_MVSA01, MASK_CM_MVSA01, match_sreg1_not_eq_sreg2, 0 },
+/* Zcmt instructions */
+{"cm.jt", 0, INSN_CLASS_ZCMT, "WcI", MATCH_CM_JT, MASK_CM_JT, match_cm_jt, 0 },
+{"cm.jalt", 0, INSN_CLASS_ZCMT, "Wci", MATCH_CM_JALT, MASK_CM_JALT, match_cm_jalt, 0 },
+
/* Supervisor instructions. */
{"csrr", 0, INSN_CLASS_ZICSR, "d,E", MATCH_CSRRS, MASK_CSRRS|MASK_RS1, match_opcode, INSN_ALIAS },
{"csrwi", 0, INSN_CLASS_ZICSR, "E,Z", MATCH_CSRRWI, MASK_CSRRWI|MASK_RD, match_opcode, INSN_ALIAS },