fcfid(z), fctid(z) -- both largely untested.
This commit is contained in:
parent
84fb802166
commit
778efdb276
|
@ -18,6 +18,11 @@ using namespace xe::cpu::ppc;
|
||||||
using namespace AsmJit;
|
using namespace AsmJit;
|
||||||
|
|
||||||
|
|
||||||
|
// Good source of information:
|
||||||
|
// http://mamedev.org/source/src/emu/cpu/powerpc/ppc_ops.c
|
||||||
|
// The correctness of that code is not reflected here yet -_-
|
||||||
|
|
||||||
|
|
||||||
// Enable rounding numbers to single precision as required.
|
// Enable rounding numbers to single precision as required.
|
||||||
// This adds a bunch of work per operation and I'm not sure it's required.
|
// This adds a bunch of work per operation and I'm not sure it's required.
|
||||||
#define ROUND_TO_SINGLE
|
#define ROUND_TO_SINGLE
|
||||||
|
@ -377,28 +382,131 @@ XEEMITTER(fnmsubsx, 0xEC00003C, A )(X64Emitter& e, X86Compiler& c, InstrDat
|
||||||
// Floating-point rounding and conversion (A-10)
|
// Floating-point rounding and conversion (A-10)
|
||||||
|
|
||||||
XEEMITTER(fcfidx, 0xFC00069C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(fcfidx, 0xFC00069C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// frD <- signed_int64_to_double( frB )
|
||||||
return 1;
|
|
||||||
|
XmmVar v(c.newXmmVar());
|
||||||
|
c.movq(v, e.fpr_value(i.A.FRB));
|
||||||
|
c.save(v);
|
||||||
|
c.cvtsi2sd(v, v.m64());
|
||||||
|
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(fctidx, 0xFC00065C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(fctidx, 0xFC00065C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// frD <- double_to_signed_int64( frB )
|
||||||
return 1;
|
|
||||||
|
Label over_max(c.newLabel());
|
||||||
|
Label under_min(c.newLabel());
|
||||||
|
Label done(c.newLabel());
|
||||||
|
GpVar tmp(c.newGpVar());
|
||||||
|
XmmVar xmm_tmp(c.newXmmVar());
|
||||||
|
|
||||||
|
XmmVar v(c.newXmmVar());
|
||||||
|
c.movq(v, e.fpr_value(i.X.RB));
|
||||||
|
// Max value: 2^63 - 1
|
||||||
|
c.mov(tmp, imm(0x43e0000000000000));
|
||||||
|
c.movq(xmm_tmp, tmp);
|
||||||
|
c.cmpsd(v, xmm_tmp, 0);
|
||||||
|
c.jg(over_max);
|
||||||
|
// Min value: -2^63
|
||||||
|
c.mov(tmp, imm(0xc3e0000000000000));
|
||||||
|
c.movq(xmm_tmp, tmp);
|
||||||
|
c.cmpsd(v, xmm_tmp, 0);
|
||||||
|
c.jl(under_min);
|
||||||
|
c.save(v);
|
||||||
|
c.cvtsd2si(tmp, v.m64());
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.jmp(done);
|
||||||
|
c.bind(over_max);
|
||||||
|
c.mov(tmp, imm(0x7FFFFFFFFFFFFFFF));
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.jmp(done);
|
||||||
|
c.bind(under_min);
|
||||||
|
c.mov(tmp, imm(0x8000000000000000));
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.bind(done);
|
||||||
|
e.update_fpr_value(i.X.RT, 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(fctidzx, 0xFC00065E, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(fctidzx, 0xFC00065E, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
||||||
return 1;
|
return InstrEmit_fctidx(e, c, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fctiwx, 0xFC00001C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(fctiwx, 0xFC00001C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// frD <- double_to_signed_int32( frB )
|
||||||
return 1;
|
|
||||||
|
Label over_max(c.newLabel());
|
||||||
|
Label under_min(c.newLabel());
|
||||||
|
Label done(c.newLabel());
|
||||||
|
GpVar tmp(c.newGpVar());
|
||||||
|
XmmVar xmm_tmp(c.newXmmVar());
|
||||||
|
|
||||||
|
XmmVar v(c.newXmmVar());
|
||||||
|
c.movq(v, e.fpr_value(i.X.RB));
|
||||||
|
// Max value: 2^31 - 1
|
||||||
|
c.mov(tmp, imm(0x41efffffffe00000));
|
||||||
|
c.movq(xmm_tmp, tmp);
|
||||||
|
c.cmpsd(v, xmm_tmp, 0);
|
||||||
|
c.jg(over_max);
|
||||||
|
// Min value: -2^31
|
||||||
|
c.mov(tmp, imm(0xc1e0000000000000));
|
||||||
|
c.movq(xmm_tmp, tmp);
|
||||||
|
c.cmpsd(v, xmm_tmp, 0);
|
||||||
|
c.jl(under_min);
|
||||||
|
c.save(v);
|
||||||
|
c.cvtsd2si(tmp, v.m64());
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.jmp(done);
|
||||||
|
c.bind(over_max);
|
||||||
|
c.mov(tmp, imm(0x7FFFFFFF));
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.jmp(done);
|
||||||
|
c.bind(under_min);
|
||||||
|
c.mov(tmp, imm(0x80000000));
|
||||||
|
c.movq(v, tmp);
|
||||||
|
c.bind(done);
|
||||||
|
e.update_fpr_value(i.X.RT, 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(fctiwzx, 0xFC00001E, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(fctiwzx, 0xFC00001E, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
||||||
return 1;
|
return InstrEmit_fctiwx(e, c, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(frspx, 0xFC000018, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(frspx, 0xFC000018, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
|
|
Loading…
Reference in New Issue