Moved the softfloat-enabled ops back to the cpu directory.
Made softfloat always enabled, thus dynarec disabled, only for the IBM PS/2 model 70 type 4, in preparation for its comeback to main use.
This commit is contained in:
@@ -1,750 +0,0 @@
|
||||
#define sf_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \
|
||||
static int sf_FADD##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) \
|
||||
result = floatx80_add(a, use_var, &status); \
|
||||
\
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FDIV##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) { \
|
||||
result = floatx80_div(a, use_var, &status); \
|
||||
} \
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FDIVR##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) { \
|
||||
result = floatx80_div(use_var, a, &status); \
|
||||
} \
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv##cycle_postfix) : ((x87_concurrency.fdiv##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FMUL##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) { \
|
||||
result = floatx80_mul(a, use_var, &status); \
|
||||
} \
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul##cycle_postfix) : ((x87_timings.fmul##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul##cycle_postfix) : ((x87_concurrency.fmul##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FSUB##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) \
|
||||
result = floatx80_sub(a, use_var, &status); \
|
||||
\
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FSUBR##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a, result; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
FPU_check_pending_exceptions(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_stack_underflow(fetchdat, 0, 0); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (!is_nan) \
|
||||
result = floatx80_sub(use_var, a, &status); \
|
||||
\
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_save_regi(result, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
sf_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32)
|
||||
#ifndef FPU_8087
|
||||
sf_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32)
|
||||
#endif
|
||||
sf_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64)
|
||||
#ifndef FPU_8087
|
||||
sf_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64)
|
||||
#endif
|
||||
|
||||
sf_FPU(iw, uint16_t, 16, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16)
|
||||
#ifndef FPU_8087
|
||||
sf_FPU(iw, uint16_t, 32, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16)
|
||||
#endif
|
||||
sf_FPU(il, uint32_t, 16, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32)
|
||||
#ifndef FPU_8087
|
||||
sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32)
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
static int
|
||||
sf_FADD_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_add(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FADD_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_add(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FADDP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_add(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FDIV_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FDIV_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FDIVP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FDIVR_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FDIVR_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FDIVRP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_div(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FMUL_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_mul(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FMUL_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_mul(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FMULP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_mul(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FSUB_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FSUB_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FSUBP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FSUBR_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(fetchdat & 7);
|
||||
b = FPU_read_regi(0);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FSUBR_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FSUBRP_sti_st0(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_stack_underflow(fetchdat, fetchdat & 7, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
result = floatx80_sub(a, b, &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, fetchdat & 7);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FSQRT(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
result = floatx80_sqrt(FPU_read_regi(0), &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsqrt) : (x87_timings.fsqrt * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsqrt) : (x87_concurrency.fsqrt * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FRNDINT(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
result = floatx80_round_to_int(FPU_read_regi(0), &status);
|
||||
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,489 +0,0 @@
|
||||
#define cmp_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \
|
||||
static int sf_FCOM##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a; \
|
||||
int rc; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \
|
||||
setcc(C0 | C2 | C3); \
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (is_nan) { \
|
||||
rc = float_relation_unordered; \
|
||||
float_raise(&status, float_flag_invalid); \
|
||||
} else { \
|
||||
rc = floatx80_compare_two(a, use_var, &status); \
|
||||
} \
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc)); \
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int sf_FCOMP##name##_a##a_size(uint32_t fetchdat) \
|
||||
{ \
|
||||
floatx80 a; \
|
||||
int rc; \
|
||||
struct float_status_t status; \
|
||||
optype temp; \
|
||||
FP_ENTER(); \
|
||||
fetch_ea_##a_size(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
load_var = rw; \
|
||||
if (cpu_state.abrt) \
|
||||
return 1;\
|
||||
clear_C1(); \
|
||||
if (IS_TAG_EMPTY(0)) { \
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \
|
||||
setcc(C0 | C2 | C3); \
|
||||
if (is_IA_masked()) \
|
||||
FPU_pop(); \
|
||||
\
|
||||
goto next_ins; \
|
||||
} \
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word()); \
|
||||
a = FPU_read_regi(0); \
|
||||
if (is_nan) { \
|
||||
rc = float_relation_unordered; \
|
||||
float_raise(&status, float_flag_invalid); \
|
||||
} else { \
|
||||
rc = floatx80_compare_two(a, use_var, &status); \
|
||||
} \
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc)); \
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \
|
||||
FPU_pop(); \
|
||||
\
|
||||
next_ins: \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
// clang-format off
|
||||
cmp_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32)
|
||||
#ifndef FPU_8087
|
||||
cmp_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32)
|
||||
#endif
|
||||
cmp_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64)
|
||||
#ifndef FPU_8087
|
||||
cmp_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64)
|
||||
#endif
|
||||
|
||||
cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16)
|
||||
#ifndef FPU_8087
|
||||
cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16)
|
||||
#endif
|
||||
cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32)
|
||||
#ifndef FPU_8087
|
||||
cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32)
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
static int
|
||||
sf_FCOM_sti(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_two(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FCOMP_sti(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
if (is_IA_masked()) {
|
||||
FPU_pop();
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_two(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FCOMPP(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
if (is_IA_masked()) {
|
||||
FPU_pop();
|
||||
FPU_pop();
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(1);
|
||||
rc = floatx80_compare_two(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FUCOMPP(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
if (is_IA_masked()) {
|
||||
FPU_pop();
|
||||
FPU_pop();
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(1);
|
||||
rc = floatx80_compare_quiet(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FCOMI_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_two(a, b, &status);
|
||||
FPU_write_eflags_fpu_compare(rc);
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FCOMIP_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG);
|
||||
if (is_IA_masked()) {
|
||||
FPU_pop();
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_two(a, b, &status);
|
||||
FPU_write_eflags_fpu_compare(rc);
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FUCOM_sti(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_quiet(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FUCOMP_sti(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
if (is_IA_masked())
|
||||
FPU_pop();
|
||||
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_quiet(a, b, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_pop();
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FUCOMI_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_quiet(a, b, &status);
|
||||
FPU_write_eflags_fpu_compare(rc);
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
sf_FUCOMIP_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b;
|
||||
struct float_status_t status;
|
||||
int rc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG);
|
||||
if (is_IA_masked())
|
||||
FPU_pop();
|
||||
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(fetchdat & 7);
|
||||
rc = floatx80_compare_quiet(a, b, &status);
|
||||
FPU_write_eflags_fpu_compare(rc);
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_pop();
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FTST(uint32_t fetchdat)
|
||||
{
|
||||
int rc;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
setcc(C0 | C2 | C3);
|
||||
} else {
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
rc = floatx80_compare_two(FPU_read_regi(0), Const_Z, &status);
|
||||
setcc(FPU_status_word_flags_fpu_compare(rc));
|
||||
FPU_exception(fetchdat, status.float_exception_flags, 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FXAM(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 reg;
|
||||
int sign;
|
||||
float_class_t aClass;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
reg = FPU_read_regi(0);
|
||||
sign = floatx80_sign(reg);
|
||||
/*
|
||||
* Examine the contents of the ST(0) register and sets the condition
|
||||
* code flags C0, C2 and C3 in the FPU status word to indicate the
|
||||
* class of value or number in the register.
|
||||
*/
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
setcc(C3 | C1 | C0);
|
||||
} else {
|
||||
aClass = floatx80_class(reg);
|
||||
switch (aClass) {
|
||||
case float_zero:
|
||||
setcc(C3 | C1);
|
||||
break;
|
||||
case float_SNaN:
|
||||
case float_QNaN:
|
||||
// unsupported handled as NaNs
|
||||
if (floatx80_is_unsupported(reg)) {
|
||||
setcc(C1);
|
||||
} else {
|
||||
setcc(C1 | C0);
|
||||
}
|
||||
break;
|
||||
case float_negative_inf:
|
||||
case float_positive_inf:
|
||||
setcc(C2 | C1 | C0);
|
||||
break;
|
||||
case float_denormal:
|
||||
setcc(C3 | C2 | C1);
|
||||
break;
|
||||
case float_normalized:
|
||||
setcc(C2 | C1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The C1 flag is set to the sign of the value in ST(0), regardless
|
||||
* of whether the register is empty or full.
|
||||
*/
|
||||
if (!sign)
|
||||
clear_C1();
|
||||
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/* A fast way to find out whether x is one of RC_DOWN or RC_CHOP
|
||||
(and not one of RC_RND or RC_UP).
|
||||
*/
|
||||
#define DOWN_OR_CHOP() (fpu_state.cwd & FPU_CW_RC & FPU_RC_DOWN)
|
||||
|
||||
static __inline floatx80
|
||||
FPU_round_const(const floatx80 a, int adj)
|
||||
{
|
||||
floatx80 result = a;
|
||||
result.fraction += adj;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDL2T(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(FPU_round_const(Const_L2T, (fpu_state.cwd & FPU_CW_RC) == X87_ROUNDING_UP), 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDL2E(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(FPU_round_const(Const_L2E, DOWN_OR_CHOP() ? -1 : 0), 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDPI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(FPU_round_const(Const_PI, DOWN_OR_CHOP() ? -1 : 0), 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDEG2(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(FPU_round_const(Const_LG2, DOWN_OR_CHOP() ? -1 : 0), 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDLN2(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(FPU_round_const(Const_LN2, DOWN_OR_CHOP() ? -1 : 0), 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLD1(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(Const_1, 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDZ(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (!IS_TAG_EMPTY(-1))
|
||||
FPU_stack_overflow(fetchdat);
|
||||
else {
|
||||
FPU_push();
|
||||
FPU_save_regi(Const_Z, 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +0,0 @@
|
||||
static int
|
||||
sf_FXCH_sti(uint32_t fetchdat)
|
||||
{
|
||||
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
|
||||
floatx80 st0_reg, sti_reg;
|
||||
int st0_tag, sti_tag;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
st0_tag = FPU_gettagi(0);
|
||||
sti_tag = FPU_gettagi(fetchdat & 7);
|
||||
st0_reg = FPU_read_regi(0);
|
||||
sti_reg = FPU_read_regi(fetchdat & 7);
|
||||
|
||||
clear_C1();
|
||||
if ((st0_tag == X87_TAG_EMPTY) || (sti_tag == X87_TAG_EMPTY)) {
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
if (is_IA_masked()) {
|
||||
/* Masked response */
|
||||
if (st0_tag == X87_TAG_EMPTY)
|
||||
st0_reg = floatx80_default_nan;
|
||||
if (sti_tag == X87_TAG_EMPTY)
|
||||
sti_reg = floatx80_default_nan;
|
||||
} else
|
||||
goto next_ins;
|
||||
}
|
||||
FPU_save_regi(st0_reg, fetchdat & 7);
|
||||
FPU_save_regi(sti_reg, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxch) : (x87_timings.fxch * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxch) : (x87_concurrency.fxch * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FCHS(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 st0_reg;
|
||||
floatx80 result;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
if (IS_TAG_EMPTY(0))
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
else {
|
||||
clear_C1();
|
||||
st0_reg = FPU_read_regi(0);
|
||||
result = floatx80_chs(st0_reg);
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fchs) : (x87_timings.fchs * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fchs) : (x87_concurrency.fchs * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FABS(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 st0_reg;
|
||||
floatx80 result;
|
||||
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
if (IS_TAG_EMPTY(0))
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
else {
|
||||
clear_C1();
|
||||
st0_reg = FPU_read_regi(0);
|
||||
result = floatx80_abs(st0_reg);
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fabs) : (x87_timings.fabs * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fabs) : (x87_concurrency.fabs * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FDECSTP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
fpu_state.tos = (fpu_state.tos - 1) & 7;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FINCSTP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
fpu_state.tos = (fpu_state.tos + 1) & 7;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FFREE_sti(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
FPU_settagi(X87_TAG_EMPTY, fetchdat & 7);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FFREEP_sti(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
FPU_check_pending_exceptions();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
FPU_settagi(X87_TAG_EMPTY, fetchdat & 7);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
FPU_pop();
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,593 +0,0 @@
|
||||
static uint32_t
|
||||
fpu_save_environment(void)
|
||||
{
|
||||
int tag;
|
||||
unsigned offset;
|
||||
|
||||
/* read all registers in stack order and update x87 tag word */
|
||||
for (int n = 0; n < 8; n++) {
|
||||
// update tag only if it is not empty
|
||||
if (!IS_TAG_EMPTY(n)) {
|
||||
tag = FPU_tagof(FPU_read_regi(n));
|
||||
FPU_settagi(tag, n);
|
||||
}
|
||||
}
|
||||
|
||||
fpu_state.swd = (fpu_state.swd & ~(7 << 11)) | ((fpu_state.tos & 7) << 11);
|
||||
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) {
|
||||
case 0x000: { /*16-bit real mode*/
|
||||
uint16_t tmp;
|
||||
uint32_t fp_ip, fp_dp;
|
||||
|
||||
fp_ip = ((uint32_t)(fpu_state.fcs << 4)) | fpu_state.fip;
|
||||
fp_dp = ((uint32_t)(fpu_state.fds << 4)) | fpu_state.fdp;
|
||||
|
||||
tmp = i387_get_control_word();
|
||||
writememw(easeg, cpu_state.eaaddr + 0x00, tmp);
|
||||
tmp = i387_get_status_word();
|
||||
writememw(easeg, cpu_state.eaaddr + 0x02, tmp);
|
||||
tmp = fpu_state.tag;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x04, tmp);
|
||||
tmp = fp_ip & 0xffff;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x06, tmp);
|
||||
tmp = (uint16_t)((fp_ip & 0xf0000) >> 4) | fpu_state.foo;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x08, tmp);
|
||||
tmp = fp_dp & 0xffff;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x0a, tmp);
|
||||
tmp = (uint16_t)((fp_dp & 0xf0000) >> 4);
|
||||
writememw(easeg, cpu_state.eaaddr + 0x0c, tmp);
|
||||
offset = 0x0e;
|
||||
}
|
||||
break;
|
||||
case 0x001: {/*16-bit protected mode*/
|
||||
uint16_t tmp;
|
||||
tmp = i387_get_control_word();
|
||||
writememw(easeg, cpu_state.eaaddr + 0x00, tmp);
|
||||
tmp = i387_get_status_word();
|
||||
writememw(easeg, cpu_state.eaaddr + 0x02, tmp);
|
||||
tmp = fpu_state.tag;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x04, tmp);
|
||||
tmp = (uint16_t)(fpu_state.fip) & 0xffff;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x06, tmp);
|
||||
tmp = fpu_state.fcs;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x08, tmp);
|
||||
tmp = (uint16_t)(fpu_state.fdp) & 0xffff;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x0a, tmp);
|
||||
tmp = fpu_state.fds;
|
||||
writememw(easeg, cpu_state.eaaddr + 0x0c, tmp);
|
||||
offset = 0x0e;
|
||||
}
|
||||
break;
|
||||
case 0x100: { /*32-bit real mode*/
|
||||
uint32_t tmp, fp_ip, fp_dp;
|
||||
|
||||
fp_ip = ((uint32_t)(fpu_state.fcs << 4)) | fpu_state.fip;
|
||||
fp_dp = ((uint32_t)(fpu_state.fds << 4)) | fpu_state.fdp;
|
||||
|
||||
tmp = 0xffff0000 | i387_get_control_word();
|
||||
writememl(easeg, cpu_state.eaaddr + 0x00, tmp);
|
||||
tmp = 0xffff0000 | i387_get_status_word();
|
||||
writememl(easeg, cpu_state.eaaddr + 0x04, tmp);
|
||||
tmp = 0xffff0000 | fpu_state.tag;
|
||||
writememl(easeg, cpu_state.eaaddr + 0x08, tmp);
|
||||
tmp = 0xffff0000 | (fp_ip & 0xffff);
|
||||
writememl(easeg, cpu_state.eaaddr + 0x0c, tmp);
|
||||
tmp = ((fp_ip & 0xffff0000) >> 4) | fpu_state.foo;
|
||||
writememl(easeg, cpu_state.eaaddr + 0x10, tmp);
|
||||
tmp = 0xffff0000 | (fp_dp & 0xffff);
|
||||
writememl(easeg, cpu_state.eaaddr + 0x14, tmp);
|
||||
tmp = (fp_dp & 0xffff0000) >> 4;
|
||||
writememl(easeg, cpu_state.eaaddr + 0x18, tmp);
|
||||
offset = 0x1c;
|
||||
}
|
||||
break;
|
||||
case 0x101: { /*32-bit protected mode*/
|
||||
uint32_t tmp;
|
||||
tmp = 0xffff0000 | i387_get_control_word();
|
||||
writememl(easeg, cpu_state.eaaddr + 0x00, tmp);
|
||||
tmp = 0xffff0000 | i387_get_status_word();
|
||||
writememl(easeg, cpu_state.eaaddr + 0x04, tmp);
|
||||
tmp = 0xffff0000 | fpu_state.tag;
|
||||
writememl(easeg, cpu_state.eaaddr + 0x08, tmp);
|
||||
tmp = (uint32_t)(fpu_state.fip);
|
||||
writememl(easeg, cpu_state.eaaddr + 0x0c, tmp);
|
||||
tmp = fpu_state.fcs | (((uint32_t)(fpu_state.foo)) << 16);
|
||||
writememl(easeg, cpu_state.eaaddr + 0x10, tmp);
|
||||
tmp = (uint32_t)(fpu_state.fdp);
|
||||
writememl(easeg, cpu_state.eaaddr + 0x14, tmp);
|
||||
tmp = 0xffff0000 | fpu_state.fds;
|
||||
writememl(easeg, cpu_state.eaaddr + 0x18, tmp);
|
||||
offset = 0x1c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (cpu_state.eaaddr + offset);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
fpu_load_environment(void)
|
||||
{
|
||||
unsigned offset;
|
||||
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) {
|
||||
case 0x000: { /*16-bit real mode*/
|
||||
uint16_t tmp;
|
||||
uint32_t fp_ip, fp_dp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x0c);
|
||||
fp_dp = (tmp & 0xf000) << 4;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x0a);
|
||||
fpu_state.fdp = fp_dp | tmp;
|
||||
fpu_state.fds = 0;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x08);
|
||||
fp_ip = (tmp & 0xf000) << 4;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x06);
|
||||
fpu_state.fip = fp_ip | tmp;
|
||||
fpu_state.fcs = 0;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x04);
|
||||
fpu_state.tag = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x02);
|
||||
fpu_state.swd = tmp;
|
||||
fpu_state.tos = (tmp >> 11) & 7;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x00);
|
||||
fpu_state.cwd = tmp;
|
||||
offset = 0x0e;
|
||||
}
|
||||
break;
|
||||
case 0x001: {/*16-bit protected mode*/
|
||||
uint16_t tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x0c);
|
||||
fpu_state.fds = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x0a);
|
||||
fpu_state.fdp = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x08);
|
||||
fpu_state.fcs = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x06);
|
||||
fpu_state.fip = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x04);
|
||||
fpu_state.tag = tmp;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x02);
|
||||
fpu_state.swd = tmp;
|
||||
fpu_state.tos = (tmp >> 11) & 7;
|
||||
tmp = readmemw(easeg, cpu_state.eaaddr + 0x00);
|
||||
fpu_state.cwd = tmp;
|
||||
offset = 0x0e;
|
||||
}
|
||||
break;
|
||||
case 0x100: { /*32-bit real mode*/
|
||||
uint32_t tmp, fp_ip, fp_dp;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x18);
|
||||
fp_dp = (tmp & 0x0ffff000) << 4;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x14);
|
||||
fp_dp |= (tmp & 0xffff);
|
||||
fpu_state.fdp = fp_dp;
|
||||
fpu_state.fds = 0;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x10);
|
||||
fpu_state.foo = tmp & 0x07ff;
|
||||
fp_ip = (tmp & 0x0ffff000) << 4;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x0c);
|
||||
fp_ip |= (tmp & 0xffff);
|
||||
fpu_state.fip = fp_ip;
|
||||
fpu_state.fcs = 0;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x08);
|
||||
fpu_state.tag = tmp & 0xffff;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x04);
|
||||
fpu_state.swd = tmp & 0xffff;
|
||||
fpu_state.tos = (tmp >> 11) & 7;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x00);
|
||||
fpu_state.cwd = tmp & 0xffff;
|
||||
offset = 0x1c;
|
||||
}
|
||||
break;
|
||||
case 0x101: { /*32-bit protected mode*/
|
||||
uint32_t tmp;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x18);
|
||||
fpu_state.fds = tmp & 0xffff;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x14);
|
||||
fpu_state.fdp = tmp;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x10);
|
||||
fpu_state.fcs = tmp & 0xffff;
|
||||
fpu_state.foo = (tmp >> 16) & 0x07ff;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x0c);
|
||||
fpu_state.fip = tmp;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x08);
|
||||
fpu_state.tag = tmp & 0xffff;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x04);
|
||||
fpu_state.swd = tmp & 0xffff;
|
||||
fpu_state.tos = (tmp >> 11) & 7;
|
||||
tmp = readmeml(easeg, cpu_state.eaaddr + 0x00);
|
||||
fpu_state.cwd = tmp & 0xffff;
|
||||
offset = 0x1c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* always set bit 6 as '1 */
|
||||
fpu_state.cwd = (fpu_state.cwd & ~FPU_CW_Reserved_Bits) | 0x0040;
|
||||
|
||||
/* check for unmasked exceptions */
|
||||
if (fpu_state.swd & ~fpu_state.cwd & FPU_CW_Exceptions_Mask) {
|
||||
/* set the B and ES bits in the status-word */
|
||||
fpu_state.swd |= (FPU_SW_Summary | FPU_SW_Backward);
|
||||
} else {
|
||||
/* clear the B and ES bits in the status-word */
|
||||
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
|
||||
}
|
||||
|
||||
return (cpu_state.eaaddr + offset);
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDCW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
tempw = geteaw();
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
fpu_state.cwd = (tempw & ~FPU_CW_Reserved_Bits) | 0x0040; // bit 6 is reserved as '1
|
||||
/* check for unmasked exceptions */
|
||||
if (fpu_state.swd & (~fpu_state.cwd & FPU_CW_Exceptions_Mask)) {
|
||||
/* set the B and ES bits in the status-word */
|
||||
fpu_state.swd |= (FPU_SW_Summary | FPU_SW_Backward);
|
||||
} else {
|
||||
/* clear the B and ES bits in the status-word */
|
||||
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FLDCW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
tempw = geteaw();
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
fpu_state.cwd = (tempw & ~FPU_CW_Reserved_Bits) | 0x0040; // bit 6 is reserved as '1
|
||||
/* check for unmasked exceptions */
|
||||
if (fpu_state.swd & (~fpu_state.cwd & FPU_CW_Exceptions_Mask)) {
|
||||
/* set the B and ES bits in the status-word */
|
||||
fpu_state.swd |= (FPU_SW_Summary | FPU_SW_Backward);
|
||||
} else {
|
||||
/* clear the B and ES bits in the status-word */
|
||||
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNSTCW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t cwd = i387_get_control_word();
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cwd);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FNSTCW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t cwd = i387_get_control_word();
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cwd);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNSTSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t swd = i387_get_status_word();
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(swd);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FNSTSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t swd = i387_get_status_word();
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(swd);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FPU_8087
|
||||
static int
|
||||
sf_FI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
fpu_state.cwd &= ~FPU_SW_Summary;
|
||||
if (rmdat == 0xe1)
|
||||
fpu_state.cwd |= FPU_SW_Summary;
|
||||
wait(3, 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
sf_FNSTSW_AX(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
AX = i387_get_status_word();
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FRSTOR_a16(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 tmp;
|
||||
int offset;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
offset = fpu_load_environment();
|
||||
for (int n = 0; n < 8; n++) {
|
||||
tmp.fraction = readmemq(easeg, offset + (n * 10));
|
||||
tmp.exp = readmemw(easeg, offset + (n * 10) + 8);
|
||||
FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FRSTOR_a32(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 tmp;
|
||||
int offset;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
offset = fpu_load_environment();
|
||||
for (int n = 0; n < 8; n++) {
|
||||
tmp.fraction = readmemq(easeg, offset + (n * 10));
|
||||
tmp.exp = readmemw(easeg, offset + (n * 10) + 8);
|
||||
FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n);
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNSAVE_a16(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 stn;
|
||||
int offset;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
offset = fpu_save_environment();
|
||||
/* save all registers in stack order. */
|
||||
for (int m = 0; m < 8; m++) {
|
||||
stn = FPU_read_regi(m);
|
||||
writememq(easeg, offset + (m * 10), stn.fraction);
|
||||
writememw(easeg, offset + (m * 10) + 8, stn.exp);
|
||||
}
|
||||
|
||||
#ifdef FPU_8087
|
||||
fpu_state.swd = 0x3FF;
|
||||
#else
|
||||
fpu_state.cwd = 0x37F;
|
||||
#endif
|
||||
fpu_state.swd = 0;
|
||||
fpu_state.tos = 0;
|
||||
fpu_state.tag = 0xffff;
|
||||
cpu_state.ismmx = 0;
|
||||
fpu_state.foo = 0;
|
||||
fpu_state.fds = 0;
|
||||
fpu_state.fdp = 0;
|
||||
fpu_state.fcs = 0;
|
||||
fpu_state.fip = 0;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FNSAVE_a32(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 stn;
|
||||
int offset;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
offset = fpu_save_environment();
|
||||
/* save all registers in stack order. */
|
||||
for (int m = 0; m < 8; m++) {
|
||||
stn = FPU_read_regi(m);
|
||||
writememq(easeg, offset + (m * 10), stn.fraction);
|
||||
writememw(easeg, offset + (m * 10) + 8, stn.exp);
|
||||
}
|
||||
|
||||
#ifdef FPU_8087
|
||||
fpu_state.swd = 0x3FF;
|
||||
#else
|
||||
fpu_state.cwd = 0x37F;
|
||||
#endif
|
||||
fpu_state.swd = 0;
|
||||
fpu_state.tos = 0;
|
||||
fpu_state.tag = 0xffff;
|
||||
cpu_state.ismmx = 0;
|
||||
fpu_state.foo = 0;
|
||||
fpu_state.fds = 0;
|
||||
fpu_state.fdp = 0;
|
||||
fpu_state.fcs = 0;
|
||||
fpu_state.fip = 0;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNCLEX(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
fpu_state.swd &= ~(FPU_SW_Backward | FPU_SW_Summary | FPU_SW_Stack_Fault | FPU_SW_Precision |
|
||||
FPU_SW_Underflow | FPU_SW_Overflow | FPU_SW_Zero_Div | FPU_SW_Denormal_Op |
|
||||
FPU_SW_Invalid);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FNINIT(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
#ifdef FPU_8087
|
||||
fpu_state.cwd = 0x3FF;
|
||||
#else
|
||||
fpu_state.cwd = 0x37F;
|
||||
#endif
|
||||
fpu_state.swd = 0;
|
||||
fpu_state.tos = 0;
|
||||
fpu_state.tag = 0xffff;
|
||||
fpu_state.foo = 0;
|
||||
fpu_state.fds = 0;
|
||||
fpu_state.fdp = 0;
|
||||
fpu_state.fcs = 0;
|
||||
fpu_state.fip = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.finit) : (x87_timings.finit * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.finit) : (x87_concurrency.finit * cpu_multi));
|
||||
CPU_BLOCK_END();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FLDENV_a16(uint32_t fetchdat)
|
||||
{
|
||||
int tag;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
fpu_load_environment();
|
||||
/* read all registers in stack order and update x87 tag word */
|
||||
for (int n = 0; n < 8; n++) {
|
||||
// update tag only if it is not empty
|
||||
if (!IS_TAG_EMPTY(n)) {
|
||||
tag = FPU_tagof(FPU_read_regi(n));
|
||||
FPU_settagi(tag, n);
|
||||
}
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FLDENV_a32(uint32_t fetchdat)
|
||||
{
|
||||
int tag;
|
||||
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
fpu_load_environment();
|
||||
/* read all registers in stack order and update x87 tag word */
|
||||
for (int n = 0; n < 8; n++) {
|
||||
// update tag only if it is not empty
|
||||
if (!IS_TAG_EMPTY(n)) {
|
||||
tag = FPU_tagof(FPU_read_regi(n));
|
||||
FPU_settagi(tag, n);
|
||||
}
|
||||
}
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNSTENV_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
fpu_save_environment();
|
||||
/* mask all floating point exceptions */
|
||||
fpu_state.cwd |= FPU_CW_Exceptions_Mask;
|
||||
/* clear the B and ES bits in the status word */
|
||||
fpu_state.swd &= ~(FPU_SW_Backward|FPU_SW_Summary);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FNSTENV_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
fpu_save_environment();
|
||||
/* mask all floating point exceptions */
|
||||
fpu_state.cwd |= FPU_CW_Exceptions_Mask;
|
||||
/* clear the B and ES bits in the status word */
|
||||
fpu_state.swd &= ~(FPU_SW_Backward|FPU_SW_Summary);
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi));
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FNOP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
static int
|
||||
sf_F2XM1(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
result = f2xm1(FPU_read_regi(0), &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.f2xm1) : (x87_timings.f2xm1 * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.f2xm1) : (x87_concurrency.f2xm1 * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FYL2X(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 1, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
result = fyl2x(FPU_read_regi(0), FPU_read_regi(1), &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2x) : (x87_timings.fyl2x * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2x) : (x87_concurrency.fyl2x * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FPTAN(uint32_t fetchdat)
|
||||
{
|
||||
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
|
||||
floatx80 y;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0) || !IS_TAG_EMPTY(-1)) {
|
||||
if (IS_TAG_EMPTY(0))
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
else
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0);
|
||||
|
||||
/* The masked response */
|
||||
if (is_IA_masked()) {
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
y = FPU_read_regi(0);
|
||||
if (ftan(&y, &status) == -1) {
|
||||
fpu_state.swd |= C2;
|
||||
goto next_ins;
|
||||
}
|
||||
|
||||
if (floatx80_is_nan(y)) {
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(y, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(y, 0);
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(y, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(Const_1, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FPATAN(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 1, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(1);
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
result = fpatan(a, b, &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_pop();
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fpatan) : (x87_timings.fpatan * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fpatan) : (x87_concurrency.fpatan * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FXTRACT(uint32_t fetchdat)
|
||||
{
|
||||
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
|
||||
struct float_status_t status;
|
||||
floatx80 a, b;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
|
||||
#if 0 //TODO
|
||||
if ((IS_TAG_EMPTY(0) || IS_TAG_EMPTY(-1))) {
|
||||
if (IS_TAG_EMPTY(0))
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
else
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0);
|
||||
|
||||
/* The masked response */
|
||||
if (is_IA_masked()) {
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = floatx80_extract(&a, &status);
|
||||
if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(b, 0); // exponent
|
||||
FPU_push();
|
||||
FPU_save_regi(a, 0); // fraction
|
||||
}
|
||||
|
||||
#if 0 //TODO.
|
||||
next_ins:
|
||||
#endif
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxtract) : (x87_timings.fxtract * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxtract) : (x87_concurrency.fxtract * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FPREM1(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
uint64_t quotient = 0;
|
||||
int flags, cc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(1);
|
||||
flags = floatx80_ieee754_remainder(a, b, &result, "ient, &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
if (flags >= 0) {
|
||||
cc = 0;
|
||||
if (flags)
|
||||
cc = C2;
|
||||
else {
|
||||
if (quotient & 1)
|
||||
cc |= C1;
|
||||
if (quotient & 2)
|
||||
cc |= C3;
|
||||
if (quotient & 4)
|
||||
cc |= C0;
|
||||
}
|
||||
setcc(cc);
|
||||
}
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FPREM(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 a, b, result;
|
||||
struct float_status_t status;
|
||||
uint64_t quotient = 0;
|
||||
int flags, cc;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
a = FPU_read_regi(0);
|
||||
b = FPU_read_regi(1);
|
||||
// handle unsupported extended double-precision floating encodings
|
||||
flags = floatx80_remainder(a, b, &result, "ient, &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
if (flags >= 0) {
|
||||
cc = 0;
|
||||
if (flags)
|
||||
cc = C2;
|
||||
else {
|
||||
if (quotient & 1)
|
||||
cc |= C1;
|
||||
if (quotient & 2)
|
||||
cc |= C3;
|
||||
if (quotient & 4)
|
||||
cc |= C0;
|
||||
}
|
||||
setcc(cc);
|
||||
}
|
||||
FPU_save_regi(result, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FYL2XP1(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 1, 1);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
result = fyl2xp1(FPU_read_regi(0), FPU_read_regi(1), &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(result, 1);
|
||||
FPU_pop();
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2xp1) : (x87_timings.fyl2xp1 * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2xp1) : (x87_concurrency.fyl2xp1 * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FSINCOS(uint32_t fetchdat)
|
||||
{
|
||||
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
|
||||
struct float_status_t status;
|
||||
floatx80 y, sin_y, cos_y;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0) || !IS_TAG_EMPTY(-1)) {
|
||||
if (IS_TAG_EMPTY(0))
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0);
|
||||
else
|
||||
FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0);
|
||||
|
||||
/* The masked response */
|
||||
if (is_IA_masked()) {
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(floatx80_default_nan, 0);
|
||||
}
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
y = FPU_read_regi(0);
|
||||
if (fsincos(y, &sin_y, &cos_y, &status) == -1) {
|
||||
fpu_state.swd |= C2;
|
||||
goto next_ins;
|
||||
}
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0)) {
|
||||
FPU_save_regi(sin_y, 0);
|
||||
FPU_push();
|
||||
FPU_save_regi(cos_y, 0);
|
||||
}
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FSCALE(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 result;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word());
|
||||
result = floatx80_scale(FPU_read_regi(0), FPU_read_regi(1), &status);
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(result, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fscale) : (x87_timings.fscale * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fscale) : (x87_concurrency.fscale * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int
|
||||
sf_FSIN(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 y;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
y = FPU_read_regi(0);
|
||||
if (fsin(&y, &status) == -1) {
|
||||
fpu_state.swd |= C2;
|
||||
goto next_ins;
|
||||
}
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(y, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sf_FCOS(uint32_t fetchdat)
|
||||
{
|
||||
floatx80 y;
|
||||
struct float_status_t status;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
clear_C1();
|
||||
clear_C2();
|
||||
if (IS_TAG_EMPTY(0)) {
|
||||
FPU_stack_underflow(fetchdat, 0, 0);
|
||||
goto next_ins;
|
||||
}
|
||||
status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS);
|
||||
y = FPU_read_regi(0);
|
||||
if (fcos(&y, &status) == -1) {
|
||||
fpu_state.swd |= C2;
|
||||
goto next_ins;
|
||||
}
|
||||
if (! FPU_exception(fetchdat, status.float_exception_flags, 0))
|
||||
FPU_save_regi(y, 0);
|
||||
|
||||
next_ins:
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi));
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user