libnx/nx/source/runtime/exception.s

191 lines
4.2 KiB
ArmAsm

.macro CODE_BEGIN name
.section .text.\name, "ax", %progbits
.global \name
.type \name, %function
.align 2
.cfi_startproc
\name:
.endm
.macro CODE_END
.cfi_endproc
.endm
// Called by crt0 when the args at the time of entry indicate an exception occured.
.weak __libnx_exception_handler
.weak __libnx_exception_entry
CODE_BEGIN __libnx_exception_entry
cmp x1, #0
beq __libnx_exception_entry_abort
// Abort exception handling when __libnx_exception_handler is not defined.
adrp x5, :got:__libnx_exception_handler
ldr x5, [x5, #:got_lo12:__libnx_exception_handler]
cmp x5, #0
beq __libnx_exception_entry_abort
// Load IsCurrentProcessBeingDebugged.
stp x9, x10, [sp, #-16]!
stp x11, x12, [sp, #-16]!
stp x13, x14, [sp, #-16]!
stp x15, x16, [sp, #-16]!
stp x17, x18, [sp, #-16]!
stp x19, x20, [sp, #-16]!
str x21, [sp, #-16]!
stp x0, x1, [sp, #-16]!
sub sp, sp, #16
mov x0, sp
mov x1, #8
mov w2, wzr
mov x3, #0
bl svcGetInfo
mov w6, w0
ldr x7, [sp], #16
ldp x0, x1, [sp], #16
ldr x21, [sp], #16
ldp x19, x20, [sp], #16
ldp x17, x18, [sp], #16
ldp x15, x16, [sp], #16
ldp x13, x14, [sp], #16
ldp x11, x12, [sp], #16
ldp x9, x10, [sp], #16
// Abort when svcGetInfo failed.
cbnz w6, __libnx_exception_entry_abort
// Abort when IsCurrentProcessBeingDebugged is set where __nx_exception_ignoredebug==0.
adrp x6, __nx_exception_ignoredebug
ldr w5, [x6, #:lo12:__nx_exception_ignoredebug]
cbnz w5, __libnx_exception_entry_start
cbnz x7, __libnx_exception_entry_abort
__libnx_exception_entry_start:
adrp x2, __nx_exceptiondump
add x2, x2, #:lo12:__nx_exceptiondump
mov x5, x2
// error_desc
str w0, [x2], #4
// pad
str wzr, [x2], #4
str wzr, [x2], #4
str wzr, [x2], #4
// GPRs 0..8
ldp x3, x4, [x1]
str x5, [x1], #16 // x0 = __nx_exceptiondump
stp x3, x4, [x2], #16
ldp x3, x4, [x1], #16
stp x3, x4, [x2], #16
ldp x3, x4, [x1], #16
stp x3, x4, [x2], #16
ldp x3, x4, [x1], #16
stp x3, x4, [x2], #16
ldr x3, [x1], #8
str x3, [x2], #8
// GPRs 9..28
str x9, [x2], #8
stp x10, x11, [x2], #16
stp x12, x13, [x2], #16
stp x14, x15, [x2], #16
stp x16, x17, [x2], #16
stp x18, x19, [x2], #16
stp x20, x21, [x2], #16
stp x22, x23, [x2], #16
stp x24, x25, [x2], #16
stp x26, x27, [x2], #16
str x28, [x2], #8
// fp
str x29, [x2], #8
// lr
ldr x3, [x1], #8
str x3, [x2], #8
// sp
adrp x4, __nx_exception_stack
add x4, x4, #:lo12:__nx_exception_stack
adrp x5, __nx_exception_stack_size
ldr x5, [x5, #:lo12:__nx_exception_stack_size]
add x4, x4, x5
ldr x3, [x1]
str x4, [x1], #8 // sp = __nx_exception_stack + __nx_exception_stack_size
str x3, [x2], #8
// elr_el1 (pc)
adrp x4, __libnx_exception_returnentry
add x4, x4, #:lo12:__libnx_exception_returnentry
ldr x3, [x1]
str x4, [x1], #8 // elr_el1 = __libnx_exception_returnentry
str x3, [x2], #8
// padding
str xzr, [x2], #8
// fpu_gprs
stp q0, q1, [x2], #32
stp q2, q3, [x2], #32
stp q4, q5, [x2], #32
stp q6, q7, [x2], #32
stp q8, q9, [x2], #32
stp q10, q11, [x2], #32
stp q12, q13, [x2], #32
stp q14, q15, [x2], #32
stp q16, q17, [x2], #32
stp q18, q19, [x2], #32
stp q20, q21, [x2], #32
stp q22, q23, [x2], #32
stp q24, q25, [x2], #32
stp q26, q27, [x2], #32
stp q28, q29, [x2], #32
stp q30, q31, [x2], #32
// 4 u32s: pstate, afsr0, afsr1, and esr.
ldr w3, [x1], #4
str w3, [x2], #4
ldr w3, [x1], #4
str w3, [x2], #4
ldr w3, [x1], #4
str w3, [x2], #4
ldr w3, [x1], #4
str w3, [x2], #4
//far
ldr x3, [x1], #8
str x3, [x2], #8
mov w0, wzr
b __libnx_exception_entry_end
__libnx_exception_entry_abort:
mov w0, #0xf801
__libnx_exception_entry_end:
bl svcReturnFromException
b .
CODE_END
// Jumped to by kernel in svcReturnFromException via the overridden elr_el1, with x0 set to __nx_exceptiondump.
CODE_BEGIN __libnx_exception_returnentry
bl __libnx_exception_handler
mov w0, wzr
mov x1, #0
mov x2, #0
bl svcBreak
b .
CODE_END