summaryrefslogtreecommitdiff
path: root/arm9/lib/src/OS_exception.c
blob: 5a66b2c444addcb046f7e6293fcd6d7de82f0697 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "OS_exception.h"
#include "function_target.h"
#include "OS_protectionUnit.h"

static OSiExContext OSi_ExContext;

static OSExceptionHandler OSi_UserExceptionHandler;
static void *OSi_UserExceptionHandlerArg;

static void *OSi_DebuggerHandler = NULL;

#define HW_EXCEP_VECTOR_BUF_FOR_DEBUGGER 0x027ffd9c

ARM_FUNC void OS_InitException(void)
{
    if (0x2600000 <= *(u32 *)HW_EXCEP_VECTOR_BUF_FOR_DEBUGGER
        && *(u32 *)HW_EXCEP_VECTOR_BUF_FOR_DEBUGGER < 0x2800000)
    {
        OSi_DebuggerHandler = *(void **)HW_EXCEP_VECTOR_BUF_FOR_DEBUGGER;
    }
    else
    {
        OSi_DebuggerHandler = NULL;
    }

    if (!OSi_DebuggerHandler)
    {
        *(u32 *)(HW_EXCEP_VECTOR_BUF_FOR_DEBUGGER) = (u32)OSi_ExceptionHandler;

        *(u32 *)(HW_EXCP_VECTOR_BUF) = (u32)OSi_ExceptionHandler;
    }

    OSi_UserExceptionHandler = NULL;
}

ARM_FUNC asm void OSi_ExceptionHandler(void)
{
    ldr r12, =OSi_DebuggerHandler
    ldr r12, [r12]
    cmp r12, #0
    movne lr, pc
    bxne r12

    ldr r12, =HW_ITCM_END
    stmfd r12!, {r0-r3, sp, lr}

    and r0, sp, #1
    mov sp, r12

    mrs r1, cpsr
    and r1, r1, #0x1f

    teq r1, #0x17
    bne _020CCA38
    bl OSi_GetAndDisplayContext
    b _020CCA44

_020CCA38:
    teq r1, #0x1b
    bne _020CCA44
    bl OSi_GetAndDisplayContext

_020CCA44:
    ldr r12, =OSi_DebuggerHandler
    ldr r12, [r12]
    cmp r12, #0

_020CCA50:
    beq _020CCA50

_020CCA54:
    mov r0, r0
    b _020CCA54

    ldmfd sp!, {r0-r3, r12, lr}
    mov sp, r12
    bx lr
}

ARM_FUNC static asm void OSi_GetAndDisplayContext(void)
{
    stmfd sp!, {r0, lr}

    bl OSi_SetExContext
    bl OSi_DisplayExContext

    ldmfd sp!, {r0, lr}
    bx lr
}

ARM_FUNC static asm void OSi_SetExContext(void)
{
    ldr r1, =OSi_ExContext;

    mrs r2, cpsr
    str r2, [r1, #OSiExContext.debug[1]]

    str r0, [r1, #OSiExContext.exinfo]

    ldr r0, [r12, #0]
    str r0, [r1, #4]
    ldr r0, [r12, #4]
    str r0, [r1, #8]
    ldr r0, [r12, #8]
    str r0, [r1, #12]
    ldr r0, [r12, #12]
    str r0, [r1, #16]
    ldr r2, [r12, #16]
    bic r2, r2, #1

    add r0, r1, #20
    stmia r0, {r4-r11}

    str r12, [r1, #OSiExContext.debug[0]]

    ldr r0, [r2, #0]
    str r0, [r1, #OSiExContext.cp15]
    ldr r3, [r2, #4]
    str r3, [r1, #0]
    ldr r0, [r2, #8]
    str r0, [r1, #52]
    ldr r0, [r2, #12]
    str r0, [r1, #64]

    mrs r0, cpsr
    orr r3, r3, #0x80
    bic r3, r3, #0x20
    msr cpsr_cxsf, r3

    str sp, [r1, #56]
    str lr, [r1, #60]
    mrs r2, spsr

    str r2, [r1, #OSiExContext.debug[3]]

    msr cpsr_cxsf, r0
    bx lr
}

ARM_FUNC static void OSi_DisplayExContext(void)
{
    if (OSi_UserExceptionHandler)
    {
        asm
        {
            mov r0, sp
            ldr r1, =0x9f
            msr CPSR_cxsf, r1
            mov sp, r0
        }

        OS_EnableProtectionUnit();

        ((void (*)(u32, void *))OSi_UserExceptionHandler)((u32)&OSi_ExContext, OSi_UserExceptionHandlerArg);

        OS_DisableProtectionUnit();
    }
}