turbo-pascal-assembly

Test for presence and identify 8087/80287/80387 FPU

This routine, called durining initialization, will attempt to detect and identify the system’s FPU.

SYS074C: MOV BX,FPU.StatusWord

Get pointer to Status Word of FPU Data.

SYS074F: XOR DI,DI
SYS0751: MOV ES,[PrefixSeg]
SYS0755: ES:
SYS0756: MOV ES,[PrefixSeg:002C]

Set ES:DI to the address of DOS environment in the PrefixSeg:002C.

SYS075A: MOV CX,7FFF
SYS075D: CLD

Prepare to search the entire segment (64K bytes ~ 32K words).

SYS075E: ES:
SYS075F: MOV AX,[DI]
SYS0761: OR AL,AL
SYS0763: JZ 0780

Check if we have reached the end of the environment string.

SYS0765: CMP AX,3738

Check if the characters in ES:DI are ‘87’.

SYS0768: JNZ 077A
SYS076A: ES:
SYS076B: MOV AX,[DI+02]
SYS076E: CMP AL,3D
SYS0770: JNZ 077A

Check if the next character is ‘=’ (3Dh).

SYS0772: AND AH,DF
SYS0775: CMP AH,59
SYS0778: JMP 079D

Check if the environment string contains the cahracters ‘87=Y’.

SYS077A: XOR AX,AX
SYS077C: REPNZ
SYS077D: SCASB
SYS077E: JZ 075E

Continue searching through the environment variables.

SYS0780: XOR AX,AX
SYS0782: PUSH SP
SYS0783: POP DX
SYS0784: CMP DX,SP
SYS0786: JNZ 078A

Check stack?

SYS0788: OUT F0,AL

Clear FPU Busy Latch (Port F0) by writing 00h to it.

SYS078A: FINIT
SYS078C: MOV [BX],AX

Intializes:

SYS078E: FSTCW [BX]

Get Control Word and Store in [BX].

SYS0790: MOV CX,0014
SYS0793: LOOP 0793

Delay?

SYS0795: MOV AX,[BX]
SYS0797: AND AX,0F3F
SYS079A: CMP AX,033F

Retrieve Control Word from [BX] then check if:

SYS079D: MOV DX,1330
SYS07A0: MOV AL,00

Set defaults:

SYS07A2: JNZ 07D1

Exit if Control Word does not match expected setting, i.e. No FPU.

SYS07A4: PUSH SP
SYS07A5: POP AX
SYS07A6: CMP AX,SP
SYS07A8: MOV AL,01
SYS07AA: JNZ 07D1

If stack behavior is different then:

SYS07AC: WAIT
SYS07AD: FINIT

Initialize FPU again.

SYS07AF: WAIT
SYS07B0: FLD1

Load 1.0 onto the stack.

SYS07B2: WAIT
SYS07B3: FLDZ

Load 0.0 onto the stack.

SYS07B5: WAIT
SYS07B6: FDIVP ST(1),ST

Divide ST(1) = ST(1) / ST = 1.0 / 0.0, then pop off the stack.

SYS07B8: WAIT
SYS07B9: FLD ST(0)

Push ST(0) onto the stack.

SYS07BB: WAIT
SYS07BC: FCHS

Change the sign of ST(0)

SYS07BE: WAIT
SYS07BF: FCOMPP ST(1)

Compare ST(0) and ST(1).

SYS07C1: WAIT
SYS07C2: FSTSW [BX]

Store Status Word in [BX] ([FPU.StatusWord]).

SYS07C4: WAIT
SYS07C5: MOV AX,[BX]

Copy Status Word to AX.

SYS07C7: SAHF

Store AH to Flags. At this point AH contains the upper-8 bits of the Status Word:

Bit Name Description Flag
07 B Busy SF
06 C3 Condition Code 3 ZF
05 ST Stack Top Pointer 0
04   Stack Top Pointer AF
03   Stack Top Pointer 0
02 C2 Condition Code 2 PF
01 C1 Condition Code 1 1
00 C0 Condition Code 0 CF

SAHF transfers its value into the Flags register using the mapping above.

SYS07C8: MOV AL,02
SYS07CA: JZ 07D1

If ZF is set (= 1) then FPU is a 80287 (AL = 02) because it does not distinguish between a postive infinity and a negative infinity.

SYS07CC: MOV DX,1332
SYS07CF: MOV AL,03

Set:

SYS07D1: MOV [Test8087],AL
SYS07D4: MOV [FPU.ControlWord],DX
SYS07D8: RET

Set FPU type and Control Word and return.

Because it returns with a NEAR RET, it can only be called from within the system library.

See also: Test8087 (Variable), 8087/80287/80387 Control Word, 8087/80287/80387 Status Word, 8087/80287/80387 x87 FPU Evironment, 8087/80287/80387 Temporary data, or go back