68k exception handling: Difference between revisions

From NeoGeo Development Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
[[File:Exceptionillegal.png|frame|Exception screen showing the PC where it was raised: Always better than a quiet reset !]]
[[File:Unibios_exc.png|thumb| The [[Universe BIOS]] provides some exception handling.]]
See [[68k vector table]].
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===
==Divide by zero/Illegal instruction==


(DIVU or DIVS by zero, or bad opcode)
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


<pre>
<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
</pre>
</syntaxhighlight>


===Address error/Bus error===
==Address error/Bus error==


(Misaligned read/writes, hardware fault ?)
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


<pre>
<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
</pre>
</syntaxhighlight>


==Displaying for debug==
==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:
<pre>
<syntaxhighlight>
     ori.w  #$0700,sr
     ori.w  #$0700,sr
</pre>
</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]]:


<pre>
<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  #$20,VRAM_MOD
     move.w  #32,VRAM_MOD   ; Write char-by-char
     move.l  d0,d1
     move.b #8,d7
    move.l #8-1,d7
.writerlp:
.writerlp:
     move.b  d0,REG_DIPSW  ;Watchdog
     move.b  d0,REG_DIPSW  ; Kick watchdog
     andi.l #$F0000000,d0  ;x0000000
     rol.l   #4,d0         ; BCDEFGHA
     lsl.#4,d0          ;0000000x
    move.b d0,d1
     andi.#$F,d1        ; xxxx000A
     jsr    .hexshift
     jsr    .hexshift
     addi.w #ASCIISTART,d0
     add.w   #ASCIISTART,d1
     ori.w  #$F000,d0     ;Palette $F
     ori.w  #$F000,d1     ; Palette $F
     move.w  d0,VRAM_RW
     move.w  d1,VRAM_RW
     lsl.#4,d1
     subq.#1,d7
     move.l  d1,d0
     bne     .writerlp
     dbra    d7,.writerlp
     rts
     rts


.hexshift:
.hexshift:
     cmp.b  #$A,d0
     cmp.b  #10,d1
     blt.b  .r
     blt.b  .r
     addq.b  #7,d0
     addq.b  #7,d1
.r:
.r:
     rts
     rts
</pre>
</syntaxhighlight>
 
Don't forget to set up a palette.


[[Category:Code]]
[[Category:Code]]

Latest revision as of 00:37, 27 August 2017

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

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

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:

    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.