|
데브피아에서.. CYRIX CPU 정보 알아내는 소스를 구했는데여....
C와 asm 으로 되어있는데...asm으로 된 함수를 콜하는 부분이 있는데..
Cbuilder에서 어떻게 사용해야 하나여...
넘 초보라.....어찌 해야할지 모르겠네여...
넘 개념없는 질문이라....고생스럽더라도...ㅠ.ㅠ
/* ..................................................................... */
/* includes */
/* ..................................................................... */
#include <string.h>
#include "cyrix.h"
#include "cpu_type.h"
#include "cpu_mhz.h"
/* ..................................................................... */
/* implemention functions prototypes */
/* ..................................................................... */
/* Used for cpu_type */
#define Cx486 0x1
#define _5x86 0x2
#define MediaGX 0x3
#define _6x86 0x4
#define _6x86MX 0x5
/* .ASM functions used */
int isfpu (void);
int iscyrixfpu (void);
int is_cpuid_supported (void);
int oldiscyrix (void);
int is486(void);
int isv86(void);
char cx_r (char);
void cx_w (char, char);
unsigned long cpu_speed( unsigned int );
void read_time_stamp( unsigned long *v1, unsigned long *v2 );
void get_cpuid_info (long v1, long *v2, long *v3, long *v4, long *v5);
/* functions used internally only */
static unsigned short Get_DIRs(char *, char *);
static void NameByDIRs (unsigned char, unsigned char, char* );
static void Set_Features(unsigned char, unsigned char, CPUInfo* );
static int cpu_type(void);
//Cyrixasm.asm 파일-------------------------------------------------------------------------public _is_cpuid_supported
public _get_cpuid_info
public _extended_cpuid_supported
public _oldiscyrix
public _iscyrixfpu
public _is486
public _isfpu
public _isv86
public _cx_r
public _cx_w
public _read_time_stamp
public _cpu_speed
assume cs:_TEXT
rdtsc macro
db 0fh, 031h
endm
_TEXT segment byte public 'CODE'
;**************************************************************************
; Function: int is_cpuid_supported ()
;
; Purpose: Check for existence of CPUID instruction.
; If exists execute CPUID with eax==0.
;
; Inputs: none
;
; Output:
;
; Returns: 0 - no CPUID instruction supported
; 1 - CPUID instruction supported
;**************************************************************************
cpuid macro
db 0fh, 0a2h
endm
_is_cpuid_supported proc near
.386
pushfd ; save current flags
push eax
push ebx
pushfd ; get extended flags
pop eax
mov ebx, eax ; save current flags
xor eax, 200000h ; toggle bit 21
push eax ; put new flags on stack
popfd ; flags updated now in flags
pushfd ; get extended flags
pop eax
xor eax, ebx ; if bit 21 r/w then eax <> 0
pop ebx
pop eax
je no_cpuid ; can't toggle id bit (21) no cpuid here
mov eax, 1 ; cpuid supported
jmp done_cpuid_sup
no_cpuid:
mov eax, 0 ; cpuid not supported
done_cpuid_sup:
popfd ; restore original flags
ret
_is_cpuid_supported endp
;**************************************************************************
; Function: void get_cpuid_info (long level,
; long ®_eax,
; long ®_ebx,
; long ®_ecx,
; long ®_edx)
;
; Purpose: Execute CPUID instruction at level (eax==level)
;
; Inputs: level - eax value when CPU is executed
;
; Output: reg_eax - eax after executing CPUID
; reg_ebx - ebx after executing CPUID
; reg_ecx - ecx after executing CPUID
; reg_edx - edx after executing CPUID
;**************************************************************************
_get_cpuid_info proc near
.386
push bp
mov bp, sp
push eax
push ebx
push ecx
push edx
push esi
mov eax, dword ptr [bp+4] ; get level
cpuid
mov si,word ptr [bp+8]
mov dword ptr [si],eax ; reg_eax := eax
mov si,word ptr [bp+10]
mov dword ptr [si],ebx ; reg_ebx := ebx
mov si,word ptr [bp+12] ; reg_ecx := ecx
mov dword ptr [si],ecx
mov si,word ptr [bp+14] ; reg_edx := edx
mov dword ptr [si],edx
pop esi
pop edx
pop ecx
pop ebx
pop eax
mov sp,bp
pop bp
ret
_get_cpuid_info endp
;**************************************************************************
; Function: int extended_cpuid_supported
;
; Purpose: Determine if ExtendedCPUID is supported
; Technique: Do CPUID with eax = 8000 0000, if eax returns a
; value greater than 1, then it is supported
; Inputs: none
; Output: ax == 1 ExtendedCPUID supported, 0 if not
;**************************************************************************
_extended_cpuid_supported proc near
.386
mov eax, 80000000h ; try extended CPUID
cpuid
cmp eax, 1 ; eax > 1
jle no_ecpuid
mov eax, 1 ; extended cpuid supported
jmp done_ecpuid
no_ecpuid:
mov eax, 0 ; extended cpuid not supported
done_ecpuid:
ret
_extended_cpuid_supported endp
;**************************************************************************
; Function: int oldiscyrix ()
;
; Purpose: Determine if Cyrix CPU is present via 5/2 method
; Technique: Cyrix CPUs do not change flags where flags change
; in an undefined manner on other CPUs
; Inputs: none
; Output: ax == 1 Cyrix present, 0 if not
;**************************************************************************
_oldiscyrix proc near
push bx
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 not_cyrix1 ; flags changed not Cyrix
mov ax, 1 ; TRUE Cyrix CPU
jmp done1
not_cyrix1:
mov ax, 0 ; FALSE NON-Cyrix CPU
done1:
pop bx
ret
_oldiscyrix endp
;**************************************************************************
; Function: int iscyrixfpu()
; Technique:
; On both the Cyrix and Intel math coprocessor the function
; 2^x-1 is undefined when its argument does not lie between
; -1 and +1. Therefore, when this function is evaluated at
; x=pi it is not surprising that the answers returned by the
; Cyrix and Intel chips are distinct. This program computes
; 2^PI-1 and stores the result as a single precision number
; VALUE. It is possible to distinguish between the Cyrix and
; Intel math coprocessors by comparing VALUE with the known
; value obtained when using a Cyrix or Intel math coprocessor.
;
; Purpose: Determine if Cyrix FPU is present
; Inputs: None
; Output: AX=1 if Cyrix FPU Present else AX=0
;**************************************************************************
_iscyrixfpu proc near
push bp
mov bp,sp
sub sp,4 ; get stack space
push si ; use as temp
finit ; inialize fpu
fldpi ; fpu loads pi
f2xm1 ; 2^pi - 1
fstp dword ptr [bp-4] ; store computed value
lea si, word ptr [bp-2] ; get address of stored value
cmp word ptr [si], 3FC9h ; compare stored value to Cyrix
jne short not_cyrix2
mov ax, 1 ; True Cyrix FPU present
jmp short done2
not_cyrix2:
mov ax, 0 ; FALSE Cyrix FPU not present
done2:
pop si
mov sp,bp
pop bp
ret
_iscyrixfpu endp
;**************************************************************************
; Function: is486 ()
;
; Purpose: Check for presence of a 486 level support.
;
; Returns: 1 if 486 or better present.
; 0 if earlier than a 486 is present.
;
;**************************************************************************
_is486 proc near
.486
pushfd ; save EFLAGS
pop eax ; get EFLAGS
mov ecx, eax ; temp storage EFLAGS
xor eax, 1 SHL 18 ; change AC bit in EFLAGS
push eax ; put new EFLAGS value on stack
popfd ; replace current EFLAGS value
pushfd ; get EFLAGS
pop eax ; save new EFLAGS in EAX
cmp eax, ecx ; compare temp and new EFLAGS
jz is_not_80486
mov ax, 1 ; 80486 present
jmp done3
is_not_80486:
mov ax, 0 ; 80486 not present
done3:
push ecx ; get original EFLAGS
popfd ; restore EFLAGS
ret
_is486 endp
;**************************************************************************
; Function: isfpu ()
;
; Purpose: Determine if FPU is present
; Inputs: None
; Output: ax=1 if FPU present, 0 otherwise
;**************************************************************************
_isfpu proc near
.386
.387
fninit
mov ax, 5a5ah
fnstsw ax
cmp ax, 0
jne no_fpu
mov ax, 1
jmp done4
no_fpu:
mov ax, 0
done4:
ret
_isfpu endp
;**************************************************************************
; Function: isv86()
;
; Purpose: Determine if CPU is in REAL or V86
; Technique: Check PE bit. If set then assume V86.
; *** Note *** This technique only works
; for distinguishing V86 vs REAL.
; IT does not hold for anything else!
; Inputs: none
; Output: ax == 1 in V86 mode, else 0
;**************************************************************************
_isv86 proc near
.486P
smsw ax
test al, 1
jz no_v86
mov ax, 1
jmp done5
no_v86:
mov ax, 0
done5:
ret
_isv86 endp
;**************************************************************************
; Function: char cx_r (char index)
;
; Purpose: Reads Cyrix Configuration Register at index
; Inputs: byte index, Cyrix Configuration Register
; Output: al, Contents of Cyrix Configuration Register
;**************************************************************************
_cx_r proc near
push bp
mov bp,sp
pushf ; save flags
cli ; clear interrupt in flags
mov al, byte ptr [bp+4] ; get index
out 22h, al ; tell CPU which config. register
in al, 23h ; write to CPU config. register
popf ; restore flags
mov sp,bp
pop bp
ret
_cx_r endp
;**************************************************************************
; Function: void cx_w (char index, char val)
;
; Purpose: Write Cyrix Configuration Register at index with val
; Inputs: byte index, Cyrix Configuration Register
; byte val, value to be written to index
; Output: nothing
;**************************************************************************
_cx_w proc near
push bp
mov bp,sp
pushf ; save flags
cli ; clear interrupt in flags
mov al, byte ptr [bp+4] ; get index
out 22h, al ; tell CPU which config. register
mov al, byte ptr [bp+6] ; get val
out 23h, al ; write to CPU config. register
popf ; restore flags
mov sp,bp
pop bp
ret
_cx_w endp
.386p
;***********************************************************************
; Function: void read_time_stamp( long*, long* );
; Purpose: read Time Stamp Counter
;
; Inputs: pointers to two longs
; Param1 = Upper DWord
; Param2 = Lower DWord
; Returns: values of Time Stamp Counter
;
; NOTE: You must check for TSC before using this function!!!
;***********************************************************************
_read_time_stamp proc near
push bp
mov bp, sp
push eax ; save off values
push edx
push si
rdtsc ; db 0fh, 031h
mov si,word ptr [bp+4]
mov dword ptr [si],edx ; param 1 = edx (Upper DWord)
mov si,word ptr [bp+6]
mov dword ptr [si],eax ; param 2 = eax (Lower DWord)
pop si ; restore old values
pop edx
pop eax
mov sp,bp
pop bp
ret
_read_time_stamp endp
;***********************************************************************
; Function: unsigned long _cpu_speed( unsigned int )
; "C" style caller
; Purpose: calculate the elapsed time req'd to complete a loop of IDIVs
;
; Technique: Use the PC's high resolution timer/counter chip (the 8254)
; to measure elapsed time of a software loop consisting
; of the IDIV and LOOP instruction.
; Definitions: The 8254 recieves a 1.19318MHz clock (0.8380966 usec).
; One "tick" is equal to one rising clock edge applied
; to the 8254 clock input.
;
; Inputs: ax = no. of loops for cpu_speed_loop
; Returns: ax = no. of 1.19318MHz clk ticks req'd to complete the loop
; dx = state of 8254 out pin
;***********************************************************************
PortB EQU 061h
Timer_Ctrl_Reg EQU 043h
Timer_2_Data EQU 042h
stk$dx EQU 10 ;dx register offset
stk$ax EQU 14 ;ax register offset
stack$ax EQU [bp]+stk$ax
stack$dx EQU [bp]+stk$dx
Loop_Count EQU [bp+16]+4
_cpu_speed proc near
pushf ;save interrupt flag
pusha ;pushes 16 bytes on stack
mov bp,sp ;init base ptr
cli ;disable interrupts
;-------disable clock to timer/counter 2
in al, PortB
and al, NOT (1 SHL 0) ; clear bit 0
out PortB, al
mov di, ax
;-------initialize the 8254 counter to "0", known value
mov al,0b0h
out Timer_Ctrl_Reg, al ;control word to set channel 2 count
mov al,0ffh
out Timer_2_Data, al ;init count to 0, lsb
out Timer_2_Data, al ;init count to 0, msb
;-------get the number of loops from the caller's stack
mov cx,Loop_Count ;loop count
;-------load dividend and divisor, clk count for IDIV depend on operands!
xor edx,edx ;dividend EDX:EAX
xor eax,eax
mov ebx,1 ;divisor
;-------enable the timer/counter's clock. Begin timed portion of test!
xchg ax, di ;save ax for moment
or al, 1
out PortB, al ;enable timer/counter 2 clk
xchg ax, di ;restore ax
;-------skip loop if Loop_Count = 0
cmp cx, 0
jz after_loop
;-------this is the core loop.
; ALIGN 2 ; This should really be ALIGN 16
cpu_speed_loop:
idiv ebx
idiv ebx
idiv ebx
idiv ebx
idiv ebx
loop cpu_speed_loop
after_loop:
;-------disable the timer/counter's clk. End timed portion of test!
mov ax, di
and al, NOT (1 SHL 0) ; clear bit 0
out PortB, al
;-------send latch status command to the timer/counter
mov al, 0c8h ;latch status and count
out Timer_Ctrl_Reg, al
;-------read status byte, and count value "ticks" from the timer/cntr
in al, Timer_2_Data ;read status
mov dl, al
and dx, 080h
shr dx, 7 ; bit 0 = state of 8254 output pin
in al, Timer_2_Data ;read LSB
mov bl, al
in al, Timer_2_Data ;read MSB
mov bh, al
not bx ;invert count
;-------send command to clear the timer/counter
mov al, 0b6h
out Timer_Ctrl_Reg, al ;clear channel 2 count
xor al, al
out Timer_2_Data, al ;set count to 0, lsb
out Timer_2_Data, al ;set count to 0, msb
;-------put return values on the stack for the caller
mov [bp+stk$ax], bx
mov [bp+stk$dx], dx
popa
popf ;restores interrupt flag
ret
_cpu_speed endp
_TEXT ends
end
|