1/* 2 * Copyright (c) 2022 Travis Geiselbrecht 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8#include <lk/asm.h> 9#include <arch/riscv.h> 10#include <arch/riscv/asm.h> 11 12#if RISCV_FPU 13 14// enable full use of all of the fpu instructions 15#if __riscv_xlen == 32 16.attribute arch, "rv32imafdc" 17#elif __riscv_xlen == 64 18.attribute arch, "rv64imafdc" 19#else 20#error unknown xlen 21#endif 22 23// conditionally use fcvt or fmv based on 32 or 64bit ISA 24.macro ZERO_FPU_REG reg, width 25#if __riscv_xlen == 32 26 fcvt.\width\().w \reg, zero 27#elif __riscv_xlen == 64 28 fmv.\width\().x \reg, zero 29#endif 30.endm 31 32// called just before entering user space for the first time. 33// must not use the stack and is okay to be called with interrupts disabled. 34FUNCTION(riscv_fpu_zero) 35 // zero out the fpu state 36 // TODO: handle single precision implementations 37 csrw fcsr, zero 38 ZERO_FPU_REG f0, d 39 ZERO_FPU_REG f1, d 40 ZERO_FPU_REG f2, d 41 ZERO_FPU_REG f3, d 42 ZERO_FPU_REG f4, d 43 ZERO_FPU_REG f5, d 44 ZERO_FPU_REG f6, d 45 ZERO_FPU_REG f7, d 46 ZERO_FPU_REG f8, d 47 ZERO_FPU_REG f9, d 48 ZERO_FPU_REG f10, d 49 ZERO_FPU_REG f11, d 50 ZERO_FPU_REG f12, d 51 ZERO_FPU_REG f13, d 52 ZERO_FPU_REG f14, d 53 ZERO_FPU_REG f15, d 54 ZERO_FPU_REG f16, d 55 ZERO_FPU_REG f17, d 56 ZERO_FPU_REG f18, d 57 ZERO_FPU_REG f19, d 58 ZERO_FPU_REG f20, d 59 ZERO_FPU_REG f21, d 60 ZERO_FPU_REG f22, d 61 ZERO_FPU_REG f23, d 62 ZERO_FPU_REG f24, d 63 ZERO_FPU_REG f25, d 64 ZERO_FPU_REG f26, d 65 ZERO_FPU_REG f27, d 66 ZERO_FPU_REG f28, d 67 ZERO_FPU_REG f29, d 68 ZERO_FPU_REG f30, d 69 ZERO_FPU_REG f31, d 70 71 // put the hardware in the initial state 72 // FS[1:0] == 1 set in two steps: one to set bit 0, second one to clear bit 1 73 // this ensures it doesn't go through the disabled state (00) 74 li a0, (1 << 13) 75 csrs RISCV_CSR_XSTATUS, a0 76 li a0, (1 << 14) 77 csrc RISCV_CSR_XSTATUS, a0 78 79 ret 80END_FUNCTION(riscv_fpu_zero) 81 82// void riscv_fpu_save(struct riscv_fpu_state *state); 83FUNCTION(riscv_fpu_save) 84 fsd f0, 0*8(a0) 85 fsd f1, 1*8(a0) 86 fsd f2, 2*8(a0) 87 fsd f3, 3*8(a0) 88 fsd f4, 4*8(a0) 89 fsd f5, 5*8(a0) 90 fsd f6, 6*8(a0) 91 fsd f7, 7*8(a0) 92 fsd f8, 8*8(a0) 93 fsd f9, 9*8(a0) 94 fsd f10, 10*8(a0) 95 fsd f11, 11*8(a0) 96 fsd f12, 12*8(a0) 97 fsd f13, 13*8(a0) 98 fsd f14, 14*8(a0) 99 fsd f15, 15*8(a0) 100 fsd f16, 16*8(a0) 101 fsd f17, 17*8(a0) 102 fsd f18, 18*8(a0) 103 fsd f19, 19*8(a0) 104 fsd f20, 20*8(a0) 105 fsd f21, 21*8(a0) 106 fsd f22, 22*8(a0) 107 fsd f23, 23*8(a0) 108 fsd f24, 24*8(a0) 109 fsd f25, 25*8(a0) 110 fsd f26, 26*8(a0) 111 fsd f27, 27*8(a0) 112 fsd f28, 28*8(a0) 113 fsd f29, 29*8(a0) 114 fsd f30, 30*8(a0) 115 fsd f31, 31*8(a0) 116 csrr a1, fcsr 117 sw a1, 32*8(a0) 118 ret 119END_FUNCTION(riscv_fpu_save) 120 121// void riscv_fpu_restore(struct riscv_fpu_state *state); 122FUNCTION(riscv_fpu_restore) 123 fld f0, 0*8(a0) 124 fld f1, 1*8(a0) 125 fld f2, 2*8(a0) 126 fld f3, 3*8(a0) 127 fld f4, 4*8(a0) 128 fld f5, 5*8(a0) 129 fld f6, 6*8(a0) 130 fld f7, 7*8(a0) 131 fld f8, 8*8(a0) 132 fld f9, 9*8(a0) 133 fld f10, 10*8(a0) 134 fld f11, 11*8(a0) 135 fld f12, 12*8(a0) 136 fld f13, 13*8(a0) 137 fld f14, 14*8(a0) 138 fld f15, 15*8(a0) 139 fld f16, 16*8(a0) 140 fld f17, 17*8(a0) 141 fld f18, 18*8(a0) 142 fld f19, 19*8(a0) 143 fld f20, 20*8(a0) 144 fld f21, 21*8(a0) 145 fld f22, 22*8(a0) 146 fld f23, 23*8(a0) 147 fld f24, 24*8(a0) 148 fld f25, 25*8(a0) 149 fld f26, 26*8(a0) 150 fld f27, 27*8(a0) 151 fld f28, 28*8(a0) 152 fld f29, 29*8(a0) 153 fld f30, 30*8(a0) 154 fld f31, 31*8(a0) 155 lw a1, 32*8(a0) 156 csrw fcsr, a1 157 ret 158END_FUNCTION(riscv_fpu_restore) 159#endif // RISCV_FPU 160