diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 783479981f..096c38f0f3 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -815,6 +815,12 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DEFINE_XAMO(sc_d) } + if (isa->extension_enabled(EXT_ZACAS)) { + DEFINE_XAMO(amocas_w) + DEFINE_XAMO(amocas_d) + DEFINE_XAMO(amocas_q) + } + add_insn(new disasm_insn_t("j", match_jal, mask_jal | mask_rd, {&jump_target})); add_insn(new disasm_insn_t("jal", match_jal | match_rd_ra, mask_jal | mask_rd, {&jump_target})); add_insn(new disasm_insn_t("jal", match_jal, mask_jal, {&xrd, &jump_target})); diff --git a/fesvr/byteorder.h b/fesvr/byteorder.h index 2b1dbf981c..d9e503a271 100644 --- a/fesvr/byteorder.h +++ b/fesvr/byteorder.h @@ -15,6 +15,13 @@ static inline int16_t swap(int16_t n) { return int16_t(swap(uint16_t(n))); } static inline int32_t swap(int32_t n) { return int32_t(swap(uint32_t(n))); } static inline int64_t swap(int64_t n) { return int64_t(swap(uint64_t(n))); } +#ifdef HAVE_INT128 +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; +static inline uint128_t swap(uint128_t n) { return (uint128_t(swap(uint64_t(n))) << 64) | swap(uint64_t(n >> 64)); } +static inline int128_t swap(int128_t n) { return int128_t(swap(uint128_t(n))); } +#endif + #ifdef WORDS_BIGENDIAN template static inline T from_be(T n) { return n; } template static inline T to_be(T n) { return n; } diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 7ba132c196..f39149b172 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -10,11 +10,6 @@ #include "softfloat_types.h" #include "specialize.h" -#ifdef HAVE_INT128 -typedef __int128 int128_t; -typedef unsigned __int128 uint128_t; -#endif - // helpful macros, etc #define MMU (*p->get_mmu()) #define STATE (*p->get_state()) diff --git a/riscv/encoding.h b/riscv/encoding.h index e39f535ceb..db7b0215b6 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -4,7 +4,7 @@ /* * This file is auto-generated by running 'make' in - * https://github.com/riscv/riscv-opcodes (8d70e77) + * https://github.com/riscv/riscv-opcodes (3ca60c5) */ #ifndef RISCV_CSR_ENCODING_H @@ -421,6 +421,12 @@ #define MASK_AMOAND_D 0xf800707f #define MATCH_AMOAND_W 0x6000202f #define MASK_AMOAND_W 0xf800707f +#define MATCH_AMOCAS_D 0x2800302f +#define MASK_AMOCAS_D 0xf800707f +#define MATCH_AMOCAS_Q 0x2800402f +#define MASK_AMOCAS_Q 0xf800707f +#define MATCH_AMOCAS_W 0x2800202f +#define MASK_AMOCAS_W 0xf800707f #define MATCH_AMOMAX_D 0xa000302f #define MASK_AMOMAX_D 0xf800707f #define MATCH_AMOMAX_W 0xa000202f @@ -1995,6 +2001,28 @@ #define MASK_VADD_VV 0xfc00707f #define MATCH_VADD_VX 0x4057 #define MASK_VADD_VX 0xfc00707f +#define MATCH_VAESDF_VS 0xa600a077 +#define MASK_VAESDF_VS 0xfe0ff07f +#define MATCH_VAESDF_VV 0xa200a077 +#define MASK_VAESDF_VV 0xfe0ff07f +#define MATCH_VAESDM_VS 0xa6002077 +#define MASK_VAESDM_VS 0xfe0ff07f +#define MATCH_VAESDM_VV 0xa2002077 +#define MASK_VAESDM_VV 0xfe0ff07f +#define MATCH_VAESEF_VS 0xa601a077 +#define MASK_VAESEF_VS 0xfe0ff07f +#define MATCH_VAESEF_VV 0xa201a077 +#define MASK_VAESEF_VV 0xfe0ff07f +#define MATCH_VAESEM_VS 0xa6012077 +#define MASK_VAESEM_VS 0xfe0ff07f +#define MATCH_VAESEM_VV 0xa2012077 +#define MASK_VAESEM_VV 0xfe0ff07f +#define MATCH_VAESKF1_VI 0x8a002077 +#define MASK_VAESKF1_VI 0xfe00707f +#define MATCH_VAESKF2_VI 0xaa002077 +#define MASK_VAESKF2_VI 0xfe00707f +#define MATCH_VAESZ_VS 0xa603a077 +#define MASK_VAESZ_VS 0xfe0ff07f #define MATCH_VAMOADDEI16_V 0x502f #define MASK_VAMOADDEI16_V 0xf800707f #define MATCH_VAMOADDEI32_V 0x602f @@ -2073,6 +2101,10 @@ #define MASK_VAND_VV 0xfc00707f #define MATCH_VAND_VX 0x24004057 #define MASK_VAND_VX 0xfc00707f +#define MATCH_VANDN_VV 0x4000057 +#define MASK_VANDN_VV 0xfc00707f +#define MATCH_VANDN_VX 0x4004057 +#define MASK_VANDN_VX 0xfc00707f #define MATCH_VASUB_VV 0x2c002057 #define MASK_VASUB_VV 0xfc00707f #define MATCH_VASUB_VX 0x2c006057 @@ -2081,10 +2113,28 @@ #define MASK_VASUBU_VV 0xfc00707f #define MATCH_VASUBU_VX 0x28006057 #define MASK_VASUBU_VX 0xfc00707f +#define MATCH_VBREV8_V 0x48042057 +#define MASK_VBREV8_V 0xfc0ff07f +#define MATCH_VBREV_V 0x48052057 +#define MASK_VBREV_V 0xfc0ff07f +#define MATCH_VCLMUL_VV 0x30002057 +#define MASK_VCLMUL_VV 0xfc00707f +#define MATCH_VCLMUL_VX 0x30006057 +#define MASK_VCLMUL_VX 0xfc00707f +#define MATCH_VCLMULH_VV 0x34002057 +#define MASK_VCLMULH_VV 0xfc00707f +#define MATCH_VCLMULH_VX 0x34006057 +#define MASK_VCLMULH_VX 0xfc00707f +#define MATCH_VCLZ_V 0x48062057 +#define MASK_VCLZ_V 0xfc0ff07f #define MATCH_VCOMPRESS_VM 0x5e002057 #define MASK_VCOMPRESS_VM 0xfe00707f #define MATCH_VCPOP_M 0x40082057 #define MASK_VCPOP_M 0xfc0ff07f +#define MATCH_VCPOP_V 0x48072057 +#define MASK_VCPOP_V 0xfc0ff07f +#define MATCH_VCTZ_V 0x4806a057 +#define MASK_VCTZ_V 0xfc0ff07f #define MATCH_VDIV_VV 0x84002057 #define MASK_VDIV_VV 0xfc00707f #define MATCH_VDIV_VX 0x84006057 @@ -2285,6 +2335,10 @@ #define MASK_VFWSUB_WF 0xfc00707f #define MATCH_VFWSUB_WV 0xd8001057 #define MASK_VFWSUB_WV 0xfc00707f +#define MATCH_VGHSH_VV 0xb2002077 +#define MASK_VGHSH_VV 0xfe00707f +#define MATCH_VGMUL_VV 0xa208a077 +#define MASK_VGMUL_VV 0xfe0ff07f #define MATCH_VID_V 0x5008a057 #define MASK_VID_V 0xfdfff07f #define MATCH_VIOTA_M 0x50082057 @@ -2631,6 +2685,8 @@ #define MASK_VREMU_VV 0xfc00707f #define MATCH_VREMU_VX 0x88006057 #define MASK_VREMU_VX 0xfc00707f +#define MATCH_VREV8_V 0x4804a057 +#define MASK_VREV8_V 0xfc0ff07f #define MATCH_VRGATHER_VI 0x30003057 #define MASK_VRGATHER_VI 0xfc00707f #define MATCH_VRGATHER_VV 0x30000057 @@ -2639,6 +2695,16 @@ #define MASK_VRGATHER_VX 0xfc00707f #define MATCH_VRGATHEREI16_VV 0x38000057 #define MASK_VRGATHEREI16_VV 0xfc00707f +#define MATCH_VROL_VV 0x54000057 +#define MASK_VROL_VV 0xfc00707f +#define MATCH_VROL_VX 0x54004057 +#define MASK_VROL_VX 0xfc00707f +#define MATCH_VROR_VI 0x50003057 +#define MASK_VROR_VI 0xf800707f +#define MATCH_VROR_VV 0x50000057 +#define MASK_VROR_VV 0xfc00707f +#define MATCH_VROR_VX 0x50004057 +#define MASK_VROR_VX 0xfc00707f #define MATCH_VRSUB_VI 0xc003057 #define MASK_VRSUB_VI 0xfc00707f #define MATCH_VRSUB_VX 0xc004057 @@ -2695,6 +2761,12 @@ #define MASK_VSEXT_VF4 0xfc0ff07f #define MATCH_VSEXT_VF8 0x4801a057 #define MASK_VSEXT_VF8 0xfc0ff07f +#define MATCH_VSHA2CH_VV 0xba002077 +#define MASK_VSHA2CH_VV 0xfe00707f +#define MATCH_VSHA2CL_VV 0xbe002077 +#define MASK_VSHA2CL_VV 0xfe00707f +#define MATCH_VSHA2MS_VV 0xb6002077 +#define MASK_VSHA2MS_VV 0xfe00707f #define MATCH_VSLIDE1DOWN_VX 0x3c006057 #define MASK_VSLIDE1DOWN_VX 0xfc00707f #define MATCH_VSLIDE1UP_VX 0x38006057 @@ -2713,6 +2785,16 @@ #define MASK_VSLL_VV 0xfc00707f #define MATCH_VSLL_VX 0x94004057 #define MASK_VSLL_VX 0xfc00707f +#define MATCH_VSM3C_VI 0xae002077 +#define MASK_VSM3C_VI 0xfe00707f +#define MATCH_VSM3ME_VV 0x82002077 +#define MASK_VSM3ME_VV 0xfe00707f +#define MATCH_VSM4K_VI 0x86002077 +#define MASK_VSM4K_VI 0xfe00707f +#define MATCH_VSM4R_VS 0xa6082077 +#define MASK_VSM4R_VS 0xfe0ff07f +#define MATCH_VSM4R_VV 0xa2082077 +#define MASK_VSM4R_VV 0xfe0ff07f #define MATCH_VSM_V 0x2b00027 #define MASK_VSM_V 0xfff0707f #define MATCH_VSMUL_VV 0x9c000057 @@ -2849,6 +2931,12 @@ #define MASK_VWREDSUM_VS 0xfc00707f #define MATCH_VWREDSUMU_VS 0xc0000057 #define MASK_VWREDSUMU_VS 0xfc00707f +#define MATCH_VWSLL_VI 0xd4003057 +#define MASK_VWSLL_VI 0xfc00707f +#define MATCH_VWSLL_VV 0xd4000057 +#define MASK_VWSLL_VV 0xfc00707f +#define MATCH_VWSLL_VX 0xd4004057 +#define MASK_VWSLL_VX 0xfc00707f #define MATCH_VWSUB_VV 0xcc002057 #define MASK_VWSUB_VV 0xfc00707f #define MATCH_VWSUB_VX 0xcc006057 @@ -3486,6 +3574,9 @@ DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) +DECLARE_INSN(amocas_d, MATCH_AMOCAS_D, MASK_AMOCAS_D) +DECLARE_INSN(amocas_q, MATCH_AMOCAS_Q, MASK_AMOCAS_Q) +DECLARE_INSN(amocas_w, MATCH_AMOCAS_W, MASK_AMOCAS_W) DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) @@ -4273,6 +4364,17 @@ DECLARE_INSN(vadc_vxm, MATCH_VADC_VXM, MASK_VADC_VXM) DECLARE_INSN(vadd_vi, MATCH_VADD_VI, MASK_VADD_VI) DECLARE_INSN(vadd_vv, MATCH_VADD_VV, MASK_VADD_VV) DECLARE_INSN(vadd_vx, MATCH_VADD_VX, MASK_VADD_VX) +DECLARE_INSN(vaesdf_vs, MATCH_VAESDF_VS, MASK_VAESDF_VS) +DECLARE_INSN(vaesdf_vv, MATCH_VAESDF_VV, MASK_VAESDF_VV) +DECLARE_INSN(vaesdm_vs, MATCH_VAESDM_VS, MASK_VAESDM_VS) +DECLARE_INSN(vaesdm_vv, MATCH_VAESDM_VV, MASK_VAESDM_VV) +DECLARE_INSN(vaesef_vs, MATCH_VAESEF_VS, MASK_VAESEF_VS) +DECLARE_INSN(vaesef_vv, MATCH_VAESEF_VV, MASK_VAESEF_VV) +DECLARE_INSN(vaesem_vs, MATCH_VAESEM_VS, MASK_VAESEM_VS) +DECLARE_INSN(vaesem_vv, MATCH_VAESEM_VV, MASK_VAESEM_VV) +DECLARE_INSN(vaeskf1_vi, MATCH_VAESKF1_VI, MASK_VAESKF1_VI) +DECLARE_INSN(vaeskf2_vi, MATCH_VAESKF2_VI, MASK_VAESKF2_VI) +DECLARE_INSN(vaesz_vs, MATCH_VAESZ_VS, MASK_VAESZ_VS) DECLARE_INSN(vamoaddei16_v, MATCH_VAMOADDEI16_V, MASK_VAMOADDEI16_V) DECLARE_INSN(vamoaddei32_v, MATCH_VAMOADDEI32_V, MASK_VAMOADDEI32_V) DECLARE_INSN(vamoaddei64_v, MATCH_VAMOADDEI64_V, MASK_VAMOADDEI64_V) @@ -4312,12 +4414,23 @@ DECLARE_INSN(vamoxorei8_v, MATCH_VAMOXOREI8_V, MASK_VAMOXOREI8_V) DECLARE_INSN(vand_vi, MATCH_VAND_VI, MASK_VAND_VI) DECLARE_INSN(vand_vv, MATCH_VAND_VV, MASK_VAND_VV) DECLARE_INSN(vand_vx, MATCH_VAND_VX, MASK_VAND_VX) +DECLARE_INSN(vandn_vv, MATCH_VANDN_VV, MASK_VANDN_VV) +DECLARE_INSN(vandn_vx, MATCH_VANDN_VX, MASK_VANDN_VX) DECLARE_INSN(vasub_vv, MATCH_VASUB_VV, MASK_VASUB_VV) DECLARE_INSN(vasub_vx, MATCH_VASUB_VX, MASK_VASUB_VX) DECLARE_INSN(vasubu_vv, MATCH_VASUBU_VV, MASK_VASUBU_VV) DECLARE_INSN(vasubu_vx, MATCH_VASUBU_VX, MASK_VASUBU_VX) +DECLARE_INSN(vbrev8_v, MATCH_VBREV8_V, MASK_VBREV8_V) +DECLARE_INSN(vbrev_v, MATCH_VBREV_V, MASK_VBREV_V) +DECLARE_INSN(vclmul_vv, MATCH_VCLMUL_VV, MASK_VCLMUL_VV) +DECLARE_INSN(vclmul_vx, MATCH_VCLMUL_VX, MASK_VCLMUL_VX) +DECLARE_INSN(vclmulh_vv, MATCH_VCLMULH_VV, MASK_VCLMULH_VV) +DECLARE_INSN(vclmulh_vx, MATCH_VCLMULH_VX, MASK_VCLMULH_VX) +DECLARE_INSN(vclz_v, MATCH_VCLZ_V, MASK_VCLZ_V) DECLARE_INSN(vcompress_vm, MATCH_VCOMPRESS_VM, MASK_VCOMPRESS_VM) DECLARE_INSN(vcpop_m, MATCH_VCPOP_M, MASK_VCPOP_M) +DECLARE_INSN(vcpop_v, MATCH_VCPOP_V, MASK_VCPOP_V) +DECLARE_INSN(vctz_v, MATCH_VCTZ_V, MASK_VCTZ_V) DECLARE_INSN(vdiv_vv, MATCH_VDIV_VV, MASK_VDIV_VV) DECLARE_INSN(vdiv_vx, MATCH_VDIV_VX, MASK_VDIV_VX) DECLARE_INSN(vdivu_vv, MATCH_VDIVU_VV, MASK_VDIVU_VV) @@ -4418,6 +4531,8 @@ DECLARE_INSN(vfwsub_vf, MATCH_VFWSUB_VF, MASK_VFWSUB_VF) DECLARE_INSN(vfwsub_vv, MATCH_VFWSUB_VV, MASK_VFWSUB_VV) DECLARE_INSN(vfwsub_wf, MATCH_VFWSUB_WF, MASK_VFWSUB_WF) DECLARE_INSN(vfwsub_wv, MATCH_VFWSUB_WV, MASK_VFWSUB_WV) +DECLARE_INSN(vghsh_vv, MATCH_VGHSH_VV, MASK_VGHSH_VV) +DECLARE_INSN(vgmul_vv, MATCH_VGMUL_VV, MASK_VGMUL_VV) DECLARE_INSN(vid_v, MATCH_VID_V, MASK_VID_V) DECLARE_INSN(viota_m, MATCH_VIOTA_M, MASK_VIOTA_M) DECLARE_INSN(vl1re16_v, MATCH_VL1RE16_V, MASK_VL1RE16_V) @@ -4591,10 +4706,16 @@ DECLARE_INSN(vrem_vv, MATCH_VREM_VV, MASK_VREM_VV) DECLARE_INSN(vrem_vx, MATCH_VREM_VX, MASK_VREM_VX) DECLARE_INSN(vremu_vv, MATCH_VREMU_VV, MASK_VREMU_VV) DECLARE_INSN(vremu_vx, MATCH_VREMU_VX, MASK_VREMU_VX) +DECLARE_INSN(vrev8_v, MATCH_VREV8_V, MASK_VREV8_V) DECLARE_INSN(vrgather_vi, MATCH_VRGATHER_VI, MASK_VRGATHER_VI) DECLARE_INSN(vrgather_vv, MATCH_VRGATHER_VV, MASK_VRGATHER_VV) DECLARE_INSN(vrgather_vx, MATCH_VRGATHER_VX, MASK_VRGATHER_VX) DECLARE_INSN(vrgatherei16_vv, MATCH_VRGATHEREI16_VV, MASK_VRGATHEREI16_VV) +DECLARE_INSN(vrol_vv, MATCH_VROL_VV, MASK_VROL_VV) +DECLARE_INSN(vrol_vx, MATCH_VROL_VX, MASK_VROL_VX) +DECLARE_INSN(vror_vi, MATCH_VROR_VI, MASK_VROR_VI) +DECLARE_INSN(vror_vv, MATCH_VROR_VV, MASK_VROR_VV) +DECLARE_INSN(vror_vx, MATCH_VROR_VX, MASK_VROR_VX) DECLARE_INSN(vrsub_vi, MATCH_VRSUB_VI, MASK_VRSUB_VI) DECLARE_INSN(vrsub_vx, MATCH_VRSUB_VX, MASK_VRSUB_VX) DECLARE_INSN(vs1r_v, MATCH_VS1R_V, MASK_VS1R_V) @@ -4623,6 +4744,9 @@ DECLARE_INSN(vsetvli, MATCH_VSETVLI, MASK_VSETVLI) DECLARE_INSN(vsext_vf2, MATCH_VSEXT_VF2, MASK_VSEXT_VF2) DECLARE_INSN(vsext_vf4, MATCH_VSEXT_VF4, MASK_VSEXT_VF4) DECLARE_INSN(vsext_vf8, MATCH_VSEXT_VF8, MASK_VSEXT_VF8) +DECLARE_INSN(vsha2ch_vv, MATCH_VSHA2CH_VV, MASK_VSHA2CH_VV) +DECLARE_INSN(vsha2cl_vv, MATCH_VSHA2CL_VV, MASK_VSHA2CL_VV) +DECLARE_INSN(vsha2ms_vv, MATCH_VSHA2MS_VV, MASK_VSHA2MS_VV) DECLARE_INSN(vslide1down_vx, MATCH_VSLIDE1DOWN_VX, MASK_VSLIDE1DOWN_VX) DECLARE_INSN(vslide1up_vx, MATCH_VSLIDE1UP_VX, MASK_VSLIDE1UP_VX) DECLARE_INSN(vslidedown_vi, MATCH_VSLIDEDOWN_VI, MASK_VSLIDEDOWN_VI) @@ -4632,6 +4756,11 @@ DECLARE_INSN(vslideup_vx, MATCH_VSLIDEUP_VX, MASK_VSLIDEUP_VX) DECLARE_INSN(vsll_vi, MATCH_VSLL_VI, MASK_VSLL_VI) DECLARE_INSN(vsll_vv, MATCH_VSLL_VV, MASK_VSLL_VV) DECLARE_INSN(vsll_vx, MATCH_VSLL_VX, MASK_VSLL_VX) +DECLARE_INSN(vsm3c_vi, MATCH_VSM3C_VI, MASK_VSM3C_VI) +DECLARE_INSN(vsm3me_vv, MATCH_VSM3ME_VV, MASK_VSM3ME_VV) +DECLARE_INSN(vsm4k_vi, MATCH_VSM4K_VI, MASK_VSM4K_VI) +DECLARE_INSN(vsm4r_vs, MATCH_VSM4R_VS, MASK_VSM4R_VS) +DECLARE_INSN(vsm4r_vv, MATCH_VSM4R_VV, MASK_VSM4R_VV) DECLARE_INSN(vsm_v, MATCH_VSM_V, MASK_VSM_V) DECLARE_INSN(vsmul_vv, MATCH_VSMUL_VV, MASK_VSMUL_VV) DECLARE_INSN(vsmul_vx, MATCH_VSMUL_VX, MASK_VSMUL_VX) @@ -4700,6 +4829,9 @@ DECLARE_INSN(vwmulu_vv, MATCH_VWMULU_VV, MASK_VWMULU_VV) DECLARE_INSN(vwmulu_vx, MATCH_VWMULU_VX, MASK_VWMULU_VX) DECLARE_INSN(vwredsum_vs, MATCH_VWREDSUM_VS, MASK_VWREDSUM_VS) DECLARE_INSN(vwredsumu_vs, MATCH_VWREDSUMU_VS, MASK_VWREDSUMU_VS) +DECLARE_INSN(vwsll_vi, MATCH_VWSLL_VI, MASK_VWSLL_VI) +DECLARE_INSN(vwsll_vv, MATCH_VWSLL_VV, MASK_VWSLL_VV) +DECLARE_INSN(vwsll_vx, MATCH_VWSLL_VX, MASK_VWSLL_VX) DECLARE_INSN(vwsub_vv, MATCH_VWSUB_VV, MASK_VWSUB_VV) DECLARE_INSN(vwsub_vx, MATCH_VWSUB_VX, MASK_VWSUB_VX) DECLARE_INSN(vwsub_wv, MATCH_VWSUB_WV, MASK_VWSUB_WV) diff --git a/riscv/insns/amocas_d.h b/riscv/insns/amocas_d.h new file mode 100644 index 0000000000..e002e6ab75 --- /dev/null +++ b/riscv/insns/amocas_d.h @@ -0,0 +1,37 @@ +require_extension(EXT_ZACAS); + +if (xlen == 32) { + // RV32: the spec defines two 32-bit comparisons. Since we're + // loading 64-bit for memory we have to adjust for endianness. + uint64_t comp, swap, res; + + require_align(insn.rd(), 2); + require_align(insn.rs2(), 2); + if (insn.rd() == 0) { + comp = 0; + } else if (MMU.is_target_big_endian()) { + comp = (uint32_t)READ_REG(insn.rd() + 1) | (RD << 32); + } else { + comp = (uint32_t)RD | (READ_REG(insn.rd() + 1) << 32); + } + if (insn.rs2() == 0) { + swap = 0; + } else if (MMU.is_target_big_endian()) { + swap = (uint32_t)READ_REG(insn.rs2() + 1) | (RS2 << 32); + } else { + swap = (uint32_t)RS2 | (READ_REG(insn.rs2() + 1) << 32); + } + res = MMU.amo_compare_and_swap(RS1, comp, swap); + if (insn.rd() != 0) { + if (MMU.is_target_big_endian()) { + WRITE_REG(insn.rd() + 1, sext32((uint32_t)res)); + WRITE_REG(insn.rd(), sext32(res >> 32)); + } else { + WRITE_REG(insn.rd(), sext32((uint32_t)res)); + WRITE_REG(insn.rd() + 1, sext32(res >> 32)); + } + } + } else { + // RV64 + WRITE_RD(MMU.amo_compare_and_swap(RS1, RD, RS2)); +} diff --git a/riscv/insns/amocas_q.h b/riscv/insns/amocas_q.h new file mode 100644 index 0000000000..0b7593b3dc --- /dev/null +++ b/riscv/insns/amocas_q.h @@ -0,0 +1,34 @@ +require_extension(EXT_ZACAS); +require_rv64; +require_align(insn.rd(), 2); +require_align(insn.rs2(), 2); + +// The spec defines two 64-bit comparisons. Since we're loading +// 128-bit for memory we have to adjust for endianness. + +uint128_t comp, swap, res; + +if (insn.rd() == 0) { + comp = 0; +} else if (MMU.is_target_big_endian()) { + comp = READ_REG(insn.rd() + 1) | ((uint128_t)RD << 64); +} else { + comp = RD | ((uint128_t)READ_REG(insn.rd() + 1) << 64); +} +if (insn.rs2() == 0) { + swap = 0; +} else if (MMU.is_target_big_endian()) { + swap = READ_REG(insn.rs2() + 1) | ((uint128_t)RS2 << 64); +} else { + swap = RS2 | ((uint128_t)READ_REG(insn.rs2() + 1) << 64); +} +res = MMU.amo_compare_and_swap(RS1, comp, swap); +if (insn.rd() != 0) { + if (MMU.is_target_big_endian()) { + WRITE_REG(insn.rd(), res >> 64); + WRITE_REG(insn.rd() + 1, res); + } else { + WRITE_REG(insn.rd(), res); + WRITE_REG(insn.rd() + 1, res >> 64); + } +} diff --git a/riscv/insns/amocas_w.h b/riscv/insns/amocas_w.h new file mode 100644 index 0000000000..a78c21cb73 --- /dev/null +++ b/riscv/insns/amocas_w.h @@ -0,0 +1,2 @@ +require_extension(EXT_ZACAS); +WRITE_RD(sext32(MMU.amo_compare_and_swap(RS1, RD, RS2))); diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc index 8bb8c495b3..1c4300c958 100644 --- a/riscv/isa_parser.cc +++ b/riscv/isa_parser.cc @@ -120,6 +120,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) // HINTs encoded in base-ISA instructions are always present. } else if (ext_str == "zihintntl") { // HINTs encoded in base-ISA instructions are always present. + } else if (ext_str == "zacas") { + extension_table[EXT_ZACAS] = true; } else if (ext_str == "zmmul") { extension_table[EXT_ZMMUL] = true; } else if (ext_str == "zba") { @@ -301,6 +303,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) bad_isa_string(str, "'Zcf/Zcd/Zcb/Zcmp/Zcmt' extensions require 'Zca' extension"); } + if (extension_table[EXT_ZACAS] && !extension_table['A']) { + bad_isa_string(str, "'Zacas' extension requires 'A' extension"); + } + std::string lowercase = strtolower(priv); bool user = false, supervisor = false; diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 4e6856195c..3cbee7dea0 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -61,6 +61,7 @@ typedef enum { EXT_ZVFBFMIN, EXT_ZVFBFWMA, EXT_SSTC, + EXT_ZACAS, EXT_INTERNAL_ZFH_MOVE, NUM_ISA_EXTENSIONS } isa_extension_t; diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 358ccd3e42..3f90060e82 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -242,6 +242,11 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t load_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0)); } + while (len > sizeof(reg_t)) { + check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes)); + len -= sizeof(reg_t); + bytes += sizeof(reg_t); + } check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(len, bytes)); } @@ -275,8 +280,16 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment) { auto access_info = generate_access_info(addr, STORE, xlate_flags); - if (actually_store) - check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(len, bytes)); + if (actually_store) { + reg_t trig_len = len; + const uint8_t* trig_bytes = bytes; + while (trig_len > sizeof(reg_t)) { + check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes)); + trig_len -= sizeof(reg_t); + trig_bytes += sizeof(reg_t); + } + check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes)); + } if (addr & (len - 1)) { bool gva = access_info.effective_virt; diff --git a/riscv/mmu.h b/riscv/mmu.h index efc6e9de14..46c54ce88a 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -187,6 +187,17 @@ class mmu_t }) } + template + T amo_compare_and_swap(reg_t addr, T comp, T swap) { + convert_load_traps_to_store_traps({ + store_slow_path(addr, sizeof(T), nullptr, {false, false, false}, false, true); + auto lhs = load(addr); + if (lhs == comp) + store(addr, swap); + return lhs; + }) + } + void store_float128(reg_t addr, float128_t val) { if (unlikely(addr & (sizeof(float128_t)-1)) && !is_misaligned_enabled()) { diff --git a/riscv/processor.cc b/riscv/processor.cc index a75b0ff6f1..1d5675a51a 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -47,6 +47,11 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, fprintf(stderr, "V extension is not supported on platforms without __int128 type\n"); abort(); } + + if (isa->extension_enabled(EXT_ZACAS) && isa->get_max_xlen() == 64) { + fprintf(stderr, "Zacas extension is not supported on 64-bit platforms without __int128 type\n"); + abort(); + } #endif parse_varch_string(cfg->varch()); diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index db63290205..6472982ed5 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1335,6 +1335,11 @@ riscv_insn_ext_bf16 = \ $(riscv_insn_ext_zvfbfmin) \ $(riscv_insn_ext_zvfbfwma) \ +riscv_insn_ext_zacas = \ + amocas_w \ + amocas_d \ + $(if $(HAVE_INT128),amocas_q) + riscv_insn_list = \ $(riscv_insn_ext_a) \ $(riscv_insn_ext_c) \ @@ -1360,6 +1365,7 @@ riscv_insn_list = \ $(riscv_insn_ext_cmo) \ $(riscv_insn_ext_zicond) \ $(riscv_insn_ext_bf16) \ + $(riscv_insn_ext_zacas) \ riscv_gen_srcs = $(addsuffix .cc,$(riscv_insn_list))