From: Petr Pavlu Date: Tue, 11 Apr 2023 19:30:43 +0000 (+0000) Subject: riscv64: Add initial support: VEX modifications X-Git-Tag: VALGRIND_3_25_0~132 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=33833e37bf519c7532e69954f2b46f23a5215cab;p=thirdparty%2Fvalgrind.git riscv64: Add initial support: VEX modifications The following people contributed to the initial RISC-V support: Petr Pavlu Xeonacid laokz Chelsea E. Manning zhaomingxin Jojo R https://bugs.kde.org/show_bug.cgi?id=493507 --- diff --git a/VEX/auxprogs/genoffsets.c b/VEX/auxprogs/genoffsets.c index 6b70cd087..48c9723dc 100644 --- a/VEX/auxprogs/genoffsets.c +++ b/VEX/auxprogs/genoffsets.c @@ -53,6 +53,7 @@ #include "../pub/libvex_guest_s390x.h" #include "../pub/libvex_guest_mips32.h" #include "../pub/libvex_guest_mips64.h" +#include "../pub/libvex_guest_riscv64.h" #define VG_STRINGIFZ(__str) #__str #define VG_STRINGIFY(__str) VG_STRINGIFZ(__str) @@ -265,6 +266,74 @@ void foo ( void ) GENOFFSET(MIPS64,mips64,PC); GENOFFSET(MIPS64,mips64,HI); GENOFFSET(MIPS64,mips64,LO); + + // riscv64 + GENOFFSET(RISCV64,riscv64,x0); + GENOFFSET(RISCV64,riscv64,x1); + GENOFFSET(RISCV64,riscv64,x2); + GENOFFSET(RISCV64,riscv64,x3); + GENOFFSET(RISCV64,riscv64,x4); + GENOFFSET(RISCV64,riscv64,x5); + GENOFFSET(RISCV64,riscv64,x6); + GENOFFSET(RISCV64,riscv64,x7); + GENOFFSET(RISCV64,riscv64,x8); + GENOFFSET(RISCV64,riscv64,x9); + GENOFFSET(RISCV64,riscv64,x10); + GENOFFSET(RISCV64,riscv64,x11); + GENOFFSET(RISCV64,riscv64,x12); + GENOFFSET(RISCV64,riscv64,x13); + GENOFFSET(RISCV64,riscv64,x14); + GENOFFSET(RISCV64,riscv64,x15); + GENOFFSET(RISCV64,riscv64,x16); + GENOFFSET(RISCV64,riscv64,x17); + GENOFFSET(RISCV64,riscv64,x18); + GENOFFSET(RISCV64,riscv64,x19); + GENOFFSET(RISCV64,riscv64,x20); + GENOFFSET(RISCV64,riscv64,x21); + GENOFFSET(RISCV64,riscv64,x22); + GENOFFSET(RISCV64,riscv64,x23); + GENOFFSET(RISCV64,riscv64,x24); + GENOFFSET(RISCV64,riscv64,x25); + GENOFFSET(RISCV64,riscv64,x26); + GENOFFSET(RISCV64,riscv64,x27); + GENOFFSET(RISCV64,riscv64,x28); + GENOFFSET(RISCV64,riscv64,x29); + GENOFFSET(RISCV64,riscv64,x30); + GENOFFSET(RISCV64,riscv64,x31); + GENOFFSET(RISCV64,riscv64,pc); + GENOFFSET(RISCV64,riscv64,f0); + GENOFFSET(RISCV64,riscv64,f1); + GENOFFSET(RISCV64,riscv64,f2); + GENOFFSET(RISCV64,riscv64,f3); + GENOFFSET(RISCV64,riscv64,f4); + GENOFFSET(RISCV64,riscv64,f5); + GENOFFSET(RISCV64,riscv64,f6); + GENOFFSET(RISCV64,riscv64,f7); + GENOFFSET(RISCV64,riscv64,f8); + GENOFFSET(RISCV64,riscv64,f9); + GENOFFSET(RISCV64,riscv64,f10); + GENOFFSET(RISCV64,riscv64,f11); + GENOFFSET(RISCV64,riscv64,f12); + GENOFFSET(RISCV64,riscv64,f13); + GENOFFSET(RISCV64,riscv64,f14); + GENOFFSET(RISCV64,riscv64,f15); + GENOFFSET(RISCV64,riscv64,f16); + GENOFFSET(RISCV64,riscv64,f17); + GENOFFSET(RISCV64,riscv64,f18); + GENOFFSET(RISCV64,riscv64,f19); + GENOFFSET(RISCV64,riscv64,f20); + GENOFFSET(RISCV64,riscv64,f21); + GENOFFSET(RISCV64,riscv64,f22); + GENOFFSET(RISCV64,riscv64,f23); + GENOFFSET(RISCV64,riscv64,f24); + GENOFFSET(RISCV64,riscv64,f25); + GENOFFSET(RISCV64,riscv64,f26); + GENOFFSET(RISCV64,riscv64,f27); + GENOFFSET(RISCV64,riscv64,f28); + GENOFFSET(RISCV64,riscv64,f29); + GENOFFSET(RISCV64,riscv64,f30); + GENOFFSET(RISCV64,riscv64,f31); + GENOFFSET(RISCV64,riscv64,fcsr); } /*--------------------------------------------------------------------*/ diff --git a/VEX/priv/host_generic_regs.h b/VEX/priv/host_generic_regs.h index 2387f49c6..2b369f2eb 100644 --- a/VEX/priv/host_generic_regs.h +++ b/VEX/priv/host_generic_regs.h @@ -36,6 +36,7 @@ #include "libvex_basictypes.h" +#include "main_util.h" /*---------------------------------------------------------*/ /*--- Representing HOST REGISTERS ---*/ diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index e6c788d0c..91bb3bbbf 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -43,6 +43,7 @@ #include "libvex_guest_s390x.h" #include "libvex_guest_mips32.h" #include "libvex_guest_mips64.h" +#include "libvex_guest_riscv64.h" #include "main_globals.h" #include "main_util.h" @@ -57,6 +58,7 @@ #include "host_s390_defs.h" #include "host_mips_defs.h" #include "host_nanomips_defs.h" +#include "host_riscv64_defs.h" #include "guest_generic_bb_to_IR.h" #include "guest_x86_defs.h" @@ -67,6 +69,7 @@ #include "guest_s390_defs.h" #include "guest_mips_defs.h" #include "guest_nanomips_defs.h" +#include "guest_riscv64_defs.h" #include "host_generic_simd128.h" @@ -163,6 +166,14 @@ #define NANOMIPSST(f) vassert(0) #endif +#if defined(VGA_riscv64) || defined(VEXMULTIARCH) +#define RISCV64FN(f) f +#define RISCV64ST(f) f +#else +#define RISCV64FN(f) NULL +#define RISCV64ST(f) vassert(0) +#endif + /* This file contains the top level interface to the library. */ /* --------- fwds ... --------- */ @@ -541,6 +552,23 @@ IRSB* LibVEX_FrontEnd ( /*MOD*/ VexTranslateArgs* vta, vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4); break; + case VexArchRISCV64: + preciseMemExnsFn + = RISCV64FN(guest_riscv64_state_requires_precise_mem_exns); + disInstrFn = RISCV64FN(disInstr_RISCV64); + specHelper = RISCV64FN(guest_riscv64_spechelper); + guest_layout = RISCV64FN(&riscv64guest_layout); + offB_CMSTART = offsetof(VexGuestRISCV64State,guest_CMSTART); + offB_CMLEN = offsetof(VexGuestRISCV64State,guest_CMLEN); + offB_GUEST_IP = offsetof(VexGuestRISCV64State,guest_pc); + szB_GUEST_IP = sizeof( ((VexGuestRISCV64State*)0)->guest_pc ); + vassert(vta->archinfo_guest.endness == VexEndnessLE); + vassert(0 == sizeof(VexGuestRISCV64State) % LibVEX_GUEST_STATE_ALIGN); + vassert(sizeof( ((VexGuestRISCV64State*)0)->guest_CMSTART ) == 8); + vassert(sizeof( ((VexGuestRISCV64State*)0)->guest_CMLEN ) == 8); + vassert(sizeof( ((VexGuestRISCV64State*)0)->guest_NRADDR ) == 8); + break; + default: vpanic("LibVEX_Translate: unsupported guest insn set"); } @@ -878,6 +906,14 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta, offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR); break; + case VexArchRISCV64: + preciseMemExnsFn + = RISCV64FN(guest_riscv64_state_requires_precise_mem_exns); + guest_sizeB = sizeof(VexGuestRISCV64State); + offB_HOST_EvC_COUNTER = offsetof(VexGuestRISCV64State,host_EvC_COUNTER); + offB_HOST_EvC_FAILADDR = offsetof(VexGuestRISCV64State,host_EvC_FAILADDR); + break; + default: vpanic("LibVEX_Codegen: unsupported guest insn set"); } @@ -1052,6 +1088,22 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta, || vta->archinfo_host.endness == VexEndnessBE); break; + case VexArchRISCV64: + mode64 = True; + rRegUniv = RISCV64FN(getRRegUniverse_RISCV64()); + getRegUsage + = CAST_TO_TYPEOF(getRegUsage) RISCV64FN(getRegUsage_RISCV64Instr); + mapRegs = CAST_TO_TYPEOF(mapRegs) RISCV64FN(mapRegs_RISCV64Instr); + genSpill = CAST_TO_TYPEOF(genSpill) RISCV64FN(genSpill_RISCV64); + genReload = CAST_TO_TYPEOF(genReload) RISCV64FN(genReload_RISCV64); + genMove = CAST_TO_TYPEOF(genMove) RISCV64FN(genMove_RISCV64); + ppInstr = CAST_TO_TYPEOF(ppInstr) RISCV64FN(ppRISCV64Instr); + ppReg = CAST_TO_TYPEOF(ppReg) RISCV64FN(ppHRegRISCV64); + iselSB = RISCV64FN(iselSB_RISCV64); + emit = CAST_TO_TYPEOF(emit) RISCV64FN(emit_RISCV64Instr); + vassert(vta->archinfo_host.endness == VexEndnessLE); + break; + default: vpanic("LibVEX_Translate: unsupported host insn set"); } @@ -1297,6 +1349,11 @@ VexInvalRange LibVEX_Chain ( VexArch arch_host, place_to_chain, disp_cp_chain_me_EXPECTED, place_to_jump_to)); + case VexArchRISCV64: + RISCV64ST(return chainXDirect_RISCV64(endness_host, + place_to_chain, + disp_cp_chain_me_EXPECTED, + place_to_jump_to)); default: vassert(0); } @@ -1359,6 +1416,11 @@ VexInvalRange LibVEX_UnChain ( VexArch arch_host, place_to_unchain, place_to_jump_to_EXPECTED, disp_cp_chain_me)); + case VexArchRISCV64: + RISCV64ST(return unchainXDirect_RISCV64(endness_host, + place_to_unchain, + place_to_jump_to_EXPECTED, + disp_cp_chain_me)); default: vassert(0); } @@ -1387,8 +1449,10 @@ Int LibVEX_evCheckSzB ( VexArch arch_host ) MIPS32ST(cached = evCheckSzB_MIPS()); break; case VexArchMIPS64: MIPS64ST(cached = evCheckSzB_MIPS()); break; - case VexArchNANOMIPS: + case VexArchNANOMIPS: NANOMIPSST(cached = evCheckSzB_NANOMIPS()); break; + case VexArchRISCV64: + RISCV64ST(cached = evCheckSzB_RISCV64()); break; default: vassert(0); } @@ -1432,6 +1496,9 @@ VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host, case VexArchNANOMIPS: NANOMIPSST(return patchProfInc_NANOMIPS(endness_host, place_to_patch, location_of_counter)); + case VexArchRISCV64: + RISCV64ST(return patchProfInc_RISCV64(endness_host, place_to_patch, + location_of_counter)); default: vassert(0); } @@ -1515,6 +1582,7 @@ const HChar* LibVEX_ppVexArch ( VexArch arch ) case VexArchMIPS32: return "MIPS32"; case VexArchMIPS64: return "MIPS64"; case VexArchNANOMIPS: return "NANOMIPS"; + case VexArchRISCV64: return "RISCV64"; default: return "VexArch???"; } } @@ -1586,6 +1654,7 @@ static IRType arch_word_size (VexArch arch) { case VexArchMIPS64: case VexArchPPC64: case VexArchS390X: + case VexArchRISCV64: return Ity_I64; default: @@ -1929,6 +1998,11 @@ static const HChar* show_hwcaps_mips64 ( UInt hwcaps ) return "Unsupported baseline"; } +static const HChar* show_hwcaps_riscv64 ( UInt hwcaps ) +{ + return "riscv64"; +} + #undef NUM_HWCAPS /* Thie function must not return NULL. */ @@ -1936,15 +2010,16 @@ static const HChar* show_hwcaps_mips64 ( UInt hwcaps ) static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps ) { switch (arch) { - case VexArchX86: return show_hwcaps_x86(hwcaps); - case VexArchAMD64: return show_hwcaps_amd64(hwcaps); - case VexArchPPC32: return show_hwcaps_ppc32(hwcaps); - case VexArchPPC64: return show_hwcaps_ppc64(hwcaps); - case VexArchARM: return show_hwcaps_arm(hwcaps); - case VexArchARM64: return show_hwcaps_arm64(hwcaps); - case VexArchS390X: return show_hwcaps_s390x(hwcaps); - case VexArchMIPS32: return show_hwcaps_mips32(hwcaps); - case VexArchMIPS64: return show_hwcaps_mips64(hwcaps); + case VexArchX86: return show_hwcaps_x86(hwcaps); + case VexArchAMD64: return show_hwcaps_amd64(hwcaps); + case VexArchPPC32: return show_hwcaps_ppc32(hwcaps); + case VexArchPPC64: return show_hwcaps_ppc64(hwcaps); + case VexArchARM: return show_hwcaps_arm(hwcaps); + case VexArchARM64: return show_hwcaps_arm64(hwcaps); + case VexArchS390X: return show_hwcaps_s390x(hwcaps); + case VexArchMIPS32: return show_hwcaps_mips32(hwcaps); + case VexArchMIPS64: return show_hwcaps_mips64(hwcaps); + case VexArchRISCV64: return show_hwcaps_riscv64(hwcaps); default: return NULL; } } @@ -2207,6 +2282,11 @@ static void check_hwcaps ( VexArch arch, UInt hwcaps ) return; invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n"); + case VexArchRISCV64: + if (hwcaps == 0) + return; + invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n"); + default: vpanic("unknown architecture"); } diff --git a/VEX/priv/main_util.h b/VEX/priv/main_util.h index 2fa26b062..7fd304dd1 100644 --- a/VEX/priv/main_util.h +++ b/VEX/priv/main_util.h @@ -100,6 +100,17 @@ extern SizeT vex_strlen ( const HChar* str ); extern void vex_bzero ( void* s, SizeT n ); +/* Math ops */ + +/* Sign extend an N-bit value up to 64 bits, by copying bit N-1 into all higher + positions. */ +static inline ULong vex_sx_to_64( ULong x, UInt n ) +{ + vassert(n >= 1 && n < 64); + return (ULong)((Long)(x << (64 - n)) >> (64 - n)); +} + + /* Storage management: clear the area, and allocate from it. */ /* By default allocation occurs in the temporary area. However, it is diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 168107734..d99be23a0 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -60,6 +60,7 @@ typedef VexArchMIPS32, VexArchMIPS64, VexArchNANOMIPS, + VexArchRISCV64, } VexArch; @@ -1033,6 +1034,16 @@ extern void LibVEX_InitIRI ( const IRICB * ); ~~~~~ r21 is GSP. + riscv64 + ~~~~~~~ + On entry, x8/s0 should point to the guest state + 2048. RISC-V has + load/store instructions with immediate (offset from the base + register) in range -2048 to 2047. The adjustment of 2048 allows + LibVEX to effectively use the full range. When translating + riscv64->riscv64, only a single instruction is then needed to + read/write values in the guest state (primary + 2x shadow state + areas) and most of the spill area. + ALL GUEST ARCHITECTURES ~~~~~~~~~~~~~~~~~~~~~~~ The guest state must contain two pseudo-registers, guest_CMSTART diff --git a/VEX/pub/libvex_basictypes.h b/VEX/pub/libvex_basictypes.h index e3f1485d5..6c48b227c 100644 --- a/VEX/pub/libvex_basictypes.h +++ b/VEX/pub/libvex_basictypes.h @@ -153,7 +153,6 @@ typedef unsigned long HWord; #undef VEX_HOST_WORDSIZE #undef VEX_REGPARM -/* The following 4 work OK for Linux. */ #if defined(__x86_64__) # define VEX_HOST_WORDSIZE 8 # define VEX_REGPARM(_n) /* */ @@ -198,6 +197,10 @@ typedef unsigned long HWord; # define VEX_HOST_WORDSIZE 4 # define VEX_REGPARM(_n) /* */ +#elif defined(__riscv) && (__riscv_xlen == 64) +# define VEX_HOST_WORDSIZE 8 +# define VEX_REGPARM(_n) /* */ + #else # error "Vex: Fatal: Can't establish the host architecture" #endif diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 2d09e37cb..80ef8f27a 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -2089,7 +2089,8 @@ typedef Irrm_PREPARE_SHORTER = 5, // Round to prepare for shorter // precision Irrm_AWAY_FROM_ZERO = 6, // Round to away from 0 - Irrm_NEAREST_TIE_TOWARD_0 = 7 // Round to nearest, ties towards 0 + Irrm_NEAREST_TIE_TOWARD_0 = 7, // Round to nearest, ties towards 0 + Irrm_INVALID = 8 // Invalid mode } IRRoundingMode; diff --git a/VEX/useful/test_main.c b/VEX/useful/test_main.c index cfed7a598..85168e704 100644 --- a/VEX/useful/test_main.c +++ b/VEX/useful/test_main.c @@ -101,7 +101,8 @@ int main ( int argc, char** argv ) VexTranslateResult tres; VexControl vcon; VexGuestExtents vge; - VexArchInfo vai_x86, vai_amd64, vai_ppc32, vai_arm, vai_mips32, vai_mips64; + VexArchInfo vai_x86, vai_amd64, vai_ppc32, vai_arm, vai_mips32, vai_mips64, + vai_riscv64; VexAbiInfo vbi; VexTranslateArgs vta; @@ -190,6 +191,10 @@ int main ( int argc, char** argv ) LibVEX_default_VexArchInfo(&vai_mips64); vai_mips64.endness = VexEndnessLE; + LibVEX_default_VexArchInfo(&vai_riscv64); + vai_riscv64.hwcaps = 0; + vai_riscv64.endness = VexEndnessLE; + LibVEX_default_VexAbiInfo(&vbi); vbi.guest_stack_redzone_size = 128; @@ -245,6 +250,12 @@ int main ( int argc, char** argv ) vta.guest_bytes = &origbuf[18 +1]; vta.guest_bytes_addr = (Addr) &origbuf[18 +1]; #endif +#if 0 /* riscv64 -> riscv64 */ + vta.arch_guest = VexArchRISCV64; + vta.archinfo_guest = vai_riscv64; + vta.arch_host = VexArchRISCV64; + vta.archinfo_host = vai_riscv64; +#endif #if 1 /* no instrumentation */ vta.instrument1 = NULL;