68k exception handling: Difference between revisions
Jump to navigation
Jump to search
m (moved 68k error handling to 68k exception handling) |
No edit summary |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
[[File:Unibios_exc.png|thumb| The [[Universe BIOS]] provides some exception handling.]] | |||
A [[68k]] program may produce exceptions, often caused by bugs. For debugging, an exception handler can be of great use. | |||
Some games were published with their exception handler, while some others just reset the system. | |||
=Generic exception handler= | |||
Allocate a longword variable called "PCERROR". Make the appropriate vectors point to the related routines below. | |||
==Divide by zero/Illegal instruction== | |||
Cause: See [[68k vector table]]. | |||
6 bytes stack frame: 0:SR.w, 2:PC.l | 6 bytes stack frame: 0:SR.w, 2:PC.l | ||
< | <syntaxhighlight> | ||
ErrDivZero: | ErrDivZero: | ||
move.l 2(a7),PCERROR | move.l 2(a7),PCERROR ; Store PC from stack frame | ||
movem.l d0-d7/a0-a6,-(a7) | movem.l d0-d7/a0-a6,-(a7) ; Store registers | ||
lea ERR_DIVZERO,a0 | lea ERR_DIVZERO,a0 | ||
jmp DispErr | jmp DispErr | ||
</ | </syntaxhighlight> | ||
==Address error/Bus error== | |||
Cause: See [[68k vector table]]. | |||
14 bytes stack frame: 0:R/W.w, 2:Access address.l, 6:Instruction.l, 8:SR.w, 10:PC.l | 14 bytes stack frame: 0:R/W.w, 2:Access address.l, 6:Instruction.l, 8:SR.w, 10:PC.l | ||
< | <syntaxhighlight> | ||
ErrAddr: | ErrAddr: | ||
move.l 10(a7),PCERROR | move.l 10(a7),PCERROR ; Store PC from stack frame | ||
movem.l d0-d7/a0-a6,-(a7) | movem.l d0-d7/a0-a6,-(a7) ; Store registers | ||
lea ERR_ADDR,a0 | lea ERR_ADDR,a0 | ||
jmp DispErr | jmp DispErr | ||
</ | </syntaxhighlight> | ||
== | ==Display for debug== | ||
[[File:Exceptionillegal.png|frame|Exception screen showing the PC where it was raised: Always better than a quiet reset !]] | |||
Don't forget to mask out all interrupts as soon as an exception is raised: | Don't forget to mask out all interrupts as soon as an exception is raised: | ||
< | <syntaxhighlight> | ||
ori.w #$0700,sr | ori.w #$0700,sr | ||
</ | </syntaxhighlight> | ||
All register values can be retrieved from the previous MOVEMs and displayed on the [[fix layer]]: | All register values can be retrieved from the previous MOVEMs and displayed on the [[fix layer]]: | ||
< | <syntaxhighlight> | ||
;D0: 32bit value | ;D0: 32bit value to display | ||
;VRAM address needs to be set before | ;VRAM address needs to be set before call | ||
Write32bit: | Write32bit: | ||
move.w # | move.w #32,VRAM_MOD ; Write char-by-char | ||
move. | move.b #8,d7 | ||
.writerlp: | .writerlp: | ||
move.b d0,REG_DIPSW ; | move.b d0,REG_DIPSW ; Kick watchdog | ||
rol.l #4,d0 ; BCDEFGHA | |||
move.b d0,d1 | |||
andi.w #$F,d1 ; xxxx000A | |||
jsr .hexshift | jsr .hexshift | ||
add.w #ASCIISTART,d1 | |||
ori.w #$F000, | ori.w #$F000,d1 ; Palette $F | ||
move.w | move.w d1,VRAM_RW | ||
subq.b #1,d7 | |||
bne .writerlp | |||
rts | rts | ||
.hexshift: | .hexshift: | ||
cmp.b # | cmp.b #10,d1 | ||
blt.b .r | blt.b .r | ||
addq.b #7, | addq.b #7,d1 | ||
.r: | .r: | ||
rts | rts | ||
</ | </syntaxhighlight> | ||
Don't forget to set up a palette. | |||
[[Category:Code]] | [[Category:Code]] |
Latest revision as of 00:37, 27 August 2017
A 68k program may produce exceptions, often caused by bugs. For debugging, an exception handler can be of great use.
Some games were published with their exception handler, while some others just reset the system.
Generic exception handler
Allocate a longword variable called "PCERROR". Make the appropriate vectors point to the related routines below.
Divide by zero/Illegal instruction
Cause: See 68k vector table.
6 bytes stack frame: 0:SR.w, 2:PC.l
ErrDivZero:
move.l 2(a7),PCERROR ; Store PC from stack frame
movem.l d0-d7/a0-a6,-(a7) ; Store registers
lea ERR_DIVZERO,a0
jmp DispErr
Address error/Bus error
Cause: See 68k vector table.
14 bytes stack frame: 0:R/W.w, 2:Access address.l, 6:Instruction.l, 8:SR.w, 10:PC.l
ErrAddr:
move.l 10(a7),PCERROR ; Store PC from stack frame
movem.l d0-d7/a0-a6,-(a7) ; Store registers
lea ERR_ADDR,a0
jmp DispErr
Display for debug
Don't forget to mask out all interrupts as soon as an exception is raised:
ori.w #$0700,sr
All register values can be retrieved from the previous MOVEMs and displayed on the fix layer:
;D0: 32bit value to display
;VRAM address needs to be set before call
Write32bit:
move.w #32,VRAM_MOD ; Write char-by-char
move.b #8,d7
.writerlp:
move.b d0,REG_DIPSW ; Kick watchdog
rol.l #4,d0 ; BCDEFGHA
move.b d0,d1
andi.w #$F,d1 ; xxxx000A
jsr .hexshift
add.w #ASCIISTART,d1
ori.w #$F000,d1 ; Palette $F
move.w d1,VRAM_RW
subq.b #1,d7
bne .writerlp
rts
.hexshift:
cmp.b #10,d1
blt.b .r
addq.b #7,d1
.r:
rts
Don't forget to set up a palette.