PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
intrman.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "intrman.h"
12#include "irx_imports.h"
13#include "kerr.h"
14
16#include "iop_mmio_hwport.h"
17
18extern struct irx_export_table _exp_intrman;
19
20#ifdef _IOP
21IRX_ID("Interrupt_Manager", 1, 1);
22#endif
23// Based on the module from SCE SDK 1.3.4.
24
25#define PRID $15
26
27#define _mfc0(reg) \
28 ({ \
29 u32 val; \
30 __asm__ volatile("mfc0 %0, " #reg : "=r"(val)); \
31 val; \
32 })
33
34#define mfc0(reg) _mfc0(reg)
35
36extern int CpuGetICTRL();
37extern void CpuEnableICTRL();
38extern int dma_interrupt_handler(void *userdata);
39
40extern exception_handler_struct_t exception_interrupt_handler;
41extern exception_handler_struct_t exception_priority_interrupt_handler;
42extern exception_handler_struct_t exception_system_handler;
43
44static intrman_internals_t intrman_internals;
45
46int _start(int ac, char **av)
47{
48 s32 prid;
49 int i;
50 USE_IOP_MMIO_HWPORT();
51 USE_IOP_LOW_MEMORY_GLOBALS();
52
53 (void)ac;
54 (void)av;
55
56 prid = mfc0(PRID);
57
58#ifdef BUILDING_INTRMANP
59 if ( prid >= 16 )
60 {
61 if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 8) == 0 )
62 {
63 return MODULE_NO_RESIDENT_END;
64 }
65 }
66#else
67 if ( prid < 16 )
68 {
69 return MODULE_NO_RESIDENT_END;
70 }
71
72 if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 8) != 0 )
73 {
74 return MODULE_NO_RESIDENT_END;
75 }
76#endif
77
78#pragma GCC diagnostic push
79#pragma GCC diagnostic ignored "-Warray-bounds"
80 iop_low_memory_globals->dispatch_interrupt_state = -1;
81#pragma GCC diagnostic pop
82 iop_mmio_hwport->imask = 0;
83 iop_mmio_hwport->dmac1.dicr1 = 0;
84#ifndef BUILDING_INTRMANP
85 iop_mmio_hwport->dmac2.dicr2 = 0;
86#endif
87 intrman_internals.masked_icr_1 = -1;
88 intrman_internals.masked_icr_2 = -1;
89 intrman_internals.interrupt_handler_table = &(iop_low_memory_globals->intr_handlers[0]);
90 // Unofficial: The upper bound was changed from 0x40 because it is not actually used
91 for ( i = 0; i < 0x30; i += 1 )
92 {
93#pragma GCC diagnostic push
94#pragma GCC diagnostic ignored "-Warray-bounds"
95 intrman_internals.interrupt_handler_table[i].handler = NULL;
96 intrman_internals.interrupt_handler_table[i].userdata = NULL;
97#pragma GCC diagnostic pop
98 }
99 RegisterExceptionHandler(0, &exception_interrupt_handler);
100 RegisterPriorityExceptionHandler(0, 3, &exception_priority_interrupt_handler);
101 RegisterExceptionHandler(8, &exception_system_handler);
102 // Unofficial: pass internal structure
103 RegisterIntrHandler(IOP_IRQ_DMA, 1, dma_interrupt_handler, (void *)&intrman_internals);
104 RegisterLibraryEntries(&_exp_intrman);
105 return 0;
106}
107
108int intrman_deinit(void)
109{
110 USE_IOP_MMIO_HWPORT();
111
112 iop_mmio_hwport->imask = 0;
113 iop_mmio_hwport->dmac1.dicr1 = 0;
114#ifndef BUILDING_INTRMANP
115 iop_mmio_hwport->dmac2.dicr2 = 0;
116#endif
117 return 0;
118}
119
120intrman_internals_t *GetIntrmanInternalData(void)
121{
122 return &intrman_internals;
123}
124
125int RegisterIntrHandler(int irq, int mode, int (*handler)(void *), void *arg)
126{
127 int intr_handler_offset;
128 int state;
129
130 if ( QueryIntrContext() != 0 )
131 {
132 return KE_ILLEGAL_CONTEXT;
133 }
134 CpuSuspendIntr(&state);
135 if ( irq >= IOP_IRQ_VBLANK && irq <= IOP_IRQ_DMA_SIO2_OUT )
136 {
137 intr_handler_offset = irq;
138 }
139 else if ( irq >= IOP_IRQ_SW1 && IOP_IRQ_SW1 <= IOP_IRQ_SW2 )
140 {
141 intr_handler_offset = irq - 0x10;
142 }
143 else
144 {
145 CpuResumeIntr(state);
146 return KE_ILLEGAL_INTRCODE;
147 }
148 if ( intrman_internals.interrupt_handler_table[intr_handler_offset].handler )
149 {
150 CpuResumeIntr(state);
151 return KE_FOUND_HANDLER;
152 }
153 if ( irq < IOP_IRQ_DMA_MDEC_IN || irq > IOP_IRQ_DMA_SIO2_OUT )
154 {
155 intrman_internals.interrupt_handler_table[intr_handler_offset].handler =
156 (int (*)(void *))((uiptr)handler | (mode & 3));
157 }
158 else
159 {
160 intrman_internals.interrupt_handler_table[intr_handler_offset].handler = handler;
161 }
162 intrman_internals.interrupt_handler_table[intr_handler_offset].userdata = arg;
163 CpuResumeIntr(state);
164 return 0;
165}
166
168{
169 int intr_handler_offset;
170 int state;
171
172 if ( QueryIntrContext() != 0 )
173 {
174 return KE_ILLEGAL_CONTEXT;
175 }
176 CpuSuspendIntr(&state);
177 if ( irq >= IOP_IRQ_VBLANK && irq <= IOP_IRQ_DMA_SIO2_OUT )
178 {
179 intr_handler_offset = irq;
180 }
181 else if ( irq >= IOP_IRQ_SW1 && IOP_IRQ_SW1 <= IOP_IRQ_SW2 )
182 {
183 intr_handler_offset = irq - 0x10;
184 }
185 else
186 {
187 CpuResumeIntr(state);
188 return KE_ILLEGAL_INTRCODE;
189 }
190 if ( !intrman_internals.interrupt_handler_table[intr_handler_offset].handler )
191 {
192 CpuResumeIntr(state);
193 return KE_NOTFOUND_HANDLER;
194 }
195 intrman_internals.interrupt_handler_table[intr_handler_offset].handler = NULL;
196 CpuResumeIntr(state);
197 return 0;
198}
199
200extern int intrman_syscall_04_CpuDisableIntr(void);
201extern int intrman_syscall_08_CpuEnableIntr(void);
202extern int intrman_syscall_10(void);
203extern int intrman_syscall_14(int state);
204
205int CpuSuspendIntr(int *state)
206{
207 int intrstate;
208
209#ifdef BUILDING_INTRMANP
210 intrstate = intrman_syscall_10();
211#else
212 USE_IOP_MMIO_HWPORT();
213 intrstate = iop_mmio_hwport->iop_sbus_info;
214#endif
215 if ( state )
216 *state = intrstate;
217#ifdef BUILDING_INTRMANP
218 if ( (intrstate & 0x404) != 0x404 )
219 return KE_CPUDI;
220#else
221 if ( !intrstate )
222 return KE_CPUDI;
223#endif
224 return 0;
225}
226
227int CpuResumeIntr(int state)
228{
229#ifdef BUILDING_INTRMANP
230 intrman_syscall_14(state);
231#else
232 USE_IOP_MMIO_HWPORT();
233 iop_mmio_hwport->iop_sbus_info = state;
234#endif
235 return 0;
236}
237
239{
240#ifdef BUILDING_INTRMANP
241 if ( intrman_syscall_04_CpuDisableIntr() == 0 )
242 return KE_CPUDI;
243#else
244 if ( CpuGetICTRL() == 0 )
245 return KE_CPUDI;
246#endif
247 return 0;
248}
249
251{
252 intrman_syscall_08_CpuEnableIntr();
253#ifndef BUILDING_INTRMANP
254 CpuEnableICTRL();
255#endif
256 return 0;
257}
258
259int CpuGetICTRL()
260{
261#ifdef BUILDING_INTRMANP
262 return intrman_syscall_04_CpuDisableIntr();
263#else
264 USE_IOP_MMIO_HWPORT();
265 return iop_mmio_hwport->iop_sbus_info;
266#endif
267}
268
269void CpuEnableICTRL()
270{
271#ifdef BUILDING_INTRMANP
272 intrman_syscall_08_CpuEnableIntr();
273#else
274 USE_IOP_MMIO_HWPORT();
275 iop_mmio_hwport->iop_sbus_info = 1;
276#endif
277}
278
279// clang-format off
280__asm__ (
281 "\t" ".set push" "\n"
282 "\t" ".set noat" "\n"
283 "\t" ".set noreorder" "\n"
284 "\t" ".global intrman_syscall_04_CpuDisableIntr" "\n"
285 "\t" "intrman_syscall_04_CpuDisableIntr:" "\n"
286 "\t" " addiu $v0, $zero, 0x04" "\n"
287 "\t" " syscall 0" "\n"
288 "\t" " jr $ra" "\n"
289 "\t" " nop" "\n"
290 "\t" ".set pop" "\n"
291);
292
293__asm__ (
294 "\t" ".set push" "\n"
295 "\t" ".set noat" "\n"
296 "\t" ".set noreorder" "\n"
297 "\t" ".global intrman_syscall_08_CpuEnableIntr" "\n"
298 "\t" "intrman_syscall_08_CpuEnableIntr:" "\n"
299 "\t" " addiu $v0, $zero, 0x08" "\n"
300 "\t" " syscall 0" "\n"
301 "\t" " jr $ra" "\n"
302 "\t" " nop" "\n"
303 "\t" ".set pop" "\n"
304);
305
306__asm__ (
307 "\t" ".set push" "\n"
308 "\t" ".set noat" "\n"
309 "\t" ".set noreorder" "\n"
310 "\t" ".global intrman_syscall_10" "\n"
311 "\t" "intrman_syscall_10:" "\n"
312 "\t" " addiu $v0, $zero, 0x10" "\n"
313 "\t" " syscall 0" "\n"
314 "\t" " jr $ra" "\n"
315 "\t" " nop" "\n"
316 "\t" ".set pop" "\n"
317);
318
319__asm__ (
320 "\t" ".set push" "\n"
321 "\t" ".set noat" "\n"
322 "\t" ".set noreorder" "\n"
323 "\t" ".global intrman_syscall_14" "\n"
324 "\t" "intrman_syscall_14:" "\n"
325 "\t" " addiu $v0, $zero, 0x14" "\n"
326 "\t" " syscall 0" "\n"
327 "\t" " jr $ra" "\n"
328 "\t" " nop" "\n"
329 "\t" ".set pop" "\n"
330);
331
332__asm__ (
333 "\t" ".set push" "\n"
334 "\t" ".set noat" "\n"
335 "\t" ".set noreorder" "\n"
336 "\t" ".global CpuInvokeInKmode" "\n"
337 "\t" "CpuInvokeInKmode:" "\n"
338 "\t" " addiu $v0, $zero, 0x0C" "\n"
339 "\t" " syscall 0" "\n"
340 "\t" " jr $ra" "\n"
341 "\t" " nop" "\n"
342 "\t" ".set pop" "\n"
343);
344// clang-format on
345
346int EnableIntr(int irq)
347{
348 int ret;
349 int irq_index;
350 int state;
351 USE_IOP_MMIO_HWPORT();
352
353 ret = 0;
354 irq_index = irq & 0xFF;
355 CpuSuspendIntr(&state);
356 if ( irq_index < IOP_IRQ_DMA_MDEC_IN )
357 {
358 iop_mmio_hwport->imask |= (1 << irq_index);
359 }
360 else if ( (irq_index >= IOP_IRQ_DMA_MDEC_IN) && (irq_index <= IOP_IRQ_DMA_GPU_OTC) )
361 {
362 iop_mmio_hwport->dmac1.dicr1 = (iop_mmio_hwport->dmac1.dicr1 & (~(1 << (irq_index - 32)) & 0xFFFFFF))
363 | (((((irq & 0xFF00) >> 8) & 0x1) != 0) ? (1 << (irq_index - 32)) : 0)
364 | (1 << (irq_index - 32 + 16)) | 0x800000;
365#ifndef BUILDING_INTRMANP
366 iop_mmio_hwport->dmac2.dicr2 = (iop_mmio_hwport->dmac2.dicr2 & (~(1 << (irq_index - 32)) & 0xFFFFFF))
367 | (((((irq & 0xFF00) >> 8) & 0x2) != 0) ? (1 << (irq_index - 32)) : 0);
368#endif
369 iop_mmio_hwport->imask |= 8;
370#if 0
371 /* The following was in the original. */
372#ifdef BUILDING_INTRMANP
373 ret = KE_ILLEGAL_INTRCODE;
374#endif
375#endif
376 }
377#ifndef BUILDING_INTRMANP
378 else if ( (irq_index >= IOP_IRQ_DMA_SPU2) && (irq_index <= IOP_IRQ_DMA_SIO2_OUT) )
379 {
380 iop_mmio_hwport->dmac2.dicr2 = (iop_mmio_hwport->dmac2.dicr2 & (~(1 << (irq_index - 40 + 7)) & 0xFFFFFF))
381 | (((((irq & 0xFF00) >> 8) & 0x2) != 0) ? (1 << (irq_index - 33)) : 0)
382 | (1 << (irq_index - 40 + 16));
383 iop_mmio_hwport->dmac1.dicr1 = (iop_mmio_hwport->dmac1.dicr1 & 0x7FFFFF) | 0x800000;
384 iop_mmio_hwport->imask |= 8;
385 }
386#endif
387 else
388 {
389 ret = KE_ILLEGAL_INTRCODE;
390 }
391 CpuResumeIntr(state);
392 return ret;
393}
394
395int DisableIntr(int irq, int *res)
396{
397 int ret;
398 int res_temp;
399 int irq_index;
400 u32 imask;
401 int dicr_tmp;
402 int state;
403 USE_IOP_MMIO_HWPORT();
404
405 ret = 0;
406 res_temp = KE_INTRDISABLE;
407 irq_index = irq & 0xFF;
408 CpuSuspendIntr(&state);
409 if ( irq_index < IOP_IRQ_DMA_MDEC_IN )
410 {
411 imask = iop_mmio_hwport->imask;
412 iop_mmio_hwport->imask = imask & ~(1 << irq_index);
413 if ( (imask & (1 << irq_index)) != 0 )
414 {
415 res_temp = irq_index;
416 }
417 else
418 {
419 ret = KE_INTRDISABLE;
420 }
421 }
422 else if ( (irq_index >= IOP_IRQ_DMA_MDEC_IN) && (irq_index <= IOP_IRQ_DMA_GPU_OTC) )
423 {
424 dicr_tmp = iop_mmio_hwport->dmac1.dicr1 & 0xFFFFFF;
425 if ( (dicr_tmp & (1 << (irq_index - 16))) != 0 )
426 {
427 res_temp = irq_index;
428 if ( ((dicr_tmp >> (irq_index - 32)) & 1) != 0 )
429 res_temp |= 0x100;
430#ifndef BUILDING_INTRMANP
431 if ( iop_mmio_hwport->dmac2.dicr2 & (1 << (irq_index - 32)) )
432 res_temp |= 0x200;
433#endif
434 iop_mmio_hwport->dmac1.dicr1 = dicr_tmp & ~(1 << (irq_index - 16));
435 }
436 else
437 {
438 ret = KE_INTRDISABLE;
439 }
440 }
441#ifndef BUILDING_INTRMANP
442 else if ( (irq_index >= IOP_IRQ_DMA_SPU2) && (irq_index <= IOP_IRQ_DMA_SIO2_OUT) )
443 {
444 dicr_tmp = iop_mmio_hwport->dmac2.dicr2 & 0xFFFFFF;
445 if ( (dicr_tmp & (1 << (irq_index - 24))) != 0 )
446 {
447 res_temp = irq_index;
448 if ( (dicr_tmp >> (irq_index - 33)) & 1 )
449 res_temp |= 0x200;
450 iop_mmio_hwport->dmac2.dicr2 = dicr_tmp & ~(1 << (irq_index - 24));
451 }
452 else
453 {
454 ret = KE_INTRDISABLE;
455 }
456 }
457#endif
458 else
459 {
460 ret = KE_ILLEGAL_INTRCODE;
461 }
462 if ( res )
463 *res = res_temp;
464 CpuResumeIntr(state);
465 return ret;
466}
467
469{
470 int irq_index;
471 int state;
472 USE_IOP_LOW_MEMORY_GLOBALS();
473
474 irq_index = irq & 0xFF;
475 CpuSuspendIntr(&state);
476 if ( irq_index < IOP_IRQ_DMA_MDEC_IN )
477 {
478#pragma GCC diagnostic push
479#pragma GCC diagnostic ignored "-Warray-bounds"
480 iop_low_memory_globals->dispatch_interrupt_state |= 1 << irq_index;
481#pragma GCC diagnostic pop
482 }
483 else if ( (irq_index >= IOP_IRQ_DMA_MDEC_IN) && (irq_index <= IOP_IRQ_DMA_BERR) )
484 {
485 intrman_internals.masked_icr_1 |= 1 << (irq_index - 8);
486 }
487 else if ( (irq_index >= IOP_IRQ_DMA_SPU2) && (irq_index <= IOP_IRQ_DMA_SIO2_OUT) )
488 {
489 intrman_internals.masked_icr_2 |= 1 << (irq_index - 16);
490 }
491 CpuResumeIntr(state);
492}
493
495{
496 int irq_index;
497 int state;
498 USE_IOP_LOW_MEMORY_GLOBALS();
499
500 irq_index = irq & 0xFF;
501 CpuSuspendIntr(&state);
502 if ( irq_index < IOP_IRQ_DMA_MDEC_IN )
503 {
504#pragma GCC diagnostic push
505#pragma GCC diagnostic ignored "-Warray-bounds"
506 iop_low_memory_globals->dispatch_interrupt_state &= ~(1 << irq_index);
507#pragma GCC diagnostic pop
508 }
509 else if ( (irq_index >= IOP_IRQ_DMA_MDEC_IN) && (irq_index <= IOP_IRQ_DMA_BERR) )
510 {
511 intrman_internals.masked_icr_1 &= ~(1 << (irq_index - 8));
512 }
513 else if ( (irq_index >= IOP_IRQ_DMA_SPU2) && (irq_index <= IOP_IRQ_DMA_SIO2_OUT) )
514 {
515 intrman_internals.masked_icr_2 &= ~(1 << (irq_index - 16));
516 }
517 CpuResumeIntr(state);
518}
519
520void intrman_set_dmac2_interrupt_handler_mask(int mask)
521{
522 intrman_internals.dmac2_interrupt_handler_mask = mask;
523}
524
525#ifndef BUILDING_INTRMANP
526// Unofficial: reference relative to internal structure
527static void dmac2_enable_set(const intrman_internals_t *p_intrman_internals, int mask)
528{
529 USE_IOP_MMIO_HWPORT();
530
531 if ( (p_intrman_internals->dmac2_interrupt_handler_mask & mask) != 0 )
532 {
533 while ( iop_mmio_hwport->dmac2.dmacen != 1 )
534 {
535 iop_mmio_hwport->dmac2.dmacen = 1;
536 }
537 }
538}
539
540// Unofficial: reference relative to internal structure
541static void dmac2_enable_unset(const intrman_internals_t *p_intrman_internals, int mask)
542{
543 USE_IOP_MMIO_HWPORT();
544
545 if ( (p_intrman_internals->dmac2_interrupt_handler_mask & mask) != 0 )
546 {
547 while ( iop_mmio_hwport->dmac2.dmacen != 0 )
548 {
549 iop_mmio_hwport->dmac2.dmacen = 0;
550 }
551 }
552}
553#endif
554
555int dma_interrupt_handler(void *userdata)
556{
557#ifndef BUILDING_INTRMANP
558 u32 dma2_intr_flags;
559#endif
560 u32 dma1_intr_flags_tmp;
561 u32 dma1_intr_flags;
562 int bus_error_intr_flag;
563 int i;
564 int masked_icr_1_tmp;
565#ifndef BUILDING_INTRMANP
566 int masked_icr_2_tmp;
567#endif
568 intrman_internals_t *p_intrman_internals;
569 intrman_intr_handler_data_t *interrupt_handler_table;
570 USE_IOP_MMIO_HWPORT();
571
572 // Unofficial: reference relative to internal structure
573 p_intrman_internals = (intrman_internals_t *)userdata;
574 interrupt_handler_table = p_intrman_internals->interrupt_handler_table;
575 masked_icr_1_tmp = p_intrman_internals->masked_icr_1;
576#ifndef BUILDING_INTRMANP
577 masked_icr_2_tmp = p_intrman_internals->masked_icr_2;
578#endif
579#ifndef BUILDING_INTRMANP
580 dmac2_enable_unset(p_intrman_internals, 1);
581#endif
582 while ( 1 )
583 {
584#ifndef BUILDING_INTRMANP
585 dmac2_enable_unset(p_intrman_internals, 2);
586#endif
587#ifndef BUILDING_INTRMANP
588 dma2_intr_flags = ((iop_mmio_hwport->dmac2.dicr2 & masked_icr_2_tmp) >> 24) & 0x3F;
589#endif
590 dma1_intr_flags_tmp = iop_mmio_hwport->dmac1.dicr1 & masked_icr_1_tmp;
591 dma1_intr_flags = ((dma1_intr_flags_tmp & 0xFF00) >> 8) & 0x7F;
592 bus_error_intr_flag = (dma1_intr_flags_tmp >> 15) & 1;
593#ifndef BUILDING_INTRMANP
594 dmac2_enable_set(p_intrman_internals, 2);
595#endif
596#ifdef BUILDING_INTRMANP
597 if ( !(dma1_intr_flags | bus_error_intr_flag) )
598 break;
599#else
600 if ( !(dma1_intr_flags | dma2_intr_flags | bus_error_intr_flag) )
601 break;
602#endif
603 if ( bus_error_intr_flag )
604 {
605#ifndef BUILDING_INTRMANP
606 dmac2_enable_unset(p_intrman_internals, 2);
607#endif
608 iop_mmio_hwport->dmac1.dicr1 &= 0xFF7FFF;
609#ifndef BUILDING_INTRMANP
610 dmac2_enable_set(p_intrman_internals, 2);
611#endif
612 if ( interrupt_handler_table[IOP_IRQ_DMA_BERR].handler )
613 {
614 interrupt_handler_table[IOP_IRQ_DMA_BERR].handler(interrupt_handler_table[IOP_IRQ_DMA_BERR].userdata);
615 }
616 }
617 if ( dma1_intr_flags )
618 {
619 for ( i = 0; i < 7; i += 1 )
620 {
621 if ( (dma1_intr_flags & 1) != 0 )
622 {
623#ifndef BUILDING_INTRMANP
624 dmac2_enable_unset(p_intrman_internals, 2);
625#endif
626 iop_mmio_hwport->dmac1.dicr1 &= ((1 << (i + 24)) | 0xFFFFFF);
627 if ( interrupt_handler_table[i + IOP_IRQ_DMA_MDEC_IN].handler )
628 {
629#ifndef BUILDING_INTRMANP
630 dmac2_enable_set(p_intrman_internals, 4);
631#endif
632 if ( !interrupt_handler_table[i + IOP_IRQ_DMA_MDEC_IN].handler(
633 interrupt_handler_table[i + IOP_IRQ_DMA_MDEC_IN].userdata) )
634 {
635#ifndef BUILDING_INTRMANP
636 dmac2_enable_unset(p_intrman_internals, 4);
637#endif
638 iop_mmio_hwport->dmac1.dicr1 &= 0xFFFFFF & ~(1 << (i + 16));
639 }
640#ifndef BUILDING_INTRMANP
641 dmac2_enable_unset(p_intrman_internals, 4);
642#endif
643 }
644 else
645 {
646 iop_mmio_hwport->dmac1.dicr1 &= 0xFFFFFF & ~(1 << (i + 16));
647 }
648#ifndef BUILDING_INTRMANP
649 dmac2_enable_set(p_intrman_internals, 2);
650#endif
651 }
652 dma1_intr_flags >>= 1;
653 if ( !dma1_intr_flags )
654 break;
655 }
656 }
657#ifndef BUILDING_INTRMANP
658 if ( dma2_intr_flags )
659 {
660 for ( i = 0; i < 6; i += 1 )
661 {
662 if ( (dma2_intr_flags & 1) != 0 )
663 {
664 dmac2_enable_unset(p_intrman_internals, 2);
665 iop_mmio_hwport->dmac2.dicr2 &= (1 << (i + 24)) | 0xFFFFFF;
666 if ( interrupt_handler_table[i + IOP_IRQ_DMA_SPU2].handler )
667 {
668 dmac2_enable_set(p_intrman_internals, 4);
669 if ( !(interrupt_handler_table[i + IOP_IRQ_DMA_SPU2].handler(
670 interrupt_handler_table[i + IOP_IRQ_DMA_SPU2].userdata)) )
671 {
672 dmac2_enable_unset(p_intrman_internals, 4);
673 iop_mmio_hwport->dmac2.dicr2 &= 0xFFFFFF & ~(1 << (i + 16));
674 }
675 dmac2_enable_unset(p_intrman_internals, 4);
676 }
677 else
678 {
679 iop_mmio_hwport->dmac2.dicr2 &= 0xFFFFFF & ~(1 << (i + 16));
680 }
681 dmac2_enable_set(p_intrman_internals, 2);
682 }
683 dma2_intr_flags >>= 1;
684 if ( !dma2_intr_flags )
685 break;
686 }
687 }
688#endif
689 }
690#ifndef BUILDING_INTRMANP
691 dmac2_enable_unset(p_intrman_internals, 2);
692#endif
693 {
694 u32 dicr1x;
695
696 dicr1x = iop_mmio_hwport->dmac1.dicr1;
697 iop_mmio_hwport->dmac1.dicr1 = (dicr1x & 0x7FFFFF);
698 iop_mmio_hwport->dmac1.dicr1 = (dicr1x & 0x7FFFFF) | 0x800000;
699 }
700#ifndef BUILDING_INTRMANP
701 dmac2_enable_set(p_intrman_internals, 2);
702 dmac2_enable_set(p_intrman_internals, 1);
703#endif
704 return 1;
705}
706
707static void *new_context_stub_cb(void *ctx);
708static int preempt_stub_cb(int unk);
709
710void *ctx_switch_cb = new_context_stub_cb;
711void *ctx_switch_required_cb = preempt_stub_cb;
712
713void SetNewCtxCb(void *cb)
714{
715 ctx_switch_cb = cb;
716}
717
718void ResetNewCtxCb(void)
719{
720 ctx_switch_cb = new_context_stub_cb;
721}
722
723void SetShouldPreemptCb(void *cb)
724{
725 ctx_switch_required_cb = cb;
726}
727
728void ResetShouldPreemptCb(void)
729{
730 ctx_switch_required_cb = preempt_stub_cb;
731}
732
733u32 tempstack[0x200];
734
735// clang-format off
736__asm__ (
737 "\t" ".set push" "\n"
738 "\t" ".set noat" "\n"
739 "\t" ".set noreorder" "\n"
740 "\t" ".global QueryIntrContext" "\n"
741 "\t" "QueryIntrContext:" "\n"
742 "\t" " addu $a0, $sp, $zero" "\n"
743 "\t" ".global QueryIntrStack" "\n"
744 "\t" "QueryIntrStack:" "\n"
745 "\t" " lui $v1, %hi(tempstack + 0x800)" "\n"
746 "\t" " addiu $v1, $v1, %lo(tempstack + 0x800)" "\n" // sizeof(tempstack)
747 "\t" " sltu $v0, $a0, $v1" "\n"
748 "\t" " beqz $v0, 9f" "\n"
749 "\t" " nop" "\n"
750 "\t" " addiu $v1, $v1, -0x800" "\n"
751 "\t" " sltu $v0, $v1, $a0" "\n"
752 "\t" "9:" "\n"
753 "\t" " jr $ra" "\n"
754 "\t" " nop" "\n"
755 "\t" ".set pop" "\n"
756);
757
758__asm__ (
759 "\t" ".set push" "\n"
760 "\t" ".set noat" "\n"
761 "\t" ".set noreorder" "\n"
762 "\t" ".global iCatchMultiIntr" "\n"
763 "\t" "iCatchMultiIntr:" "\n"
764 "\t" " lui $v1, %hi(tempstack + 0x800)" "\n"
765 "\t" " addiu $v1, $v1, %lo(tempstack + 0x800)" "\n" // sizeof(tempstack)
766 "\t" " sltu $v0, $sp, $v1" "\n"
767 "\t" " beqz $v0, 1f" "\n"
768 "\t" " nop" "\n"
769 "\t" " addiu $v1, $v1, -0x800" "\n"
770 "\t" " sltu $v0, $v1, $sp" "\n"
771 "\t" " beqz $v0, 2f" "\n"
772 "\t" " nop" "\n"
773 "\t" " addiu $v1, $v1, 0x160" "\n"
774 "\t" " sltu $v0, $v1, $sp" "\n"
775 "\t" " beqz $v0, 1f" "\n"
776 "\t" " nop" "\n"
777 "\t" " mfc0 $v0, $12" "\n"
778 "\t" " nop" "\n"
779 "\t" " andi $v1, $v0, 0x1" "\n"
780 "\t" " bnez $v1, 1f" "\n"
781 "\t" " ori $v1, $v0, 0x1" "\n"
782 "\t" " mtc0 $v1, $12" "\n"
783 "\t" " nop" "\n"
784 "\t" " nop" "\n"
785 "\t" " mtc0 $v0, $12" "\n"
786 "\t" "1:" "\n"
787 "\t" " jr $ra" "\n"
788 "\t" " nop" "\n"
789 "\t" "2:" "\n"
790 "\t" " break 2" "\n"
791 "\t" " jr $ra" "\n"
792 "\t" " nop" "\n"
793 "\t" ".set pop" "\n"
794);
795
796__asm__ (
797 "\t" ".set push" "\n"
798 "\t" ".set noat" "\n"
799 "\t" ".set noreorder" "\n"
800 "\t" "exception_interrupt_handler:" "\n"
801 "\t" " .word 0" "\n"
802 "\t" " .word 0" "\n"
803
804 "\t" "exception_interrupt_handler_code:" "\n"
805 "\t" " addiu $sp, $sp, -0x98" "\n"
806 "\t" " lw $at, 0x400($zero)" "\n"
807 "\t" " sw $ra, 0x7C($sp)" "\n"
808 "\t" " sw $at, 0x4($sp)" "\n"
809 "\t" " sw $v0, 0x8($sp)" "\n"
810 "\t" " sw $v1, 0xC($sp)" "\n"
811 "\t" " sw $a0, 0x10($sp)" "\n"
812 "\t" " sw $a1, 0x14($sp)" "\n"
813 "\t" " sw $a2, 0x18($sp)" "\n"
814 "\t" " sw $a3, 0x1C($sp)" "\n"
815 "\t" " addiu $v0, $sp, 0x98" "\n"
816 "\t" " sw $v0, 0x74($sp)" "\n"
817 "\t" " mfhi $v0" "\n"
818 "\t" " mflo $v1" "\n"
819 "\t" " sw $v0, 0x80($sp)" "\n"
820 "\t" " sw $v1, 0x84($sp)" "\n"
821 "\t" " lw $v0, 0x408($zero)" "\n"
822 "\t" " lw $v1, 0x404($zero)" "\n"
823 "\t" " sw $v0, 0x88($sp)" "\n"
824 "\t" " sw $v1, 0x8C($sp)" "\n"
825#ifndef BUILDING_INTRMANP
826 "\t" " lui $v0, (0xBF801078 >> 16)" "\n"
827 "\t" " ori $v0, $v0, (0xBF801078 & 0xFFFF)" "\n"
828 "\t" " lw $v1, 0x0($v0)" "\n"
829 "\t" " addiu $a0, $zero, 0x1" "\n"
830 "\t" " sw $v1, 0x90($sp)" "\n"
831 "\t" " sw $a0, 0x0($v0)" "\n"
832#endif
833 "\t" " lui $v0, (0xAC0000FE >> 16)" "\n"
834 "\t" " ori $v0, $v0, (0xAC0000FE & 0xFFFF)" "\n"
835 "\t" " sw $v0, 0x0($sp)" "\n"
836 "\t" " jal QueryIntrContext" "\n"
837 "\t" " nop" "\n"
838 "\t" " beqz $v0, .Lexception_interrupt_handler_code_1" "\n"
839 "\t" " nop" "\n"
840 "\t" " addu $v0, $sp, $zero" "\n"
841 "\t" " addiu $sp, $sp, -0x18" "\n"
842 "\t" " b .Lexception_interrupt_handler_code_2" "\n"
843 "\t" " sw $v0, 0x14($sp)" "\n"
844 "\t" ".Lexception_interrupt_handler_code_1:" "\n"
845 "\t" " addu $v0, $sp, $zero" "\n"
846 "\t" " lui $sp, %hi(tempstack + 0x7E0)" "\n"
847 "\t" " addiu $sp, $sp, %lo(tempstack + 0x7E0)" "\n"
848 "\t" " sw $v0, 0x14($sp)" "\n"
849 "\t" ".Lexception_interrupt_handler_code_2:" "\n"
850 "\t" " lw $a0, 0x40C($zero)" "\n"
851 "\t" " nop" "\n"
852 "\t" " sll $a0, $a0, 22" "\n"
853 "\t" " srl $a0, $a0, 30" "\n"
854 "\t" " bne $zero, $a0, .Lexception_interrupt_handler_code_5" "\n"
855 "\t" " nop" "\n"
856 "\t" " lui $k0, (0xBF801070 >> 16)" "\n"
857 "\t" " ori $k0, $k0, (0xBF801070 & 0xFFFF)" "\n"
858 "\t" " lw $k1, 0x4($k0)" "\n"
859 "\t" " lw $a0, 0x0($k0)" "\n"
860 "\t" " lw $a1, 0x41C($zero)" "\n"
861 "\t" " and $a0, $a0, $k1" "\n"
862 "\t" " and $a0, $a0, $a1" "\n"
863 "\t" " beq $zero, $a0, .Lexception_interrupt_handler_code_4" "\n"
864 "\t" " nop" "\n"
865 "\t" " addiu $v0, $zero, -0x4" "\n"
866 "\t" ".Lexception_interrupt_handler_code_3:" "\n"
867 "\t" " sll $a2, $a0, 28" "\n"
868 "\t" " srl $a0, $a0, 4" "\n"
869 "\t" " beqz $a2, .Lexception_interrupt_handler_code_3" "\n"
870 "\t" " addi $v0, $v0, 0x4" "\n"
871 "\t" " srl $a0, $a2, 26" "\n"
872 "\t" " andi $a0, $a0, 0x1C" "\n"
873 "\t" " lui $a2, (0x1020103 >> 16)" "\n"
874 "\t" " ori $a2, $a2, (0x1020103 & 0xFFFF)" "\n"
875 "\t" " srlv $a2, $a2, $a0" "\n"
876 "\t" " andi $a2, $a2, 0xF" "\n"
877 "\t" " add $v0, $v0, $a2" "\n"
878 "\t" " addiu $a2, $zero, 0x1" "\n"
879 "\t" " sllv $a2, $a2, $v0" "\n"
880 "\t" " sw $a2, 0x10($sp)" "\n"
881 "\t" " not $a2, $a2" "\n"
882 "\t" " and $a3, $a2, $k1" "\n"
883 "\t" " sw $a3, 0x4($k0)" "\n"
884 "\t" " sw $a2, 0x0($k0)" "\n"
885 "\t" " sll $a2, $v0, 3" "\n"
886 "\t" " lw $a3, 0x480($a2)" "\n"
887 "\t" " lw $a0, 0x484($a2)" "\n"
888 "\t" " bne $zero, $a3, .Lexception_interrupt_handler_code_7" "\n"
889 "\t" " nop" "\n"
890 "\t" ".Lexception_interrupt_handler_code_4:" "\n"
891 "\t" " lw $sp, 0x14($sp)" "\n"
892 "\t" " nop" "\n"
893 "\t" " lw $ra, 0x7C($sp)" "\n"
894 "\t" " lw $at, 0x4($sp)" "\n"
895 "\t" " lw $v0, 0x8($sp)" "\n"
896 "\t" " lw $v1, 0xC($sp)" "\n"
897 "\t" " lw $a0, 0x10($sp)" "\n"
898 "\t" " lw $a1, 0x14($sp)" "\n"
899 "\t" " lw $a2, 0x18($sp)" "\n"
900 "\t" " lw $a3, 0x1C($sp)" "\n"
901 "\t" " addiu $sp, $sp, 0x98" "\n"
902 "\t" " lui $k0, %hi(exception_interrupt_handler)" "\n"
903 "\t" " lw $k0, %lo(exception_interrupt_handler)($k0)" "\n"
904 "\t" " nop" "\n"
905 "\t" " jr $k0" "\n"
906 "\t" " nop" "\n"
907 "\t" ".Lexception_interrupt_handler_code_5:" "\n"
908 "\t" " sw $zero, 0x10($sp)" "\n"
909 "\t" " andi $a0, $a0, 0x1" "\n"
910 "\t" " bnez $a0, .Lexception_interrupt_handler_code_6" "\n"
911 "\t" " addiu $v0, $zero, 0x0" "\n"
912 "\t" " addiu $v0, $zero, 0x1" "\n"
913 "\t" ".Lexception_interrupt_handler_code_6:" "\n"
914 "\t" " addiu $a2, $zero, 0x100" "\n"
915 "\t" " sllv $a2, $a2, $v0" "\n"
916 "\t" " mfc0 $a0, $13" "\n"
917 "\t" " not $a2, $a2" "\n"
918 "\t" " and $a0, $a0, $a2" "\n"
919 "\t" " mtc0 $a0, $13" "\n"
920 "\t" " sll $a2, $v0, 3" "\n"
921 "\t" " lw $a3, 0x5F0($a2)" "\n"
922 "\t" " lw $a0, 0x5F4($a2)" "\n"
923 "\t" " beq $zero, $a3, .Lexception_interrupt_handler_code_4" "\n"
924 "\t" " nop" "\n"
925 "\t" ".Lexception_interrupt_handler_code_7:" "\n"
926 "\t" " sll $a2, $a3, 30" "\n"
927 "\t" " bnez $a2, .Lexception_interrupt_handler_code_8" "\n"
928 "\t" " nop" "\n"
929 "\t" " srl $a3, $a3, 2" "\n"
930 "\t" " sll $a3, $a3, 2" "\n"
931 "\t" " jalr $a3" "\n"
932 "\t" " nop" "\n"
933 "\t" " b .Lexception_interrupt_handler_code_10" "\n"
934 "\t" " nop" "\n"
935 "\t" ".Lexception_interrupt_handler_code_8:" "\n"
936 "\t" " lw $v0, 0x14($sp)" "\n"
937 "\t" " nop" "\n"
938 "\t" " sw $t0, 0x20($v0)" "\n"
939 "\t" " sw $t1, 0x24($v0)" "\n"
940 "\t" " sw $t2, 0x28($v0)" "\n"
941 "\t" " sw $t3, 0x2C($v0)" "\n"
942 "\t" " sw $t4, 0x30($v0)" "\n"
943 "\t" " sw $t5, 0x34($v0)" "\n"
944 "\t" " sw $t6, 0x38($v0)" "\n"
945 "\t" " sw $t7, 0x3C($v0)" "\n"
946 "\t" " sw $t8, 0x60($v0)" "\n"
947 "\t" " sw $t9, 0x64($v0)" "\n"
948 "\t" " sw $gp, 0x70($v0)" "\n"
949 "\t" " sw $fp, 0x78($v0)" "\n"
950 "\t" " lui $t0, (0xFF00FFFE >> 16)" "\n"
951 "\t" " ori $t0, $t0, (0xFF00FFFE & 0xFFFF)" "\n"
952 "\t" " sw $t0, 0x0($v0)" "\n"
953 "\t" " lui $gp, (0xFFFF0000 >> 16)" "\n"
954 "\t" " sll $a2, $a2, 1" "\n"
955 "\t" " beqz $a2, .Lexception_interrupt_handler_code_9" "\n"
956 "\t" " nop" "\n"
957 "\t" " srl $a3, $a3, 2" "\n"
958 "\t" " sll $a3, $a3, 2" "\n"
959 "\t" " jalr $a3" "\n"
960 "\t" " nop" "\n"
961 "\t" " b .Lexception_interrupt_handler_code_10" "\n"
962 "\t" " nop" "\n"
963 "\t" ".Lexception_interrupt_handler_code_9:" "\n"
964 "\t" " lw $v0, 0x14($sp)" "\n"
965 "\t" " nop" "\n"
966 "\t" " sw $s0, 0x40($v0)" "\n"
967 "\t" " sw $s1, 0x44($v0)" "\n"
968 "\t" " sw $s2, 0x48($v0)" "\n"
969 "\t" " sw $s3, 0x4C($v0)" "\n"
970 "\t" " sw $s4, 0x50($v0)" "\n"
971 "\t" " sw $s5, 0x54($v0)" "\n"
972 "\t" " sw $s6, 0x58($v0)" "\n"
973 "\t" " sw $s7, 0x5C($v0)" "\n"
974 "\t" " addiu $t0, $zero, -0x2" "\n"
975 "\t" " sw $t0, 0x0($v0)" "\n"
976 "\t" " srl $a3, $a3, 2" "\n"
977 "\t" " sll $a3, $a3, 2" "\n"
978 "\t" " jalr $a3" "\n"
979 "\t" " nop" "\n"
980 "\t" ".Lexception_interrupt_handler_code_10:" "\n"
981 "\t" " lw $a3, 0x10($sp)" "\n"
982 "\t" " mtc0 $zero, $12" "\n"
983 "\t" " lui $a0, (0xBF801074 >> 16)" "\n"
984 "\t" " beq $zero, $v0, .Lexception_interrupt_handler_code_11" "\n"
985 "\t" " ori $a0, $a0, (0xBF801074 & 0xFFFF)" "\n"
986 "\t" " lw $a2, 0x0($a0)" "\n"
987 "\t" " nop" "\n"
988 "\t" " or $a3, $a3, $a2" "\n"
989 "\t" " sw $a3, 0x0($a0)" "\n"
990 "\t" ".Lexception_interrupt_handler_code_11:" "\n"
991 "\t" " lw $a0, 0x14($sp)" "\n"
992 "\t" " jal QueryIntrStack" "\n"
993 "\t" " nop" "\n"
994 "\t" " bnez $v0, .Lexception_interrupt_handler_code_14" "\n"
995 "\t" " nop" "\n"
996 "\t" " lui $v1, %hi(ctx_switch_required_cb)" "\n"
997 "\t" " lw $v1, %lo(ctx_switch_required_cb)($v1)" "\n"
998 "\t" " nop" "\n"
999 "\t" " jalr $v1" "\n"
1000 "\t" " nop" "\n"
1001 "\t" " lw $a0, 0x14($sp)" "\n"
1002 "\t" " beqz $v0, .Lexception_interrupt_handler_code_14" "\n"
1003 "\t" " nop" "\n"
1004 "\t" " lw $v0, 0x0($a0)" "\n"
1005 "\t" " addiu $a1, $zero, -0x2" "\n"
1006 "\t" " beq $v0, $a1, intrman_perform_context_switch" "\n"
1007 "\t" " nop" "\n"
1008 "\t" " lui $a1, (0xFF00FFFE >> 16)" "\n"
1009 "\t" " ori $a1, $a1, (0xFF00FFFE & 0xFFFF)" "\n"
1010 "\t" " beq $v0, $a1, .Lexception_interrupt_handler_code_12" "\n"
1011 "\t" " nop" "\n"
1012 "\t" " sw $t0, 0x20($a0)" "\n"
1013 "\t" " sw $t1, 0x24($a0)" "\n"
1014 "\t" " sw $t2, 0x28($a0)" "\n"
1015 "\t" " sw $t3, 0x2C($a0)" "\n"
1016 "\t" " sw $t4, 0x30($a0)" "\n"
1017 "\t" " sw $t5, 0x34($a0)" "\n"
1018 "\t" " sw $t6, 0x38($a0)" "\n"
1019 "\t" " sw $t7, 0x3C($a0)" "\n"
1020 "\t" " sw $t8, 0x60($a0)" "\n"
1021 "\t" " sw $t9, 0x64($a0)" "\n"
1022 "\t" " sw $gp, 0x70($a0)" "\n"
1023 "\t" " sw $fp, 0x78($a0)" "\n"
1024 "\t" ".Lexception_interrupt_handler_code_12:" "\n"
1025 "\t" " sw $s0, 0x40($a0)" "\n"
1026 "\t" " sw $s1, 0x44($a0)" "\n"
1027 "\t" " sw $s2, 0x48($a0)" "\n"
1028 "\t" " sw $s3, 0x4C($a0)" "\n"
1029 "\t" " sw $s4, 0x50($a0)" "\n"
1030 "\t" " sw $s5, 0x54($a0)" "\n"
1031 "\t" " sw $s6, 0x58($a0)" "\n"
1032 "\t" " sw $s7, 0x5C($a0)" "\n"
1033 "\t" " addiu $v0, $zero, -0x2" "\n"
1034 "\t" " sw $v0, 0x0($a0)" "\n"
1035 "\t" "intrman_perform_context_switch:" "\n"
1036 "\t" " lui $v1, %hi(ctx_switch_cb)" "\n"
1037 "\t" " lw $v1, %lo(ctx_switch_cb)($v1)" "\n"
1038 "\t" " nop" "\n"
1039 "\t" " jalr $v1" "\n"
1040 "\t" " nop" "\n"
1041 "\t" " addu $a0, $v0, $zero" "\n"
1042 "\t" ".Lexception_interrupt_handler_code_14:" "\n"
1043 "\t" " addu $sp, $a0, $zero" "\n"
1044 "\t" " lw $a0, 0x0($sp)" "\n"
1045 "\t" " lui $a1, (0xF0FF000C >> 16)" "\n"
1046 "\t" " ori $a1, $a1, (0xF0FF000C & 0xFFFF)" "\n"
1047 "\t" " beq $a0, $a1, .Lintrman_perform_context_switch_4" "\n"
1048 "\t" " lui $a1, (0xAC0000FE >> 16)" "\n"
1049 "\t" " ori $a1, $a1, (0xAC0000FE & 0xFFFF)" "\n"
1050 "\t" " beq $a0, $a1, .Lintrman_perform_context_switch_2" "\n"
1051 "\t" " lui $a1, (0xFF00FFFE >> 16)" "\n"
1052 "\t" " ori $a1, $a1, (0xFF00FFFE & 0xFFFF)" "\n"
1053 "\t" " beq $a0, $a1, .Lintrman_perform_context_switch_1" "\n"
1054 "\t" " nop" "\n"
1055 "\t" " lw $s0, 0x40($sp)" "\n"
1056 "\t" " lw $s1, 0x44($sp)" "\n"
1057 "\t" " lw $s2, 0x48($sp)" "\n"
1058 "\t" " lw $s3, 0x4C($sp)" "\n"
1059 "\t" " lw $s4, 0x50($sp)" "\n"
1060 "\t" " lw $s5, 0x54($sp)" "\n"
1061 "\t" " lw $s6, 0x58($sp)" "\n"
1062 "\t" " lw $s7, 0x5C($sp)" "\n"
1063 "\t" ".Lintrman_perform_context_switch_1:" "\n"
1064 "\t" " lw $t0, 0x20($sp)" "\n"
1065 "\t" " lw $t1, 0x24($sp)" "\n"
1066 "\t" " lw $t2, 0x28($sp)" "\n"
1067 "\t" " lw $t3, 0x2C($sp)" "\n"
1068 "\t" " lw $t4, 0x30($sp)" "\n"
1069 "\t" " lw $t5, 0x34($sp)" "\n"
1070 "\t" " lw $t6, 0x38($sp)" "\n"
1071 "\t" " lw $t7, 0x3C($sp)" "\n"
1072 "\t" " lw $t8, 0x60($sp)" "\n"
1073 "\t" " lw $t9, 0x64($sp)" "\n"
1074 "\t" " lw $gp, 0x70($sp)" "\n"
1075 "\t" " lw $fp, 0x78($sp)" "\n"
1076 "\t" ".Lintrman_perform_context_switch_2:" "\n"
1077#ifndef BUILDING_INTRMANP
1078 "\t" " lw $v1, 0x90($sp)" "\n"
1079 "\t" " lui $v0, (0xBF801078 >> 16)" "\n"
1080 "\t" " ori $v0, $v0, (0xBF801078 & 0xFFFF)" "\n"
1081 "\t" " sw $v1, 0x0($v0)" "\n"
1082#endif
1083 "\t" " lw $v0, 0x80($sp)" "\n"
1084 "\t" " lw $v1, 0x84($sp)" "\n"
1085 "\t" " mthi $v0" "\n"
1086 "\t" " mtlo $v1" "\n"
1087 "\t" " lw $a0, 0x88($sp)" "\n"
1088 "\t" " lw $ra, 0x7C($sp)" "\n"
1089 "\t" " srl $a0, $a0, 1" "\n"
1090 "\t" " sll $a0, $a0, 1" "\n"
1091 "\t" " mtc0 $a0, $12" "\n"
1092 "\t" " lw $at, 0x4($sp)" "\n"
1093 "\t" " lw $v0, 0x8($sp)" "\n"
1094 "\t" " lw $v1, 0xC($sp)" "\n"
1095 "\t" " lw $a0, 0x10($sp)" "\n"
1096 "\t" " lw $a1, 0x14($sp)" "\n"
1097 "\t" " lw $a2, 0x18($sp)" "\n"
1098 "\t" " lw $a3, 0x1C($sp)" "\n"
1099 "\t" ".Lintrman_perform_context_switch_3:" "\n"
1100 "\t" " lw $k0, 0x8C($sp)" "\n"
1101 "\t" " lw $sp, 0x74($sp)" "\n"
1102 "\t" " jr $k0" "\n"
1103 "\t" " .word 0x42000010" "\n" // cop0 0x10 # return from exception
1104 "\t" " nop" "\n"
1105 "\t" ".Lintrman_perform_context_switch_4:" "\n"
1106#ifndef BUILDING_INTRMANP
1107 "\t" " lw $v1, 0x90($sp)" "\n"
1108 "\t" " lui $v0, (0xBF801078 >> 16)" "\n"
1109 "\t" " ori $v0, $v0, (0xBF801078 & 0xFFFF)" "\n"
1110 "\t" " sw $v1, 0x0($v0)" "\n"
1111#endif
1112 "\t" " lw $s0, 0x40($sp)" "\n"
1113 "\t" " lw $s1, 0x44($sp)" "\n"
1114 "\t" " lw $s2, 0x48($sp)" "\n"
1115 "\t" " lw $s3, 0x4C($sp)" "\n"
1116 "\t" " lw $s4, 0x50($sp)" "\n"
1117 "\t" " lw $s5, 0x54($sp)" "\n"
1118 "\t" " lw $s6, 0x58($sp)" "\n"
1119 "\t" " lw $s7, 0x5C($sp)" "\n"
1120 "\t" " lw $v0, 0x8($sp)" "\n"
1121 "\t" " lw $v1, 0xC($sp)" "\n"
1122 "\t" " lw $gp, 0x70($sp)" "\n"
1123 "\t" " lw $fp, 0x78($sp)" "\n"
1124 "\t" " lw $a0, 0x88($sp)" "\n"
1125 "\t" " lw $ra, 0x7C($sp)" "\n"
1126 "\t" " srl $a0, $a0, 1" "\n"
1127 "\t" " sll $a0, $a0, 1" "\n"
1128 "\t" " mtc0 $a0, $12" "\n"
1129 "\t" " b .Lintrman_perform_context_switch_3" "\n"
1130 "\t" " nop" "\n"
1131 "\t" ".set pop" "\n"
1132);
1133// clang-format on
1134
1135static void *new_context_stub_cb(void *ctx)
1136{
1137 return ctx;
1138}
1139
1140static int preempt_stub_cb(int unk)
1141{
1142 (void)unk;
1143
1144 return 0;
1145}
1146
1147// clang-format off
1148__asm__ (
1149 "\t" ".set push" "\n"
1150 "\t" ".set noat" "\n"
1151 "\t" ".set noreorder" "\n"
1152 "\t" "exception_priority_interrupt_handler:" "\n"
1153 "\t" " .word 0" "\n"
1154 "\t" " .word 0" "\n"
1155
1156 "\t" "exception_priority_interrupt_handler_code:" "\n"
1157 "\t" " lw $k0, 0x408($zero)" "\n"
1158 "\t" " lw $at, 0x400($zero)" "\n"
1159 "\t" " mtc0 $k0, $12" "\n"
1160 "\t" " lw $k0, 0x404($zero)" "\n"
1161 "\t" " nop" "\n"
1162 "\t" " jr $k0" "\n"
1163 "\t" " .word 0x42000010" "\n" // cop0 0x10 # return from exception
1164 "\t" ".set pop" "\n"
1165);
1166
1167__asm__ (
1168 "\t" ".set push" "\n"
1169 "\t" ".set noat" "\n"
1170 "\t" ".set noreorder" "\n"
1171 "\t" "exception_system_handler:" "\n"
1172 "\t" " .word 0" "\n"
1173 "\t" " .word 0" "\n"
1174
1175 "\t" "exception_system_handler_code:" "\n"
1176 "\t" " andi $k0, $v0, 0x3" "\n"
1177 "\t" " beqz $k0, syscall_handler_dispatch" "\n"
1178
1179 "\t" "syscall_handler_callnext:" "\n"
1180 "\t" " lui $k0, %hi(exception_system_handler)" "\n"
1181 "\t" " lw $k0, %lo(exception_system_handler)($k0)" "\n"
1182 "\t" " nop" "\n"
1183 "\t" " jr $k0" "\n"
1184 "\t" " nop" "\n"
1185
1186 "\t" "syscall_handler_dispatch:" "\n"
1187 "\t" " lui $k0, %hi(syscall_dsp)" "\n"
1188 "\t" " addiu $k0, $k0, %lo(syscall_dsp)" "\n"
1189 "\t" " addu $k0, $k0, $v0" "\n"
1190 "\t" " lw $k0, 0x0($k0)" "\n"
1191 "\t" " nop" "\n"
1192 "\t" " jr $k0" "\n"
1193 "\t" " nop" "\n"
1194
1195 "\t" "syscall_handler_0C_CpuInvokeInKmode:" "\n"
1196 "\t" " lw $t0, 0x404($zero)" "\n"
1197 "\t" " lw $t1, 0x408($zero)" "\n"
1198 "\t" " addiu $sp, $sp, -0x1C" "\n"
1199 "\t" " sw $ra, 0x10($sp)" "\n"
1200 "\t" " sw $t0, 0x14($sp)" "\n"
1201 "\t" " sw $t1, 0x18($sp)" "\n"
1202 "\t" " addu $t0, $a0, $zero" "\n"
1203 "\t" " addu $a0, $a1, $zero" "\n"
1204 "\t" " addu $a1, $a2, $zero" "\n"
1205 "\t" " addu $a2, $a3, $zero" "\n"
1206 "\t" " jalr $t0" "\n"
1207 "\t" " nop" "\n"
1208 "\t" " lw $ra, 0x10($sp)" "\n"
1209 "\t" " lw $t0, 0x14($sp)" "\n"
1210 "\t" " lw $t1, 0x18($sp)" "\n"
1211 "\t" " addiu $sp, $sp, 0x1C" "\n"
1212 "\t" " mtc0 $t1, $12" "\n"
1213 "\t" " addiu $t0, $t0, 0x4" "\n"
1214 "\t" " jr $t0" "\n"
1215 "\t" " .word 0x42000010" "\n" // cop0 0x10 # return from exception
1216
1217 "\t" "syscall_handler_10:" "\n"
1218 "\t" " lw $t0, 0x408($zero)" "\n"
1219 "\t" " addiu $t1, $zero, 0x414" "\n"
1220 "\t" " and $v0, $t0, $t1" "\n"
1221 "\t" " addiu $at, $zero, -0x405" "\n"
1222 "\t" " b do_set_status_register" "\n"
1223 "\t" " and $t0, $t0, $at" "\n"
1224
1225 "\t" "syscall_handler_14:" "\n"
1226 "\t" " lw $t0, 0x408($zero)" "\n"
1227 "\t" " addiu $t1, $zero, -0x415" "\n"
1228 "\t" " and $t0, $t0, $t1" "\n"
1229 "\t" " b do_set_status_register" "\n"
1230 "\t" " or $t0, $t0, $a0" "\n"
1231
1232 "\t" "syscall_handler_08_CpuEnableIntr:" "\n"
1233 "\t" " lw $t0, 0x408($zero)" "\n"
1234 "\t" " b do_set_status_register" "\n"
1235 "\t" " ori $t0, $t0, 0x404" "\n"
1236
1237 "\t" "syscall_handler_04_CpuDisableIntr:" "\n"
1238 "\t" " lw $t0, 0x408($zero)" "\n"
1239 "\t" " addiu $t1, $zero, 0x404" "\n"
1240 "\t" " and $v0, $t0, $t1" "\n"
1241 "\t" " beq $v0, $t1, 9f" "\n"
1242 "\t" " nop" "\n"
1243 "\t" " addiu $v0, $zero, 0x0" "\n"
1244 "\t" "9:" "\n"
1245 "\t" " addiu $at, $zero, -0x405" "\n"
1246 "\t" " and $t0, $t0, $at" "\n"
1247 "\t" "do_set_status_register:" "\n"
1248 "\t" " mtc0 $t0, $12" "\n" // $12
1249
1250 "\t" "syscall_handler_00_return_from_exception:" "\n"
1251 "\t" " lw $a0, 0x404($zero)" "\n"
1252 "\t" " nop" "\n"
1253 "\t" " addiu $a0, $a0, 0x4" "\n"
1254 "\t" " jr $a0" "\n"
1255 "\t" " .word 0x42000010" "\n" // cop0 0x10 # return from exception
1256
1257 "\t" "syscall_handler_20_threadman:" "\n"
1258 "\t" " addiu $sp, $sp, -0x98" "\n"
1259#ifndef BUILDING_INTRMANP
1260 "\t" " sw $a2, 0x90($sp)" "\n"
1261#endif
1262 "\t" " lw $t0, 0x408($zero)" "\n"
1263#ifdef BUILDING_INTRMANP
1264 "\t" " addiu $t1, $zero, -0x415" "\n"
1265 "\t" " and $t0, $t0, $t1" "\n"
1266 "\t" " or $t0, $t0, $a2" "\n"
1267#endif
1268 "\t" " lw $t1, 0x404($zero)" "\n"
1269 "\t" " sw $t0, 0x88($sp)" "\n"
1270 "\t" " addiu $t1, $t1, 0x4" "\n"
1271 "\t" " sw $t1, 0x8C($sp)" "\n"
1272 "\t" " sw $s0, 0x40($sp)" "\n"
1273 "\t" " sw $s1, 0x44($sp)" "\n"
1274 "\t" " sw $s2, 0x48($sp)" "\n"
1275 "\t" " sw $s3, 0x4C($sp)" "\n"
1276 "\t" " sw $s4, 0x50($sp)" "\n"
1277 "\t" " sw $s5, 0x54($sp)" "\n"
1278 "\t" " sw $s6, 0x58($sp)" "\n"
1279 "\t" " sw $s7, 0x5C($sp)" "\n"
1280 "\t" " sw $a0, 0x8($sp)" "\n"
1281 "\t" " sw $a1, 0xC($sp)" "\n"
1282 "\t" " sw $gp, 0x70($sp)" "\n"
1283 "\t" " sw $fp, 0x78($sp)" "\n"
1284 "\t" " sw $ra, 0x7C($sp)" "\n"
1285 "\t" " addiu $t0, $sp, 0x98" "\n"
1286 "\t" " sw $t0, 0x74($sp)" "\n"
1287 "\t" " lui $t0, (0xF0FF000C >> 16)" "\n"
1288 "\t" " ori $t0, $t0, (0xF0FF000C & 0xFFFF)" "\n"
1289 "\t" " sw $t0, 0x0($sp)" "\n"
1290 "\t" " addu $a0, $sp, $zero" "\n"
1291 "\t" " addiu $sp, $sp, -0x10" "\n"
1292 "\t" " j intrman_perform_context_switch" "\n"
1293 "\t" " nop" "\n"
1294 "\t" ".set pop" "\n"
1295);
1296// clang-format on
1297
1298extern u32 syscall_handler_00_return_from_exception[];
1299extern u32 syscall_handler_04_CpuDisableIntr[];
1300extern u32 syscall_handler_08_CpuEnableIntr[];
1301extern u32 syscall_handler_0C_CpuInvokeInKmode[];
1302extern u32 syscall_handler_10[];
1303extern u32 syscall_handler_14[];
1304extern u32 syscall_handler_callnext[];
1305extern u32 syscall_handler_20_threadman[];
1306
1307void *syscall_dsp[] = {
1308 &syscall_handler_00_return_from_exception,
1309 &syscall_handler_04_CpuDisableIntr,
1310 &syscall_handler_08_CpuEnableIntr,
1311 &syscall_handler_0C_CpuInvokeInKmode,
1312 &syscall_handler_10,
1313 &syscall_handler_14,
1314 &syscall_handler_callnext,
1315 &syscall_handler_callnext,
1316 &syscall_handler_20_threadman,
1317 &syscall_handler_callnext,
1318 &syscall_handler_callnext,
1319 &syscall_handler_callnext,
1320 &syscall_handler_callnext,
1321 &syscall_handler_callnext,
1322 &syscall_handler_callnext,
1323 &syscall_handler_callnext,
1324};
int RegisterExceptionHandler(int exception, exception_handler_t handler)
Definition excepman.c:70
int CpuEnableIntr()
Definition intrman.c:250
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
void DisableDispatchIntr(int irq)
Definition intrman.c:494
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
void SetNewCtxCb(void *cb)
Definition intrman.c:713
int CpuDisableIntr()
Definition intrman.c:238
void EnableDispatchIntr(int irq)
Definition intrman.c:468
int QueryIntrContext(void)
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
@ IOP_IRQ_DMA
Definition intrman.h:31
@ IOP_IRQ_SW1
Definition intrman.h:75
@ IOP_IRQ_SW2
Definition intrman.h:77
@ IOP_IRQ_DMA_BERR
Definition intrman.h:66
int EnableIntr(int irq)
Definition intrman.c:346