Files
86Box/src/cpu/x87_ops_sf_arith.h
Cacodemon345 5f3641ecbd Implement Cyrix EMMI extensions and 4 FPU instructions
PADDSIW, PSUBSIW, PMULHRW (named PMULHRWC in the code as recognized by some assemblers), PMULHRIW, PDISTIB, PMACHRIW, PAVEB, PMAGW, PMVZB, PMVNZB, PMVLZB, PMVGEZB, FTSTP, FRINT2, FRINEAR, FRICHOP are implemented for Cyrix 6x86MX. Cyrix 6x86(L) only has the last 4 instructions.
2025-03-06 03:05:10 +06:00

884 lines
48 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 softfloat_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 = extF80_add(a, use_var, &status); \
\
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_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 = extF80_div(a, use_var, &status); \
} \
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_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 = extF80_div(use_var, a, &status); \
} \
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_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 = extF80_mul(a, use_var, &status); \
} \
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_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 = extF80_sub(a, use_var, &status); \
\
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_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 = extF80_sub(use_var, a, &status); \
\
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32)
#ifndef FPU_8087
sf_FPU(s, float32, 32, temp, geteal(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32)
#endif
sf_FPU(d, float64, 16, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64)
#ifndef FPU_8087
sf_FPU(d, float64, 32, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64)
#endif
sf_FPU(iw, uint16_t, 16, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16)
#ifndef FPU_8087
sf_FPU(iw, uint16_t, 32, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16)
#endif
sf_FPU(il, uint32_t, 16, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32)
#ifndef FPU_8087
sf_FPU(il, uint32_t, 32, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32)
#endif
// clang-format on
static int sf_FADD_st0_stj(uint32_t fetchdat)
{
floatx80 a;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_add(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_add(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_add(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(fetchdat & 7);
b = FPU_read_regi(0);
result = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(0);
b = FPU_read_regi(fetchdat & 7);
result = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(0);
b = FPU_read_regi(fetchdat & 7);
result = extF80_div(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_mul(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(0);
b = FPU_read_regi(fetchdat & 7);
result = extF80_mul(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_mul(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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 = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(fetchdat & 7);
b = FPU_read_regi(0);
result = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(0);
b = FPU_read_regi(fetchdat & 7);
result = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
floatx80 b;
floatx80 result;
struct softfloat_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(0);
b = FPU_read_regi(fetchdat & 7);
result = extF80_sub(a, b, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_status_t status;
FP_ENTER();
FPU_check_pending_exceptions();
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 = extF80_sqrt(FPU_read_regi(0), &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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 softfloat_status_t status;
FP_ENTER();
FPU_check_pending_exceptions();
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 = extF80_roundToInt_normal(FPU_read_regi(0), &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
}
static int
sf_FRINT2(uint32_t fetchdat)
{
floatx80 result;
struct softfloat_status_t status;
FP_ENTER();
FPU_check_pending_exceptions();
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 = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_maxMag, true, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
}
static int
sf_FRINEAR(uint32_t fetchdat)
{
floatx80 result;
struct softfloat_status_t status;
FP_ENTER();
FPU_check_pending_exceptions();
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 = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_even, true, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
}
static int
sf_FRICHOP(uint32_t fetchdat)
{
floatx80 result;
struct softfloat_status_t status;
FP_ENTER();
FPU_check_pending_exceptions();
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 = extF80_roundToInt(FPU_read_regi(0), softfloat_round_to_zero, true, &status);
if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 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;
}