.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