Skip to content

Commit

Permalink
Implement fsqrt
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Nov 16, 2018
1 parent aaa5015 commit 57d3367
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 0 deletions.
1 change: 1 addition & 0 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0xd960: TRACE("f2xm1"); F2XM1(); break;
case 0xd961: TRACE("fyl2x"); FYL2X(); break;
case 0xd970: TRACE("fprem"); FPREM(); break;
case 0xd972: TRACE("fsqrt"); FSQRT(); break;
case 0xd974: TRACE("frndint"); FRNDINT(); break;
case 0xdf40: TRACE("fnstsw ax"); FSTSW(reg_a); break;
default: TRACE("undefined"); UNDEFINED;
Expand Down
16 changes: 16 additions & 0 deletions emu/float80.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,19 @@ float80 f80_log2(float80 x) {
return res;
}

float80 f80_sqrt(float80 x) {
if (f80_isnan(x) || x.sign)
return F80_NAN;
// 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
float80 old_guess;
float80 two = f80_from_int(2);
int i = 0;
do {
old_guess = guess;
guess = f80_div(f80_add(guess, f80_div(x, guess)), two);
} while (!f80_eq(guess, old_guess) && i++ < 100);
return guess;
}
1 change: 1 addition & 0 deletions emu/float80.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ extern __thread enum f80_rounding_mode f80_rounding_mode;
#define F80_INF ((float80) {.signif = 0x8000000000000000, .exp = 0x7fff, .sign = 0})

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

#endif
4 changes: 4 additions & 0 deletions emu/fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ void fpu_rndint(struct cpu_state *cpu) {
ST(0) = f80_from_int(f80_to_int(ST(0)));
}

void fpu_sqrt(struct cpu_state *cpu) {
ST(0) = f80_sqrt(ST(0));
}

void fpu_yl2x(struct cpu_state *cpu) {
ST(1) = f80_mul(ST(1), f80_log2(ST(0)));
fpu_pop(cpu);
Expand Down
1 change: 1 addition & 0 deletions emu/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void fpu_prem(struct cpu_state *cpu);
void fpu_rndint(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);
void fpu_yl2x(struct cpu_state *cpu);
void fpu_2xm1(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 @@
#define FRNDINT() UNDEFINED
#define FYL2X() UNDEFINED
#define F2XM1() UNDEFINED
#define FSQRT() UNDEFINED

#define FUCOMI() \
cpu->zf = f80_eq(ST(0), ST_i); \
Expand Down
1 change: 1 addition & 0 deletions jit/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ static inline bool gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a
#define FLDC(what) hh(fpu_ldc, fconst_##what)
#define FPREM() h(fpu_prem)
#define FRNDINT() h(fpu_rndint)
#define FSQRT() h(fpu_sqrt)
#define FYL2X() h(fpu_yl2x)
#define F2XM1() h(fpu_2xm1)
#define FSTSW(dst) if (arg_##dst == arg_reg_a) g(fstsw_ax); else UNDEFINED
Expand Down

0 comments on commit 57d3367

Please sign in to comment.