1 2; for new GOGO-no-coda (1999/09) 3; Copyright (C) 1999 shigeo 4; modified by Keiichi SAKAI, URURI, Hash 5 6; 99/07/29 7; 99/09/06 �ե饰�ɲ� 8; 99/09/07 SSE�ν������̤ˤ��� 9; 99/09/29 Cx586�к� 10; 99/11/10 Cxrix�к� 11 12; int haveUNIT(void); 13 14; 486̤����CPU�ޤ���FPU����ܤ��Ƥ��ʤ����0 15; ����ʳ��ϼ����ͤ������� 16; PIII�Ǥϴݤ����ͼθ����⡼�ɤˤ���(�餷��) 17 18; haveunit.h�Ȥ���������� 19 20%include "nasm.h" 21 22tFPU equ (1<<0) 23tMMX equ (1<<1) 24t3DN equ (1<<2) 25tSSE equ (1<<3) 26tCMOV equ (1<<4) 27tE3DN equ (1<<5) ;/* Athlon�� (extend 3D Now!)*/ 28tEMMX equ (1<<6) ;/* EMMX=E3DNow!_INT=SSE_INT */ 29 30tSPC1 equ (1<<16) ;/* ���̤ʥ����å� */ 31tSPC2 equ (1<<17) ;/* ���ӤϷ�ޤäƤʤ� */ 32 33tINTEL equ (1<<8) 34tAMD equ (1<<9) 35tCYRIX equ (1<<10) 36tIDT equ (1<<11) 37tUNKNOWN equ (1<<15) ;�٥������ʬ����ʤ� 38 39tFAMILY4 equ (1<<20) ;/* 486 ���λ��٥����Ƚ������Ƥˤʤ�ʤ� */ 40tFAMILY5 equ (1<<21) ;/* 586 (P5, P5-MMX, K6, K6-2, K6-III) */ 41tFAMILY6 equ (1<<22) ;/* 686�ʹ� P-Pro, P-II, P-III, Athlon */ 42 43 globaldef haveUNIT 44 globaldef setPIII_round 45 globaldef maskFPU_exception 46 47 segment_data 48 segment_code 49 50ACflag equ (1<<18) 51IDflag equ (1<<21) 52 53 align 16 54haveUNIT: 55 push ebx 56 push esi 57 xor esi,esi 58 call near haveFPU 59 jnz near .Lexit 60 or esi,tFPU 61 pushfd ;flag��¸ 62 pushfd 63 pop eax ;eax=flag 64 or eax,ACflag ;eax=flag|ACflag 65 push eax 66 popfd ;flag=eax 67 pushfd 68 pop eax ;eax=flag 69 popfd ;flag���� 70 test eax,ACflag ;ACflag���Ѳ��������� 71 jz near .Lexit 72;486�ʹ� 73 pushfd ;flag��¸ 74 pushfd 75 pop eax ;eax=flag 76 or eax,IDflag ;eax=flag|IDflag 77 push eax 78 popfd ;flag=eax 79 pushfd 80 pop eax ;eax=flag 81 popfd ;flag���� 82 test eax,IDflag 83; jz short .Lexit 84 jnz .L586 85 86%if 1 87 ;Cyrix 486CPU check Cyrix �� HP �ˤ��ä���� by Hash 88 89 xor ax, ax ; clear ax 90 sahf ; clear flags, bit 1 is always 1 in flags 91 mov ax, 5 92 mov bx, 2 93 div bl ; do an operation that does not change flags 94 lahf ; get flags 95 cmp ah, 2 ; check for change in flags 96 jne .L486intel ; flags changed not Cyrix 97 or esi,tCYRIX ; TRUE Cyrix CPU 98 jmp .L486 99 100.L486intel: 101 or esi,tINTEL 102.L486: 103 or esi,tFAMILY4 104 jmp .Lexit 105 106%else 107 ; check for Cyrix 486DLC -- based on check routine 108 ; documented in "Cx486SLC/e SMM Programmer's Guide" 109 xor dx,dx 110 cmp dx,dx 111 pushf 112 pop cx 113 mov ax,0FFFFh 114 mov bx,4 115 div bx 116 pushf 117 pop ax 118 and ax,8D5h 119 and cx,8D5h 120 cmp ax,cx 121 jnz .L486intel 122 or esi,tCYRIX 123 jmp .L486 124.L486intel: 125 or esi,tINTEL 126.L486: 127 or esi,tFAMILY4 128 jmp .Lexit 129%endif 130 131 132.L586: 133 134;cpuid �� eax,ebx,ecx,edx���˲�����Τ���ա����� 135 136 xor eax,eax 137 cpuid 138; cmp ecx,"letn" 139 cmp ecx,"ntel" ;�����NASM��ȿ�Ф����֤����� 140 jne .F00 141 or esi,tINTEL 142 jmp .F09 143.F00: 144; cmp ecx,"DMAc" 145 cmp ecx,"cAMD" 146 jne .F01 147 or esi,tAMD 148 jmp .F09 149.F01: 150; cmp ecx,"daet" 151 cmp ecx,"tead" 152 jne .F02 153 or esi,tCYRIX 154 jmp .F09 155.F02: 156; cmp ecx,"slua" 157 cmp ecx,"auls" 158 jne .F03 159 or esi,tIDT 160 jmp .F09 161.F03: 162 or esi,tUNKNOWN 163 jmp .F09 164.F09: 165 mov eax,1 166 cpuid 167 cmp ah,4 168 jne .F10 169 or esi,tFAMILY4 170 jmp .Lexit 171.F10: 172 cmp ah,5 173 jne .F11 174 or esi,tFAMILY5 175 jmp .F19 176.F11: 177 cmp ah,6 178 jne .F12 179 or esi,tFAMILY6 180 jmp .F19 181.F12: 182 or esi,tFAMILY6 ; 7�ʾ��6�ȸ��ʤ� 183.F19: 184 185 ;for AMD, IDT 186 mov eax,80000001h 187 cpuid 188 test edx,(1 << 31) 189 jz .F20 190 or esi,t3DN 191.F20: 192 test edx,(1 << 15) ;CMOVcc 193 jz .F21 194; test edx,(1 << 16) ;FCMOVcc ;K7�����ѹ� by URURI 195; jz .F21 196 or esi,tCMOV 197.F21: 198 test edx,(1 << 30) ;��ĥ 3D Now! 199 jz .F22 200%ifdef USE_E3DN 201 or esi,tE3DN 202%endif 203.F22: 204 test edx,(1 << 22) ;AMD MMX Ext 205 jz .F23 206 or esi,tEMMX 207.F23: 208 ;Intel�� 209 mov eax,1 210 cpuid 211 test edx,(1 << 23) 212 jz .F30 213 or esi,tMMX 214.F30: 215 test edx,(1 << 15) ;CMOVcc and FCMOV if FPU=1 216 jz .F31 217 or esi,tCMOV 218.F31: 219 test edx,(1 << 25) 220 jz short .Lexit 221 or esi,tEMMX 222%ifndef UNAVAILABLE_SSE 223 or esi,tSSE 224%endif 225.Lexit: 226 mov eax,esi 227 pop esi 228 pop ebx 229 ret 230 231; in:none 232; out:ZF FPU����=1, �ʤ�=0 233; dest:eax 234 235 align 16 236haveFPU: 237 mov al,1 238 fninit 239 fnstsw ax 240 cmp al,0 241 jne short .LhF_exit 242 sub esp,4 243 fnstcw word [esp] 244 mov ax,[esp] 245 add esp,4 246 and ax,103Fh 247 cmp ax,3Fh 248.LhF_exit: 249 ret 250 251setPIII_round: 252 ;P-III��SSE��μ¤˻ͼθ����⡼�ɤ� 253; mov eax,0x1f80 ; default mode 254 mov eax,0x9f80 ; flush to ZERO mode 255 push eax 256 ldmxcsr [esp] ; setup MXCSR 257 pop eax 258 ret 259 260; for Win32 Delphi 261maskFPU_exception: 262 push eax 263 fnstcw word [esp] 264 and word [esp],0xFFF2 265 fldcw word [esp] 266 pop eax 267 ret 268 269 end 270