use core::arch::global_asm; global_asm!( r#" .section .text .align 4 .globl trap_vector trap_vector: csrrw sp, sscratch, sp bnez sp, _from_user csrrw sp, sscratch, sp _from_user: addi sp, sp, -272 sd x1, 8(sp) sd x3, 24(sp) sd x4, 32(sp) sd x5, 40(sp) sd x6, 48(sp) sd x7, 56(sp) sd x8, 64(sp) sd x9, 72(sp) sd x10, 80(sp) sd x11, 88(sp) sd x12, 96(sp) sd x13, 104(sp) sd x14, 112(sp) sd x15, 120(sp) sd x16, 128(sp) sd x17, 136(sp) sd x18, 144(sp) sd x19, 152(sp) sd x20, 160(sp) sd x21, 168(sp) sd x22, 176(sp) sd x23, 184(sp) sd x24, 192(sp) sd x25, 200(sp) sd x26, 208(sp) sd x27, 216(sp) sd x28, 224(sp) sd x29, 232(sp) sd x30, 240(sp) sd x31, 248(sp) csrr t0, sscratch sd t0, 16(sp) csrr t0, sepc sd t0, 256(sp) csrr t0, sstatus sd t0, 264(sp) mv a0, sp call trap_handler_rust j _restore_frame # trap_return(frame): resume `frame` as if returning from the trap that saved it. .globl trap_return trap_return: mv sp, a0 _restore_frame: ld t0, 256(sp) csrw sepc, t0 ld t0, 264(sp) csrw sstatus, t0 andi t1, t0, 0x100 bnez t1, _restore_smode ld t0, 16(sp) csrw sscratch, t0 _restore_smode: ld x1, 8(sp) ld x3, 24(sp) ld x4, 32(sp) ld x6, 48(sp) ld x7, 56(sp) ld x8, 64(sp) ld x9, 72(sp) ld x10, 80(sp) ld x11, 88(sp) ld x12, 96(sp) ld x13, 104(sp) ld x14, 112(sp) ld x15, 120(sp) ld x16, 128(sp) ld x17, 136(sp) ld x18, 144(sp) ld x19, 152(sp) ld x20, 160(sp) ld x21, 168(sp) ld x22, 176(sp) ld x23, 184(sp) ld x24, 192(sp) ld x25, 200(sp) ld x26, 208(sp) ld x27, 216(sp) ld x28, 224(sp) ld x29, 232(sp) ld x30, 240(sp) ld x31, 248(sp) # t0 (x5) is restored last on each path; it is the only scratch register. csrr t0, sstatus andi t0, t0, 0x100 bnez t0, _sret_smode ld x5, 40(sp) addi sp, sp, 272 csrrw sp, sscratch, sp sret _sret_smode: ld x5, 40(sp) addi sp, sp, 272 sret "# );