+/*
+ * Ensures the stack is safely aligned, usually in preparation for an external branch
+ * arg0: temp register for storing the stack offset
+ * arg1: temp register for storing the previous stack pointer
+ */
+.macro ALIGN_STACK
+/*
+ * For armv7k ABI, the stack needs to be 16-byte aligned
+ */
+#if __BIGGEST_ALIGNMENT__ > 4
+ and $0, sp, #0x0F // sp mod 16-bytes
+ cmp $0, #4 // need space for the sp on the stack
+ addlt $0, $0, #0x10 // make room if needed, but keep stack aligned
+ mov $1, sp // get current sp
+ sub sp, sp, $0 // align stack
+ str $1, [sp] // store previous sp on stack
+#endif
+.endmacro
+
+/*
+ * Restores the stack pointer to its previous value following an ALIGN_STACK call
+ */
+.macro UNALIGN_STACK
+#if __BIGGEST_ALIGNMENT__ > 4
+ ldr sp, [sp]
+#endif
+.endmacro
+
+/*
+ * Checks that cpu is currently in the expected mode, panics if not.
+ * arg0: the expected mode, should be one of the PSR_*_MODE defines
+ */
+.macro VERIFY_EXCEPTION_MODE
+ mrs sp, cpsr // Read cpsr
+ and sp, sp, #PSR_MODE_MASK // Extract current mode
+ cmp sp, $0 // Check specified mode
+ movne r0, sp
+ bne EXT(ExceptionVectorPanic)
+.endmacro
+
+/*
+ * Checks previous processor mode. If usermode, will execute the code
+ * following the macro to handle the userspace exception. Otherwise,
+ * will branch to a ELSE_IF_KERNELMODE_EXCEPTION call with the same
+ * argument.
+ * arg0: arbitrary string indicating the exception class, e.g. 'dataabt'
+ */
+.macro IF_USERMODE_EXCEPTION
+ mrs sp, spsr
+ and sp, sp, #PSR_MODE_MASK // Is it from user?
+ cmp sp, #PSR_USER_MODE
+ beq $0_from_user
+ cmp sp, #PSR_IRQ_MODE
+ beq $0_from_irq
+ cmp sp, #PSR_FIQ_MODE
+ beq $0_from_fiq
+ bne $0_from_svc
+$0_from_user:
+.endmacro
+
+/*
+ * Handles an exception taken from kernelmode (IRQ/FIQ/SVC/etc).
+ * Places the processor into the correct mode and executes the
+ * code following the macro to handle the kernel exception.
+ * Intended to be paired with a prior call to IF_USERMODE_EXCEPTION.
+ * arg0: arbitrary string indicating the exception class, e.g. 'dataabt'
+ */
+.macro ELSE_IF_KERNELMODE_EXCEPTION
+$0_from_irq:
+ cpsid i, #PSR_IRQ_MODE
+ b $0_from_kernel
+$0_from_fiq:
+ cpsid i, #PSR_FIQ_MODE
+ b $0_from_kernel
+$0_from_svc:
+ cpsid i, #PSR_SVC_MODE
+$0_from_kernel:
+.endmacro
+
+LEXT(fleh_undef)
+VERIFY_EXCEPTION_MODE PSR_UND_MODE
+ mrs sp, spsr // For check the previous mode