;       SCCSID = @(#)status.asm	6.1 92/01/29
title   status.asm
page    55,132
;************************************************************************
;
;                        S T A T U S . M O D
;                        ===================
;
;       ================================================================
;               INTEL CORPORATION PROPRIETARY INFORMATION
;    This software  is  supplied  under  the  terms  of  a  license
;    agreement  or non-disclosure agreement  with Intel Corporation
;    and  may not be copied nor disclosed except in accordance with
;    the terms of that agreement.
;       =================================================================
;
;       FUNCTION:
;              OPERATION CLUSTER FOR 80387 STATUS REGISTER
;
;       PUBLIC PROCEDURES:
;
;       STCW                    STENV                   POP_FREE
;       INCR_TOP                DECR_TOP                SAVE_STATUS
;       RESTORE_STATUS          CLEAR_P_ERROR           INIT
;       CLEX                    STSW                    LDCW
;       GET_PRECISION           STORE_PRECISION         GET_RND_CONTROL
;       STORE_RND_CONTROL       U_MASKED?               Z_MASKED?
;       D_MASKED?               I_MASKED?               O_MASKED?
;       GET_REG_TAG             AFFINE_INFINITY?        GET_TOP
;       SET_P_ERROR             P_ERROR?                SET_U_ERROR
;       SET_O_ERROR             SET_Z_ERROR             SET_I_ERROR
;       I_ERROR?                D_ERROR?                SET_D_ERROR
;       SET_Z_BIT               CLEAR_Z_BIT             SET_S_BIT
;       CLEAR_S_BIT             SET_A_BIT               CLEAR_A_BITS
;       SET_C_BIT               CLEAR_C_BIT             STORE_REG_TAG
;       SET_I_MASKED?           SET_D_MASKED?           SET_Z_MASKED?
;       CLEAR_COND_BITS
;
;************************************************************************
;
;...OCTOBER 23, 1986...
;
; 12-18-91 mth removed USE16 and itel ifdef's
;--------------------------------------------

                NAME    A?MST
                .386P
                .XLIST
                INCLUDE E80387.INC
                .LIST

EMULATOR_DATA   segment dword public 'FAR_DATA'
        assume  ds:EMULATOR_DATA

;...DEFINE THE 80387 STATUS REGISTER...

A?MSR_DATA      EQU     DWORD PTR SR_MASKS

SR_MASKS        DB      07FH    ; BIT 6 ON FOR D-STEP 8087  05/21/81
SR_CONTROLS     DB      13H
SR_RESERVED1    DW      0       ; reserveds take care of 386 env
SR_ERRORS       DB      0
SR_FLAGS        DB      0       ; BIT 2 OFF FOR SIM286  09/14/83
SR_RESERVED2    DW      0
SR_TAGS         DW      0FFFFH
SR_RESERVED3    DW      0
SR_INSTR_OFFSET DD      0
SR_INSTR_BASE   DW      0
SR_RESERVED4    DW      0
SR_MEM_OFFSET   DD      0
SR_MEM_BASE     DW      0
SR_RESERVED5    DW      0
SR_REGSTACK     DW      40 DUP (0)

SR_INIT_FLG     DB      0CBh      ; anything but means not init'd

public Trap7Handler
Trap7Handler    dd      0
EMULATOR_DATA  ENDS

EMULATOR_DATA_END   segment dword public 'FAR_DATA'
public NPXFPDataSize
NPXFPDataSize   label   byte
EMULATOR_DATA_END ends

                ASSUME  DS:EMULATOR_DATA

EMULATOR_CODE    SEGMENT dword  public  'CODE'
                ASSUME CS:FLAT

;
        PUBLIC  SR_MEM_OFFSET, SR_CONTROLS
        PUBLIC  SR_MEM_BASE
        PUBLIC  A?MSR_DATA
        PUBLIC  SR_REGSTACK, SR_FLAGS
        PUBLIC  SR_MASKS, SR_ERRORS, SR_INSTR_OFFSET, SR_INSTR_BASE, SR_TAGS
        PUBLIC  INCR_TOP, DECR_TOP, SAVE_STATUS, POP_FREE, LDCW, STENV, CLEX
        PUBLIC  STSW, STCW, GET_PRECISION, STORE_PRECISION, GET_RND_CONTROL
        PUBLIC  STORE_RND_CONTROL, U_MASKED?, D_MASKED?, GET_TOP
        PUBLIC  I_MASKED?, O_MASKED?, GET_REG_TAG, AFFINE_INFINITY?
        PUBLIC  SET_P_ERROR, SET_U_ERROR, SET_O_ERROR, INIT, CLEAR_P_ERROR
        PUBLIC  SET_I_ERROR, SET_D_ERROR, I_ERROR?, D_ERROR?, P_ERROR?
        PUBLIC  SET_Z_BIT, CLEAR_Z_BIT, SET_S_BIT, CLEAR_S_BIT, SET_A_BIT
        PUBLIC  CLEAR_COND_BITS, SET_C_BIT, CLEAR_C_BIT, STORE_REG_TAG
        PUBLIC  SET_I_MASKED?, SET_D_MASKED?, SET_Z_MASKED?, CLEAR_A_BIT
        PUBLIC  RESTORE_STATUS, SET_STK_U_ERROR, SET_STK_O_ERROR
        PUBLIC  CORRECT_TAG_WORD, FREE_REG
        PUBLIC  SR_INIT_FLG
        PUBLIC  Trap7Handler

PAGE
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;
;       The routines in this section manipulate the status and control
;       information stored in the 80387 status data segment, A?MSR.
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;  Transfer field group:   GET_PRECISION, STORE_PRECISION, GET_RND_CONTROL
;                 STORE_RND_CONTROL, GET_TOP, GET_REG_TAG, STORE_REG_TAG
;
;  Inputs: The "GET" routines require no input parameters, except for the
;          procedures GET_REG_TAG and STORE_REG_TAG which expect the
;          register number to be in AL and CL, respectively
;          The "STORE" routines input the value to be stored in AL.
;
;  Outputs:  GET_PRECISON returns the 2-bit precision field in DL.
;            All other routines return justified values in AL.
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

IFNDEF USE_MACROS
;;
;; The following procedures have been defined as macros in the e80387.inc
;; file. If the conditional USE_MACROS is defined during assembly, the
;; macros are used instead of calling the procedures. This is an attempt to
;; save the overhead associated with CALL.
;;

GET_PRECISION   PROC

        MOV     DL,PRECISION_MASK       ; load precision field mask
        AND     DL,SR_CONTROLS          ; mask in precision control
        RET

GET_PRECISION   ENDP


STORE_PRECISION PROC

        AND     SR_CONTROLS,NOT PRECISION_MASK ; clear precision
        OR      SR_CONTROLS,AL                 ; store new precision control
        RET

STORE_PRECISION ENDP


GET_RND_CONTROL PROC

        MOV     AL,SR_CONTROLS          ; load control byte
        AND     AL,RND_CONTROL_MASK     ; mask in rounding control
        RET

GET_RND_CONTROL ENDP


STORE_RND_CONTROL PROC

        AND     SR_CONTROLS,NOT RND_CONTROL_MASK ; clear old field
        OR      SR_CONTROLS,AL                   ; store new rounding control
        RET

STORE_RND_CONTROL ENDP


GET_TOP         PROC

        MOV     AL,SR_FLAGS             ; load status flag byte
        AND     AL,TOP_MASK             ; mask in top field
        SHR     AL,3                    ; right justify top field
        RET

GET_TOP         ENDP

ENDIF


GET_REG_TAG     PROC

        MOVZX   EAX,AL          ; form word bit count
        MOV     ECX,EAX         ; store in CX
        SHL     ECX,1           ; bit count = 2 * reg num
        MOV     EBX,ECX         ; else,must examine register
        SHL     EBX,2           ; form index to SR_REGSTACK
        ADD     EBX,ECX                 ; index = 10 * register num
        ADD     EBX,OFFSET SR_REGSTACK  ;       + start of SR_REGSTACK
        MOV     AX,SR_TAGS              ; load tag word
        SHR     AX,CL           ; shift to tag of interest
        AND     AL,EMPTY        ; mask out other tags
        CMP     AL,INV          ; if tag not = 2,
        JNE     GOT_TAG         ; no further decoding needed

        MOV     AX,[EBX + 8]    ; load register exponent
        AND     AX,7FFFH        ; mask off sign bit
        JNZ     CHECK_UNSUPP    ; IF EXPON /= 0,CHECK UNSUPPORTED FORMAT

        MOV     AL,DENORMD      ; if exponent zero,denormal
        RET

CHECK_UNSUPP:
        MOV     EAX,[EBX + 4]   ; GET TOP 32 BITS OF SIGNIFICAND
        TEST    EAX,080000000H  ; IS HIGHEST BIT SET.
        JNZ     CHECK_NAN       ; IF SO,CHECK FOR NAN

        MOV     AL,UNSUPP       ; IF NOT,IT'S AN UNSUPPORTED FORMAT.
        RET

CHECK_NAN:
        AND     EAX,07FFFFFFFH  ; ZERO OUT MOST SIGNIFICANT BIT
        OR      EAX,[EBX]       ; OR BOTTOM 32 BITS INTO TOP 32 BITS.
        MOV     AL,INFINTY      ; TENTATIVELY SET TAG TO INFINITY'S
        JZ      GOT_TAG         ; IF FRACTION IS 0,IT'S INFINITY

        MOV     AL,INV          ; FRACTION IS NON ZERO,SO TAG AS NAN.
GOT_TAG:
        RET

GET_REG_TAG     ENDP
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;       Test status bit group:  U_MASKED?,Z_MASKED?,D_MASKED?,I_MASKED?,
;        O_MASKED?,AFFINE_INFINITY?,P_ERROR?,I_ERROR?,D_ERROR?,
;        SET_I_MASKED?,SET_D_MASKED?
;
;       Inputs:  No input values are required.
;
;       Outputs:  All boolean function return the complemented bit value
;                 in the ZF.  (Test with JZ on bit = 0.)
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
U_MASKED?       PROC

        TEST    SR_MASKS,UNDERFLOW_MASK         ; test the U mask
        RET

U_MASKED?       ENDP


SET_D_MASKED?   PROC

        CALL    SET_D_ERROR                     ; set the D error
D_MASKED?:
        TEST    SR_MASKS,DENORM_MASK            ; test the D mask
        RET

SET_D_MASKED?   ENDP


SET_I_MASKED?   PROC

        CALL    SET_I_ERROR                     ; set the I error
I_MASKED?:
        TEST    SR_MASKS,INVALID_MASK           ; test the I mask
        RET

SET_I_MASKED?   ENDP


O_MASKED?       PROC

        TEST    SR_MASKS,OVERFLOW_MASK          ; test the O mask
        RET

O_MASKED?       ENDP


AFFINE_INFINITY? PROC

        TEST    SR_CONTROLS,INFINITY_CONTROL_MASK  ; test IC
        RET

AFFINE_INFINITY? ENDP


P_ERROR?        PROC

        TEST    SR_ERRORS,INEXACT_MASK          ; test the P error
        RET

P_ERROR?        ENDP


I_ERROR?        PROC

        TEST    SR_ERRORS,INVALID_MASK          ; test the I error
        RET

I_ERROR?        ENDP


D_ERROR?        PROC

        TEST    SR_ERRORS,DENORM_MASK           ; test the D error
        RET

D_ERROR?        ENDP


;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;       Set and reset bit group:  SET_P_ERROR,SET_U_ERROR,SET_O_ERROR
;        SET_Z_MASKED?,SET_I_ERROR,SET_D_ERROR,CLEAR_S_BIT,CLEAR_Z_BIT
;        SET_S_BIT,SET_Z_BIT,SET_A_BIT,CLEAR_A_BIT,SET_C_BIT,CLEAR_C_BIT
;        CLEAR_COND_BITS,CLEAR_P_ERROR,SET_STK_U_ERROR,SET_STK_O_ERROR
;
;       Inputs:  No input values are required.
;
;       Outputs:  All procedures set or reset the indicated status bit
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
SET_STK_U_ERROR         PROC

        OR      SR_ERRORS,INVALID_MASK + ZERO_MASK
        AND     SR_FLAGS,NOT A_MASK                     ; clear the A-bit
        RET

SET_STK_U_ERROR         ENDP


SET_STK_O_ERROR         PROC

        OR      SR_ERRORS,INVALID_MASK + ZERO_MASK
        OR      SR_FLAGS,A_MASK                         ; set the A-bit
        RET

SET_STK_O_ERROR         ENDP


SET_P_ERROR     PROC

        OR      SR_ERRORS,INEXACT_MASK                  ; set the P-error
        RET

SET_P_ERROR     ENDP


SET_U_ERROR     PROC

        OR      SR_ERRORS,UNDERFLOW_MASK                ; set the U-error
        RET

SET_U_ERROR     ENDP


SET_O_ERROR     PROC

        OR      SR_ERRORS,OVERFLOW_MASK                 ; set the O-error
        RET

SET_O_ERROR     ENDP


SET_I_ERROR     PROC

        OR      SR_ERRORS,INVALID_MASK                  ; set the I-error
        RET

SET_I_ERROR     ENDP


SET_D_ERROR     PROC

        OR      SR_ERRORS,DENORM_MASK                   ; set the D-error
        RET

SET_D_ERROR     ENDP


SET_Z_MASKED?   PROC

        OR      SR_ERRORS,ZERO_DIVIDE_MASK              ; set the Z-error
        TEST    SR_MASKS,ZERO_DIVIDE_MASK               ; test the Z mask
        RET

SET_Z_MASKED?   ENDP


SET_S_BIT       PROC

        OR      SR_FLAGS,SIGN_MASK                      ; set the S-bit
        RET

SET_S_BIT       ENDP


SET_Z_BIT       PROC

        OR      SR_FLAGS,ZERO_MASK                      ; set the Z-bit
        RET

SET_Z_BIT       ENDP


SET_A_BIT       PROC

        OR      SR_FLAGS,A_MASK                         ; set the A-bit
        RET

SET_A_BIT       ENDP


SET_C_BIT       PROC

        OR      SR_FLAGS,C_MASK                         ; set the C-bit
        RET

SET_C_BIT       ENDP


CLEAR_S_BIT     PROC

        AND     SR_FLAGS,NOT SIGN_MASK                  ; clear the S-bit
        RET

CLEAR_S_BIT     ENDP


CLEAR_Z_BIT     PROC

        AND     SR_FLAGS,NOT ZERO_MASK                  ; clear the Z-bit
        RET

CLEAR_Z_BIT     ENDP


CLEAR_A_BIT     PROC

        AND     SR_FLAGS,NOT A_MASK                     ; clear the A-bit
        RET

CLEAR_A_BIT     ENDP


CLEAR_COND_BITS PROC

        AND     SR_FLAGS,NOT (C_MASK + ZERO_MASK + SIGN_MASK + A_MASK)

        RET                     ; clear all condition bits

CLEAR_COND_BITS ENDP


CLEAR_C_BIT     PROC

        AND     SR_FLAGS,NOT C_MASK                     ; clear the C-bit
        RET

CLEAR_C_BIT     ENDP


CLEAR_P_ERROR   PROC

        AND     SR_ERRORS,NOT INEXACT_MASK              ; clear the P-error
        RET

CLEAR_P_ERROR   ENDP


PAGE
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                       POP_FREE:
;   FUNCTION:
;             POPS THE STACK AND/OR FREES THE REGISTER(S) AS REQUIRED
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
POP_FREE        PROC

        CALL    I_MASKED?               ; IS INVALID MASKED?
        JNZ     CHECK_OP1               ; IF SO,FORGET ERROR

        CALL    I_ERROR?                ; CHECK FOR I-ERROR
        JNZ     COMMON_RETURN           ; IF ERROR, DON'T POP

FREE_REG:

CHECK_OP1:

        MOV     AL,[EBP].OP1_USE_UP     ; POP OR FREE OP1
        CALL    PROCESS_USE_UP
        MOV     AL,[EBP].OP2_USE_UP     ; POP OR FREE OP2

PROCESS_USE_UP:

        CMP     AL,POP_STACK            ; IS IT A POP_STACK?
        JE      POP_IT                  ; YES,PROCESS IT

        XOR     AL,FREE                 ; NO,IS IT FREE REG?
        JNZ     EXIT_PROCESS            ; NO,DONE WITH USE_UP

        CALL    GET_TOP                 ; YES,GET TOP POINTER
        ADD     AL,[EBP].REG_NUM        ; CONVERT RELATIVE NUM
        AND     AL,07H                  ;  TO ABSOLUTE REG NUM

EMPTY_REG_TAG:

        MOV     CL,AL                   ; CL = REG NUMBER
        MOV     AL,EMPTY                ; AL = NEW TAG VALUE

STORE_REG_TAG:

        SHL     CL,1                    ; bit count = 2 * reg num
        ROR     SR_TAGS,CL                      ; rotate tag to low bits
        AND     BYTE PTR SR_TAGS,NOT EMPTY      ; clear old reg num tag
        AND     AL,EMPTY                        ; clear bits 2-7 of new tag
        OR      BYTE PTR SR_TAGS,AL     ; store new reg num tag and
        ROL     SR_TAGS,CL              ; rotate the tag word back

EXIT_PROCESS:

        RET

POP_IT:

        CALL    GET_TOP                 ; POP THE STACK ONCE

;------------------------------------------------------------------
; THE FOLLOWING SIX INSTRUCTIONS HAVE BEEN COMMENTED OUT TO PREVENT
; AN INVALID OPERATION FROM BEING SIGNALED WHEN THE '87 TOS IS SUBJECT
; TO A FREEP ST(i) (*6 in the 80387 T-SPEC).  IN OTHER WORDS,IT WILL
; BE O.K. TO FREE ST(0) AND DECREMENT STACKPOINTER,SO IT WILL ALSO BE
; O.K. TO FREE AN ALREADY EMPTY ST(0).
;       CALL    GET_REG_TAG     ; GET REGISTER TAG
;       CMP     AL,EMPTY        ; IS THE TOP EMPTY?
;       JNE     POP_OK          ; NO,STACK MAY BE POPPED
;       CALL    SET_I_MASKED?   ; YES,STACK ERROR
;       JZ      EXIT_PROCESS    ; ABORT IF UNMASKED
;POP_OK:
;       CALL    GET_TOP
;-----------------------

        CALL    EMPTY_REG_TAG   ;SET TAG OF TOP EMPTY

POP_FREE        ENDP            ; ENTER INCR_TOP

PAGE
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                      INCR_TOP:
;     FUNCTION:
;              INCREMENTS STACK POINTER
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
INCR_TOP        PROC

        MOV     CL,08H                  ; LOAD INCREMENT TOP CONSTANT
        JMP     SHORT ADJUST_TOP        ; MERGE WITH DECR_TOP

INCR_TOP        ENDP

;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                  DECR_TOP:
;       FUNCTION:
;                DECREMENTS STACK POINTER
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
DECR_TOP        PROC

        MOV     CL,38H          ; LOAD DECREMENT TOP CONSTANT

ADJUST_TOP:

        MOV     AL,SR_FLAGS     ; GET OLD TOP
        AND     AL,TOP_MASK
        XOR     SR_FLAGS,AL     ; CLEAR OLD TOP FIELD
        ADD     AL,CL           ; INCREMENT/DECREMENT TOP
        AND     AL,TOP_MASK     ; MASK OFF BITS 6-7
        OR      SR_FLAGS,AL     ; STORE NEW TOP FIELD

COMMON_RETURN:
        RET

DECR_TOP        ENDP

PAGE
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                           RESTORE_STATUS:
;       FUNCTION:
;                IMPLEMENTS THE 80387 LDENV INSTRUCTION.
;                RESTORES STATUS REGISTER FROM MEMORY.
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
RESTORE_STATUS  PROC

        PUSH    DS
        POP     ES                      ; LOAD DESTINATION BASE

                                        ; load environment pointer
        LDS     ESI,FWORD PTR [EBP].MEM_OPERAND_POINTER

        MOV     EDI,OFFSET  SR_MASKS    ; LOAD DEST OFFSET
        MOV     ECX,0007H               ; LOAD ENVIRONMENT FROM MEMORY
        CMP     [EBP].OPRND_SIZ32,1     ;is it a 32 bit operand
        JNE     RESTORE_STATUS16        ;no restore 16 bit status

        REP     MOVSD                   ; MOVE ENVIRONMENT TO A?MSR
        PUSH    ES                      ; reload A?MSR base
        POP     DS
        OR      SR_MASKS,40H            ; SET STACK MASK
        JMP     CORRECT_TAG_WORD

RESTORE_STATUS16:                       ;16 bit protected mode
        MOVSW                           ; mov words
        INC     EDI
        INC     EDI
        LOOP    RESTORE_STATUS16

        PUSH    ES                      ; reload A?MSR base
        POP     DS
        OR      SR_MASKS,40H            ; SET STACK MASK

CORRECT_TAG_WORD:
        MOV     ECX,8
        XOR     EBX,EBX

SET_TAGS_LOOP:          ;LOOPING THROUGH PHYSICAL LOCATIONS OF 0-7 REGS

        MOV     EAX,10
        MUL     EBX
        MOV     ESI,OFFSET SR_REGSTACK
        ADD     ESI,EAX
        MOV     EAX,00000003H
        AND     EAX,DWORD PTR  SR_TAGS
        CMP     EAX,3
        JE      LOOP_BACK

        MOV     AX,[ESI+8]
        AND     AX,7FFFH                        ; STRIP OFF SIGN BIT
        JZ      EXPON_ZERO                      ; BRANCH IF EXPONENT 0

        TEST    BYTE PTR [ESI+7],80H
        JNZ     MAX_EXPON?

        MOV     DL,2                            ; WE HAVE AN
        JMP     SHORT   SET_TAG                 ; UNSUPPORTED FORMAT

MAX_EXPON?:
        CMP     AX,7FFFH                        ; CHECK FOR INVALID
        JE      NOT_VALIDX                      ; OR INFINITY

        MOV     DL,0                            ; OPERAND IS VALID
        JMP     SHORT   SET_TAG

NOT_VALIDX:
        MOV     DL,2
        JMP     SHORT   SET_TAG

EXPON_ZERO:
        MOV     EAX,DWORD PTR [ESI+4]
        OR      EAX,DWORD PTR [ESI]
        MOV     DL,1                            ; SET TAG TO SPECIAL
        JZ      SET_TAG                         ; IF NUMBER IS +/- 0

        MOV     DL,2                            ; SET TAG TO DENORMD

SET_TAG:
        AND     BYTE PTR SR_TAGS,NOT EMPTY      ; clear old reg num tag
        OR      BYTE PTR SR_TAGS,DL             ; store new reg num tag and

LOOP_BACK:

        ROR     SR_TAGS,2                       ;  GET NEXT TWO BITS
        INC     EBX
        LOOP    SET_TAGS_LOOP

        RET

RESTORE_STATUS  ENDP

;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                                INIT:
;   FUNCTION:
;            IMPLEMENTS 80387 INIT INSTRUCTION.  INTIALIZES
;            STATUS REGISTER INCLUDING MODE WORD AND ERROR MASK.
;
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
INIT            PROC

        MOV     AX,137FH                ; initialize mode word
        MOV     WORD PTR SR_MASKS,AX
        MOV     AX,0FFFFH               ; AX = 0FFFFH
        MOV     SR_TAGS,AX              ; register tags = empty
        INC     AX      ; AX = 0000H
        MOV     WORD PTR SR_ERRORS,AX   ; clear the error flags

        MOV     AL,0CBH                 ; SET psudo init flag byte
        MOV     SR_INIT_FLG,AL

        RET
INIT            ENDP

;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                                LDCW:
;   FUNCTION:
;            IMPLEMENTS 80387 LDCW INSTRUCTION.  80387 CONTROL WORD
;            LOADED (FROM MEMORY LOCATION SPECIFIED IN INSTRUCTION).
;
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
LDCW            PROC

        LES     EBX,FWORD PTR [EBP].MEM_OPERAND_POINTER ;GET NEW MODE WORD
        MOV     AX,ES:[EBX]
        OR      AX,40H                  ; SET STACK MASK
        MOV     WORD PTR SR_MASKS,AX    ; STORE IN STATUS REG
        RET
LDCW            ENDP

;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                                STENV:
;   FUNCTION:
;            IMPLEMENTS 80387 FSTENV INSTRUCTION.  80387 ENVIRONMEMT
;            STORED (IN MEMORY LOCATION SPECIFIED IN THE INSTRUCTION).
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
STENV           PROC

        CALL    SAVE_STATUS             ; store status to memory
        OR      SR_MASKS,07FH           ; SET ALL INDIVIDUAL MASKS
        RET

STENV           ENDP

;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                                CLEX:
;   FUNCTION:
;            CLEARS ALL 80387 ERRORS SET IN STATUS REGISTER
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CLEX            PROC

        MOV     SR_ERRORS,0             ; clear error byte
        RET

CLEX            ENDP

;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                                STSW
;   FUNCTION:
;            STORES STATUS WORD IN MEMORY LOCATION.  (I.E.,IMPLEMENTS
;            FSTSW INSTRUCTION.)  ALSO IMPLEMENTS 'FSTSW AX'.
;
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
STSW            PROC

        MOV     AL,[EBP].OP2_LOCATION   ; load OP2 location
        CMP     AL,REG                  ; is this FSTSW AX?
        MOV     AX,WORD PTR SR_ERRORS   ; get status word
        JE      STSW_AX                 ; branch on FSTSW AX

STORE_WORD:

        LES     EBX,FWORD PTR [EBP].MEM_OPERAND_POINTER

        MOV     ES:[EBX],AX             ; store status to memory
        RET

STSW_AX:
        MOV     WORD PTR [EBP].SAVED_EAX,AX     ; store into register AX
        RET
STSW            ENDP

;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                               STCW:
;   FUNCTION:
;            STORES CONTROL WORD IN MEMORY LOCATION. (I.E.,IMPLEMENTS
;            FSTCW INSTRUCTION.)
;
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
STCW            PROC

        MOV     AX,WORD PTR SR_MASKS    ;GET CONTROL WORD
        AND     AX,1F7FH
        OR      AX,1040H                ;set/reset reserved bits
        JMP     STORE_WORD              ;STORE IT

STCW            ENDP

;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
;                               SAVE_STATUS:
;   FUNCTION:
;            SAVES STATUS REGISTER TO LOCATION SPECIFIED BY
;            MEMORY OPERAND POINTER(IN ES:DI)
;
;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
SAVE_STATUS     PROC

        AND     WORD PTR SR_MASKS,1F7FH
        OR      WORD PTR SR_MASKS,1040H         ;set/reset reserved bits
        MOV     ESI,OFFSET  SR_MASKS            ; load source offset

                                                ; load destination pointer
        LES     EDI,FWORD PTR [EBP].MEM_OPERAND_POINTER
        MOV     ECX,0007H
        CMP     [EBP].OPRND_SIZ32,1
        JNE     SAVE_STATUS16

        REP     MOVSD                           ; store 80387 state to memory
        RET

SAVE_STATUS16:                                  ;16 bit protected mode
        MOVSW                                   ; mov words
        INC     ESI
        INC     ESI
        LOOP    SAVE_STATUS16
        RET

SAVE_STATUS     ENDP

EMULATOR_CODE ENDS

        END
