diff options
author | Andrew Waterman <waterman@s144.Millennium.Berkeley.EDU> | 2010-10-15 17:51:37 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s144.Millennium.Berkeley.EDU> | 2010-10-15 17:51:37 -0700 |
commit | b4fd490d689415205cf315c02f673b9386ece337 (patch) | |
tree | 73f93d81b6241b1d1204d7add68af065f9638ea9 /pk | |
parent | 2b7fd5fa6ac24f3d6d6cb8f0d6c1c32b85c39f02 (diff) | |
download | pk-b4fd490d689415205cf315c02f673b9386ece337.zip pk-b4fd490d689415205cf315c02f673b9386ece337.tar.gz pk-b4fd490d689415205cf315c02f673b9386ece337.tar.bz2 |
[pk, sim] added FPU emulation support to proxy kernel
Diffstat (limited to 'pk')
-rw-r--r-- | pk/entry.S | 10 | ||||
-rw-r--r-- | pk/fp.c | 358 | ||||
-rw-r--r-- | pk/handlers.c | 16 | ||||
-rw-r--r-- | pk/pk.c | 6 | ||||
-rw-r--r-- | pk/pk.h | 12 | ||||
-rw-r--r-- | pk/pk.mk.in | 10 | ||||
-rw-r--r-- | pk/riscv-opc.h | 309 | ||||
-rw-r--r-- | pk/riscv-pk.c | 6 | ||||
-rw-r--r-- | pk/syscall.c | 2 |
9 files changed, 721 insertions, 8 deletions
@@ -52,14 +52,20 @@ save_tf: # write the trap frame onto the stack # get sr, epc, badvaddr, cause, cr29 (tid) mfpcr $x2,ASM_CR(PCR_SR) # sr STORE $x2,32*REGBYTES($x1) - mfpcr $x2,ASM_CR(PCR_EPC) # epc - STORE $x2,33*REGBYTES($x1) + mfpcr $x3,ASM_CR(PCR_EPC) # epc + STORE $x3,33*REGBYTES($x1) mfpcr $x2,ASM_CR(PCR_BADVADDR) # badvaddr STORE $x2,34*REGBYTES($x1) mfpcr $x2,ASM_CR(PCR_CAUSE) # cause STORE $x2,35*REGBYTES($x1) mfcr $x2,ASM_CR(29) # cr29 (tid) STORE $x2,36*REGBYTES($x1) + + # get insn + and $x3,$x3,~3 + lw $x2,0($x3) + STORE $x2, 37*REGBYTES($x1) + jr $ra .end save_tf @@ -0,0 +1,358 @@ +#include "softfloat.h" +#include "riscv-opc.h" +#include "pk.h" +#include <stdint.h> + +#define noisy 0 + +static void set_fp_reg(unsigned int which, unsigned int dp, uint64_t val); +static uint64_t get_fp_reg(unsigned int which, unsigned int dp); + +uint64_t fp_regs[32]; +uint32_t fsr; + +void validate_address(trapframe_t* tf, long addr, int size, int store) +{ + if(addr & (size-1)) + handle_misaligned_ldst(tf); + if(addr >= USER_MEM_SIZE) + store ? handle_fault_store(tf) : handle_fault_load(tf); +} + +int emulate_fp(trapframe_t* tf) +{ + if(noisy) + printk("FPU emulation at pc %lx, insn %x\n",tf->epc,(uint32_t)tf->insn); + + #define RRS1 ((tf->insn >> 15) & 0x1F) + #define RRS2 ((tf->insn >> 20) & 0x1F) + #define RRS3 ((tf->insn >> 5) & 0x1F) + #define RRDR ( tf->insn & 0x1F) + #define RRDI RRS2 + + #define XRS1 (tf->gpr[RRS1]) + #define XRS2 (tf->gpr[RRS2]) + #define XRDR (tf->gpr[RRDR]) + #define FRS1S get_fp_reg(RRS1,0) + #define FRS2S get_fp_reg(RRS2,0) + #define FRS3S get_fp_reg(RRS3,0) + #define FRS1D get_fp_reg(RRS1,1) + #define FRS2D get_fp_reg(RRS2,1) + #define FRS3D get_fp_reg(RRS3,1) + + #define IMM (((int32_t)tf->insn << 20) >> 20) + #define EFFECTIVE_ADDRESS (XRS1+IMM) + + #define IS_INSN(x) ((tf->insn & MASK_ ## x) == MATCH_ ## x) + + if(IS_INSN(L_S)) + { + validate_address(tf, EFFECTIVE_ADDRESS, 4, 0); + set_fp_reg(RRDI, 0, *(uint32_t*)EFFECTIVE_ADDRESS); + } + else if(IS_INSN(L_D)) + { + validate_address(tf, EFFECTIVE_ADDRESS, 8, 0); + set_fp_reg(RRDI, 1, *(uint64_t*)EFFECTIVE_ADDRESS); + } + else if(IS_INSN(S_S)) + { + validate_address(tf, EFFECTIVE_ADDRESS, 4, 1); + *(uint32_t*)EFFECTIVE_ADDRESS = FRS2S; + } + else if(IS_INSN(S_D)) + { + validate_address(tf, EFFECTIVE_ADDRESS, 8, 1); + *(uint64_t*)EFFECTIVE_ADDRESS = FRS2D; + } + else if(IS_INSN(MFF_S)) + XRDR = FRS2S; + else if(IS_INSN(MFF_D)) + XRDR = FRS2D; + else if(IS_INSN(MFFL_D)) + XRDR = (int32_t)FRS2D; + else if(IS_INSN(MFFH_D)) + XRDR = (int64_t)FRS2D >> 32; + else if(IS_INSN(MTF_S)) + set_fp_reg(RRDR, 0, XRS1); + else if(IS_INSN(MTF_D)) + set_fp_reg(RRDR, 1, XRS1); + else if(IS_INSN(MTFLH_D)) + set_fp_reg(RRDR, 1, (uint32_t)XRS1 | (XRS2 << 32)); + else if(IS_INSN(SGNINJ_S)) + set_fp_reg(RRDR, 0, (FRS1S &~ (uint32_t)INT32_MIN) | (FRS2S & (uint32_t)INT32_MIN)); + else if(IS_INSN(SGNINJ_D)) + set_fp_reg(RRDR, 1, (FRS1D &~ INT64_MIN) | (FRS2D & INT64_MIN)); + else if(IS_INSN(SGNINJN_S)) + set_fp_reg(RRDR, 0, (FRS1S &~ (uint32_t)INT32_MIN) | ((~FRS2S) & (uint32_t)INT32_MIN)); + else if(IS_INSN(SGNINJN_D)) + set_fp_reg(RRDR, 1, (FRS1D &~ INT64_MIN) | ((~FRS2D) & INT64_MIN)); + else if(IS_INSN(SGNMUL_S)) + set_fp_reg(RRDR, 0, FRS1S ^ (FRS2S & (uint32_t)INT32_MIN)); + else if(IS_INSN(SGNMUL_D)) + set_fp_reg(RRDR, 1, FRS1D ^ (FRS2D & INT64_MIN)); + else if(IS_INSN(C_EQ_S)) + XRDR = f32_eq(FRS1S, FRS2S); + else if(IS_INSN(C_EQ_D)) + XRDR = f64_eq(FRS1D, FRS2D); + else if(IS_INSN(C_LE_S)) + XRDR = f32_le(FRS1S, FRS2S); + else if(IS_INSN(C_LE_D)) + XRDR = f64_le(FRS1D, FRS2D); + else if(IS_INSN(C_LT_S)) + XRDR = f32_lt(FRS1S, FRS2S); + else if(IS_INSN(C_LT_D)) + XRDR = f64_lt(FRS1D, FRS2D); + else if(IS_INSN(CVT_S_W)) + set_fp_reg(RRDR, 0, i32_to_f32(XRS1)); + else if(IS_INSN(CVT_S_L)) + set_fp_reg(RRDR, 0, i64_to_f32(XRS1)); + else if(IS_INSN(CVT_S_D)) + set_fp_reg(RRDR, 0, f64_to_f32(FRS1D)); + else if(IS_INSN(CVT_D_W)) + set_fp_reg(RRDR, 1, i32_to_f64(XRS1)); + else if(IS_INSN(CVT_D_L)) + set_fp_reg(RRDR, 1, i64_to_f64(XRS1)); + else if(IS_INSN(CVT_D_S)) + set_fp_reg(RRDR, 1, f32_to_f64(FRS1S)); + else if(IS_INSN(CVTU_S_W)) + set_fp_reg(RRDR, 0, ui32_to_f32(XRS1)); + else if(IS_INSN(CVTU_S_L)) + set_fp_reg(RRDR, 0, ui64_to_f32(XRS1)); + else if(IS_INSN(CVTU_D_W)) + set_fp_reg(RRDR, 1, ui32_to_f64(XRS1)); + else if(IS_INSN(CVTU_D_L)) + set_fp_reg(RRDR, 1, ui64_to_f64(XRS1)); + else if(IS_INSN(ADD_S)) + set_fp_reg(RRDR, 0, f32_add(FRS1S, FRS2S)); + else if(IS_INSN(ADD_D)) + set_fp_reg(RRDR, 1, f64_add(FRS1D, FRS2D)); + else if(IS_INSN(SUB_S)) + set_fp_reg(RRDR, 0, f32_sub(FRS1S, FRS2S)); + else if(IS_INSN(SUB_D)) + set_fp_reg(RRDR, 1, f64_sub(FRS1D, FRS2D)); + else if(IS_INSN(MUL_S)) + set_fp_reg(RRDR, 0, f32_mul(FRS1S, FRS2S)); + else if(IS_INSN(MUL_D)) + set_fp_reg(RRDR, 1, f64_mul(FRS1D, FRS2D)); + else if(IS_INSN(MADD_S)) + set_fp_reg(RRDR, 0, f32_mulAdd(FRS1S, FRS2S, FRS3S)); + else if(IS_INSN(MADD_D)) + set_fp_reg(RRDR, 1, f64_mulAdd(FRS1D, FRS2D, FRS3D)); + else if(IS_INSN(MSUB_S)) + set_fp_reg(RRDR, 0, f32_mulAdd(FRS1S, FRS2S, FRS3S ^ (uint32_t)INT32_MIN)); + else if(IS_INSN(MSUB_D)) + set_fp_reg(RRDR, 1, f64_mulAdd(FRS1D, FRS2D, FRS3D ^ INT64_MIN)); + else if(IS_INSN(NMADD_S)) + set_fp_reg(RRDR, 0, f32_mulAdd(FRS1S, FRS2S, FRS3S) ^ (uint32_t)INT32_MIN); + else if(IS_INSN(NMADD_D)) + set_fp_reg(RRDR, 1, f64_mulAdd(FRS1D, FRS2D, FRS3D) ^ INT64_MIN); + else if(IS_INSN(NMSUB_S)) + set_fp_reg(RRDR, 0, f32_mulAdd(FRS1S, FRS2S, FRS3S ^ (uint32_t)INT32_MIN) ^ (uint32_t)INT32_MIN); + else if(IS_INSN(NMSUB_D)) + set_fp_reg(RRDR, 1, f64_mulAdd(FRS1D, FRS2D, FRS3D ^ INT64_MIN) ^ INT64_MIN); + else if(IS_INSN(DIV_S)) + set_fp_reg(RRDR, 0, f32_div(FRS1S, FRS2S)); + else if(IS_INSN(DIV_D)) + set_fp_reg(RRDR, 1, f64_div(FRS1D, FRS2D)); + else if(IS_INSN(SQRT_S)) + set_fp_reg(RRDR, 0, f32_sqrt(FRS1S)); + else if(IS_INSN(SQRT_D)) + set_fp_reg(RRDR, 1, f64_sqrt(FRS1D)); + else if(IS_INSN(TRUNC_W_S)) + XRDR = f32_to_i32_r_minMag(FRS1S,true); + else if(IS_INSN(TRUNC_W_D)) + XRDR = f64_to_i32_r_minMag(FRS1D,true); + else if(IS_INSN(TRUNC_L_S)) + XRDR = f32_to_i64_r_minMag(FRS1S,true); + else if(IS_INSN(TRUNC_L_D)) + XRDR = f64_to_i64_r_minMag(FRS1D,true); + else if(IS_INSN(TRUNCU_W_S)) + XRDR = f32_to_ui32_r_minMag(FRS1S,true); + else if(IS_INSN(TRUNCU_W_D)) + XRDR = f64_to_ui32_r_minMag(FRS1D,true); + else if(IS_INSN(TRUNCU_L_S)) + XRDR = f32_to_ui64_r_minMag(FRS1S,true); + else if(IS_INSN(TRUNCU_L_D)) + XRDR = f64_to_ui64_r_minMag(FRS1D,true); + else + return -1; + + advance_pc(tf); + + return 0; +} + +#define STR(x) XSTR(x) +#define XSTR(x) #x + +#define PUT_FP_REG_S(which) case which: \ + if(have_fp) \ + asm volatile("mtf.s $f" STR(which) ",%0" : : "r"(val)); \ + else fp_regs[which] = val; \ + if(noisy) printk("set fp sp reg %x to %x\n",which,val); \ + break +#define PUT_FP_REG_D(which) case 32+which: \ + if(have_fp) \ + asm volatile("mtf.d $f" STR(which) ",%0" : : "r"(val)); \ + else fp_regs[which] = val; \ + if(noisy) printk("set fp dp reg %x to %x%x\n",which,(uint32_t)(val>>32),(uint32_t)val); \ + break +#define GET_FP_REG_S(which) case which: \ + if(have_fp) asm volatile("mff.s %0,$f" STR(which) : "=r"(val));\ + else val = (uint64_t)(int64_t)(int32_t)fp_regs[which]; \ + if(noisy) printk("get fp sp reg %x v %x\n",which,val); \ + break +#define GET_FP_REG_D(which) case 32+which: \ + if(have_fp) asm volatile("mff.d %0,$f" STR(which) : "=r"(val));\ + else val = fp_regs[which]; \ + if(noisy) printk("get fp dp reg %x v %x%x\n",which,(uint32_t)(val>>32),(uint32_t)val); \ + break + +static void set_fp_reg(unsigned int which, unsigned int dp, uint64_t val) +{ + switch(which + (!!dp)*32) + { + PUT_FP_REG_S(0); + PUT_FP_REG_S(1); + PUT_FP_REG_S(2); + PUT_FP_REG_S(3); + PUT_FP_REG_S(4); + PUT_FP_REG_S(5); + PUT_FP_REG_S(6); + PUT_FP_REG_S(7); + PUT_FP_REG_S(8); + PUT_FP_REG_S(9); + PUT_FP_REG_S(10); + PUT_FP_REG_S(11); + PUT_FP_REG_S(12); + PUT_FP_REG_S(13); + PUT_FP_REG_S(14); + PUT_FP_REG_S(15); + PUT_FP_REG_S(16); + PUT_FP_REG_S(17); + PUT_FP_REG_S(18); + PUT_FP_REG_S(19); + PUT_FP_REG_S(20); + PUT_FP_REG_S(21); + PUT_FP_REG_S(22); + PUT_FP_REG_S(23); + PUT_FP_REG_S(24); + PUT_FP_REG_S(25); + PUT_FP_REG_S(26); + PUT_FP_REG_S(27); + PUT_FP_REG_S(28); + PUT_FP_REG_S(29); + PUT_FP_REG_S(30); + PUT_FP_REG_S(31); + PUT_FP_REG_D(0); + PUT_FP_REG_D(1); + PUT_FP_REG_D(2); + PUT_FP_REG_D(3); + PUT_FP_REG_D(4); + PUT_FP_REG_D(5); + PUT_FP_REG_D(6); + PUT_FP_REG_D(7); + PUT_FP_REG_D(8); + PUT_FP_REG_D(9); + PUT_FP_REG_D(10); + PUT_FP_REG_D(11); + PUT_FP_REG_D(12); + PUT_FP_REG_D(13); + PUT_FP_REG_D(14); + PUT_FP_REG_D(15); + PUT_FP_REG_D(16); + PUT_FP_REG_D(17); + PUT_FP_REG_D(18); + PUT_FP_REG_D(19); + PUT_FP_REG_D(20); + PUT_FP_REG_D(21); + PUT_FP_REG_D(22); + PUT_FP_REG_D(23); + PUT_FP_REG_D(24); + PUT_FP_REG_D(25); + PUT_FP_REG_D(26); + PUT_FP_REG_D(27); + PUT_FP_REG_D(28); + PUT_FP_REG_D(29); + PUT_FP_REG_D(30); + PUT_FP_REG_D(31); + default: + panic("bad fp register"); + } +} + +static uint64_t get_fp_reg(unsigned int which, unsigned int dp) +{ + uint64_t val; + switch(which + (!!dp)*32) + { + GET_FP_REG_S(0); + GET_FP_REG_S(1); + GET_FP_REG_S(2); + GET_FP_REG_S(3); + GET_FP_REG_S(4); + GET_FP_REG_S(5); + GET_FP_REG_S(6); + GET_FP_REG_S(7); + GET_FP_REG_S(8); + GET_FP_REG_S(9); + GET_FP_REG_S(10); + GET_FP_REG_S(11); + GET_FP_REG_S(12); + GET_FP_REG_S(13); + GET_FP_REG_S(14); + GET_FP_REG_S(15); + GET_FP_REG_S(16); + GET_FP_REG_S(17); + GET_FP_REG_S(18); + GET_FP_REG_S(19); + GET_FP_REG_S(20); + GET_FP_REG_S(21); + GET_FP_REG_S(22); + GET_FP_REG_S(23); + GET_FP_REG_S(24); + GET_FP_REG_S(25); + GET_FP_REG_S(26); + GET_FP_REG_S(27); + GET_FP_REG_S(28); + GET_FP_REG_S(29); + GET_FP_REG_S(30); + GET_FP_REG_S(31); + GET_FP_REG_D(0); + GET_FP_REG_D(1); + GET_FP_REG_D(2); + GET_FP_REG_D(3); + GET_FP_REG_D(4); + GET_FP_REG_D(5); + GET_FP_REG_D(6); + GET_FP_REG_D(7); + GET_FP_REG_D(8); + GET_FP_REG_D(9); + GET_FP_REG_D(10); + GET_FP_REG_D(11); + GET_FP_REG_D(12); + GET_FP_REG_D(13); + GET_FP_REG_D(14); + GET_FP_REG_D(15); + GET_FP_REG_D(16); + GET_FP_REG_D(17); + GET_FP_REG_D(18); + GET_FP_REG_D(19); + GET_FP_REG_D(20); + GET_FP_REG_D(21); + GET_FP_REG_D(22); + GET_FP_REG_D(23); + GET_FP_REG_D(24); + GET_FP_REG_D(25); + GET_FP_REG_D(26); + GET_FP_REG_D(27); + GET_FP_REG_D(28); + GET_FP_REG_D(29); + GET_FP_REG_D(30); + GET_FP_REG_D(31); + default: + panic("bad fp register"); + } + return val; +} diff --git a/pk/handlers.c b/pk/handlers.c index 38745bf..7eee536 100644 --- a/pk/handlers.c +++ b/pk/handlers.c @@ -1,6 +1,8 @@ #include "pcr.h" #include "pk.h" +int have_fp = 1; + void handle_breakpoint(trapframe_t* tf) { printk("Breakpoint\n"); @@ -10,7 +12,16 @@ void handle_breakpoint(trapframe_t* tf) void handle_fp_disabled(trapframe_t* tf) { - tf->sr |= SR_EF; + if(have_fp) + tf->sr |= SR_EF; + else + { + if(emulate_fp(tf) != 0) + { + dump_tf(tf); + panic("FPU emulation failed!"); + } + } } void handle_badtrap(trapframe_t* tf) @@ -27,6 +38,9 @@ void handle_privileged_instruction(trapframe_t* tf) void handle_illegal_instruction(trapframe_t* tf) { + if(emulate_fp(tf) == 0) + return; + dump_tf(tf); panic("An illegal instruction was executed!"); } @@ -3,6 +3,7 @@ #include "file.h" #include "frontend.h" #include <stdarg.h> +#include <stdint.h> #include <stdbool.h> #include <string.h> @@ -25,7 +26,7 @@ static void vsprintk(char* out, const char* s, va_list vl) for(int i = 2*(longarg ? sizeof(long) : sizeof(int))-1; i >= 0; i--) { int d = (n >> (4*i)) & 0xF; - *out++ = (d < 10 ? '0'+d : 'A'+d-10); + *out++ = (d < 10 ? '0'+d : 'a'+d-10); } longarg = false; format = false; @@ -117,7 +118,8 @@ void dump_tf(trapframe_t* tf) for(int j = 0; j < 4; j++) printk("%s %lx%c",regnames[i+j],tf->gpr[i+j],j < 3 ? ' ' : '\n'); } - printk("sr %lx pc %lx va %lx\n",tf->sr,tf->epc,tf->badvaddr); + printk("sr %lx pc %lx va %lx insn %x\n",tf->sr,tf->epc,tf->badvaddr, + (uint32_t)tf->insn); } void init_tf(trapframe_t* tf, long pc, long sp) @@ -9,6 +9,7 @@ typedef struct long badvaddr; long cause; long cr29; + long insn; } trapframe_t; #define USER_MEM_SIZE 0x70000000 @@ -22,6 +23,9 @@ typedef struct extern "C" { #endif +extern int have_fp; +int emulate_fp(trapframe_t*); + void printk(const char* s, ...); void init_tf(trapframe_t*, long pc, long sp); void pop_tf(trapframe_t*); @@ -30,10 +34,18 @@ void dump_tf(trapframe_t*); void unhandled_trap(trapframe_t*); void handle_syscall(trapframe_t*); void handle_breakpoint(trapframe_t*); +void handle_misaligned_ldst(trapframe_t*); +void handle_fault_load(trapframe_t*); +void handle_fault_store(trapframe_t*); void boot(); void sys_exit(int code) __attribute__((noreturn)); +static inline void advance_pc(trapframe_t* tf) +{ + tf->epc += 4; +} + #ifdef __cplusplus } #endif diff --git a/pk/pk.mk.in b/pk/pk.mk.in index a9957ed..1de66e8 100644 --- a/pk/pk.mk.in +++ b/pk/pk.mk.in @@ -1,14 +1,22 @@ pk_subproject_deps = \ + softfloat_riscv \ + softfloat \ pk_hdrs = \ pk.h \ + pcr.h \ + atomic.h \ + file.h \ + frontend.h \ + riscv-opc.h \ -pk_srcs = \ +pk_c_srcs = \ pk.c \ file.c \ syscall.c \ handlers.c \ frontend.c \ + fp.c \ pk_asm_srcs = \ entry.S \ diff --git a/pk/riscv-opc.h b/pk/riscv-opc.h new file mode 100644 index 0000000..9f4aea3 --- /dev/null +++ b/pk/riscv-opc.h @@ -0,0 +1,309 @@ +/* Automatically generated by parse-opcodes */ +#define MATCH_MFF_D 0xd4006b00 +#define MASK_MFF_D 0xfe0fffe0 +#define MATCH_SGNINJ_D 0xd40060a0 +#define MASK_SGNINJ_D 0xfe007fe0 +#define MATCH_AMO_ADD 0xf4003000 +#define MASK_AMO_ADD 0xfe007fe0 +#define MATCH_REMUW 0xee0010e0 +#define MASK_REMUW 0xfe007fe0 +#define MATCH_NMADD_S 0xd6000c00 +#define MASK_NMADD_S 0xfe007c00 +#define MATCH_BLTU 0xe6006000 +#define MASK_BLTU 0xfe007000 +#define MATCH_C_EQ_S 0xd40002a0 +#define MASK_C_EQ_S 0xfe007fe0 +#define MATCH_SGNINJ_S 0xd40000a0 +#define MASK_SGNINJ_S 0xfe007fe0 +#define MATCH_DIV_D 0xd4006060 +#define MASK_DIV_D 0xfe007fe0 +#define MATCH_CVT_S_W 0xd40001c0 +#define MASK_CVT_S_W 0xfff07fe0 +#define MATCH_NMADD_D 0xd6006c00 +#define MASK_NMADD_D 0xfe007c00 +#define MATCH_C_EQ_D 0xd40062a0 +#define MASK_C_EQ_D 0xfe007fe0 +#define MATCH_SLLIW 0xec007040 +#define MASK_SLLIW 0xfe007fe0 +#define MATCH_LB 0xf0000000 +#define MASK_LB 0xfe007000 +#define MATCH_CVTU_D_L 0xd40061a0 +#define MASK_CVTU_D_L 0xfff07fe0 +#define MATCH_TRUNC_W_D 0xd4006140 +#define MASK_TRUNC_W_D 0xfff07fe0 +#define MATCH_LH 0xf0001000 +#define MASK_LH 0xfe007000 +#define MATCH_LW 0xf0002000 +#define MASK_LW 0xfe007000 +#define MATCH_ADD 0xea000000 +#define MASK_ADD 0xfe007fe0 +#define MATCH_AMOW_AND 0xf4002040 +#define MASK_AMOW_AND 0xfe007fe0 +#define MATCH_MFPCR 0xfc004000 +#define MASK_MFPCR 0xfe0fffe0 +#define MATCH_TRUNC_W_S 0xd4000140 +#define MASK_TRUNC_W_S 0xfff07fe0 +#define MATCH_CVTU_D_W 0xd40061e0 +#define MASK_CVTU_D_W 0xfff07fe0 +#define MATCH_BNE 0xe6001000 +#define MASK_BNE 0xfe007000 +#define MATCH_MTPCR 0xfc005000 +#define MASK_MTPCR 0xfe007fff +#define MATCH_ADD_S 0xd4000000 +#define MASK_ADD_S 0xfe007fe0 +#define MATCH_BGEU 0xe6007000 +#define MASK_BGEU 0xfe007000 +#define MATCH_DI 0xfc001000 +#define MASK_DI 0xffffffe0 +#define MATCH_SLTIU 0xe8003000 +#define MASK_SLTIU 0xfe007000 +#define MATCH_MFFL_D 0xd4006b20 +#define MASK_MFFL_D 0xfe0fffe0 +#define MATCH_BREAK 0xf6006000 +#define MASK_BREAK 0xfffff000 +#define MATCH_ADD_D 0xd4006000 +#define MASK_ADD_D 0xfe007fe0 +#define MATCH_MUL 0xea001000 +#define MASK_MUL 0xfe007fe0 +#define MATCH_AMOW_MIN 0xf4002080 +#define MASK_AMOW_MIN 0xfe007fe0 +#define MATCH_NOR 0xea0000e0 +#define MASK_NOR 0xfe007fe0 +#define MATCH_NMSUB_D 0xd6006800 +#define MASK_NMSUB_D 0xfe007c00 +#define MATCH_AMO_SWAP 0xf4003020 +#define MASK_AMO_SWAP 0xfe007fe0 +#define MATCH_SRLI 0xe8007080 +#define MASK_SRLI 0xfe007fc0 +#define MATCH_DIVUW 0xee0010a0 +#define MASK_DIVUW 0xfe007fe0 +#define MATCH_MFFH_D 0xd4006b40 +#define MASK_MFFH_D 0xfe0fffe0 +#define MATCH_SRLW 0xee007080 +#define MASK_SRLW 0xfe007fe0 +#define MATCH_NMSUB_S 0xd6000800 +#define MASK_NMSUB_S 0xfe007c00 +#define MATCH_MFCR 0xf6002000 +#define MASK_MFCR 0xfe0fffe0 +#define MATCH_C_LE_D 0xd40062e0 +#define MASK_C_LE_D 0xfe007fe0 +#define MATCH_DIV 0xea001080 +#define MASK_DIV 0xfe007fe0 +#define MATCH_MFF_S 0xd4000b00 +#define MASK_MFF_S 0xfe0fffe0 +#define MATCH_AMOW_OR 0xf4002060 +#define MASK_AMOW_OR 0xfe007fe0 +#define MATCH_EI 0xfc000000 +#define MASK_EI 0xffffffe0 +#define MATCH_SGNMUL_D 0xd40060e0 +#define MASK_SGNMUL_D 0xfe007fe0 +#define MATCH_SYNC 0xf6004000 +#define MASK_SYNC 0xffffffff +#define MATCH_MTF_S 0xd4000b80 +#define MASK_MTF_S 0xfff07fe0 +#define MATCH_S_S 0xd2002000 +#define MASK_S_S 0xfe007000 +#define MATCH_MTCR 0xf6003000 +#define MASK_MTCR 0xfe007fff +#define MATCH_MSUB_S 0xd6000400 +#define MASK_MSUB_S 0xfe007c00 +#define MATCH_ADDW 0xee000000 +#define MASK_ADDW 0xfe007fe0 +#define MATCH_SLTU 0xea000060 +#define MASK_SLTU 0xfe007fe0 +#define MATCH_XOR 0xea0000c0 +#define MASK_XOR 0xfe007fe0 +#define MATCH_SUB 0xea000020 +#define MASK_SUB 0xfe007fe0 +#define MATCH_ERET 0xfc002000 +#define MASK_ERET 0xffffffff +#define MATCH_BLT 0xe6004000 +#define MASK_BLT 0xfe007000 +#define MATCH_SGNINJN_D 0xd40060c0 +#define MASK_SGNINJN_D 0xfe007fe0 +#define MATCH_REM 0xea0010c0 +#define MASK_REM 0xfe007fe0 +#define MATCH_SRLIW 0xec007080 +#define MASK_SRLIW 0xfe007fe0 +#define MATCH_LUI 0xe2000000 +#define MASK_LUI 0xfe000000 +#define MATCH_ADDI 0xe8000000 +#define MASK_ADDI 0xfe007000 +#define MATCH_MULH 0xea001040 +#define MASK_MULH 0xfe007fe0 +#define MATCH_MULHUW 0xee001060 +#define MASK_MULHUW 0xfe007fe0 +#define MATCH_SGNINJN_S 0xd40000c0 +#define MASK_SGNINJN_S 0xfe007fe0 +#define MATCH_SRAI 0xe80070c0 +#define MASK_SRAI 0xfe007fc0 +#define MATCH_SRAW 0xee0070c0 +#define MASK_SRAW 0xfe007fe0 +#define MATCH_LD 0xf0003000 +#define MASK_LD 0xfe007000 +#define MATCH_ORI 0xe8005000 +#define MASK_ORI 0xfe007000 +#define MATCH_AMOW_MAX 0xf40020a0 +#define MASK_AMOW_MAX 0xfe007fe0 +#define MATCH_ADDIW 0xec000000 +#define MASK_ADDIW 0xfe007000 +#define MATCH_MULW 0xee001000 +#define MASK_MULW 0xfe007fe0 +#define MATCH_MTFLH_D 0xd4006f80 +#define MASK_MTFLH_D 0xfe007fe0 +#define MATCH_CVT_D_S 0xd4006600 +#define MASK_CVT_D_S 0xfff07fe0 +#define MATCH_SRA 0xea0070c0 +#define MASK_SRA 0xfe007fe0 +#define MATCH_TRUNC_L_S 0xd4000100 +#define MASK_TRUNC_L_S 0xfff07fe0 +#define MATCH_BGE 0xe6005000 +#define MASK_BGE 0xfe007000 +#define MATCH_SRAIW 0xec0070c0 +#define MASK_SRAIW 0xfe007fe0 +#define MATCH_SRL 0xea007080 +#define MASK_SRL 0xfe007fe0 +#define MATCH_TRUNC_L_D 0xd4006100 +#define MASK_TRUNC_L_D 0xfff07fe0 +#define MATCH_OR 0xea0000a0 +#define MASK_OR 0xfe007fe0 +#define MATCH_SUBW 0xee000020 +#define MASK_SUBW 0xfe007fe0 +#define MATCH_JALR_C 0xf6000000 +#define MASK_JALR_C 0xfff07fe0 +#define MATCH_CVTU_S_W 0xd40001e0 +#define MASK_CVTU_S_W 0xfff07fe0 +#define MATCH_AMOW_MINU 0xf40020c0 +#define MASK_AMOW_MINU 0xfe007fe0 +#define MATCH_JALR_J 0xf6000040 +#define MASK_JALR_J 0xfff07fe0 +#define MATCH_S_D 0xd2003000 +#define MASK_S_D 0xfe007000 +#define MATCH_TRUNCU_L_S 0xd4000120 +#define MASK_TRUNCU_L_S 0xfff07fe0 +#define MATCH_AMO_OR 0xf4003060 +#define MASK_AMO_OR 0xfe007fe0 +#define MATCH_XORI 0xe8006000 +#define MASK_XORI 0xfe007000 +#define MATCH_JALR_R 0xf6000020 +#define MASK_JALR_R 0xfff07fe0 +#define MATCH_TRUNCU_L_D 0xd4006120 +#define MASK_TRUNCU_L_D 0xfff07fe0 +#define MATCH_CVTU_S_L 0xd40001a0 +#define MASK_CVTU_S_L 0xfff07fe0 +#define MATCH_AMO_MAX 0xf40030a0 +#define MASK_AMO_MAX 0xfe007fe0 +#define MATCH_AMO_MIN 0xf4003080 +#define MASK_AMO_MIN 0xfe007fe0 +#define MATCH_ANDI 0xe8004000 +#define MASK_ANDI 0xfe007000 +#define MATCH_JAL 0xc8000000 +#define MASK_JAL 0xf8000000 +#define MATCH_LWU 0xf0006000 +#define MASK_LWU 0xfe007000 +#define MATCH_AMO_MINU 0xf40030c0 +#define MASK_AMO_MINU 0xfe007fe0 +#define MATCH_MSUB_D 0xd6006400 +#define MASK_MSUB_D 0xfe007c00 +#define MATCH_SUB_S 0xd4000020 +#define MASK_SUB_S 0xfe007fe0 +#define MATCH_SLT 0xea000040 +#define MASK_SLT 0xfe007fe0 +#define MATCH_SLLW 0xee007040 +#define MASK_SLLW 0xfe007fe0 +#define MATCH_J 0xc0000000 +#define MASK_J 0xf8000000 +#define MATCH_SLTI 0xe8002000 +#define MASK_SLTI 0xfe007000 +#define MATCH_REMU 0xea0010e0 +#define MASK_REMU 0xfe007fe0 +#define MATCH_REMW 0xee0010c0 +#define MASK_REMW 0xfe007fe0 +#define MATCH_SLL 0xea007040 +#define MASK_SLL 0xfe007fe0 +#define MATCH_SLLI 0xe8007040 +#define MASK_SLLI 0xfe007fc0 +#define MATCH_SUB_D 0xd4006020 +#define MASK_SUB_D 0xfe007fe0 +#define MATCH_BEQ 0xe6000000 +#define MASK_BEQ 0xfe007000 +#define MATCH_AND 0xea000080 +#define MASK_AND 0xfe007fe0 +#define MATCH_LBU 0xf0004000 +#define MASK_LBU 0xfe007000 +#define MATCH_SQRT_S 0xd4000080 +#define MASK_SQRT_S 0xfff07fe0 +#define MATCH_SYSCALL 0xf6005000 +#define MASK_SYSCALL 0xfffff000 +#define MATCH_C_LT_S 0xd40002c0 +#define MASK_C_LT_S 0xfe007fe0 +#define MATCH_MTF_D 0xd4006b80 +#define MASK_MTF_D 0xfff07fe0 +#define MATCH_SQRT_D 0xd4006080 +#define MASK_SQRT_D 0xfff07fe0 +#define MATCH_AMOW_ADD 0xf4002000 +#define MASK_AMOW_ADD 0xfe007fe0 +#define MATCH_MULHW 0xee001040 +#define MASK_MULHW 0xfe007fe0 +#define MATCH_MADD_S 0xd6000000 +#define MASK_MADD_S 0xfe007c00 +#define MATCH_MULHU 0xea001060 +#define MASK_MULHU 0xfe007fe0 +#define MATCH_AMO_AND 0xf4003040 +#define MASK_AMO_AND 0xfe007fe0 +#define MATCH_SGNMUL_S 0xd40000e0 +#define MASK_SGNMUL_S 0xfe007fe0 +#define MATCH_RDNPC 0xf6001000 +#define MASK_RDNPC 0xffffffe0 +#define MATCH_CVT_S_L 0xd4000180 +#define MASK_CVT_S_L 0xfff07fe0 +#define MATCH_MADD_D 0xd6006000 +#define MASK_MADD_D 0xfe007c00 +#define MATCH_SYNCI 0xf0007000 +#define MASK_SYNCI 0xfff07000 +#define MATCH_DIV_S 0xd4000060 +#define MASK_DIV_S 0xfe007fe0 +#define MATCH_UNIMP 0x0 +#define MASK_UNIMP 0xffffffff +#define MATCH_CVT_S_D 0xd4000660 +#define MASK_CVT_S_D 0xfff07fe0 +#define MATCH_C_LE_S 0xd40002e0 +#define MASK_C_LE_S 0xfe007fe0 +#define MATCH_MUL_S 0xd4000040 +#define MASK_MUL_S 0xfe007fe0 +#define MATCH_TRUNCU_W_S 0xd4000160 +#define MASK_TRUNCU_W_S 0xfff07fe0 +#define MATCH_CVT_D_W 0xd40061c0 +#define MASK_CVT_D_W 0xfff07fe0 +#define MATCH_L_S 0xd0002000 +#define MASK_L_S 0xfe007000 +#define MATCH_CVT_D_L 0xd4006180 +#define MASK_CVT_D_L 0xfff07fe0 +#define MATCH_DIVW 0xee001080 +#define MASK_DIVW 0xfe007fe0 +#define MATCH_L_D 0xd0003000 +#define MASK_L_D 0xfe007000 +#define MATCH_DIVU 0xea0010a0 +#define MASK_DIVU 0xfe007fe0 +#define MATCH_TRUNCU_W_D 0xd4006160 +#define MASK_TRUNCU_W_D 0xfff07fe0 +#define MATCH_MUL_D 0xd4006040 +#define MASK_MUL_D 0xfe007fe0 +#define MATCH_SW 0xf2002000 +#define MASK_SW 0xfe007000 +#define MATCH_AMOW_SWAP 0xf4002020 +#define MASK_AMOW_SWAP 0xfe007fe0 +#define MATCH_LHU 0xf0005000 +#define MASK_LHU 0xfe007000 +#define MATCH_SH 0xf2001000 +#define MASK_SH 0xfe007000 +#define MATCH_AMO_MAXU 0xf40030e0 +#define MASK_AMO_MAXU 0xfe007fe0 +#define MATCH_AMOW_MAXU 0xf40020e0 +#define MASK_AMOW_MAXU 0xfe007fe0 +#define MATCH_SB 0xf2000000 +#define MASK_SB 0xfe007000 +#define MATCH_C_LT_D 0xd40062c0 +#define MASK_C_LT_D 0xfe007fe0 +#define MATCH_SD 0xf2003000 +#define MASK_SD 0xfe007000 diff --git a/pk/riscv-pk.c b/pk/riscv-pk.c index 3e4c76f..771982c 100644 --- a/pk/riscv-pk.c +++ b/pk/riscv-pk.c @@ -1,4 +1,5 @@ #include "pcr.h" +#include "pk.h" void __attribute__((section(".boottext"))) __start() { @@ -19,7 +20,10 @@ void __attribute__((section(".boottext"))) __start() sr0 |= SR_UX; #endif #endif - mtpcr(sr0,PCR_SR); + + mtpcr(sr0 | SR_EF, PCR_SR); + have_fp = mfpcr(PCR_SR) & SR_EF; + mtpcr(sr0, PCR_SR); extern void boot(); register void (*boot_p)() = &boot; diff --git a/pk/syscall.c b/pk/syscall.c index 93ff12a..790f32d 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -124,6 +124,6 @@ void handle_syscall(trapframe_t* tf) //printk("syscall %d (%x,%x,%x,%x) from %x == %d\n",n,tf->gpr[4],tf->gpr[5],tf->gpr[6],tf->gpr[7],tf->gpr[31],tf->gpr[2]); - tf->epc += 4; + advance_pc(tf); pop_tf(tf); } |