diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:54:14 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:39 -0800 |
commit | ccf79891f0f1fcb570f9a63c15270b52477fe7c0 (patch) | |
tree | e86a1ef10afca65db9908df90616f58fd8fdbeb5 /machine/emulation.c | |
parent | b94c7a4b07f96f24ae7411780abf874416549f7b (diff) | |
download | pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.zip pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.gz pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.bz2 |
Factor emulation routines into multiple files
Diffstat (limited to 'machine/emulation.c')
-rw-r--r-- | machine/emulation.c | 154 |
1 files changed, 12 insertions, 142 deletions
diff --git a/machine/emulation.c b/machine/emulation.c index 5a66997..5e3ca2e 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -10,7 +10,7 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) asm (".pushsection .rodata\n" "illegal_insn_trap_table:\n" " .word truly_illegal_insn\n" -#ifdef PK_ENABLE_FP_EMULATION +#if !defined(__riscv_hard_float) && defined(PK_ENABLE_FP_EMULATION) " .word emulate_float_load\n" #else " .word truly_illegal_insn\n" @@ -22,16 +22,24 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) " .word truly_illegal_insn\n" " .word truly_illegal_insn\n" " .word truly_illegal_insn\n" -#ifdef PK_ENABLE_FP_EMULATION +#if !defined(__riscv_hard_float) && defined(PK_ENABLE_FP_EMULATION) " .word emulate_float_store\n" #else " .word truly_illegal_insn\n" #endif " .word truly_illegal_insn\n" " .word truly_illegal_insn\n" +#if !defined(__riscv_muldiv) " .word emulate_mul_div\n" +#else " .word truly_illegal_insn\n" +#endif + " .word truly_illegal_insn\n" +#if !defined(__riscv_muldiv) && defined(__riscv64) " .word emulate_mul_div32\n" +#else + " .word truly_illegal_insn\n" +#endif " .word truly_illegal_insn\n" #ifdef PK_ENABLE_FP_EMULATION " .word emulate_fmadd\n" @@ -78,144 +86,6 @@ void __attribute__((noinline)) truly_illegal_insn(uintptr_t* regs, uintptr_t mca redirect_trap(mepc, mstatus); } -void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) -{ - union { - uint8_t bytes[8]; - uintptr_t intx; - uint64_t int64; - } val; - uintptr_t mstatus; - insn_t insn = get_insn(mepc, &mstatus); - uintptr_t addr = GET_RS1(insn, regs) + IMM_I(insn); - - int shift = 0, fp = 0, len; - if ((insn & MASK_LW) == MATCH_LW) - len = 4, shift = 8*(sizeof(uintptr_t) - len); -#ifdef __riscv64 - else if ((insn & MASK_LD) == MATCH_LD) - len = 8, shift = 8*(sizeof(uintptr_t) - len); - else if ((insn & MASK_LWU) == MATCH_LWU) - fp = 0, len = 4, shift = 0; -#endif - else if ((insn & MASK_FLD) == MATCH_FLD) - fp = 1, len = 8; - else if ((insn & MASK_FLW) == MATCH_FLW) - fp = 1, len = 4; - else if ((insn & MASK_LH) == MATCH_LH) - len = 2, shift = 8*(sizeof(uintptr_t) - len); - else if ((insn & MASK_LHU) == MATCH_LHU) - len = 2; - else - return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); - - val.int64 = 0; - for (intptr_t i = len-1; i >= 0; i--) - val.bytes[i] = load_uint8_t((void *)(addr + i), mepc); - - if (!fp) - SET_RD(insn, regs, (intptr_t)val.intx << shift >> shift); - else if (len == 8) - SET_F64_RD(insn, regs, val.int64); - else - SET_F32_RD(insn, regs, val.intx); - - write_csr(mepc, mepc + 4); -} - -void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) -{ - union { - uint8_t bytes[8]; - uintptr_t intx; - uint64_t int64; - } val; - uintptr_t mstatus; - insn_t insn = get_insn(mepc, &mstatus); - int len; - - val.intx = GET_RS2(insn, regs); - if ((insn & MASK_SW) == MATCH_SW) - len = 4; -#ifdef __riscv64 - else if ((insn & MASK_SD) == MATCH_SD) - len = 8; -#endif - else if ((insn & MASK_FSD) == MATCH_FSD) - len = 8, val.int64 = GET_F64_RS2(insn, regs); - else if ((insn & MASK_FSW) == MATCH_FSW) - len = 4, val.intx = GET_F32_RS2(insn, regs); - else if ((insn & MASK_SH) == MATCH_SH) - len = 2; - else - return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); - - uintptr_t addr = GET_RS1(insn, regs) + IMM_S(insn); - for (int i = 0; i < len; i++) - store_uint8_t((void *)(addr + i), val.bytes[i], mepc); - - write_csr(mepc, mepc + 4); -} - -#ifdef __riscv64 -typedef __int128 double_int; -#else -typedef int64_t double_int; -#endif - -DECLARE_EMULATION_FUNC(emulate_mul_div) -{ - uintptr_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs), val; - -#ifndef __riscv_muldiv - // If compiled with -mno-multiply, GCC will expand these out - if ((insn & MASK_MUL) == MATCH_MUL) - val = rs1 * rs2; - else if ((insn & MASK_DIV) == MATCH_DIV) - val = (intptr_t)rs1 / (intptr_t)rs2; - else if ((insn & MASK_DIVU) == MATCH_DIVU) - val = rs1 / rs2; - else if ((insn & MASK_REM) == MATCH_REM) - val = (intptr_t)rs1 % (intptr_t)rs2; - else if ((insn & MASK_REMU) == MATCH_REMU) - val = rs1 % rs2; - else if ((insn & MASK_MULH) == MATCH_MULH) - val = ((double_int)(intptr_t)rs1 * (double_int)(intptr_t)rs2) >> (8 * sizeof(rs1)); - else if ((insn & MASK_MULHU) == MATCH_MULHU) - val = ((double_int)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); - else if ((insn & MASK_MULHSU) == MATCH_MULHSU) - val = ((double_int)(intptr_t)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); - else -#endif - return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); - - SET_RD(insn, regs, val); -} - -DECLARE_EMULATION_FUNC(emulate_mul_div32) -{ - uint32_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs); - int32_t val; - -#if defined(__riscv64) && !defined(__riscv_muldiv) - // If compiled with -mno-multiply, GCC will expand these out - if ((insn & MASK_MULW) == MATCH_MULW) - val = rs1 * rs2; - else if ((insn & MASK_DIVW) == MATCH_DIVW) - val = (int32_t)rs1 / (int32_t)rs2; - else if ((insn & MASK_DIVUW) == MATCH_DIVUW) - val = rs1 / rs2; - else if ((insn & MASK_REMW) == MATCH_REMW) - val = (int32_t)rs1 % (int32_t)rs2; - else if ((insn & MASK_REMUW) == MATCH_REMUW) - val = rs1 % rs2; - else -#endif - return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); - - SET_RD(insn, regs, val); -} - static inline int emulate_read_csr(int num, uintptr_t mstatus, uintptr_t* result) { switch (num) @@ -252,7 +122,7 @@ static inline int emulate_read_csr(int num, uintptr_t mstatus, uintptr_t* result + HLS()->sinstret_delta) >> 32; return 0; #endif -#ifdef PK_ENABLE_FP_EMULATION +#if !defined(__riscv_hard_float) && defined(PK_ENABLE_FP_EMULATION) case CSR_FRM: if ((mstatus & MSTATUS_FS) == 0) break; *result = GET_FRM(); @@ -274,7 +144,7 @@ static inline int emulate_write_csr(int num, uintptr_t value, uintptr_t mstatus) { switch (num) { -#ifdef PK_ENABLE_FP_EMULATION +#if !defined(__riscv_hard_float) && defined(PK_ENABLE_FP_EMULATION) case CSR_FRM: SET_FRM(value); return 0; case CSR_FFLAGS: SET_FFLAGS(value); return 0; case CSR_FCSR: SET_FCSR(value); return 0; |