sys7.1-doc-wip/OS/StartMgr/ExceptionSupport.a
2019-07-27 22:37:48 +08:00

273 lines
7.0 KiB
Plaintext

;---------------------------------------------------------------------------
; File: ExceptionSupport.a
;
; Contains: This file contains routines which are used to install, de-install
; exception handlers and set interrupt levels.
;
; Written by: Test Engineering and CPU diagnostics
;
; Copyright: © 1990, 1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM2> 5/16/92 kc Roll in Horror changes. Comments follow:
; <2> 1/24/91 CCH Rolled in changes from Scott Smyers.
; <1> 8/31/90 SS first checked in
;
;
;---------------------------------------------------------------------------
include 'STDMacros.a'
include 'USTMacros.a'
IF &TYPE('LUCY')='UNDEFINED' THEN
LUCY EQU 0
ENDIF
IF &TYPE('LINUS')='UNDEFINED' THEN
LINUS EQU 0
ENDIF
IF LUCY OR LINUS THEN
CPU EQU 00
ENDIF
IF &TYPE('CPU')='UNDEFINED' THEN
CPU EQU 20
ENDIF
IF CPU = 20 THEN
MACHINE MC68020
ELSE
MACHINE MC68000
ENDIF
CASE ON
;
; ExceptionSupport.a
;
; When stub is called, address on stack will point to globs field of Exception Info
ExceptionInfo RECORD 0 ;typedef struct ExceptionInfo
;{
; instruction ds.w 1 ; UWORD instruction ; // JSR instruction
; stubAddress ds.l 1 ; void *stubAddress ; // stub address
globs ds.l 1 ; struct CTEGlobals *globs ; // pointer to globals.
handler ds.l 1 ; void (*handler)(void *info) ; // pointer to exception handler.
argPtr ds.l 1 ; void *argPtr ; // pointer to SubtestInfo structure.
oldVector ds.l 1 ; void *oldVector ; // vector from Exception Vector Table which
; // was replaced when this handler was installed.
oldInfoPtr ds.l 1 ; ExceptionInfo *oldInfoPtr ; // pointer from the ExceptionInfoPtrTable which
; // was replaced when this handler was installed.
vectorNumber ds.w 1 ; unsigned short vectorNumber ; //
ENDR ;} ExceptionInfo ;
frameFormat68K0 EQU $10000
frameFormat68K1 EQU $10001
Cpu68000 EQU $00000000 ;Vanilla 68000
CpuLucy EQU $00000002 ;Woodstock NT
CpuLinus EQU $00000003 ;Woodstock SC
CpuWoodstockBit EQU $01 ;Bit 1 set for woodstock
Cpu68020 EQU $00002000 ;Vanilla 68020
;
; int SetInterruptLevel(int newLevel) ;
;
SetInterruptLevel PROC EXPORT
IMPORT GetInterruptLevel
jsr GetInterruptLevel
move.l 4(sp),d1
lsl.w #8,d1
move sr,d2
and.w #$f8ff,d2
or.w d1,d2
move d2,sr
rts
ENDPROC
;
; int GetInterruptLevel(void) ;
;
GetInterruptLevel PROC EXPORT
move sr,d0
lsr.w #8,d0
and.w #$00000007,d0
rts
ENDPROC
;
; void *InstallExceptionVector(void *newHandler, int vecNumber) ;
;
InstallExceptionVector PROC EXPORT
IMPORT FindVectorEntry
move.l 8(sp),d0 ; push new vector.
jsr FindVectorEntry ; go find correct entry
move.l (a0),d0 ; get current vector.
move.l 4(sp),(a0) ; install new vector.
rts
ENDPROC
;
; interrupt void ExceptionHandlerStub(void) ;
;
ExceptionHandlerStub PROC EXPORT
movem.l d0-d3/a0-a1,-(sp) ;save scratch registers.
WITH ExceptionInfo
move.l 24(sp),a1 ;get exceptionInfo ptr
IF CPU <> 00 THEN
@Exception68020
move.w 34(sp),d3 ;get vector/format from exception stack frame
rol.w #4,d3 ;get format nibble
and.l #$000f,d3
ELSE
IF NOT (LUCY OR LINUS) THEN
@Exception68000
move.w vectorNumber(a1),d3 ;have to use vector number from exception info
cmp.w #2,d3 ;If this is bus error or address error,
beq.s @68000Format1
cmp.w #3,d3
bne.s @68000Format0
@68000Format1
move.l #frameFormat68K1,d3 ; use frame format 1
bra.s @CallTheHandler
ENDIF
@ExceptionWoodstock
@68000Format0
move.l #frameFormat68K0,d3 ;Otherwise, frame format 0
ENDIF ;else CPU = 00
@CallTheHandler
move.l argPtr(a1),-(sp) ;push the interrupt argument onto the stack.
IF LUCY OR LINUS THEN
pea 52(sp) ;For Woodstock, have to dig deeper for exception stack frame onto the stack.
ELSE
pea 32(sp) ;push the address of the exception stack frame onto the stack.
ENDIF
move.l d3,-(sp) ;push frame format
move.l globs(a1),-(sp) ;push globals ptr
move.l handler(a1),a0
jsr (a0) ;call the interrupt handler.
add #16,sp ;clean up the stack.
ENDWITH
IF CPU = 00 AND NOT (LUCY OR LINUS) THEN
cmp.l #frameFormat68K1,d3 ;If this is 68000 type 1,
bne.s @ExceptionRte
movem.l (sp)+,d0-d3/a0-a1 ; we have to pop extra stuff before rte
add.l #12,sp ; pop exceptionInfo & Bus/Addr err info
rte ; now we're out of here
ENDIF
@ExceptionRte
movem.l (sp)+,d0-d3/a0-a1 ;restore registers
add.l #4,sp ;pop exceptionInfo pointer
IF NOT (LUCY OR LINUS) THEN
rte ;return from exception.
ELSE
rts ;Woodstock, back to ROM-based ISR
ENDIF
ENDP
;
; FakeExceptionCall(int vectorNumber) ;
;
FakeExceptionCall PROC EXPORT
IMPORT FindVectorEntry,CalcVectorEntry
move.l 4(sp),d0 ;get new vector
IF NOT (LUCY OR LINUS) THEN
jsr FindVectorEntry ;go find correct entry
ELSE
moveq.l #0,a0 ;Find real vector address for Woodstock, this time
jsr CalcVectorEntry
ENDIF
move.l (a0),a0 ;Get Service Routine address
IF CPU <> 00 THEN
move.l 4(sp),d1 ; get vector number
asl.w #2,d1 ; mult. by 4 to get vector offset.
move.w d1,-(sp) ; push the vector offset.
ENDIF
pea @1 ;push the return program counter
move sr,-(sp) ;push the status register.
jmp (a0) ;jump to exception handler.
@1
rts
ENDP
IF LUCY THEN
WoodstockLevel1 EQU $00700020 ;Level 1 ISR addr goes here
WoodstockLevel2 EQU $00700024 ;Level 2 or above ISR addr goes here
ENDIF
IF LINUS THEN
WoodstockLevel1 EQU $0098000C ;Level 1 ISR addr goes here
WoodstockLevel2 EQU $00980010 ;Level 2 or above ISR addr goes here
ENDIF
;
; FindVectorEntry (d0 = vecNumber) ;
; return a0 = vector Address
; CalcVectorEntry (d0 = vecNumber, a0 = vector base) ;
; return a0 = vector Address
FindVectorEntry PROC EXPORT
EXPORT CalcVectorEntry
IF CPU <> 00 THEN
MACHINE MC68020
@Get68020VBase ; 68020, use vbr
movec vbr,a0 ; get base of exception vector table.
ELSEIF NOT (LUCY OR LINUS) THEN
@Get68000VBase ; 68000, assume 0 is ram
move.l #0,a0 ; get base of exception vector table.
ELSE
@GetWoodstockVBase ; Woodstock has RAM-based vector pointers
cmp.w #25,d0
bne.s @10
move.l #WoodstockLevel1,a0 ; Only have access to level 1 and 2 ints
rts
@10 move.l #WoodstockLevel2,a0
rts
ENDIF
CalcVectorEntry
lsl.w #2,d0
lea (a0,d0.w),a0 ; point to vector table entry.
rts
ENDP
;----------------------------------------------------------------------
;
; This routine needs to return a pointer to the CTE globals in d0
;
; Input: a5 - pointer to the UST globals
;
; Output: d0 - pointer to the CTE globals
;
;----------------------------------------------------------------------
CASE ON
GetCTEGlobals PROC EXPORT
move.l USTGlobals.CTEGlobals(a5),d0 ;Get the CTE globals pointer
rts ;and return
ENDPROC