fadd(s), fdiv(s), fmul(s), fsub(s), fsel, frsp, fabs, fmr, fneg, fnmsubs.
This commit is contained in:
parent
fe6df31280
commit
84fb802166
|
@ -18,6 +18,11 @@ using namespace xe::cpu::ppc;
|
|||
using namespace AsmJit;
|
||||
|
||||
|
||||
// Enable rounding numbers to single precision as required.
|
||||
// This adds a bunch of work per operation and I'm not sure it's required.
|
||||
#define ROUND_TO_SINGLE
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace x64 {
|
||||
|
@ -26,33 +31,150 @@ namespace x64 {
|
|||
// Floating-point arithmetic (A-8)
|
||||
|
||||
XEEMITTER(faddx, 0xFC00002A, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) + (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.addsd(v, e.fpr_value(i.A.FRB));
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(faddsx, 0xEC00002A, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) + (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.addsd(v, e.fpr_value(i.A.FRB));
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, v);
|
||||
c.cvtss2sd(v, v);
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fdivx, 0xFC000024, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- frA / frB
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.divsd(v, e.fpr_value(i.A.FRB));
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fdivsx, 0xEC000024, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- frA / frB
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.divsd(v, e.fpr_value(i.A.FRB));
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, v);
|
||||
c.cvtss2sd(v, v);
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fmulx, 0xFC000032, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) x (frC)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.mulsd(v, e.fpr_value(i.A.FRC));
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fmulsx, 0xEC000032, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) x (frC)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.mulsd(v, e.fpr_value(i.A.FRC));
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, v);
|
||||
c.cvtss2sd(v, v);
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fresx, 0xEC000030, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
|
@ -66,18 +188,87 @@ XEEMITTER(frsqrtex, 0xFC000034, A )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
}
|
||||
|
||||
XEEMITTER(fsubx, 0xFC000028, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) - (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.subsd(v, e.fpr_value(i.A.FRB));
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, v);
|
||||
c.cvtss2sd(v, v);
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fsubsx, 0xEC000028, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frA) - (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRA));
|
||||
c.subsd(v, e.fpr_value(i.A.FRB));
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fselx, 0xFC00002E, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if (frA) >= 0.0
|
||||
// then frD <- (frC)
|
||||
// else frD <- (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
GpVar zero(c.newGpVar());
|
||||
c.mov(zero, imm(0));
|
||||
c.movq(v, zero);
|
||||
c.cmpsd(e.fpr_value(i.A.FRA), v, 0);
|
||||
|
||||
// TODO(benvanik): find a way to do this without jumps.
|
||||
Label choose_b(c.newLabel());
|
||||
Label done(c.newLabel());
|
||||
c.jl(choose_b);
|
||||
c.movq(v, e.fpr_value(i.A.FRC));
|
||||
c.jmp(done);
|
||||
c.bind(choose_b);
|
||||
c.movq(v, e.fpr_value(i.A.FRB));
|
||||
c.bind(done);
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fsqrtx, 0xFC00002C, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
|
@ -124,13 +315,62 @@ XEEMITTER(fnmaddsx, 0xEC00003E, A )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
}
|
||||
|
||||
XEEMITTER(fnmsubx, 0xFC00003C, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- -([frA x frC] - frB)
|
||||
|
||||
XmmVar a_mul_c(c.newXmmVar());
|
||||
// TODO(benvanik): I'm sure there's an SSE op for this.
|
||||
// NOTE: we do (frB - [frA x frC]) as that's pretty much the same.
|
||||
c.movq(a_mul_c, e.fpr_value(i.A.FRA));
|
||||
c.mulsd(a_mul_c, e.fpr_value(i.A.FRC));
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRB));
|
||||
c.subsd(v, a_mul_c);
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fnmsubsx, 0xEC00003C, A )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- -([frA x frC] - frB)
|
||||
|
||||
XmmVar a_mul_c(c.newXmmVar());
|
||||
// TODO(benvanik): I'm sure there's an SSE op for this.
|
||||
// NOTE: we do (frB - [frA x frC]) as that's pretty much the same.
|
||||
c.movq(a_mul_c, e.fpr_value(i.A.FRA));
|
||||
c.mulsd(a_mul_c, e.fpr_value(i.A.FRC));
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.A.FRB));
|
||||
c.subsd(v, a_mul_c);
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, v);
|
||||
c.cvtss2sd(v, v);
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.A.FRT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.A.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -162,8 +402,31 @@ XEEMITTER(fctiwzx, 0xFC00001E, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
}
|
||||
|
||||
XEEMITTER(frspx, 0xFC000018, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- Round_single(frB)
|
||||
|
||||
#if defined(ROUND_TO_SINGLE)
|
||||
XmmVar v(c.newXmmVar());
|
||||
// TODO(benvanik): check rounding mode? etc?
|
||||
// This converts to a single then back to a double to approximate the
|
||||
// rounding on the 360.
|
||||
c.cvtsd2ss(v, e.fpr_value(i.X.RB));
|
||||
c.cvtss2sd(v, v);
|
||||
#else
|
||||
XmmVar v(e.fpr_value(i.X.RB));
|
||||
#endif // ROUND_TO_SINGLE
|
||||
e.update_fpr_value(i.X.RT, v);
|
||||
|
||||
// TODO(benvanik): update status/control register.
|
||||
|
||||
if (i.X.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -229,13 +492,45 @@ XEEMITTER(mtfsfix, 0xFC00010C, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// Floating-point move (A-21)
|
||||
|
||||
XEEMITTER(fabsx, 0xFC000210, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- abs(frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.X.RB));
|
||||
// XOR with 0 in the sign bit and ones everywhere else.
|
||||
GpVar gp_bit(c.newGpVar());
|
||||
c.mov(gp_bit, imm(0x7FFFFFFFFFFFFFFF));
|
||||
XmmVar bit(c.newXmmVar());
|
||||
c.movq(bit, gp_bit);
|
||||
c.xorpd(v, bit);
|
||||
e.update_fpr_value(i.X.RT, v);
|
||||
|
||||
if (i.X.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fmrx, 0xFC000090, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- (frB)
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.X.RB));
|
||||
e.update_fpr_value(i.X.RT, v);
|
||||
|
||||
if (i.X.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(fnabsx, 0xFC000110, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
|
@ -244,8 +539,27 @@ XEEMITTER(fnabsx, 0xFC000110, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
}
|
||||
|
||||
XEEMITTER(fnegx, 0xFC000050, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// frD <- ¬ frB[0] || frB[1-63]
|
||||
|
||||
XmmVar v(c.newXmmVar());
|
||||
c.movq(v, e.fpr_value(i.X.RB));
|
||||
// XOR with 1 in the sign bit.
|
||||
GpVar gp_bit(c.newGpVar());
|
||||
c.mov(gp_bit, imm(0x8000000000000000));
|
||||
XmmVar bit(c.newXmmVar());
|
||||
c.movq(bit, gp_bit);
|
||||
c.xorpd(v, bit);
|
||||
e.update_fpr_value(i.X.RT, v);
|
||||
|
||||
if (i.X.Rc) {
|
||||
// With cr0 update.
|
||||
XEASSERTALWAYS();
|
||||
//e.update_cr_with_cond(0, v);
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue