Files
kichikuou_xsystem35-sdl2/src/haveunit.s
T
2017-02-11 19:03:05 +09:00

270 lines
4.8 KiB
ArmAsm

; for new GOGO-no-coda (1999/09)
; Copyright (C) 1999 shigeo
; modified by Keiichi SAKAI, URURI, Hash
; 99/07/29
; 99/09/06 フラグ追加
; 99/09/07 SSEの処理を別にする
; 99/09/29 Cx586対策
; 99/11/10 Cxrix対策
; int haveUNIT(void);
; 486未満のCPUまたはFPUを搭載していなければ0
; それ以外は次の値の論理和
; PIIIでは丸め誤差を四捨五入モードにする(らしい)
; haveunit.hとの整合性注意
%include "nasm.h"
tFPU equ (1<<0)
tMMX equ (1<<1)
t3DN equ (1<<2)
tSSE equ (1<<3)
tCMOV equ (1<<4)
tE3DN equ (1<<5) ;/* Athlon用 (extend 3D Now!)*/
tEMMX equ (1<<6) ;/* EMMX=E3DNow!_INT=SSE_INT */
tSPC1 equ (1<<16) ;/* 特別なスイッチ */
tSPC2 equ (1<<17) ;/* 用途は決まってない */
tINTEL equ (1<<8)
tAMD equ (1<<9)
tCYRIX equ (1<<10)
tIDT equ (1<<11)
tUNKNOWN equ (1<<15) ;ベンダーが分からない
tFAMILY4 equ (1<<20) ;/* 486 この時ベンダー判定は当てにならない */
tFAMILY5 equ (1<<21) ;/* 586 (P5, P5-MMX, K6, K6-2, K6-III) */
tFAMILY6 equ (1<<22) ;/* 686以降 P-Pro, P-II, P-III, Athlon */
globaldef haveUNIT
globaldef setPIII_round
globaldef maskFPU_exception
segment_data
segment_code
ACflag equ (1<<18)
IDflag equ (1<<21)
align 16
haveUNIT:
push ebx
push esi
xor esi,esi
call near haveFPU
jnz near .Lexit
or esi,tFPU
pushfd ;flag保存
pushfd
pop eax ;eax=flag
or eax,ACflag ;eax=flag|ACflag
push eax
popfd ;flag=eax
pushfd
pop eax ;eax=flag
popfd ;flag復元
test eax,ACflag ;ACflagは変化したか?
jz near .Lexit
;486以降
pushfd ;flag保存
pushfd
pop eax ;eax=flag
or eax,IDflag ;eax=flag|IDflag
push eax
popfd ;flag=eax
pushfd
pop eax ;eax=flag
popfd ;flag復元
test eax,IDflag
; jz short .Lexit
jnz .L586
%if 1
;Cyrix 486CPU check Cyrix の HP にあったやつ by Hash
xor ax, ax ; clear ax
sahf ; clear flags, bit 1 is always 1 in flags
mov ax, 5
mov bx, 2
div bl ; do an operation that does not change flags
lahf ; get flags
cmp ah, 2 ; check for change in flags
jne .L486intel ; flags changed not Cyrix
or esi,tCYRIX ; TRUE Cyrix CPU
jmp .L486
.L486intel:
or esi,tINTEL
.L486:
or esi,tFAMILY4
jmp .Lexit
%else
; check for Cyrix 486DLC -- based on check routine
; documented in "Cx486SLC/e SMM Programmer's Guide"
xor dx,dx
cmp dx,dx
pushf
pop cx
mov ax,0FFFFh
mov bx,4
div bx
pushf
pop ax
and ax,8D5h
and cx,8D5h
cmp ax,cx
jnz .L486intel
or esi,tCYRIX
jmp .L486
.L486intel:
or esi,tINTEL
.L486:
or esi,tFAMILY4
jmp .Lexit
%endif
.L586:
;cpuid は eax,ebx,ecx,edxを破壊するので注意!!!
xor eax,eax
cpuid
; cmp ecx,"letn"
cmp ecx,"ntel" ;うわ〜NASMと反対に配置するんだ
jne .F00
or esi,tINTEL
jmp .F09
.F00:
; cmp ecx,"DMAc"
cmp ecx,"cAMD"
jne .F01
or esi,tAMD
jmp .F09
.F01:
; cmp ecx,"daet"
cmp ecx,"tead"
jne .F02
or esi,tCYRIX
jmp .F09
.F02:
; cmp ecx,"slua"
cmp ecx,"auls"
jne .F03
or esi,tIDT
jmp .F09
.F03:
or esi,tUNKNOWN
jmp .F09
.F09:
mov eax,1
cpuid
cmp ah,4
jne .F10
or esi,tFAMILY4
jmp .Lexit
.F10:
cmp ah,5
jne .F11
or esi,tFAMILY5
jmp .F19
.F11:
cmp ah,6
jne .F12
or esi,tFAMILY6
jmp .F19
.F12:
or esi,tFAMILY6 ; 7以上は6と見なす
.F19:
;for AMD, IDT
mov eax,80000001h
cpuid
test edx,(1 << 31)
jz .F20
or esi,t3DN
.F20:
test edx,(1 << 15) ;CMOVcc
jz .F21
; test edx,(1 << 16) ;FCMOVcc ;K7から変更 by URURI
; jz .F21
or esi,tCMOV
.F21:
test edx,(1 << 30) ;拡張 3D Now!
jz .F22
%ifdef USE_E3DN
or esi,tE3DN
%endif
.F22:
test edx,(1 << 22) ;AMD MMX Ext
jz .F23
or esi,tEMMX
.F23:
;Intel系
mov eax,1
cpuid
test edx,(1 << 23)
jz .F30
or esi,tMMX
.F30:
test edx,(1 << 15) ;CMOVcc and FCMOV if FPU=1
jz .F31
or esi,tCMOV
.F31:
test edx,(1 << 25)
jz short .Lexit
or esi,tEMMX
%ifndef UNAVAILABLE_SSE
or esi,tSSE
%endif
.Lexit:
mov eax,esi
pop esi
pop ebx
ret
; in:none
; out:ZF FPUあり=1, なし=0
; dest:eax
align 16
haveFPU:
mov al,1
fninit
fnstsw ax
cmp al,0
jne short .LhF_exit
sub esp,4
fnstcw word [esp]
mov ax,[esp]
add esp,4
and ax,103Fh
cmp ax,3Fh
.LhF_exit:
ret
setPIII_round:
;P-IIIのSSEを確実に四捨五入モードに
; mov eax,0x1f80 ; default mode
mov eax,0x9f80 ; flush to ZERO mode
push eax
ldmxcsr [esp] ; setup MXCSR
pop eax
ret
; for Win32 Delphi
maskFPU_exception:
push eax
fnstcw word [esp]
and word [esp],0xFFF2
fldcw word [esp]
pop eax
ret
end