trap-entry-single-stack.S (2907B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 // This file provides assembly glue for handling traps 5 // (interrupts or exceptions) and safely saving and 6 // restoring the processor state of the code running 7 // when the trap happened. 8 9 // It assume a single stack setup -- when an interrupt 10 // or exception occurs, the state will be saved on the 11 // active stack that sp is pointing to. 12 13 // It will call into interrupt_handler() or exception_handler() 14 // to process the interrupt or exception. 15 16 // For interrupts, only the registers that must be saved 17 // are saved (the others are callee-save so the C code 18 // called into will save them if necessary). 19 20 // For exceptions, ALL registers are saved so that the 21 // exception handler my inspect, display, or modify them 22 // as necesary. 23 24 // hw/context.h defines structures tframe_t and eframe_t 25 // that correspond to how the registers are saved on the 26 // stack 27 28 .global trap_entry 29 trap_entry: 30 // reserve stack space for a full eframe_t 31 addi sp, sp, - (32 * 4) 32 33 // save caller-save registers (tframe_t) 34 sw ra, 0x00(sp) 35 sw t0, 0x04(sp) 36 sw t1, 0x08(sp) 37 sw t2, 0x0C(sp) 38 sw t3, 0x10(sp) 39 sw t4, 0x14(sp) 40 sw t5, 0x18(sp) 41 sw t6, 0x1C(sp) 42 sw a0, 0x20(sp) 43 sw a1, 0x24(sp) 44 sw a2, 0x28(sp) 45 sw a3, 0x2C(sp) 46 sw a4, 0x30(sp) 47 sw a5, 0x34(sp) 48 sw a6, 0x38(sp) 49 sw a7, 0x3C(sp) 50 51 // save pc which hw stashed in SEPC 52 csrr t0, sepc 53 sw t0, 0x40(sp) 54 55 // if the scause high bit is clear, it is an exception 56 csrr t1, scause 57 bge t1, zero, exception_entry 58 59 // otherwise it is an interrupt, call interrupt_handler() 60 jal interrupt_handler 61 62 .globl trap_exit 63 trap_exit: 64 // return pc goes into sepc for sret 65 lw t0, 0x40(sp) 66 csrw sepc, t0 67 68 // restore the caller-save registers 69 lw ra, 0x00(sp) 70 lw t0, 0x04(sp) 71 lw t1, 0x08(sp) 72 lw t2, 0x0C(sp) 73 lw t3, 0x10(sp) 74 lw t4, 0x14(sp) 75 lw t5, 0x18(sp) 76 lw t6, 0x1C(sp) 77 lw a0, 0x20(sp) 78 lw a1, 0x24(sp) 79 lw a2, 0x28(sp) 80 lw a3, 0x2C(sp) 81 lw a4, 0x30(sp) 82 lw a5, 0x34(sp) 83 lw a6, 0x38(sp) 84 lw a7, 0x3C(sp) 85 86 // release the stack space 87 addi sp, sp, (32 * 4) 88 89 // return from trap 90 sret 91 92 exception_entry: 93 // save the callee-save registers (cframe_t) 94 // pc already stored at 0x40(sp) 95 addi t0, sp, (32 * 4) 96 sw t0, 0x44(sp) 97 sw gp, 0x48(sp) 98 sw tp, 0x4C(sp) 99 sw s0, 0x50(sp) 100 sw s1, 0x54(sp) 101 sw s2, 0x58(sp) 102 sw s3, 0x5C(sp) 103 sw s4, 0x60(sp) 104 sw s5, 0x64(sp) 105 sw s6, 0x68(sp) 106 sw s7, 0x6C(sp) 107 sw s8, 0x70(sp) 108 sw s9, 0x74(sp) 109 sw s10, 0x78(sp) 110 sw s11, 0x7C(sp) 111 112 // call exception_handler() passing eframe_t* 113 // as the first argument 114 mv a0, sp 115 jal exception_handler 116 117 .globl exception_exit 118 exception_exit: 119 lw gp, 0x48(sp) 120 lw tp, 0x4C(sp) 121 lw s0, 0x50(sp) 122 lw s1, 0x54(sp) 123 lw s2, 0x58(sp) 124 lw s3, 0x5C(sp) 125 lw s4, 0x60(sp) 126 lw s5, 0x64(sp) 127 lw s6, 0x68(sp) 128 lw s7, 0x6C(sp) 129 lw s8, 0x70(sp) 130 lw s9, 0x74(sp) 131 lw s10, 0x78(sp) 132 lw s11, 0x7C(sp) 133 134 j trap_exit