home *** CD-ROM | disk | FTP | other *** search
- PAGE ,120
-
- .386p ; 80386 code will be used
- .387 ; need coprocessor, too
-
- JMPS EQU <JMP SHORT> ; declare jumps as short
- JES EQU <JE SHORT> ; since near jumps (+/- 32K)
- JBS EQU <JB SHORT> ; are default in 386 mode
- JNZS EQU <JNZ SHORT> ; and these cannot execute
- JCS EQU <JC SHORT> ; on the older CPUs
- JZS EQU <JZ SHORT>
- JNES EQU <JNE SHORT>
- JAES EQU <JAE SHORT>
- JBES EQU <JBE SHORT>
- JAS EQU <JA SHORT>
-
- cpu_i8088 EQU 1
- cpu_i8086 EQU 2
- cpu_V20 EQU 3
- cpu_V30 EQU 4
- cpu_i188 EQU 5
- cpu_i186 EQU 6
- cpu_i286 EQU 7
- cpu_i386 EQU 8
- cpu_i386sx EQU 9
- cpu_ct38600 EQU 10
- cpu_ct38600sx EQU 11
- cpu_486dlc EQU 12
- cpu_486slc EQU 13
- cpu_RapidCAD EQU 14
- cpu_i486 EQU 15
- cpu_i486SX EQU 16
- cpu_pentium EQU 17
-
- ndp_NoCopro EQU 0
- ndp_Emul EQU 1
- ndp_i8087 EQU 2
- ndp_i80C187 EQU 3
- ndp_i80287 EQU 4
- ndp_i287XL EQU 5
- ndp_i387 EQU 6
- ndp_i387sx EQU 7
- ndp_2C87 EQU 8
- ndp_3C87 EQU 10
- ndp_3C87sx EQU 11
- ndp_82S87 EQU 12
- ndp_83D87 EQU 14
- ndp_83S87 EQU 15
- ndp_83C87 EQU 16
- ndp_83C87s EQU 17
- ndp_38700 EQU 18
- ndp_38700sx EQU 19
- ndp_i387DX EQU 20
- ndp_RapidCAD EQU 21
- ndp_i486 EQU 22
- ndp_82S87p EQU 23
- ndp_387plus EQU 25
- ndp_83S87p EQU 26
- ndp_emc87 EQU 27
- ndp_pentium EQU 28
-
-
- STRT_TIM MACRO
- MOV AL, 0B4h ; timer 2 is
- OUT 43h, AL ; programmed as a rate generator
- XOR AL, AL ; load zero
- OUT 42h, AL ; reset
- OUT 42h, AL ; timer 2
- ENDM
-
- STOP_TIM MACRO
- MOV AL, 80h ; timer 2
- OUT 43h, AL ; immediately latched
- IN AL, 42h ; read LSB
- MOV BL, AL ; save LSB
- IN AL, 42h ; read MSB
- MOV BH, AL ; save MSB
- NEG BX ; negate for timer count
- ENDM
-
-
-
- CODE SEGMENT BYTE USE16 PUBLIC 'CODE'
-
- ASSUME CS:CODE
-
- PUBLIC SpeedTest
-
- ; declare parameters
-
- Debug_Flag EQU [BP+24] ; <> 0, if debugging output desired
- Ext_Flag EQU [BP+22] ; zero, if no extended memory
- EMS_Flag EQU [BP+20] ; zero, if no expanded memory
- BufferPtr EQU [BP+16] ; buffer for EMS u. EXT test
- EMS_Base EQU [BP+12] ; address of EMS-frame
- ScreenPtr EQU [BP+8] ; start address of video memory
- ResultPtr EQU [BP+4] ; pointer to result struct
-
-
- ; declare local variables
-
- Stat EQU [BP-2] ; mem for 80x87 status word
- Ctrl EQU [BP-4] ; mem for 80x87 control word
- GDT EQU [BP-52] ; mem for global descriptor table
- SystemStat EQU [BP-53] ; mem for system status
- SaveCtrl EQU [BP-55] ; original 80x87 control word
-
-
- ; declare result record
- CPU_NDP_TYP EQU [SI]
- AAMTime EQU [SI+2]
- MovEvenTime EQU [SI+6]
- BIOSWrTime EQU [SI+8]
- MovByteTime EQU [SI+10]
- MovEMSTime EQU [SI+12]
- MovExtTime EQU [SI+14]
- ScrFillTime EQU [SI+16]
- Dummy2 EQU [SI+18]
- i87Time EQU [SI+20]
- i287Time EQU [SI+22]
- MovDblTime EQU [SI+24]
-
- SpeedTest PROC NEAR
- PUSH BP ; save caller's frame pointer
- MOV BP, SP ; make new frame pointer
- SUB SP, 55 ; alloc mem for local variables
- PUSH DS ; save Turbo Pascal's data segment
- PUSHF ; save original flag setting
-
- $inittimer: CLI ; disable interrupts
- CLD ; auto increment for string operations
- IN AL, 61h ; port B - system control
- MOV [SystemStat], AL ; save system status
- AND AL, 11111101b ; clear speaker bit (disable speaker)
- OR AL, 1 ; turn on bit for timer 2 (enable it)
- CMP AL, [SystemStat] ; system already configured correctly ?
- JES $aam ; no need to configure it
- OUT 61h, AL ; reconfigure system (tmr 2 on,spk off)
-
- $aam: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $aam1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg2 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $aam1 ; skip message text
-
- $dbg2 DB 'About to perform AAM speed test', 0Dh, 0Ah ,'$'
-
- $aam1: STRT_TIM ; start timer 2
- REPT 200
- AAM ; execute 200 AAMs
- ENDM
- STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [AAMTime], BX ; save time for AAMs
-
- $begin_test:CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $cpu_ndptst ; nope
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg1 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $cpu_ndptst ; skip message text
- $dbg1 DB 'About to perform CPU and NDP test', 0Dh, 0Ah ,'$'
-
- $cpu_ndptst:LDS SI, ResultPtr ; pointer to result struct
- FNSTCW [SaveCtrl] ; save original NDP ctrl word
- PUSH SP ; test updating
- POP AX ; of stackpointer
- CMP AX, SP ; stackpointer updated before push ?
- JES $286_386 ; no, must be 286, 386 or 486
- MOV AX, 1 ; try to shift
- MOV CL, 33 ; accu 33 times
- SHL AX, CL ; shift count masked off ?
- JNZS $186_188 ; yes, must be 186 or 188
- PUSHA ; PUSHA executed on 88/86 as JMP $+2
- STC ; carry set if V20 or V30
- JCS $V20_V30 ; yes, must be V20 or V30
- PUSHF ; save flags
- POP AX ; pop flags into AX
- AND AH, 00FH ; clear bits 12-15 of flag register
- PUSH AX ; put new flags in stack
- POPF ; pop into flag register
- PUSHF ; put flags on stack
- POP AX ; get flags
- AND AH, 0F0H ; test if all bits
- CMP AH, 0F0H ; in highest nibble set
- JES $88_86 ; all bits in highest nibble set
- XOR DL, DL ; failed all tests, unknown CPU
- JMPS $copro_test ; go and test NDP
- $88_86: MOV DL, cpu_i8088 ; else it's an 88 or 86
- JMPS $queue_test ; decide wether 88 or 86
- $V20_V30: POPA ; remove pushed bytes
- MOV DL, cpu_V20 ; it's an V20 or V30
- JMPS $queue_test ; decide wether V20 or V30
- $186_188: MOV DL, cpu_i188 ; 188/186
- $queue_test:LEA BX, [$patch] ; load patch address into BX
- MOV BYTE PTR CS:[BX], 42h; preset with opcode for INC DX
- MOV AL, 90H ; patch in a NOP (opcode 90h)
- MOV CL, 31 ; rotate register 31 times to use up
- ROL AH, CL ; time so prefetch queue can be filled
- MOV BYTE PTR CS:[BX], AL ; insert NOP at label $patch
- NOP ; fill
- NOP ; prefetch
- NOP ; queue
- NOP ; with NOPs
- $patch: INC DX ; patched to NOP on i88, i188 and V20
- $copro_test:JMP $ndp_test ; check for coprocessor
- $286_386: MOV DL, cpu_i286 ; 286, 386 or 486
- PUSH 7000h ; try to set
- POPF ; IOPL and NT fields
- PUSHF ; in bit 12-14
- POP AX ; of flag register
- TEST AX, 7000h ; bits cannot be set in 286 real mode
- JZS $copro_test ; bits not set --> 286
- INC DX ; CPU is an 386 (DL = 8) or 486
- MOV EBX, ESP ; save current stackpointer to align it
- AND ESP, 0FFFFFFFCh ; align stack to avoid AC fault
- PUSHFD ; save EFLAGS
- POP EAX ; get EFLAGS from stack
- MOV ECX, EAX ; original value of EFLAGS
- XOR EAX, 40000H ; toggle AC bit in EFLAGS
- PUSH EAX ; copy new value
- POPFD ; to EFLAGS
- PUSHFD ; get new EFLAGS value
- POP EAX ; put into EAX
- XOR EAX, ECX ; test if AC bit could be changed
- PUSH ECX ; restore original
- POPFD ; value of EFLAGS
- MOV ESP, EBX ; restore original stack pointer
- OR EAX, EAX ; EAX = 0 on 386, 40000h on 486
- JNZS $486_486dlc ; if <> 0, must be 486/486dlc/486slc
- $chk_38600: PUSH DX ; save CPU code
- MOV ESI, 32 ; 32 trials to check for POPAD bug
- MOV EAX, 12345678 ; load some value
- $trial_loop:MOV EBX, EAX ; save value for comparison
- MOV EDX, 0 ; prepare index and
- MOV EDI, 0 ; base register to point to DS:0
- PUSHAD ; push all 32-bit registers
- POPAD ; pop all 32-bit registers
- MOV ECX, [EDX+EDI] ; mem access changes EAX (POPAD bug!)
- CMP EAX, EBX ; EAX changed ?
- JNZS $changed ; EAX changed -> bug in AMD/Intel 386
- ROL EAX, 1 ; try next number
- DEC ESI ; decrement trial counter
- JNZS $trial_loop ; until 32 trials thru, exits with Z=1
- $changed: POP DX ; restore CPU code
- JNZS $copro_test ; EAX changed, must be Intel/AMD 386
- MOV DL, cpu_ct38600 ; C&T 38600 doesn't have that bug
- JMPS $copro_test ; now test for coprocessor
- $486_486dlc:MOV AX, 0FFFFh ; load initial multiplicand
- MOV BX, 0FFFFh ; load multiplicator
- STRT_TIM ; start timer 2
- REPT 30 ; 486: MUL takes 26, AAM 15 clocks
- MUL BX ; execute 30 MULs
- ENDM ; 486DLC: MUL takes 3, AAM 17 clocks
- STOP_TIM ; elapsed time of timer 2 in BX
- SHL BX, 3 ; time for 240 MULs
- CMP BX, [AAMTime] ; time for 240 MULs>time for 200 AAMs ?
- MOV DL, cpu_i486 ; default: it's a 486 (CPU = 15)
- JAS $ndp_test ; yes, 486 has slow MUL
- ADD BX, BX ; time for 480 MULs
- CMP BX, [AAMTime] ; time for 480 MULs>time for 200 AAMs ?
- JAS $pentium ; yes, Pentium MUL takes 11 clocks
- MOV DL, cpu_486dlc ; no, fast MUL -> 486DLC/486SLC
- JMPS $ndp_test ; continue with NDP test
- $pentium: MOV DL, cpu_pentium ; speed of Pentium between 486DLC..486
- $ndp_test: XOR DH, DH ; assume no coprocessor
- XOR AX, AX ; clear register
- OUT 0F0h, AL ; clear error signal of coprocessor
- FNINIT ; initialize coprocessor
- MOV [Ctrl], AX ; clear status variable
- NOT AX ; load all 1's
- MOV [Stat], AX ; initialize status variable to all 1's
- FNSTCW [Ctrl] ; store NDP control word
- MOV AX, [Ctrl] ; get control word
- AND AX, 0F3Fh ; extract RC, PC and exception masks
- CMP AX, 033Fh ; RC=0, PC=3, masks=3F ?
- JNES $chk_486sx ; no -> no coprocessor present
- FNSTSW [Stat] ; store NDP status
- TEST WORD PTR [Stat],383Fh; stack top & exceptions must be clear
- JNZS $chk_486sx ; ST & exceptions not clear -> no NDP
- MOV DH, ndp_Emul ; coprocessor is at least emulator (=1)
- CMP DL, cpu_i286 ; is CPU 80286 or higher ?
- JBS $no_emulat ; no, emulation impossible
- SMSW AX ; get machine status word
- TEST AL, 4 ; test if EM bit of MSW set
- JZS $no_emulat ; not set -> no NDP emulation
- $chk_486sx: CMP DL, cpu_i486 ; CPU = Intel 486 and no/emulated copro ?
- SBB DL, -1 ; yes, CPU is 486sx (increment DL)
- JMP $ndp_exit ; no further NDP checking
- $no_emulat: MOV DH, ndp_i8087 ; coprocessor is at least 8087 (=2)
- FLD1 ; load 1.0
- WAIT ; needed for 8087
- FLDZ ; load 0.0
- WAIT ; needed for 8087
- FDIV ; 1.0 / 0.0 = +infinity
- WAIT ; needed for 8087
- FLD ST(0) ; duplicate +infinity
- WAIT ; needed for 8087
- FCHS ; generate -infinity
- WAIT ; needed for 8087
- FCOMPP ; compare infinities and clear NDP stk
- WAIT ; needed for 8087
- FSTSW WORD PTR [Stat] ; save condition codes
- MOV AX, [Stat] ; load condition codes
- SAHF ; transfer into CPU flags
- JNES $187_387 ; 187, C287 or 387 if numbers not equal
- CMP DL, cpu_i286 ; is CPU >= 286 ?
- JBS $ndp_exit1 ; no, coprocessor is 8087
- MOV DH, ndp_i80287 ; coprocessor is 287
- JMPS $chk_iit ; check for IIT coprocessors
- $187_387: CMP DL, cpu_i286 ; is CPU >= 286 ?
- JAES $C287_387 ; yes, NDP is either C287, 287XL or 387
- MOV DH, ndp_i80C187 ; coprocessor is 187
- JMPS $ndp_exit1 ; store CPU and NDP code
- $C287_387: CMP DL, cpu_i386 ; is CPU >= 386 ?
- JAES $387_486 ; yes, NDP is 387 or 387sx, 486
- MOV DH, ndp_i287XL ; coprocessor is C287
- JMPS $chk_iit ; check for IIT coprocessors
- $387_486: CMP DL, cpu_i486 ; is CPU >= 486 ?
- JAES $i486 ; yes, NDP is 486 / 487
- MOV DH, ndp_i387 ; coprocessor is 387 or 387sx
- JMPS $chk_iit ; check for IIT coprocessors
- $i486: CMP DL, cpu_pentium ; is CPU Intel Pentium ?
- JES $ipentium ; yes, FPU is also Pentium
- MOV DH, ndp_i486 ; NDP = 486 / 487
- JMP $ndp_exit ; done with FPU detection
- $ipentium: MOV DH, ndp_pentium ; set FPU type = Pentium
- $ndp_exit1: JMP $ndp_exit ; no further tests required
- $chk_iit: FNINIT ; initialize coprocessor
- FLD CS:[$denormal] ; load denormal number
- FADD ST(0), ST ; result is zero on IIT
- FNSTSW AX ; get status of NDP into AX
- TEST AL, 02h ; test if denormal exception flag set
- JNZS $chk_ulsi ; Intel NDPs signal denormal exception
- ADD DH,ndp_2c87-ndp_i80287;set IIT coprocessor types
- JMPS $ndp_exit1 ; coprocessor type found
- $chk_ulsi: CMP DL, cpu_i386 ; CPU >= 386 ?
- JBS $chk_cyrix1 ; no, can not be ULSI
- FNINIT ; initialize coprocessor
- FLDCW CS:[$53bit_prec] ; PC => 53 bits (ULSI ignores PC)
- FLD TBYTE PTR CS:[$op1] ; load 2-epsilon
- FLD1 ; load 1
- FADDP ST(1), ST ; result should be 3 and PE raised
- FSTP TBYTE PTR [GDT] ; store result, clear NDP stack
- FNSTSW AX ; get coprocessor status word
- TEST AL, 20h ; precision exception ?
- JNZS $chk_cyrix1 ; ULSI computes 64 bit result, no PE!
- FWAIT ; make sure result is stored
- CMP BYTE PTR [GDT], 0F8h ; check least significant mantissa bits
- JNES $chk_cyrix1 ; not expected result for ULSI
- CMP BYTE PTR [GDT+9], 40h; check exponent hi-byte
- JNES $chk_cyrix1 ; not expected result for ULSI
- ADD DH,ndp_83C87-ndp_i387; set ULSI types
- JMPS $ndp_exit1 ; done
- $chk_cyrix1:FNINIT ; initialize coprocessor
- FLD TBYTE PTR CS:[$nan] ; load positive NaN
- FLD ST(0) ; duplicate NaN
- FCHS ; make negative NaN
- FPATAN ; ATAN (-NaN, +NaN) should return +NaN
- FSTP TBYTE PTR [GDT] ; store result, clear NDP stack
- FWAIT ; wait until result is stored
- CMP BYTE PTR [GDT+9], 7Fh; Cyrix ret. +NAN (7F),Intel -NAN (FF)
- JNES $chk_ct ; Intel coprocessor
- $chk_emc87: FNSTCW [Ctrl] ; store control word
- OR BYTE PTR [Ctrl+1],80h; set msb of control word
- FLDCW [Ctrl] ; and load back into coprocessor
- FSTCW [Ctrl] ; store control word again
- FWAIT ; wait until stored
- TEST BYTE PTR [Ctrl+1],80h; could msb be set ?
- JZS $no_emc ; no -> no EMC87
- MOV DH, ndp_emc87 ; set NDP type to EMC87
- JMPS $ndp_exit ; done
- $no_emc: ADD DH,ndp_82S87-ndp_i80287; set old Cyrix types
- FLD1 ; load 1.0
- FLD ST(0) ; load another 1.0
- FYL2XP1 ; compute 1.0*ld(2.0)
- FLD1 ; compare result with 1.0
- FCOMPP ; new Cyrix copros have correct result
- FNSTSW AX ; store coprocessor condition bits
- SAHF ; transfer to CPU flags
- JNES $ndp_exit ; if incorrect result, not new Cyrix
- ADD DH,ndp_82S87p-ndp_82S87; set NDP-type to new Cyrix types
- JMPS $ndp_exit ; done
- $chk_ct: CMP DL, cpu_i386 ; CPU >= 386 ?
- JBS $chk_387DX ; no, can not be C&T
- FNINIT ; initialize coprocessor
- FLDPI ; load pi
- F2XM1 ; 2**(pi)-1=pi/2, argument out of range
- FLD1 ; load 1.0
- FCHS ; -1.0
- FLDPI ; load pi
- FSCALE ; pi/2
- FSTP ST(1) ; pi/2
- FCOMPP ; 2**(pi)-1=pi/2 ?
- FSTSW AX ; save condition codes
- SAHF ; transfer to CPU flags
- JNES $chk_387DX ; not equal, not C&T
- ADD DH,ndp_38700-ndp_i387; set C&T types
- JMPS $ndp_exit ; done
- $chk_387DX: CMP DH, ndp_i387 ; Intel 387 ?
- JNES $ndp_exit ; no, done. Only want to check i387
- FNINIT ; initialize coprocessor
- FLD1 ; load 1.0
- FCHS ; -1.0
- FXTRACT ; split into mantissa and exponent(0)
- FSTP ST(0) ; pop mantissa
- FXAM ; look at sign of exponent
- FNSTSW AX ; store status word
- AND AH, 2 ; C1 set (negative) on old 387
- FSTP ST(0) ; clear coprocessor stack
- JNZS $ndp_exit ; C1 set, no 387DX
- MOV DH, ndp_i387DX ; set NDP-type to 387DX
- FNINIT ; initialize coprocessor
- FBSTP TBYTE PTR [GDT] ; store BCD indefinite
- CMP BYTE PTR [GDT+7],0C0h; RapidCAD stores C0h, 387DX stores 80h
- JNES $ndp_exit ; no RapidCAD
- MOV DX, ndp_RapidCAD*100H+cpu_RapidCAD; RapidCAD (NDP=21,CPU=14)
- $ndp_exit: LDS SI, ResultPtr ; pointer to result record
- MOV [SI], DX ; save CPU and NDP types
- JMPS $moveeven ; skip over test data for NDP check
-
- $denormal DT 1
- $nan DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 07Fh
- $op1 DB 0F0h, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 03Fh
- $53bit_prec DW 027Fh
-
-
- $moveeven: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $moveeven1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg3 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $moveeven1 ; skip message text
- $dbg3 DB 'About to perform MOVEEVEN memory speed test', 0Dh, 0Ah ,'$'
-
- $moveeven1: MOV AX, DS ; set up segment registers
- MOV ES, AX ; for memory move
- XOR SI, SI ; offset in both segments
- MOV DI, SI ; is zero
- MOV CX, 5000 ; move 5000
- REP MOVSW ; words
- STRT_TIM ; start timer 2
- XOR SI, SI ; offset in both segments
- MOV DI, SI ; is zero
- MOV CX, 5000 ; move 5000
- REP MOVSW ; words
- STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result record
- MOV [SI+6], BX ; save MoveEvenTime
-
-
- $movebyte: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $movebyte1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg5 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $movebyte1 ; skip message text
- $dbg5 DB 'About to perform MOVEBYTE wait state test', 0Dh, 0Ah ,'$'
-
- $movebyte1: MOV AX, DS ; set up segment registers
- MOV ES, AX ; for memory move
- MOV SI, 1 ; offset in source and destination
- MOV DI, SI ; segment is odd
- STRT_TIM ; start timer 2
- MOV CX, 5000 ; move 5000
- REP MOVSB ; bytes
- STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+10], BX ; save MoveByteTime
-
- $movedouble:CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $movedoubl1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg6 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $movedoubl1 ; skip message text
- $dbg6 DB 'About to perform MOVEDOUBLE 386sx test', 0Dh, 0Ah ,'$'
-
- $movedoubl1:LDS SI, ResultPtr ; pointer to result struct
- CMP BYTE PTR [SI],cpu_i386; CPU = iAPX 386 or i486 ?
- JBS $move_ems ; no 386/486
- MOV AX, DS ; load segment registers
- MOV ES, AX ; for memory move
- XOR SI, SI ; offset in source and destination
- MOV DI, SI ; segment is 0
- MOV CX, 5000 ; move 5000
- REP MOVSD ; double words
- STRT_TIM ; start timer 2
- XOR SI, SI ; offset in source and destination
- MOV DI, SI ; segment is 0
- MOV CX, 5000 ; move 5000
- REP MOVSD ; double words
- STOP_TIM ; elapsed time for 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+24], BX ; save MoveDouble-Time
-
- $chk_386sx: CMP BYTE PTR [SI], cpu_i486 ; CPU >= i486 ?
- JAES $move_ems ; yes, no need to test for 386sx
- MOV AX, [SI+6] ; AX = MoveWord-Time
-
- XCHG AX, BX ; AX = MoveDouble-Time,BX=MoveWord-Time
- SUB AX, BX ; MoveDTime - MoveWTime
- ADD AX, AX ; 2 * (MoveDTime - MoveWTime)
- CWD ; compute
- XOR AX, DX ; Abs (2 * (MoveDoubleTime -
- SUB AX, DX ; MoveWordTime))
- CMP BX, AX ; Abs(2*(MoveDTime-MoveWTime))>MoveWTime ?
- ADC WORD PTR [SI], 0 ; CPU type = 386sx if true
- CMP BYTE PTR [SI],cpu_ct38600sx; CPU = C&T 38600sx ?
- JNES $move_ems ; no
- MOV BYTE PTR [SI],cpu_i386sx; POPAD test unreliable for 386sx,
- ; reset to Intel 386 since more likely
-
- $move_ems: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $move_ems1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg7 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $move_ems1 ; skip message text
- $dbg7 DB 'About to perform EMS memory access test', 0Dh, 0Ah ,'$'
-
- $move_ems1: CMP BYTE PTR EMS_Flag, 0 ; does EMS memory exist ?
- JES $move_ext ; no, skip this test
- MOV AH, 43h ; #43, allocate page
- MOV BX, 1 ; one page
- INT 67h ; call EMM-driver (handle in DX)
- MOV AH, 47h ; #47, save page map
- INT 67h ; call EMM-driver
- MOV AH, 44h ; #44, map page
- MOV AL, 0 ; physical page 0
- MOV BX, 0 ; logical page 0
- INT 67h ; call EMM-driver
- LES DI, BufferPtr ; pointer to buffer
- MOV CX, 5000 ; 5000 words
- LDS SI, ResultPtr ; pointer to result struct
- STRT_TIM ; start timer 2
- CMP BYTE PTR [SI], cpu_i386 ; processor 386 or higher?
- LDS SI, EMS_Base ; pointer to EMS page frame
- JAES $is_386 ; is a 386/486
- REP MOVSW ; move words from page frame to buffer
- JMPS $no_386 ; was no 386/486
- $is_386: MOV CX, 4000 ; 4000 double words = 1 EMS page
- REP MOVSD ; move 4000 double words
- $no_386: STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+12], BX ; save MoveEMSTime
- MOV AH, 48h ; #48, restore map
- INT 67h ; call EMM-driver
- MOV AH, 45h ; #45, deallocate page
- INT 67h ; call EMM-driver
-
- $move_ext: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $move_ext1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg8 ; debugging message
- INT 21h ; call DOS, print debugging output
- JMPS $move_ext1 ; skip message text
- $dbg8 DB 'About to perform extended memory access test', 0Dh, 0Ah ,'$'
-
- $move_ext1: CMP BYTE PTR Ext_Flag, 0 ; does extended memory exist ?
- JES $screenfill ; no, skip test
- STRT_TIM ; start timer 2
- XOR AX, AX ; load zero
- MOV BX, SS ; load
- MOV ES, BX ; address
- LEA DI, GDT ; of GDT
- MOV CX, 30h ; 30h bytes long
- REP STOSB ; init with 0
- LEA SI, GDT ; reload address of GDT
- MOV WORD PTR GDT+10H,10000; number of bytes to move
- MOV WORD PTR GDT+12H, 0 ; source:
- MOV BYTE PTR GDT+14H, 10H; 100000H (start of extended memory)
- MOV BYTE PTR GDT+15H, 93H; access rights (read/write)
- MOV WORD PTR GDT+18H,10000; number of bytes to move
- LDS DI, BufferPtr ; load pointer to buffer
- MOV AX, DS ; load pointer into DX:AX
- XOR DX, DX ; linearize
- SHL AX, 1 ; address,
- RCL DX, 1 ; 32 bit result
- SHL AX, 1 ; in
- RCL DX, 1 ; DX:AX
- SHL AX, 1 ;
- RCL DX, 1 ;
- SHL AX, 1 ;
- RCL DX, 1 ;
- ADD AX, DI ;
- ADC DX, 0 ;
- MOV WORD PTR GDT+1AH, AX ; destination:
- MOV BYTE PTR GDT+1CH, DL ; buffer
- MOV BYTE PTR GDT+1DH, 93H; access rights (read/write)
- MOV AH, 87h ; move from extended memory
- MOV CX, 5000 ; move 5000 words from ext to buffer
- INT 15H ; call AT-BIOS
- STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result record
- MOV [SI+14], BX ; save MoveExtTime
-
- $screenfill:CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $screenfil1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg9 ; debugging message
- INT 21h ; call DOS, print string
- JMPS $screenfil1 ; skip message text
- $dbg9 DB 'About to perform SCREENFILL test', 0Dh, 0Ah ,'$'
-
- $screenfil1:LES DI, ScreenPtr ; pointer to start of video memory
- STRT_TIM ; start timer 2
- MOV CX, 5000 ; fill 5000 bytes
- REP STOSB ; of video memory
- STOP_TIM ; elapsed time for timer 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+16], BX ; save ScreenFillTime
-
- $bios_write:CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $bios_writ1 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg4 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $bios_writ1 ; skip message text
- $dbg4 DB 'About to perform BIOS_WRITE screen speed test', 0Dh, 0Ah ,'$'
-
- $bios_writ1:STRT_TIM ; start timer 2
- MOV SI, 20 ; write 20 characters
- $out_loop: MOV AX, 0920h ; #9, write char and attribute
- MOV BX, 0 ; page 0, attribute = blank
- MOV CX, 1 ; write one character at a time
- INT 10H ; call video-BIOS
- DEC SI ; loop over number of chars
- JNZS $out_loop ; until all 20 chars output
- STOP_TIM ; elapsed time of timer 2 in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+8], BX ; save BIOS-WriteTime
-
- $speed87: CMP WORD PTR Debug_Flag,0; debugging output desired ?
- JNZS $speed871 ; no
- MOV AH, 9 ; #9, print string
- PUSH CS ; load
- POP DS ; address of
- MOV DX, OFFSET CS:$dbg10 ; debugging message
- INT 21h ; call DOS, print debugging message
- JMPS $speed871 ; skip message text
- $dbg10 DB 'About to perform NDP speed test', 0Dh, 0Ah ,'$'
-
- $speed871: LDS SI, ResultPtr ; pointer to result struct
- CMP BYTE PTR [SI+1], 1 ; real coprocessor present ?
- JAS $cont_87 ; yes, do coprocessor tests
- JMP $no_fpu ; no, done
- $cont_87: WAIT ; for 8087
- FNINIT ; initialize coprocessor
- WAIT ; for 8087
- FLD1 ; load 1
- STRT_TIM ; start timer 2
- REPT 40 ; do following 40 times:
- WAIT ; needed on 8087
- FSQRT ; compute Sqrt(1)
- ENDM
- FWAIT ; wait until coprocessor done
- STOP_TIM ; time for 40 sqrt computations on BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [SI+20], BX ; save 87-Time
-
- $speed287: FNINIT ; initialize coprocessor
- FLD1 ; load 1
- STRT_TIM ; start timer 2
- REPT 40 ; do following 40 times:
- NOP ; needed on 8087
- FSQRT ; compute Sqrt(1)
- ENDM
- STOP_TIM ; time for 40 sqrt computations in BX
- LDS SI, ResultPtr ; pointer to result struct
- MOV [i287Time], BX ; save 287-Time
- MOV CX, [SI] ; get CPU (CL) and NDP (CH)
- $chk_387sx: CMP CL, cpu_i386sx ; CPU = 80386sx ?
- JES $has_387sx ; is SX
- CMP CL, cpu_ct38600sx ; CPU = 38600sx ?
- JES $has_387sx ; is SX
- CMP CL, cpu_486slc ; CPU = 486SLC ?
- JNES $no_387sx ; no SX
- $has_387sx: INC CH ; set SX versions of 387 coprocessors
- $no_387sx:
- $store_type:MOV [SI], CX ; save CPU and NDP type
- CMP CL, cpu_i286 ; CPU higher than 286 ?
- JBES $no_weitek ; no, Weitek only available for 386/486
- PUSH SI ; save pointer
- PUSH DS ; to result struct
- XOR EAX, EAX ; zero everything in result register
- INT 11h ; do equipment check
- TEST EAX, 01000000h ; check bit 24, set if Weitek present
- POP DS ; restore pointer
- POP SI ; to result struct
- JES $no_weitek ; bit not set, no Weitek
- OR BYTE PTR [SI+1], 80h ; set Weitek flag in coprocessor type
- $no_weitek: FNINIT ; reprogram
- FLDCW [SaveCtrl] ; original NDP control word
-
- $no_fpu: MOV AL, [SystemStat] ; get original system status
- OUT 61h, AL ; and restore it
-
- $ende: POPF ; restore original flag settings
- POP DS ; restore Turbo Pascal's data segment
- MOV SP, BP ; discard local variables
- POP BP ; restore caller's frame pointer
- RET 22 ; return, pop parameters
-
- COMMENT #
- MOV EAX, 0417A000h ; test if early 80386
- MOV ECX, 00000081h ; processor with 32 multiplication bug
- MUL ECX
- CMP EDX, 00000002h
- JNZS $mul_err
- CMP EAX, 0FE7A000h
- JNZS $mul_err
- #
-
- SpeedTest ENDP
-
-
- CODE ENDS
-
- END