aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s144.Millennium.Berkeley.EDU>2010-10-15 17:51:37 -0700
committerAndrew Waterman <waterman@s144.Millennium.Berkeley.EDU>2010-10-15 17:51:37 -0700
commitb4fd490d689415205cf315c02f673b9386ece337 (patch)
tree73f93d81b6241b1d1204d7add68af065f9638ea9
parent2b7fd5fa6ac24f3d6d6cb8f0d6c1c32b85c39f02 (diff)
downloadpk-b4fd490d689415205cf315c02f673b9386ece337.zip
pk-b4fd490d689415205cf315c02f673b9386ece337.tar.gz
pk-b4fd490d689415205cf315c02f673b9386ece337.tar.bz2
[pk, sim] added FPU emulation support to proxy kernel
-rw-r--r--Makefile.in26
-rwxr-xr-xconfigure92
-rw-r--r--configure.ac2
-rw-r--r--pk/entry.S10
-rw-r--r--pk/fp.c358
-rw-r--r--pk/handlers.c16
-rw-r--r--pk/pk.c6
-rw-r--r--pk/pk.h12
-rw-r--r--pk/pk.mk.in10
-rw-r--r--pk/riscv-opc.h309
-rw-r--r--pk/riscv-pk.c6
-rw-r--r--pk/syscall.c2
l---------softfloat1
l---------softfloat_riscv1
14 files changed, 829 insertions, 22 deletions
diff --git a/Makefile.in b/Makefile.in
index 1b0fde8..5239d00 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -168,8 +168,8 @@ define subproject_template
# system will create a library for this subproject with just the
# corresponding dummy object file.
-ifeq ($$(strip $$($(2)_srcs)),)
-$(2)_srcs += _$(1).c
+ifeq ($$(strip $$($(2)_c_srcs)),)
+$(2)_c_srcs += _$(1).c
$(2)_junk += _$(1).c
endif
@@ -178,19 +178,19 @@ _$(1).c :
# Build the object files for this subproject
-$(2)_objs := $$(patsubst %.c, %.o, $$($(2)_srcs))
+$(2)_c_objs := $$(patsubst %.c, %.o, $$($(2)_c_srcs))
$(2)_asm_objs := $$(patsubst %.S, %.o, $$($(2)_asm_srcs))
-$(2)_deps := $$(patsubst %.o, %.d, $$($(2)_objs))
-$$($(2)_objs) : %.o : %.c
+$(2)_c_deps := $$(patsubst %.o, %.d, $$($(2)_c_objs))
+$$($(2)_c_objs) : %.o : %.c
$(COMPILE) -c $$<
$$($(2)_asm_objs) : %.o : %.S
$(COMPILE) -c $$<
-$(2)_junk += $$($(2)_objs) $$($(2)_deps) $$($(2)_asm_objs)
+$(2)_junk += $$($(2)_c_objs) $$($(2)_c_deps) $$($(2)_asm_objs)
# Build a library for this subproject
-lib$(1).a : $$($(2)_objs) $$($(2)_asm_objs)
+lib$(1).a : $$($(2)_c_objs) $$($(2)_asm_objs)
$(AR) rcv $$@ $$^
$(RANLIB) $$@
@@ -218,7 +218,7 @@ $$($(2)_test_objs) : %.o : %.c
$$($(2)_test_exes) : %-utst : %.t.o $$($(2)_test_libnames)
$(LINK) -o $$@ $$< $$($(2)_test_libarg) $(LIBS)
-$(2)_deps += $$($(2)_test_deps)
+$(2)_c_deps += $$($(2)_test_deps)
$(2)_junk += \
$$($(2)_test_objs) $$($(2)_test_deps) \
$$($(2)_test_exes) *.junk-dat
@@ -245,7 +245,7 @@ $$($(2)_prog_objs) : %.o : %.c
$$($(2)_prog_exes) : % : %.o $$($(2)_prog_libnames)
$(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS)
-$(2)_deps += $$($(2)_prog_deps)
+$(2)_c_deps += $$($(2)_prog_deps)
$(2)_junk += $$($(2)_prog_objs) $$($(2)_prog_deps) $$($(2)_prog_exes)
# Build programs which will be installed
@@ -260,7 +260,7 @@ $$($(2)_install_prog_objs) : %.o : %.c
$$($(2)_install_prog_exes) : % : %.o $$($(2)_prog_libnames)
$(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS)
-$(2)_deps += $$($(2)_install_prog_deps)
+$(2)_c_deps += $$($(2)_install_prog_deps)
$(2)_junk += \
$$($(2)_install_prog_objs) $$($(2)_install_prog_deps) \
$$($(2)_install_prog_exes)
@@ -280,11 +280,11 @@ clean-$(1) :
# Update running variables
libs += lib$(1).a
-objs += $$($(2)_objs)
-srcs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_srcs))
+objs += $$($(2)_c_objs)
+srcs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_c_srcs))
hdrs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_hdrs))
junk += $$($(2)_junk)
-deps += $$($(2)_deps)
+deps += $$($(2)_c_deps)
test_outs += $$($(2)_test_outs)
diff --git a/configure b/configure
index 7c432e5..35f548d 100755
--- a/configure
+++ b/configure
@@ -4023,6 +4023,96 @@ fi
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects softfloat"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : softfloat" >&5
+$as_echo "$as_me: configuring default subproject : softfloat" >&6;}
+ ac_config_files="$ac_config_files softfloat.mk:softfloat/softfloat.mk.in"
+
+ enable_softfloat_sproj="yes"
+ subprojects_enabled="$subprojects_enabled softfloat"
+
+$as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects softfloat_riscv"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : softfloat_riscv" >&5
+$as_echo "$as_me: configuring default subproject : softfloat_riscv" >&6;}
+ ac_config_files="$ac_config_files softfloat_riscv.mk:softfloat_riscv/softfloat_riscv.mk.in"
+
+ enable_softfloat_riscv_sproj="yes"
+ subprojects_enabled="$subprojects_enabled softfloat_riscv"
+
+$as_echo "#define SOFTFLOAT_RISCV_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
# Output make variables
@@ -4729,6 +4819,8 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"pk.mk") CONFIG_FILES="$CONFIG_FILES pk.mk:pk/pk.mk.in" ;;
+ "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;;
+ "softfloat_riscv.mk") CONFIG_FILES="$CONFIG_FILES softfloat_riscv.mk:softfloat_riscv/softfloat_riscv.mk.in" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 963ba5c..33b3d09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,7 +80,7 @@ AC_SUBST([CFLAGS], ["-Wall -O3 -std=gnu99"])
# The '*' suffix indicates an optional subproject. The '**' suffix
# indicates an optional subproject which is also the name of a group.
-MCPPBS_SUBPROJECTS([ pk ])
+MCPPBS_SUBPROJECTS([ pk, softfloat, softfloat_riscv ])
#-------------------------------------------------------------------------
# MCPPBS subproject groups
diff --git a/pk/entry.S b/pk/entry.S
index 67fb025..b128e93 100644
--- a/pk/entry.S
+++ b/pk/entry.S
@@ -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
diff --git a/pk/fp.c b/pk/fp.c
new file mode 100644
index 0000000..eff9b27
--- /dev/null
+++ b/pk/fp.c
@@ -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!");
}
diff --git a/pk/pk.c b/pk/pk.c
index 9508286..d3f12ff 100644
--- a/pk/pk.c
+++ b/pk/pk.c
@@ -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)
diff --git a/pk/pk.h b/pk/pk.h
index 501010e..c98e2f9 100644
--- a/pk/pk.h
+++ b/pk/pk.h
@@ -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);
}
diff --git a/softfloat b/softfloat
new file mode 120000
index 0000000..fe7fce9
--- /dev/null
+++ b/softfloat
@@ -0,0 +1 @@
+../sim/softfloat/ \ No newline at end of file
diff --git a/softfloat_riscv b/softfloat_riscv
new file mode 120000
index 0000000..c6c4193
--- /dev/null
+++ b/softfloat_riscv
@@ -0,0 +1 @@
+../sim/softfloat_riscv/ \ No newline at end of file