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.
751 lines
30 KiB
C
751 lines
30 KiB
C
#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;
|
|
}
|