/********************************************************************* * Copyright (C) 2003 Tord Lindstrom (pukko@home.se) * This file is subject to the terms and conditions of the PS2Link License. * See the file LICENSE in the main directory of this distribution for more * details. */ # ASM exception handlers #include "r5900_regs.h" .set noat .set noreorder .text .p2align 4 .global _savedRegs .global pkoStepBP .ent pkoStepBP pkoStepBP: # Should check for cause in cop0 Cause reg # If Bp, increase EPC (DO NOT PUT 'break' in a branch delay slot!!!) mfc0 k0, EPC # cop0 EPC addiu k0, k0, 4 # Step over breakpoint mtc0 k0, EPC sync.p eret .end pkoStepBP # Save all user regs # Save HI/LO, SR, BadVAddr, Cause, EPC, ErrorEPC, # ShiftAmount, cop0: $24, $25 # Save float regs?? # Set EPC to debugger # Set stack to 'exception stack' # eret .global pkoExceptionHandler .ent pkoExceptionHandler pkoExceptionHandler: la k0, _savedRegs sq $0, 0x00(k0) sq at, 0x10(k0) sq v0, 0x20(k0) sq v1, 0x30(k0) sq a0, 0x40(k0) sq a1, 0x50(k0) sq a2, 0x60(k0) sq a3, 0x70(k0) sq t0, 0x80(k0) sq t1, 0x90(k0) sq t2, 0xa0(k0) sq t3, 0xb0(k0) sq t4, 0xc0(k0) sq t5, 0xd0(k0) sq t6, 0xe0(k0) sq t7, 0xf0(k0) sq t8, 0x100(k0) sq t9, 0x110(k0) sq s0, 0x120(k0) sq s1, 0x130(k0) sq s2, 0x140(k0) sq s3, 0x150(k0) sq s4, 0x160(k0) sq s5, 0x170(k0) sq s6, 0x180(k0) sq s7, 0x190(k0) # sq k0, 0x1a0(k0) # $k0 sq zero, 0x1a0(k0) # zero instead sq k1, 0x1b0(k0) # $k1 sq gp, 0x1c0(k0) sq sp, 0x1d0(k0) # sp sq fp, 0x1e0(k0) sq ra, 0x1f0(k0) # $ra pmfhi t0 # HI pmflo t1 # LO sq t0, 0x200(k0) sq t1, 0x210(k0) mfc0 t0, BadVAddr # Cop0 state regs mfc0 t1, Status sw t0, 0x220(k0) sw t1, 0x224(k0) mfc0 t0, Cause mfc0 t1, EPC sw t0, 0x228(k0) sw t1, 0x22c(k0) # Kernel saves these two also.. mfc0 t0, DEPC mfc0 t1, PerfCnt sw t0, 0x230(k0) sw t1, 0x234(k0) mfsa t0 sw t0, 0x238(k0) # Use our own stack.. la sp, _exceptionStack+0x2000-16 la gp, _gp # Use exception handlers _gp # Return from exception and start 'debugger' mfc0 a0, Cause # arg0 mfc0 a1, BadVAddr mfc0 a2, Status mfc0 a3, EPC addu t0, zero, k0 # arg4 = registers move t1, sp la k0, pkoDebug mtc0 k0, EPC # eret return address sync.p mfc0 k0, Status # check this out.. li v0, 0xfffffffe and k0, v0 mtc0 k0, Status sync.p nop nop nop nop eret nop .end pkoExceptionHandler # Put EE in kernel mode # Restore all user regs etc # Restore PC? & Stack ptr # Restore interrupt sources # Jump to EPC .ent pkoReturnFromDebug .global pkoReturnFromDebug pkoReturnFromDebug: lui t1, 0x1 _disable: di sync mfc0 t0, Status and t0, t1 beqz t0, _disable nop la k0, _savedRegs lq t0, 0x200(k0) lq t1, 0x210(k0) pmthi t0 # HI pmtlo t1 # LO lw t0, 0x220(k0) lw t1, 0x224(k0) mtc0 t0, BadVAddr mtc0 t1, Status lw t0, 0x228(k0) lw t1, 0x22c(k0) mtc0 t0, Cause mtc0 t1, EPC # Kernel saves these two also.. lw t0, 0x230(k0) lw t1, 0x234(k0) mtc0 t0, DEPC mtc0 t1, PerfCnt # Shift Amount reg lw t0, 0x238(k0) mtsa t0 # ori t2, 0xff # sw t2, 0(k1) # lq $0, 0x00(k0) lq $1, 0x10(k0) lq $2, 0x20(k0) lq $3, 0x30(k0) lq $4, 0x40(k0) lq $5, 0x50(k0) lq $6, 0x60(k0) lq $7, 0x70(k0) lq $8, 0x80(k0) lq $9, 0x90(k0) lq $10, 0xa0(k0) lq $11, 0xb0(k0) lq $12, 0xc0(k0) lq $13, 0xd0(k0) lq $14, 0xe0(k0) lq $15, 0xf0(k0) lq $16, 0x100(k0) lq $17, 0x110(k0) lq $18, 0x120(k0) lq $19, 0x130(k0) lq $10, 0x140(k0) lq $21, 0x150(k0) lq $22, 0x160(k0) lq $23, 0x170(k0) lq $24, 0x180(k0) lq $25, 0x190(k0) # lq $26, 0x1a0(k0) # $k0 lq $27, 0x1b0(k0) # $k1 lq $28, 0x1c0(k0) lq $29, 0x1d0(k0) # $sp lq $30, 0x1e0(k0) # lq $31, 0x1f0(k0) # $ra lw ra, 0x22c(k0) # Guess one should have some check here, and only advance PC if # we are going to step over a Breakpoint or something # (i.e. do stuff depending on Cause) addiu ra, 4 sync.p ei sync.p jr ra nop .end pkoReturnFromDebug