/*static char *SCCSID = "@(#)except.h	6.2 91/03/29";*/
/*      SCCSID = @(#)except.h	6.2 91/03/29 */

/*
 *      IBM/Microsoft Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1989
 *      Copyright (c) Microsoft Corporation 1987, 1989
 *
 *      All Rights Reserved
 */

//      Protected Mode Exception definitions

#define EXCDIVZ         0x00            // Divide-by-zero exception     ***
#define EXCDIVZI        0
#define EXCSSI          0x01            // Single Step interrupt
#define EXCNMI          0x02            // NMI interrupt
#define EXCBP           0x03            // Breakpoint Interrupt
#define EXCOV           0x04            // Overflow exception (INTO)    ***
#define EXCOVI          1
#define EXCBOUND        0x05            // Bound exception              ***
#define EXCBOUNDI       2
#define EXCOP           0x06            // Invalid opcode               ***
#define EXCOPI          3
#define EXCNOFP         0x07            // Processor extension not available***
#define EXCNOFPI        4
#define EXCDED          0x08            // Double exception detected
#define EXCFPOVR        0x09            // Processor extension segment overrun
#define EXCITSS         0x0A            // Invalid TSS
#define EXCSNP          0x0B            // Segment not present
#define EXCSSONP        0x0C            // Stack segment overrun or not present
#define EXCGP           0x0D            // General Protection
#define EXCPG           0x0E            // Page Fault
#define EXCFPERR        0x10            // Processor extension error    ***
#define EXCFPERRI       5
#define EXCALIGN        0x11            // Alignment check trap (386)
#define EXCGENERIC      0x12            // Reserved Intel traps handled here
#define EXCPVW          0x20            // Perfview software interrupt
#define EXCDOS          0x21            // Int 21h (DOS API emulation)
#define EXCDOSI         6

#define EXCSW           0xFFFF          // Software generated exception

#define EXCUSR          7               //  Number of user exceptions
/* ASM

;*      SetTrap - make a GP fault handler for this thread
;
;       SetTrap's handler MUST be in the same code segment that
;       the fault may occur in.
;
;       (sel) is saved away in "TSDselFault" for "TrapExit" which
;       passes it to be displayed as the error code.  If (sel) is
;       blank, "TSDselFault" is not modified.
;
;       ENTRY:  <handler> is the near proc to execute in case of a GP fault.
;               <sel> is the user selector that we are checking (optional).
;               <currtsdreg> is a reg with [CurrTSD] already in it (optional).
;               <trashreg> is a spare index reg to set to [CurrTSD] (optional).
;
;       EXIT:   TSDpfnFault  = handler
;               TSDselFault = sel, if not blank.
;               Previous value of BP, TSDpfnFault and TSDselFault saved on stack
;
;       USES:   SP
;       WARNING: SHOULD BE FOLLOWED BY ClrTrap

SetTrap macro   handler,sel,currtsdreg,trashreg
        .errb   <handler>                       ; handler required.
                .386
                push    bp
        ifnb    <currtsdreg>
                push    ss:[currtsdreg].TSDselFault
                push    ss:[currtsdreg].TSDpfnFault
                mov     ss:[currtsdreg].TSDpfnFault,handler
                ifnb    <sel>
                        mov     ss:[currtsdreg].TSDselFault,sel
                endif
        else
                ifb     <trashreg>
                        mov     bp,ss:[TKOPTDA].CurrTSD
                        push    [bp].TSDselFault
                        push    [bp].TSDpfnFault
                        mov     [bp].TSDpfnFault,handler
                        ifnb    <sel>
                                mov     [bp].TSDselFault,sel
                        endif
                        mov     bp,word ptr ss:[esp+6] ;; Restore BP
                else
                        mov     trashreg,ss:[TKOPTDA].CurrTSD
                        push    ss:[trashreg].TSDselFault
                        push    ss:[trashreg].TSDpfnFault
                        mov     ss:[trashreg].TSDpfnFault,handler
                        ifnb    <sel>
                                mov     ss:[trashreg].TSDselFault,sel
                        endif
                endif
        endif
        CpuMode reset
        endm


;*      PushTrap - save current GP fault handler.
;
;       PushTrap saves the current GP fault handler information on the
;       stack.
;
;       PushTrap also will clear the local GPfault handler if the
;       second argument is 'CLEAR'. If a general register is passed in the
;       3rd argument the GPF handler offset gotten (for NotPresentFault use).
;
;       THIS MACRO MODIFIES SP, AND MUST BE ACCOMPANIED WITH PopTrap.
;
;       stack frame after macro :
;               TSDselFault
;               TSDpfnFault.LowWord     <-- final SS:SP
;
;       ENTRY:  SS 'assume'd to be TASKAREA.
;
;       EXIT:   Trap information (3 words) Pushed on stack
;
;       USES:   SP, reg (if specified)

PushTrap macro  clearflag,reg
    .386p
    ifnb <clearflag>
        ifdifi <clearflag>,<CLEAR>
            %out Bad clearflag <clearflag> in PushTrap
            .err
        endif
    endif
    ifb <reg>
        push    bp                      ;; Save BP
        ifdef   TKOPTDA
            mov    bp,ss:[TKOPTDA].CurrTSD ;; (SS:BP) = TSD pointer
        else
            mov    bp,ss:CurrTSD
        endif
        push    [bp].TSDpfnFault        ;; push the handler
        ifnb <clearflag>
            ifidni <clearflag>,<CLEAR>
                mov     [bp].TSDpfnFault,0 ;; clear the handler
            else
                %out Bad clearflag <clearflag> in PushTrap
                .err
            endif
        endif
        mov     bp,[bp].TSDselFault     ;; (BP) = selector
        xchg    bp,[esp+4]              ;; (BP) = original, sel on stack
    else
        ifdef   TKOPTDA
            mov    reg,ss:[TKOPTDA].CurrTSD ;; (SS:reg) = TSD pointer
        else
            mov    reg,ss:CurrTSD
        endif
        push    ss:[reg].TSDselFault    ;; Push selector
        push    ss:[reg].TSDpfnFault    ;; push the handler
        ifnb <clearflag>
            mov     ss:[reg].TSDpfnFault,0 ;; clear the handler
        endif
    endif
    CpuMode reset
    endm


;*      PopTrap - restore saved GP fault handler.
;
;       PopTrap complements PushTrap.  TSDselFault, TSDpfnFault and
;       (SP) are all restored.
;
;       stack frame before macro :
;               TSDselFault
;               TSDpfnFault.LowWord     <-- initial SS:SP
;
;       ENTRY:  (SS:SP) -> Pushed Trap Information
;               SS 'assume'd to be TASKAREA.
;
;       EXIT:   Trap information Popped from stack
;               Old GPFault handler re-installed.
;
;       USES:   SP, reg (if specified)

PopTrap macro   reg
        .386p
        ifb     <reg>
                push    word ptr [esp+4]        ;; Copy old selector value
                mov     [esp+6],bp              ;; Save BP on stack
                ifdef   TKOPTDA
                        mov     bp,ss:[TKOPTDA].CurrTSD
                else
                        mov     bp,ss:CurrTSD   ;; (SS:BP) = TSD pointer
                endif
                pop     [bp].TSDselFault        ;; Restore selector
                pop     [bp].TSDpfnFault        ;; Restore handler
                pop     bp                      ;; Restore BP
        else
                ifdef   TKOPTDA
                        mov     reg,ss:[TKOPTDA].CurrTSD
                else
                        mov     reg,ss:CurrTSD  ;; (SS:reg) = TSD pointer
                endif
                pop     ss:[reg].TSDpfnFault    ;; Restore handler
                pop     ss:[reg].TSDselFault    ;; Restore selector
        endif
        CpuMode reset
        endm


;*      ClrTrap - reset GP fault handler to be the previous system handler
;
;       ENTRY:  (SS) = TASKAREA.
;               <currtsdreg> is a reg with [CurrTSD] already in it (optional).
;
;       EXIT:   TSDpfnFault, TSDselFault and BP restored to their pre-SetTrap
;               values
;
;       USES:   SP, BP
;       WARNING: SHOULD BE PRECEDED BY SetTrap

ClrTrap macro   currtsdreg
        .386
        ifnb    <currtsdreg>
                pop     ss:[currtsdreg].TSDpfnFault
                pop     ss:[currtsdreg].TSDselFault
        else
                mov     bp,ss:[TKOPTDA].CurrTSD
                pop     ss:[bp].TSDpfnFault
                pop     ss:[bp].TSDselFault
        endif
        pop     bp
        CpuMode reset
        endm
*/

extern void TRAPProcessFatalFault(unsigned long, unsigned long);
extern unsigned long TRAPCheckExcept16Handler(unsigned long);
extern unsigned long TRAPArmExcept16Handler(unsigned long);
extern void TRAPGetCR0CR2(unsigned long *, unsigned long *);
extern void TRAPSetCR2(unsigned long);
