1// See LICENSE for license details. 2 3#include "fp_emulation.h" 4#include "unprivileged_memory.h" 5 6#define punt_to_misaligned_handler(align, handler) \ 7 if (addr % (align) != 0) \ 8 return write_csr(mbadaddr, addr), (handler)(regs, mcause, mepc) 9 10DECLARE_EMULATION_FUNC(emulate_float_load) 11{ 12 uintptr_t addr = GET_RS1(insn, regs) + IMM_I(insn); 13 14 // if FPU is disabled, punt back to the OS 15 if (unlikely((mstatus & MSTATUS_FS) == 0)) 16 return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 17 18 switch (insn & MASK_FUNCT3) 19 { 20 case MATCH_FLW & MASK_FUNCT3: 21 punt_to_misaligned_handler(4, misaligned_load_trap); 22 SET_F32_RD(insn, regs, load_int32_t((void *)addr, mepc)); 23 break; 24 25 case MATCH_FLD & MASK_FUNCT3: 26 punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_load_trap); 27 SET_F64_RD(insn, regs, load_uint64_t((void *)addr, mepc)); 28 break; 29 30 default: 31 return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 32 } 33} 34 35DECLARE_EMULATION_FUNC(emulate_float_store) 36{ 37 uintptr_t addr = GET_RS1(insn, regs) + IMM_S(insn); 38 39 // if FPU is disabled, punt back to the OS 40 if (unlikely((mstatus & MSTATUS_FS) == 0)) 41 return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 42 43 switch (insn & MASK_FUNCT3) 44 { 45 case MATCH_FSW & MASK_FUNCT3: 46 punt_to_misaligned_handler(4, misaligned_store_trap); 47 store_uint32_t((void *)addr, GET_F32_RS2(insn, regs), mepc); 48 break; 49 50 case MATCH_FSD & MASK_FUNCT3: 51 punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_store_trap); 52 store_uint64_t((void *)addr, GET_F64_RS2(insn, regs), mepc); 53 break; 54 55 default: 56 return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 57 } 58} 59 60