progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / base / dispatch-x86ish.S
index 2c267b6..67ec05e 100644 (file)
@@ -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 --------------------------------------------------