|
|
|
@ -65,15 +65,22 @@ int emulate_fp(trapframe_t* tf) |
|
|
|
|
|
|
|
#define IS_INSN(x) ((tf->insn & MASK_ ## x) == MATCH_ ## x) |
|
|
|
|
|
|
|
int do_writeback = 0; |
|
|
|
int writeback_dp; |
|
|
|
uint64_t writeback_value; |
|
|
|
#define DO_WRITEBACK(dp, value) \ |
|
|
|
do { do_writeback = 1; writeback_dp = (dp); writeback_value = (value); } \ |
|
|
|
while(0) |
|
|
|
|
|
|
|
if(IS_INSN(FLW)) |
|
|
|
{ |
|
|
|
validate_address(tf, effective_address_load, 4, 0); |
|
|
|
set_fp_reg(RRD, 0, *(uint32_t*)effective_address_load); |
|
|
|
DO_WRITEBACK(0, *(uint32_t*)effective_address_load); |
|
|
|
} |
|
|
|
else if(IS_INSN(FLD)) |
|
|
|
{ |
|
|
|
validate_address(tf, effective_address_load, 8, 0); |
|
|
|
set_fp_reg(RRD, 1, *(uint64_t*)effective_address_load); |
|
|
|
DO_WRITEBACK(1, *(uint64_t*)effective_address_load); |
|
|
|
} |
|
|
|
else if(IS_INSN(FSW)) |
|
|
|
{ |
|
|
|
@ -90,89 +97,89 @@ int emulate_fp(trapframe_t* tf) |
|
|
|
else if(IS_INSN(MFTX_D)) |
|
|
|
XRDR = frs2d; |
|
|
|
else if(IS_INSN(MXTF_S)) |
|
|
|
set_fp_reg(RRD, 0, XRS1); |
|
|
|
DO_WRITEBACK(0, XRS1); |
|
|
|
else if(IS_INSN(MXTF_D)) |
|
|
|
set_fp_reg(RRD, 1, XRS1); |
|
|
|
DO_WRITEBACK(1, XRS1); |
|
|
|
else if(IS_INSN(FSGNJ_S)) |
|
|
|
set_fp_reg(RRD, 0, (frs1s &~ (uint32_t)INT32_MIN) | (frs2s & (uint32_t)INT32_MIN)); |
|
|
|
DO_WRITEBACK(0, (frs1s &~ (uint32_t)INT32_MIN) | (frs2s & (uint32_t)INT32_MIN)); |
|
|
|
else if(IS_INSN(FSGNJ_D)) |
|
|
|
set_fp_reg(RRD, 1, (frs1d &~ INT64_MIN) | (frs2d & INT64_MIN)); |
|
|
|
DO_WRITEBACK(1, (frs1d &~ INT64_MIN) | (frs2d & INT64_MIN)); |
|
|
|
else if(IS_INSN(FSGNJN_S)) |
|
|
|
set_fp_reg(RRD, 0, (frs1s &~ (uint32_t)INT32_MIN) | ((~frs2s) & (uint32_t)INT32_MIN)); |
|
|
|
DO_WRITEBACK(0, (frs1s &~ (uint32_t)INT32_MIN) | ((~frs2s) & (uint32_t)INT32_MIN)); |
|
|
|
else if(IS_INSN(FSGNJN_D)) |
|
|
|
set_fp_reg(RRD, 1, (frs1d &~ INT64_MIN) | ((~frs2d) & INT64_MIN)); |
|
|
|
DO_WRITEBACK(1, (frs1d &~ INT64_MIN) | ((~frs2d) & INT64_MIN)); |
|
|
|
else if(IS_INSN(FSGNJX_S)) |
|
|
|
set_fp_reg(RRD, 0, frs1s ^ (frs2s & (uint32_t)INT32_MIN)); |
|
|
|
DO_WRITEBACK(0, frs1s ^ (frs2s & (uint32_t)INT32_MIN)); |
|
|
|
else if(IS_INSN(FSGNJX_D)) |
|
|
|
set_fp_reg(RRD, 1, frs1d ^ (frs2d & INT64_MIN)); |
|
|
|
DO_WRITEBACK(1, frs1d ^ (frs2d & INT64_MIN)); |
|
|
|
else if(IS_INSN(FEQ_S)) |
|
|
|
XRDR = f32_eq(frs1s, frs2s); |
|
|
|
else if(IS_INSN(FEQ_D)) |
|
|
|
XRDR = f64_eq(frs1d, frs2d); |
|
|
|
else if(IS_INSN(FLE_S)) |
|
|
|
XRDR = f32_le(frs1s, frs2s); |
|
|
|
XRDR = f32_eq(frs1s, frs2s) || f32_lt(frs1s, frs2s); |
|
|
|
else if(IS_INSN(FLE_D)) |
|
|
|
XRDR = f64_le(frs1d, frs2d); |
|
|
|
XRDR = f64_eq(frs1d, frs2d) || f64_lt(frs1s, frs2s); |
|
|
|
else if(IS_INSN(FLT_S)) |
|
|
|
XRDR = f32_lt(frs1s, frs2s); |
|
|
|
else if(IS_INSN(FLT_D)) |
|
|
|
XRDR = f64_lt(frs1d, frs2d); |
|
|
|
else if(IS_INSN(FCVT_S_W)) |
|
|
|
set_fp_reg(RRD, 0, i32_to_f32(XRS1)); |
|
|
|
DO_WRITEBACK(0, i64_to_f32((int64_t)(int32_t)XRS1)); |
|
|
|
else if(IS_INSN(FCVT_S_L)) |
|
|
|
set_fp_reg(RRD, 0, i64_to_f32(XRS1)); |
|
|
|
DO_WRITEBACK(0, i64_to_f32(XRS1)); |
|
|
|
else if(IS_INSN(FCVT_S_D)) |
|
|
|
set_fp_reg(RRD, 0, f64_to_f32(frs1d)); |
|
|
|
DO_WRITEBACK(0, f64_to_f32(frs1d)); |
|
|
|
else if(IS_INSN(FCVT_D_W)) |
|
|
|
set_fp_reg(RRD, 1, i32_to_f64(XRS1)); |
|
|
|
DO_WRITEBACK(1, i64_to_f64((int64_t)(int32_t)XRS1)); |
|
|
|
else if(IS_INSN(FCVT_D_L)) |
|
|
|
set_fp_reg(RRD, 1, i64_to_f64(XRS1)); |
|
|
|
DO_WRITEBACK(1, i64_to_f64(XRS1)); |
|
|
|
else if(IS_INSN(FCVT_D_S)) |
|
|
|
set_fp_reg(RRD, 1, f32_to_f64(frs1s)); |
|
|
|
DO_WRITEBACK(1, f32_to_f64(frs1s)); |
|
|
|
else if(IS_INSN(FCVT_S_WU)) |
|
|
|
set_fp_reg(RRD, 0, ui32_to_f32(XRS1)); |
|
|
|
DO_WRITEBACK(0, ui64_to_f32((uint64_t)(uint32_t)XRS1)); |
|
|
|
else if(IS_INSN(FCVT_S_LU)) |
|
|
|
set_fp_reg(RRD, 0, ui64_to_f32(XRS1)); |
|
|
|
DO_WRITEBACK(0, ui64_to_f32(XRS1)); |
|
|
|
else if(IS_INSN(FCVT_D_WU)) |
|
|
|
set_fp_reg(RRD, 1, ui32_to_f64(XRS1)); |
|
|
|
DO_WRITEBACK(1, ui64_to_f64((uint64_t)(uint32_t)XRS1)); |
|
|
|
else if(IS_INSN(FCVT_D_LU)) |
|
|
|
set_fp_reg(RRD, 1, ui64_to_f64(XRS1)); |
|
|
|
DO_WRITEBACK(1, ui64_to_f64(XRS1)); |
|
|
|
else if(IS_INSN(FADD_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_add(frs1s, frs2s)); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, 0x3f800000, frs2s)); |
|
|
|
else if(IS_INSN(FADD_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_add(frs1d, frs2d)); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, 0x3ff0000000000000LL, frs2d)); |
|
|
|
else if(IS_INSN(FSUB_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_sub(frs1s, frs2s)); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, 0x3f800000, frs2s ^ (uint32_t)INT32_MIN)); |
|
|
|
else if(IS_INSN(FSUB_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_sub(frs1d, frs2d)); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, 0x3ff0000000000000LL, frs2d ^ INT64_MIN)); |
|
|
|
else if(IS_INSN(FMUL_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_mul(frs1s, frs2s)); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, frs2s, 0)); |
|
|
|
else if(IS_INSN(FMUL_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_mul(frs1d, frs2d)); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, frs2d, 0)); |
|
|
|
else if(IS_INSN(FMADD_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_mulAdd(frs1s, frs2s, frs3s)); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, frs2s, frs3s)); |
|
|
|
else if(IS_INSN(FMADD_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_mulAdd(frs1d, frs2d, frs3d)); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, frs2d, frs3d)); |
|
|
|
else if(IS_INSN(FMSUB_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_mulAdd(frs1s, frs2s, frs3s ^ (uint32_t)INT32_MIN)); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, frs2s, frs3s ^ (uint32_t)INT32_MIN)); |
|
|
|
else if(IS_INSN(FMSUB_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_mulAdd(frs1d, frs2d, frs3d ^ INT64_MIN)); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, frs2d, frs3d ^ INT64_MIN)); |
|
|
|
else if(IS_INSN(FNMADD_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_mulAdd(frs1s, frs2s, frs3s) ^ (uint32_t)INT32_MIN); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, frs2s, frs3s) ^ (uint32_t)INT32_MIN); |
|
|
|
else if(IS_INSN(FNMADD_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_mulAdd(frs1d, frs2d, frs3d) ^ INT64_MIN); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, frs2d, frs3d) ^ INT64_MIN); |
|
|
|
else if(IS_INSN(FNMSUB_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_mulAdd(frs1s, frs2s, frs3s ^ (uint32_t)INT32_MIN) ^ (uint32_t)INT32_MIN); |
|
|
|
DO_WRITEBACK(0, f32_mulAdd(frs1s, frs2s, frs3s ^ (uint32_t)INT32_MIN) ^ (uint32_t)INT32_MIN); |
|
|
|
else if(IS_INSN(FNMSUB_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_mulAdd(frs1d, frs2d, frs3d ^ INT64_MIN) ^ INT64_MIN); |
|
|
|
DO_WRITEBACK(1, f64_mulAdd(frs1d, frs2d, frs3d ^ INT64_MIN) ^ INT64_MIN); |
|
|
|
else if(IS_INSN(FDIV_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_div(frs1s, frs2s)); |
|
|
|
DO_WRITEBACK(0, f32_div(frs1s, frs2s)); |
|
|
|
else if(IS_INSN(FDIV_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_div(frs1d, frs2d)); |
|
|
|
DO_WRITEBACK(1, f64_div(frs1d, frs2d)); |
|
|
|
else if(IS_INSN(FSQRT_S)) |
|
|
|
set_fp_reg(RRD, 0, f32_sqrt(frs1s)); |
|
|
|
DO_WRITEBACK(0, f32_sqrt(frs1s)); |
|
|
|
else if(IS_INSN(FSQRT_D)) |
|
|
|
set_fp_reg(RRD, 1, f64_sqrt(frs1d)); |
|
|
|
DO_WRITEBACK(1, f64_sqrt(frs1d)); |
|
|
|
else if(IS_INSN(FCVT_W_S)) |
|
|
|
XRDR = f32_to_i32_r_minMag(frs1s,true); |
|
|
|
else if(IS_INSN(FCVT_W_D)) |
|
|
|
@ -192,6 +199,9 @@ int emulate_fp(trapframe_t* tf) |
|
|
|
else |
|
|
|
return -1; |
|
|
|
|
|
|
|
if(do_writeback) |
|
|
|
set_fp_reg(RRD, writeback_dp, writeback_value); |
|
|
|
|
|
|
|
if(have_fp) |
|
|
|
put_fp_state(fp_state.fpr,fp_state.fsr); |
|
|
|
|
|
|
|
|