From 8afb49abe04a341d60b441c1f09a956aeccf0bbb Mon Sep 17 00:00:00 2001 From: Carl Love Date: Mon, 22 Mar 2021 17:55:05 -0500 Subject: [PATCH] PPC64: Add support for the darn instruction --- Makefile.all.am | 4 ++ NEWS | 2 + VEX/priv/guest_ppc_defs.h | 2 + VEX/priv/guest_ppc_helpers.c | 21 +++++++++ VEX/priv/guest_ppc_toIR.c | 52 ++++++++++++++++++++++ configure.ac | 15 +++++++ coregrind/m_initimg/initimg-linux.c | 1 + none/tests/ppc64/Makefile.am | 8 +++- none/tests/ppc64/test_darn_inst.c | 42 +++++++++++++++++ none/tests/ppc64/test_darn_inst.stderr.exp | 2 + none/tests/ppc64/test_darn_inst.stdout.exp | 1 + none/tests/ppc64/test_darn_inst.vgtest | 2 + 12 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 none/tests/ppc64/test_darn_inst.c create mode 100644 none/tests/ppc64/test_darn_inst.stderr.exp create mode 100644 none/tests/ppc64/test_darn_inst.stdout.exp create mode 100644 none/tests/ppc64/test_darn_inst.vgtest diff --git a/Makefile.all.am b/Makefile.all.am index bcd29165da..1b66f82ea4 100644 --- a/Makefile.all.am +++ b/Makefile.all.am @@ -125,7 +125,11 @@ AM_CFLAGS_BASE = \ # Power ISA flag for use by guest_ppc_helpers.c if HAS_XSCVHPDP +if HAS_DARN +ISA_3_0_BUILD_FLAG = -DHAS_XSCVHPDP -DHAS_DARN +else ISA_3_0_BUILD_FLAG = -DHAS_XSCVHPDP +endif else ISA_3_0_BUILD_FLAG = endif diff --git a/NEWS b/NEWS index d41d529aab..4b4d33309c 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ support for X86/macOS 10.13, AMD64/macOS 10.13 and nanoMIPS/Linux. * ppc64: - ISA 3.1 support is now complete + - ISA 3.0 support for the darn instruction added. * ==================== TOOL CHANGES ==================== @@ -34,6 +35,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 429375 PPC ISA 3.1 support is missing, part 9 433801 PPC ISA 3.1 support is missing, part 10 (ISA 3.1 support complete) 433863 s390x: memcheck/tests/s390x/{cds,cs,csg} failures +434840 PPC64 darn instruction not supported To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX diff --git a/VEX/priv/guest_ppc_defs.h b/VEX/priv/guest_ppc_defs.h index d36d6c07d4..3c22096673 100644 --- a/VEX/priv/guest_ppc_defs.h +++ b/VEX/priv/guest_ppc_defs.h @@ -272,6 +272,8 @@ extern void vsx_matrix_64bit_float_ger_dirty_helper( VexGuestPPC64State* gst, ULong srcY_hi, ULong srcY_lo, UInt masks_inst ); +extern ULong darn_dirty_helper ( UInt L ); + #endif /* ndef __VEX_GUEST_PPC_DEFS_H */ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest_ppc_helpers.c b/VEX/priv/guest_ppc_helpers.c index d8131eb607..c755739989 100644 --- a/VEX/priv/guest_ppc_helpers.c +++ b/VEX/priv/guest_ppc_helpers.c @@ -2416,6 +2416,27 @@ void vsx_matrix_64bit_float_ger_dirty_helper( VexGuestPPC64State* gst, } } +/* CALLED FROM GENERATED CODE */ +/* DIRTY HELPER uses inline assembly to call random number instruction on + the host machine. Note, the dirty helper takes the value returned from + the host and returns it. The helper does not change the guest state + or guest memory. */ +ULong darn_dirty_helper ( UInt L ) +{ + ULong val = 0xFFFFFFFFFFFFFFFFULL; /* error */ + +# if defined (HAS_DARN) + if ( L == 0) + __asm__ __volatile__("darn %0,0" : "=r"(val)); + else if (L == 1) + __asm__ __volatile__("darn %0,1" : "=r"(val)); + else if (L == 2) + __asm__ __volatile__("darn %0,2" : "=r"(val)); +# endif + + return val; +} + /*----------------------------------------------*/ /*--- The exported fns .. ---*/ /*----------------------------------------------*/ diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 469c27fe5f..09e9c49087 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -35607,6 +35607,52 @@ static Int dis_nop_prefix ( UInt prefix, UInt theInstr ) return False; } +static Int dis_darn ( UInt prefix, UInt theInstr, + const VexAbiInfo* vbi ) +{ + /* darn - Deliver A Random Number */ + UInt L = IFIELD( theInstr, 16, 2); + UChar rD_addr = ifieldRegDS( theInstr ); + IRTemp rD = newTemp( Ity_I64 ); + IRDirty* d; + + /* L Format or returned value + 0 0 || CRN_32bits + 1 CRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE) + 2 RRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE) + 3 reserved + + On error, return 0xFFFFFFFFFFFFFFFF + A CRN value is a conditioned random number that was processed + to to reduce bias. + */ + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + DIP("darn r%u,%u\n", rD_addr, L); + + if (L == 3) + /* Hardware reports illegal instruction if L = 3. */ + return False; + + IRExpr** args = mkIRExprVec_1( mkU32( L ) ); + + d = unsafeIRDirty_1_N ( + rD, + 0/*regparms*/, + "darn_dirty_helper", + fnptr_to_fnentry( vbi, &darn_dirty_helper ), + args ); + + /* Execute the dirty call, returning the result in rD. The dirty + helper calls the darn instruction on the host returning the + random number generated by the darn instruction on the host. + The dirty helper does not change the state of the guest or guest + memory. */ + stmt( IRStmt_Dirty(d) ); + putIReg( rD_addr, mkexpr( rD ) ); + return True; +} + /*------------------------------------------------------------*/ /*--- Disassemble a single instruction ---*/ @@ -37170,6 +37216,12 @@ DisResult disInstr_PPC_WRK ( if (dis_int_logic( prefix, theInstr )) goto decode_success; goto decode_failure; + case 0x2F3: // darn - Deliver A Random Number + if (!allow_isa_3_0) goto decode_noP9; + if (dis_darn( prefix, theInstr, abiinfo )) + goto decode_success; + goto decode_failure; + case 0x28E: case 0x2AE: // tbegin., tend. case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc. case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. diff --git a/configure.ac b/configure.ac index 14a01ab7b5..b2f3dd91db 100755 --- a/configure.ac +++ b/configure.ac @@ -1654,6 +1654,20 @@ ac_asm_have_xscvhpdp=no AC_MSG_RESULT([no]) ]) +# darn instruction checking +AC_MSG_CHECKING([that assembler knows darn instruction ]) + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +]], [[ + __asm__ __volatile__("darn 1,0 "); +]])], [ +ac_asm_have_darn_inst=yes +AC_MSG_RESULT([yes]) +], [ +ac_asm_have_darn_inst=no +AC_MSG_RESULT([no]) +]) + # isa 3.01 checking AC_MSG_CHECKING([that assembler knows ISA 3.1 ]) @@ -1673,6 +1687,7 @@ AM_CONDITIONAL(HAS_ISA_3_00, [test x$ac_asm_have_isa_3_00 = xyes \ -a x$HWCAP_HAS_ISA_3_00 = xyes]) AM_CONDITIONAL(HAS_XSCVHPDP, [test x$ac_asm_have_xscvhpdp = xyes]) +AM_CONDITIONAL(HAS_DARN, [test x$ac_asm_have_darn_inst = xyes]) AM_CONDITIONAL(HAS_ISA_3_1, [test x$ac_asm_have_isa_3_1 = xyes \ -a x$HWCAP_HAS_ISA_3_1 = xyes]) diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index 73dab34363..55559b4923 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -821,6 +821,7 @@ Addr setup_client_stack( void* init_sp, | 0x04000000ULL /* VEC_CRYPTO */ | 0x00800000ULL /* ARCH_3_00 */ | 0x00400000ULL /* HAS_IEEE128 */ + | 0x00200000ULL /* PPC_FEATURE2_DARN */ | 0x00040000ULL); /* ARCH_3_1 */ } diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am index 38a3dc4833..00c65b5654 100644 --- a/none/tests/ppc64/Makefile.am +++ b/none/tests/ppc64/Makefile.am @@ -57,7 +57,8 @@ EXTRA_DIST = \ test_isa_3_1_Misc.vgtest test_isa_3_1_Misc.stderr.exp test_isa_3_1_Misc.stdout.exp \ test_isa_3_1_AT.vgtest test_isa_3_1_AT.stderr.exp test_isa_3_1_AT.stdout.exp \ subnormal_test.stderr.exp subnormal_test.stdout.exp \ - subnormal_test.vgtest + subnormal_test.vgtest test_darn_inst.stderr.exp \ + test_darn_inst.stdout.exp test_darn_inst.vgtest check_PROGRAMS = \ allexec \ @@ -68,7 +69,7 @@ check_PROGRAMS = \ test_isa_3_0 test_mod_instructions \ test_isa_3_1_RT test_isa_3_1_XT test_isa_3_1_VRT \ test_isa_3_1_Misc test_isa_3_1_AT \ - subnormal_test \ + subnormal_test test_darn_inst \ test_tm test_touch_tm data-cache-instructions \ power6_mf_gpr std_reg_imm \ twi_tdi tw_td power6_bcmp @@ -188,6 +189,9 @@ test_touch_tm_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(HTM_FLAG) test_isa_3_0_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(HTM_FLAG) $(ISA_3_00_FLAG) \ @FLAG_M64@ $(BUILD_FLAGS_ISA_3_00) +test_darn_inst_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(HTM_FLAG) $(ISA_3_00_FLAG) \ + @FLAG_M64@ $(BUILD_FLAGS_ISA_3_00) + test_isa_3_1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(ISA_3_1_FLAG) \ @FLAG_M64@ $(BUILD_FLAGS_ISA_3_1) test_isa_3_1_RT_CFLAGS = $(test_isa_3_1_CFLAGS) diff --git a/none/tests/ppc64/test_darn_inst.c b/none/tests/ppc64/test_darn_inst.c new file mode 100644 index 0000000000..ba828a3a90 --- /dev/null +++ b/none/tests/ppc64/test_darn_inst.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#define ERROR 0xFFFFFFFFFFFFFFFFULL + +int main() +{ + unsigned long long rand; + int success = TRUE; + + /* The random number instruction returns 0xFFFFFFFFFFFFFFFFULL on error + and an unsigned 64-bit value between 0 and 0xFFFFFFFFFFFFFFFEULL on + success. */ + __asm__ __volatile__ ("darn %0,0" : "=r" (rand)); + if (rand == ERROR) { + success = FALSE; + printf ("Error darn 0 result = 0%llx not in expected range.\n", rand); + } + + __asm__ __volatile__ ("darn %0,1" : "=r" (rand)); + if (rand == ERROR) { + success = FALSE; + printf ("Error darn 1 result = 0%llx not in expected range.\n", rand); + } + + __asm__ __volatile__ ("darn %0,2" : "=r" (rand)); + if (rand == ERROR) { + success = FALSE; + printf ("Error darn 2 result = 0%llx not in expected range.\n", rand); + } + + if (success) + printf("Success.\n"); + else + printf("Failure.\n"); + + return 0; +} diff --git a/none/tests/ppc64/test_darn_inst.stderr.exp b/none/tests/ppc64/test_darn_inst.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/ppc64/test_darn_inst.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/ppc64/test_darn_inst.stdout.exp b/none/tests/ppc64/test_darn_inst.stdout.exp new file mode 100644 index 0000000000..a9d787cc55 --- /dev/null +++ b/none/tests/ppc64/test_darn_inst.stdout.exp @@ -0,0 +1 @@ +Success. diff --git a/none/tests/ppc64/test_darn_inst.vgtest b/none/tests/ppc64/test_darn_inst.vgtest new file mode 100644 index 0000000000..b72a687e4d --- /dev/null +++ b/none/tests/ppc64/test_darn_inst.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_00 +prog: test_darn_inst -- 2.47.2