divwx/divwux.
This commit is contained in:
@@ -157,7 +157,6 @@ XEEMITTER(divdux, 0x7C000392, XO )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
XEEMITTER(divwx, 0x7C0003D6, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(divwx, 0x7C0003D6, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
// dividend[0:31] <- (RA)[32:63]
|
// dividend[0:31] <- (RA)[32:63]
|
||||||
// divisor[0:31] <- (RB)[32:63]
|
// divisor[0:31] <- (RB)[32:63]
|
||||||
@@ -168,9 +167,12 @@ XEEMITTER(divwx, 0x7C0003D6, XO )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||||||
// RT[32:63] <- dividend ÷ divisor
|
// RT[32:63] <- dividend ÷ divisor
|
||||||
// RT[0:31] <- undefined
|
// RT[0:31] <- undefined
|
||||||
|
|
||||||
jit_value_t dividend = e.trunc_to_int(e.gpr_value(i.XO.RA));
|
GpVar dividend(c.newGpVar());
|
||||||
jit_value_t divisor = e.trunc_to_int(e.gpr_value(i.XO.RB));
|
GpVar divisor(c.newGpVar());
|
||||||
|
c.mov(dividend.r32(), e.gpr_value(i.XO.RA).r32());
|
||||||
|
c.mov(divisor.r32(), e.gpr_value(i.XO.RB).r32());
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Note that we skip the zero handling block and just avoid the divide if
|
// Note that we skip the zero handling block and just avoid the divide if
|
||||||
// we are OE=0.
|
// we are OE=0.
|
||||||
BasicBlock* zero_bb = i.XO.OE ?
|
BasicBlock* zero_bb = i.XO.OE ?
|
||||||
@@ -186,33 +188,33 @@ XEEMITTER(divwx, 0x7C0003D6, XO )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||||||
e.update_xer_with_overflow(b.getInt1(1));
|
e.update_xer_with_overflow(b.getInt1(1));
|
||||||
b.CreateBr(after_bb);
|
b.CreateBr(after_bb);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Divide.
|
// Divide.
|
||||||
b.SetInsertPoint(nonzero_bb);
|
GpVar dividend_hi(c.newGpVar());
|
||||||
jit_value_t v = b.CreateSDiv(dividend, divisor);
|
c.alloc(dividend_hi, rdx);
|
||||||
v = e.sign_extend(v, jit_type_nint);
|
c.mov(dividend_hi, imm(0));
|
||||||
e.update_gpr_value(i.XO.RT, v);
|
c.alloc(dividend, rax);
|
||||||
|
c.idiv(dividend_hi, dividend.r64(), divisor.r64());
|
||||||
|
e.update_gpr_value(i.XO.RT, dividend);
|
||||||
|
|
||||||
// If we are OE=1 we need to clear the overflow bit.
|
// If we are OE=1 we need to clear the overflow bit.
|
||||||
if (i.XO.OE) {
|
if (i.XO.OE) {
|
||||||
e.update_xer_with_overflow(b.getInt1(0));
|
e.update_xer_with_overflow(e.get_uint64(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.XO.Rc) {
|
if (i.XO.Rc) {
|
||||||
// With cr0 update.
|
// With cr0 update.
|
||||||
e.update_cr_with_cond(0, v);
|
e.update_cr_with_cond(0, dividend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
b.CreateBr(after_bb);
|
b.CreateBr(after_bb);
|
||||||
|
#endif
|
||||||
// Resume.
|
|
||||||
b.SetInsertPoint(after_bb);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
XEEMITTER(divwux, 0x7C000396, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(divwux, 0x7C000396, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
// dividend[0:31] <- (RA)[32:63]
|
// dividend[0:31] <- (RA)[32:63]
|
||||||
// divisor[0:31] <- (RB)[32:63]
|
// divisor[0:31] <- (RB)[32:63]
|
||||||
@@ -223,9 +225,12 @@ XEEMITTER(divwux, 0x7C000396, XO )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||||||
// RT[32:63] <- dividend ÷ divisor
|
// RT[32:63] <- dividend ÷ divisor
|
||||||
// RT[0:31] <- undefined
|
// RT[0:31] <- undefined
|
||||||
|
|
||||||
jit_value_t dividend = e.trunc_to_int(e.gpr_value(i.XO.RA));
|
GpVar dividend(c.newGpVar());
|
||||||
jit_value_t divisor = e.trunc_to_int(e.gpr_value(i.XO.RB));
|
GpVar divisor(c.newGpVar());
|
||||||
|
c.mov(dividend.r32(), e.gpr_value(i.XO.RA).r32());
|
||||||
|
c.mov(divisor.r32(), e.gpr_value(i.XO.RB).r32());
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Note that we skip the zero handling block and just avoid the divide if
|
// Note that we skip the zero handling block and just avoid the divide if
|
||||||
// we are OE=0.
|
// we are OE=0.
|
||||||
BasicBlock* zero_bb = i.XO.OE ?
|
BasicBlock* zero_bb = i.XO.OE ?
|
||||||
@@ -241,31 +246,35 @@ XEEMITTER(divwux, 0x7C000396, XO )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||||||
e.update_xer_with_overflow(b.getInt1(1));
|
e.update_xer_with_overflow(b.getInt1(1));
|
||||||
b.CreateBr(after_bb);
|
b.CreateBr(after_bb);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Divide.
|
// Divide.
|
||||||
b.SetInsertPoint(nonzero_bb);
|
GpVar dividend_hi(c.newGpVar());
|
||||||
jit_value_t v = b.CreateUDiv(dividend, divisor);
|
c.alloc(dividend_hi, rdx);
|
||||||
v = e.zero_extend(v, jit_type_nint);
|
c.mov(dividend_hi, imm(0));
|
||||||
e.update_gpr_value(i.XO.RT, v);
|
c.alloc(dividend, rax);
|
||||||
|
c.div(dividend_hi, dividend.r64(), divisor.r64());
|
||||||
|
e.update_gpr_value(i.XO.RT, dividend);
|
||||||
|
|
||||||
// If we are OE=1 we need to clear the overflow bit.
|
// If we are OE=1 we need to clear the overflow bit.
|
||||||
if (i.XO.OE) {
|
if (i.XO.OE) {
|
||||||
e.update_xer_with_overflow(b.getInt1(0));
|
e.update_xer_with_overflow(e.get_uint64(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.XO.Rc) {
|
if (i.XO.Rc) {
|
||||||
// With cr0 update.
|
// With cr0 update.
|
||||||
e.update_cr_with_cond(0, v);
|
e.update_cr_with_cond(0, dividend);
|
||||||
}
|
}
|
||||||
|
|
||||||
b.CreateBr(after_bb);
|
c.unuse(dividend_hi);
|
||||||
|
c.unuse(dividend);
|
||||||
|
|
||||||
// Resume.
|
#if 0
|
||||||
b.SetInsertPoint(after_bb);
|
b.CreateBr(after_bb);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
XEEMITTER(mulhdx, 0x7C000092, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
XEEMITTER(mulhdx, 0x7C000092, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
@@ -1075,8 +1084,8 @@ void X64RegisterEmitCategoryALU() {
|
|||||||
XEREGISTERINSTR(addzex, 0x7C000194);
|
XEREGISTERINSTR(addzex, 0x7C000194);
|
||||||
XEREGISTERINSTR(divdx, 0x7C0003D2);
|
XEREGISTERINSTR(divdx, 0x7C0003D2);
|
||||||
XEREGISTERINSTR(divdux, 0x7C000392);
|
XEREGISTERINSTR(divdux, 0x7C000392);
|
||||||
// XEREGISTERINSTR(divwx, 0x7C0003D6);
|
XEREGISTERINSTR(divwx, 0x7C0003D6);
|
||||||
// XEREGISTERINSTR(divwux, 0x7C000396);
|
XEREGISTERINSTR(divwux, 0x7C000396);
|
||||||
XEREGISTERINSTR(mulhdx, 0x7C000092);
|
XEREGISTERINSTR(mulhdx, 0x7C000092);
|
||||||
XEREGISTERINSTR(mulhdux, 0x7C000012);
|
XEREGISTERINSTR(mulhdux, 0x7C000012);
|
||||||
XEREGISTERINSTR(mulhwx, 0x7C000096);
|
XEREGISTERINSTR(mulhwx, 0x7C000096);
|
||||||
|
|||||||
@@ -1211,22 +1211,18 @@ void X64Emitter::update_xer_value(GpVar& value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void X64Emitter::update_xer_with_overflow(GpVar& value) {
|
void X64Emitter::update_xer_with_overflow(GpVar& value) {
|
||||||
X86Compiler& c = compiler_;
|
X86Compiler& c = compiler_;
|
||||||
XEASSERT(locals_.xer.getId() != kInvalidValue);
|
GpVar xer(c.newGpVar());
|
||||||
|
c.mov(xer, xer_value());
|
||||||
// Expects a i1 indicating overflow.
|
c.and_(xer, imm(0xBFFFFFFF)); // clear bit 30
|
||||||
// Trust the caller that if it's larger than that it's already truncated.
|
c.and_(value, imm(1));
|
||||||
value = zero_extend(value, 1, 8);
|
c.shl(value, imm(30));
|
||||||
|
c.or_(xer, value);
|
||||||
GpVar& xer = xer_value();
|
c.shl(value, imm(31)); // also stick value
|
||||||
xer = jit_insn_and(fn_, xer, get_uint64(0xFFFFFFFFBFFFFFFF)); // clear bit 30
|
c.or_(xer, value);
|
||||||
xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(31)));
|
update_xer_value(xer);
|
||||||
xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(30)));
|
|
||||||
jit_insn_store(fn_, locals_.xer, value);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set with a byte value indicating carry.
|
// Set with a byte value indicating carry.
|
||||||
void X64Emitter::update_xer_with_carry(GpVar& value) {
|
void X64Emitter::update_xer_with_carry(GpVar& value) {
|
||||||
@@ -1234,7 +1230,7 @@ void X64Emitter::update_xer_with_carry(GpVar& value) {
|
|||||||
GpVar xer(c.newGpVar());
|
GpVar xer(c.newGpVar());
|
||||||
c.mov(xer, xer_value());
|
c.mov(xer, xer_value());
|
||||||
c.and_(xer, imm(0xDFFFFFFF)); // clear bit 29
|
c.and_(xer, imm(0xDFFFFFFF)); // clear bit 29
|
||||||
c.and_(value, imm(0xF));
|
c.and_(value, imm(1));
|
||||||
c.shl(value, imm(29));
|
c.shl(value, imm(29));
|
||||||
c.or_(xer, value);
|
c.or_(xer, value);
|
||||||
update_xer_value(xer);
|
update_xer_value(xer);
|
||||||
|
|||||||
Reference in New Issue
Block a user