Skip to content

Commit

Permalink
Implement log base 2 (fyl2x)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Oct 30, 2018
1 parent 9f6c6bb commit 00ec13c
Show file tree
Hide file tree
Showing 7 changed files with 47 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 @@ -608,6 +608,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0xd950: TRACE("fld1"); FLDC(one); break;
case 0xd955: TRACE("fldln2"); FLDC(ln2); break;
case 0xd956: TRACE("fldz"); FLDC(zero); break;
case 0xd961: TRACE("fyl2x"); FYL2X(); break;
case 0xd970: TRACE("fprem"); FPREM(); break;
case 0xd974: TRACE("frndint"); FRNDINT(); break;
case 0xdf40: TRACE("fnstsw ax"); FSTSW(reg_a); break;
Expand Down
36 changes: 36 additions & 0 deletions emu/float80.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,39 @@ bool f80_eq(float80 a, float80 b) {
if (f80_iszero(a)) b.sign = 0;
return a.sign == b.sign && a.exp == b.exp && a.signif == b.signif;
}

bool f80_lte(float80 a, float80 b) {
return f80_lt(a, b) || f80_eq(a, b);
}
bool f80_gt(float80 a, float80 b) {
return !f80_lte(a, b);
}

float80 f80_log2(float80 x) {
float80 zero = f80_from_int(0);
float80 one = f80_from_int(1);
float80 two = f80_from_int(2);

int ipart = 0;
while (f80_lt(x, one)) {
ipart--;
x = f80_mul(x, two);
}
while (f80_gt(x, two)) {
ipart++;
x = f80_div(x, two);
}
float80 res = f80_from_int(ipart);

float80 bit = one;
while (f80_gt(bit, zero)) {
while (f80_lte(x, two) && f80_gt(bit, zero)) {
x = f80_mul(x, x);
bit = f80_div(bit, two);
}
res = f80_add(res, bit);
x = f80_div(x, two);
}
return res;
}

2 changes: 2 additions & 0 deletions emu/float80.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ 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);

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

void fpu_yl2x(struct cpu_state *cpu) {
ST(1) = f80_mul(ST(1), f80_log2(ST(0)));
fpu_pop(cpu);
}

void fpu_ucom(struct cpu_state *cpu, int i) {
cpu->c1 = 0;
cpu->c0 = f80_lt(ST(0), ST(i));
Expand Down
1 change: 1 addition & 0 deletions emu/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,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_yl2x(struct cpu_state *cpu);
void fpu_ucom(struct cpu_state *cpu, int i);
void fpu_abs(struct cpu_state *cpu);
void fpu_chs(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 @@ -78,6 +78,7 @@
ST(0) = f80_mod(ST(0), ST(1))

#define FRNDINT() UNDEFINED
#define FYL2X() 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 @@ -358,6 +358,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 FYL2X() h(fpu_yl2x)
#define FSTSW(dst) if (arg_##dst == arg_reg_a) g(fstsw_ax); else UNDEFINED
#define FSTCW(dst) if (arg_##dst == arg_reg_a) UNDEFINED; else h_write(fpu_stcw, 16)
#define FLDCW(dst) if (arg_##dst == arg_reg_a) UNDEFINED; else h_read(fpu_ldcw, 16)
Expand Down

0 comments on commit 00ec13c

Please sign in to comment.