X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/a3ad4421ce9e122bc9079ffc6e60f45b1b06c1d7..e3da9aaf8fcb82c3c253bcdd165273eecc689b51:/base/dispatch-x86ish.S diff --git a/base/dispatch-x86ish.S b/base/dispatch-x86ish.S index 2c267b62..67ec05e6 100644 --- a/base/dispatch-x86ish.S +++ b/base/dispatch-x86ish.S @@ -44,48 +44,51 @@ FUNC(dispatch_x86ish_cpuid) // return zero if we can; otherwise fill with zero and return -1. #if CPUFAM_X86 +# define OUT edi pushreg ebx pushreg edi - mov edi, [esp + 12] - mov eax, [esp + 16] - mov ecx, [esp + 20] -# define OUT edi + mov OUT, [SP + 12] + mov eax, [SP + 16] + mov ecx, [SP + 20] #endif #if CPUFAM_AMD64 && ABI_SYSV +# define OUT rdi pushreg rbx mov eax, esi mov ecx, edx -# define OUT rdi #endif #if CPUFAM_AMD64 && ABI_WIN +# define OUT r9 pushreg rbx - mov r9, rcx + mov OUT, rcx mov eax, edx mov ecx, r8d -# define OUT r9 #endif endprologue // First, check that this is even a thing, using the complicated - // dance with the flags register. + // dance with the flags register. This is unnecessary on AMD64, + // which postdates the introduction of `cpuid'. +#if CPUFAM_X86 pushf - pop R_d(r) // current flags in d + pop DX // current flags in d - or R_d(r), EFLAGS_ID // force the id bit on and check it - push R_d(r) + or DX, EFLAGS_ID // force the id bit on and check it + push DX popf pushf - pop R_d(r) + pop DX test edx, EFLAGS_ID jz 8f - and R_d(r), ~EFLAGS_ID // force the id bit off and check it - push R_d(r) + and DX, ~EFLAGS_ID // force the id bit off and check it + push DX popf pushf - pop R_d(r) + pop DX test edx, EFLAGS_ID jnz 8f +#endif // OK, that seemed to work. cpuid @@ -108,6 +111,7 @@ FUNC(dispatch_x86ish_cpuid) ret // Failed. +#if CPUFAM_X86 8: xor eax, eax mov [OUT + 0], eax mov [OUT + 4], eax @@ -115,6 +119,9 @@ FUNC(dispatch_x86ish_cpuid) mov [OUT + 12], eax mov eax, -1 jmp 9b +#endif + +#undef OUT ENDFUNC ///-------------------------------------------------------------------------- @@ -124,33 +131,130 @@ FUNC(dispatch_x86ish_xmmregisters_p) // Enter with no arguments. Return nonzero if the XMM registers are // usable. - pushreg R_bp(r) + pushreg BP setfp stalloc 512 - and R_sp(r), ~15 + and SP, ~15 endprologue // Save the floating point and SIMD registers, and try to clobber // xmm0. - fxsave [R_sp(r)] - mov eax, [R_sp(r) + 160] - xor dword ptr [R_sp(r) + 160], 0xaaaa5555 - fxrstor [R_sp(r)] + lea DX, [SP + 160] + fxsave [SP] + mov eax, [DX] + xor dword ptr [DX], 0xaaaa5555 + fxrstor [SP] // Save them again, and read back the low word of xmm0. Undo the // clobbering and restore. - fxsave [R_sp(r)] - mov ecx, [R_sp(r) + 160] - mov [R_sp(r) + 160], eax - fxrstor [R_sp(r)] + fxsave [SP] + mov ecx, [DX] + mov [DX], eax + fxrstor [SP] // The register are live if we read different things. xor eax, ecx // Done. dropfp - popreg R_bp(r) + popreg BP + ret +ENDFUNC + +///-------------------------------------------------------------------------- +/// Checking extended control registers. + +FUNC(dispatch_x86ish_xgetbv) + // Call with two arguments: a pointer Z_OUT to 8 bytes of output space, and + // a 32-bit integer C. Read the 64-bit value of XCR(C), and store it + // at Z_OUT. + +#if CPUFAM_X86 +# define Z_OUT edi + pushreg edi + mov Z_OUT, [esp + 8] + mov ecx, [esp + 12] +#endif +#if CPUFAM_AMD64 && ABI_SYSV +# define Z_OUT rdi + mov ecx, esi +#endif +#if CPUFAM_AMD64 && ABI_WIN +# define Z_OUT r8 + mov r8, rcx + mov ecx, edx +#endif + endprologue + + xgetbv + mov [Z_OUT + 0], eax + mov [Z_OUT + 4], edx + +#if CPUFAM_X86 + popreg edi +#endif ret + +#undef Z_OUT +ENDFUNC + +///-------------------------------------------------------------------------- +/// Checking `rdrand'. + +FUNC(dispatch_x86ish_rdrand) + // Enter with two arguments: a code OP requesting either `rdrand' (0) + // or `rdseed' (1), and a pointer X_OUT to a 32-bit word. Try to + // generate a random word using the requested instruction'. If + // successful, set *X_OUT to the generated word, and return zero; + // otherwise, return -1. + +#if CPUFAM_X86 +# define OP eax +# define X_OUT edx +# define COUNT ecx + mov OP, [SP + 4] + mov X_OUT, [SP + 8] +#endif +#if CPUFAM_AMD64 && ABI_SYSV +# define OP edi +# define X_OUT rsi +# define COUNT ecx +#endif +#if CPUFAM_AMD64 && ABI_WIN +# define OP rcx +# define X_OUT rdx +# define COUNT r8d +#endif + endprologue + + cmp OP, 0 + mov COUNT, 16 // fairly persistent + jne 1f + +0: rdrand eax + jc 9f + dec COUNT + jnz 0b + jmp 8f + +1: rdseed eax + jc 9f + dec COUNT + jnz 1b + jmp 8f + + // Failed to come up with a random value. +8: mov eax, -1 + ret + + // Success. +9: mov [X_OUT], eax + xor eax, eax + ret + +#undef X_OUT +#undef COUNT + ENDFUNC ///----- That's all, folks --------------------------------------------------