Skip to content

Commit

Permalink
Implement fscale
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Dec 2, 2018
1 parent cfaef9d commit beaff8d
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 7 deletions.
1 change: 1 addition & 0 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0xd970: TRACE("fprem"); FPREM(); break;
case 0xd972: TRACE("fsqrt"); FSQRT(); break;
case 0xd974: TRACE("frndint"); FRNDINT(); break;
case 0xd975: TRACE("fscale"); FSCALE(); break;
case 0xde31: TRACE("fcompp"); FCOM(); FPOP; FPOP; break;
case 0xdf40: TRACE("fnstsw ax"); FSTSW(reg_a); break;
default: TRACE("undefined"); UNDEFINED;
Expand Down
8 changes: 7 additions & 1 deletion emu/float80.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ float80 f80_sqrt(float80 x) {
// for a rough guess, just cut the exponent by 2
float80 guess = x;
guess.exp = bias(unbias(guess.exp) / 2);
// now converge on the answer, using what newton's method
// now converge on the answer, using newton's method
float80 old_guess;
float80 two = f80_from_int(2);
int i = 0;
Expand All @@ -494,3 +494,9 @@ float80 f80_sqrt(float80 x) {
} while (!f80_eq(guess, old_guess) && i++ < 100);
return guess;
}

float80 f80_scale(float80 x, int scale) {
if (!f80_is_supported(x) || f80_isnan(x))
return F80_NAN;
return u128_normalize_round((unsigned __int128) x.signif << 64, unbias(x.exp) + scale, x.sign);
}
14 changes: 8 additions & 6 deletions emu/float80.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ bool f80_iszero(float80 f);
bool f80_isdenormal(float80 f);
bool f80_is_supported(float80 f);

float80 f80_neg(float80 f);
float80 f80_abs(float80 f);

float80 f80_add(float80 a, float80 b);
float80 f80_sub(float80 a, float80 b);
float80 f80_mul(float80 a, float80 b);
Expand All @@ -40,6 +37,14 @@ bool f80_lt(float80 a, float80 b);
bool f80_eq(float80 a, float80 b);
bool f80_uncomparable(float80 a, float80 b);

float80 f80_neg(float80 f);
float80 f80_abs(float80 f);

float80 f80_log2(float80 x);
float80 f80_sqrt(float80 x);

float80 f80_scale(float80 x, int scale);

enum f80_rounding_mode {
round_to_nearest = 0,
round_down = 1,
Expand All @@ -51,7 +56,4 @@ extern __thread enum f80_rounding_mode f80_rounding_mode;
#define F80_NAN ((float80) {.signif = 0xc000000000000000, .exp = 0x7fff, .sign = 0})
#define F80_INF ((float80) {.signif = 0x8000000000000000, .exp = 0x7fff, .sign = 0})

float80 f80_log2(float80 x);
float80 f80_sqrt(float80 x);

#endif
8 changes: 8 additions & 0 deletions emu/fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ void fpu_prem(struct cpu_state *cpu) {
ST(0) = f80_mod(ST(0), ST(1));
}

void fpu_scale(struct cpu_state *cpu) {
enum f80_rounding_mode old_mode = f80_rounding_mode;
f80_rounding_mode = round_chop;
int scale = f80_to_int(ST(1));
f80_rounding_mode = old_mode;
ST(0) = f80_scale(ST(0), scale);
}

void fpu_rndint(struct cpu_state *cpu) {
if (f80_isinf(ST(0)) || f80_isnan(ST(0)))
return;
Expand Down
1 change: 1 addition & 0 deletions emu/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void fpu_ldm80(struct cpu_state *cpu, float80 *f);

void fpu_prem(struct cpu_state *cpu);
void fpu_rndint(struct cpu_state *cpu);
void fpu_scale(struct cpu_state *cpu);
void fpu_abs(struct cpu_state *cpu);
void fpu_chs(struct cpu_state *cpu);
void fpu_sqrt(struct cpu_state *cpu);
Expand Down
1 change: 1 addition & 0 deletions emu/interp/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
ST(0) = f80_mod(ST(0), ST(1))

#define FRNDINT() UNDEFINED
#define FSCALE() UNDEFINED
#define FYL2X() UNDEFINED
#define F2XM1() UNDEFINED
#define FSQRT() UNDEFINED
Expand Down
1 change: 1 addition & 0 deletions jit/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ void helper_rdtsc(struct cpu_state *cpu);
#define FLDC(what) hh(fpu_ldc, fconst_##what)
#define FPREM() h(fpu_prem)
#define FRNDINT() h(fpu_rndint)
#define FSCALE() h(fpu_scale)
#define FSQRT() h(fpu_sqrt)
#define FYL2X() h(fpu_yl2x)
#define F2XM1() h(fpu_2xm1)
Expand Down

0 comments on commit beaff8d

Please sign in to comment.