2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: ioptrap.c 1619 2009-10-07 04:54:58Z Herben $
11 # IOP exception handling.
28 IRX_ID("ioptrap_driver", 1, 1);
30 struct irx_export_table _exp_ioptrap
;
33 static const char *exception_type_name
[] = {
39 "Address Error Store",
40 "Instruction Bus Error",
44 "Reserved Instruction",
45 "Coprocessor Unusable",
48 "Reserved 14" /* "Floating point exception" */
51 const char * get_exception_name(exception_type_t type
) {
52 return exception_type_name
[type
];
55 exception_frame_t __trap_frame
;
56 extern void def_exc_handler();
57 extern void bp_exc_handler();
59 int dbg_jmp_buf_setup
= 0;
62 exception_type_t
dbg_setjmp() {
64 if(0 == (v
= setjmp(dbg_jmp_buf
))) {
65 dbg_jmp_buf_setup
= 1;
67 dbg_jmp_buf_setup
= 0;
74 /* Module info entry. */
75 typedef struct _smod_mod_info
{
76 struct _smod_mod_info
*next
;
79 u16 newflags
; /* For modload shipped with games. */
81 u16 flags
; /* I believe this is where flags are kept for BIOS versions. */
82 u32 entry
; /* _start */
93 smod_mod_info_t
*smod_get_next_mod(smod_mod_info_t
*cur_mod
)
95 /* If cur_mod is 0, return the head of the list (IOP address 0x800). */
97 return (smod_mod_info_t
*)0x800;
102 return cur_mod
->next
;
107 char* ExceptionGetModuleName(u32 epc
, u32
* r_epc
)
109 smod_mod_info_t
*mod_info
= 0;
111 while((mod_info
= smod_get_next_mod(mod_info
)) != 0)
113 if((epc
>= mod_info
->text_start
) && (epc
<= (mod_info
->text_start
+mod_info
->text_size
)))
116 *r_epc
= epc
- mod_info
->text_start
;
118 return mod_info
->name
;
125 #define JUMP_BUF_PC 0
126 #define JUMP_BUF_SP 1
127 #define JUMP_BUF_FP 2
128 #define JUMP_BUF_S0 3
129 #define JUMP_BUF_S1 4
130 #define JUMP_BUF_S2 5
131 #define JUMP_BUF_S3 6
132 #define JUMP_BUF_S4 7
133 #define JUMP_BUF_S5 8
134 #define JUMP_BUF_S6 9
135 #define JUMP_BUF_S7 10
136 #define JUMP_BUF_GP 11
138 // Define this to something else if you want... maybe some ee_sio stuff :P
139 #define TRAP_PRINTF(args...) printf(args)
141 static trap_exception_handler_t handlers
[16];
143 trap_exception_handler_t
set_exception_handler(exception_type_t type
, trap_exception_handler_t handler
) {
144 trap_exception_handler_t old_handler
= handlers
[type
];
145 handlers
[type
] = handler
;
149 trap_exception_handler_t
get_exception_handler(exception_type_t type
) {
150 return handlers
[type
];
153 void trap(exception_type_t type
, struct exception_frame
*ex
) {
156 if(dbg_jmp_buf_setup
) {
157 u32
*p
= (u32
*)dbg_jmp_buf
;
158 /* simulate longjmp */
159 ex
->epc
= p
[JUMP_BUF_PC
];
160 ex
->regs
[29] = p
[JUMP_BUF_SP
];
161 ex
->regs
[30] = p
[JUMP_BUF_FP
];
162 ex
->regs
[16] = p
[JUMP_BUF_S0
];
163 ex
->regs
[17] = p
[JUMP_BUF_S1
];
164 ex
->regs
[18] = p
[JUMP_BUF_S2
];
165 ex
->regs
[19] = p
[JUMP_BUF_S3
];
166 ex
->regs
[20] = p
[JUMP_BUF_S4
];
167 ex
->regs
[21] = p
[JUMP_BUF_S5
];
168 ex
->regs
[22] = p
[JUMP_BUF_S6
];
169 ex
->regs
[23] = p
[JUMP_BUF_S7
];
170 ex
->regs
[28] = p
[JUMP_BUF_GP
];
171 ex
->regs
[2] = type
; /* return value from setjmp */
174 TRAP_PRINTF("IOP Exception : %s\n", exception_type_name
[type
]);
175 TRAP_PRINTF("EPC=%08x CAUSE=%08x SR=%08x BADVADDR=%08x DCIC=%08x\n", (int)ex
->epc
, (int)ex
->cause
, (int)ex
->sr
, (int)ex
->badvaddr
, (int)ex
->dcic
);
176 if((module
= ExceptionGetModuleName(ex
->epc
, &r_addr
)))
177 TRAP_PRINTF("module %s at unreloc offset %08lX\n", module
, r_addr
);
178 if((module
= ExceptionGetModuleName(ex
->regs
[31], &r_addr
)))
179 TRAP_PRINTF("ra module %s at unreloc offset %08lX\n", module
, r_addr
);
180 for(i
= 0; i
!= 32; i
+= 4) {
181 TRAP_PRINTF("r[%02d]=%08x r[%02d]=%08x r[%02d]=%08x r[%02d]=%08x\n",
182 (int)i
, (int)ex
->regs
[i
], (int)i
+1, (int)ex
->regs
[i
+1], (int)i
+2, (int)ex
->regs
[i
+2], (int)i
+3, (int)ex
->regs
[i
+3]);
185 if (handlers
[type
]) {
186 handlers
[type
](type
, ex
);
189 if(type
== EXCEPTION_Bp
) {
192 if(ex
->cause
& (1<<31)) {
193 ex
->cause
&= ~(1<<31); /* clear BD */
201 static void trigger() {
203 printf("trigger=%p\n", trigger
);
205 if(0 == (v
= setjmp(dbg_jmp_buf
))) {
206 dbg_jmp_buf_setup
= 1;
207 *(u32
*)0xdeadbeef = 0xfeedface;
209 printf("exception occurred in command, v=%08x\n", (int)v
);
211 dbg_jmp_buf_setup
= 0;
215 void main_thread(void *unused
) {
218 DelayThread(1000*1000);
220 printf("IOP: about to trap!\n");
222 printf("IOP: back from trap!\n");
224 printf("IOP: still running %d\n", i
++);
225 DelayThread(2000*1000);
232 int create_main_thread(void) {
235 thread
.attr
= 0x2000000;
237 thread
.thread
= main_thread
;
238 thread
.stacksize
= 0x8000;
239 thread
.priority
= 0x18;
240 return CreateThread(&thread
);
245 thid
= create_main_thread();
246 StartThread(thid
, NULL
);
252 int _start(int argc
, char **argv
)
256 if(RegisterLibraryEntries(&_exp_ioptrap
) != 0) return 1;
258 memset(handlers
, 0, sizeof(trap_exception_handler_t
) * 16);
259 printf("ioptrap starts.\n");
260 if((rv
= RegisterDefaultExceptionHandler(def_exc_handler
)) < 0) {
261 printf("RegisterDefaultExceptionHandler failed, rv=%d\n", rv
);
264 if((rv
= RegisterPriorityExceptionHandler(IOP_EXCEPTION_HDB
, 0, bp_exc_handler
)) < 0) {
265 // shouldn't we release the default exception handler here... ?
266 printf("RegisterDefaultExceptionHandler failed, rv=%d\n", rv
);