Implemented SDIV and UDIV instructions

This commit is contained in:
FernandoS27 2018-01-24 08:36:39 -04:00 committed by MerryMage
parent 6033b05ca6
commit ab84524806
6 changed files with 153 additions and 3 deletions

View file

@ -878,6 +878,90 @@ void EmitX64::EmitMul64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitUnsignedDiv32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.ScratchGpr({HostLoc::RAX});
ctx.reg_alloc.ScratchGpr({HostLoc::RDX});
Xbyak::Reg32 dividend = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Reg32 divisor = ctx.reg_alloc.UseGpr(args[1]).cvt32();
Xbyak::Label end;
code->xor_(eax, eax);
code->test(divisor, divisor);
code->jz(end);
code->mov(eax, dividend);
code->xor_(edx, edx);
code->div(divisor);
code->L(end);
ctx.reg_alloc.DefineValue(inst, eax);
}
void EmitX64::EmitUnsignedDiv64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.ScratchGpr({HostLoc::RAX});
ctx.reg_alloc.ScratchGpr({HostLoc::RDX});
Xbyak::Reg64 dividend = ctx.reg_alloc.UseGpr(args[0]);
Xbyak::Reg64 divisor = ctx.reg_alloc.UseGpr(args[1]);
Xbyak::Label end;
code->xor_(eax, eax);
code->test(divisor, divisor);
code->jz(end);
code->mov(rax, dividend);
code->xor_(edx, edx);
code->div(divisor);
code->L(end);
ctx.reg_alloc.DefineValue(inst, rax);
}
void EmitX64::EmitSignedDiv32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.ScratchGpr({HostLoc::RAX});
ctx.reg_alloc.ScratchGpr({HostLoc::RDX});
Xbyak::Reg32 dividend = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Reg32 divisor = ctx.reg_alloc.UseGpr(args[1]).cvt32();
Xbyak::Label end;
code->xor_(eax, eax);
code->test(divisor, divisor);
code->jz(end);
code->mov(eax, dividend);
code->cdq();
code->idiv(divisor);
code->L(end);
ctx.reg_alloc.DefineValue(inst, eax);
}
void EmitX64::EmitSignedDiv64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.ScratchGpr({HostLoc::RAX});
ctx.reg_alloc.ScratchGpr({HostLoc::RDX});
Xbyak::Reg64 dividend = ctx.reg_alloc.UseGpr(args[0]);
Xbyak::Reg64 divisor = ctx.reg_alloc.UseGpr(args[1]);
Xbyak::Label end;
code->xor_(eax, eax);
code->test(divisor, divisor);
code->jz(end);
code->mov(rax, dividend);
code->cqo();
code->idiv(divisor);
code->L(end);
ctx.reg_alloc.DefineValue(inst, rax);
}
void EmitX64::EmitAnd32(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitAnd32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);

View file

@ -274,8 +274,8 @@ INST(LDR_imm_fpsimd_2, "LDR (immediate, SIMD&FP)", "zz111
//INST(LDRA, "LDRAA, LDRAB", "11111000MS1iiiiiiiiiW1nnnnnttttt") //INST(LDRA, "LDRAA, LDRAB", "11111000MS1iiiiiiiiiW1nnnnnttttt")
// Data Processing - Register - 2 source // Data Processing - Register - 2 source
//INST(UDIV, "UDIV", "z0011010110mmmmm000010nnnnnddddd") INST(UDIV, "UDIV", "z0011010110mmmmm000010nnnnnddddd")
//INST(SDIV, "SDIV", "z0011010110mmmmm000011nnnnnddddd") INST(SDIV, "SDIV", "z0011010110mmmmm000011nnnnnddddd")
INST(LSLV, "LSLV", "z0011010110mmmmm001000nnnnnddddd") INST(LSLV, "LSLV", "z0011010110mmmmm001000nnnnnddddd")
INST(LSRV, "LSRV", "z0011010110mmmmm001001nnnnnddddd") INST(LSRV, "LSRV", "z0011010110mmmmm001001nnnnnddddd")
INST(ASRV, "ASRV", "z0011010110mmmmm001010nnnnnddddd") INST(ASRV, "ASRV", "z0011010110mmmmm001010nnnnnddddd")
@ -975,4 +975,4 @@ INST(AND_asimd, "AND (vector)", "0Q001
//INST(FMADD_float, "FMADD", "00011111yy0mmmmm0aaaaannnnnddddd") //INST(FMADD_float, "FMADD", "00011111yy0mmmmm0aaaaannnnnddddd")
//INST(FMSUB_float, "FMSUB", "00011111yy0mmmmm1aaaaannnnnddddd") //INST(FMSUB_float, "FMSUB", "00011111yy0mmmmm1aaaaannnnnddddd")
//INST(FNMADD_float, "FNMADD", "00011111yy1mmmmm0aaaaannnnnddddd") //INST(FNMADD_float, "FNMADD", "00011111yy1mmmmm0aaaaannnnnddddd")
//INST(FNMSUB_float, "FNMSUB", "00011111yy1mmmmm1aaaaannnnnddddd") //INST(FNMSUB_float, "FNMSUB", "00011111yy1mmmmm1aaaaannnnnddddd")

View file

@ -79,5 +79,29 @@ bool TranslatorVisitor::UMSUBL(Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
return true; return true;
} }
bool TranslatorVisitor::UDIV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
const size_t datasize = sf ? 64 : 32;
const IR::U32U64 m = X(datasize, Rm);
const IR::U32U64 n = X(datasize, Rn);
const IR::U32U64 result = ir.UnsignedDiv(n,m);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::SDIV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
const size_t datasize = sf ? 64 : 32;
const IR::U32U64 m = X(datasize, Rm);
const IR::U32U64 n = X(datasize, Rn);
const IR::U32U64 result = ir.SignedDiv(n,m);
X(datasize, Rd, result);
return true;
}
} // namespace A64 } // namespace A64
} // namespace Dynarmic } // namespace Dynarmic

View file

@ -269,6 +269,38 @@ U32U64 IREmitter::Mul(const U32U64& a, const U32U64& b) {
return Inst<U64>(Opcode::Mul64, a, b); return Inst<U64>(Opcode::Mul64, a, b);
} }
U32 IREmitter::UnsignedDiv(const U32& a, const U32& b) {
return Inst<U32>(Opcode::UnsignedDiv32, a, b);
}
U64 IREmitter::UnsignedDiv(const U64& a, const U64& b) {
return Inst<U64>(Opcode::UnsignedDiv64, a, b);
}
U32U64 IREmitter::UnsignedDiv(const U32U64& a, const U32U64& b) {
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::UnsignedDiv32, a, b);
}
return Inst<U64>(Opcode::UnsignedDiv64, a, b);
}
U32 IREmitter::SignedDiv(const U32& a, const U32& b) {
return Inst<U32>(Opcode::SignedDiv32, a, b);
}
U64 IREmitter::SignedDiv(const U64& a, const U64& b) {
return Inst<U64>(Opcode::SignedDiv64, a, b);
}
U32U64 IREmitter::SignedDiv(const U32U64& a, const U32U64& b) {
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::SignedDiv32, a, b);
}
return Inst<U64>(Opcode::SignedDiv64, a, b);
}
U32 IREmitter::And(const U32& a, const U32& b) { U32 IREmitter::And(const U32& a, const U32& b) {
return Inst<U32>(Opcode::And32, a, b); return Inst<U32>(Opcode::And32, a, b);
} }

View file

@ -110,6 +110,12 @@ public:
U32 Mul(const U32& a, const U32& b); U32 Mul(const U32& a, const U32& b);
U64 Mul(const U64& a, const U64& b); U64 Mul(const U64& a, const U64& b);
U32U64 Mul(const U32U64& a, const U32U64& b); U32U64 Mul(const U32U64& a, const U32U64& b);
U32 UnsignedDiv(const U32& a, const U32& b);
U64 UnsignedDiv(const U64& a, const U64& b);
U32U64 UnsignedDiv(const U32U64& a, const U32U64& b);
U32 SignedDiv(const U32& a, const U32& b);
U64 SignedDiv(const U64& a, const U64& b);
U32U64 SignedDiv(const U32U64& a, const U32U64& b);
U32 And(const U32& a, const U32& b); U32 And(const U32& a, const U32& b);
U32U64 And(const U32U64& a, const U32U64& b); U32U64 And(const U32U64& a, const U32U64& b);
U32 Eor(const U32& a, const U32& b); U32 Eor(const U32& a, const U32& b);

View file

@ -94,6 +94,10 @@ OPCODE(Sub32, T::U32, T::U32, T::U32,
OPCODE(Sub64, T::U64, T::U64, T::U64, T::U1 ) OPCODE(Sub64, T::U64, T::U64, T::U64, T::U1 )
OPCODE(Mul32, T::U32, T::U32, T::U32 ) OPCODE(Mul32, T::U32, T::U32, T::U32 )
OPCODE(Mul64, T::U64, T::U64, T::U64 ) OPCODE(Mul64, T::U64, T::U64, T::U64 )
OPCODE(UnsignedDiv32, T::U32, T::U32, T::U32 )
OPCODE(UnsignedDiv64, T::U64, T::U64, T::U64 )
OPCODE(SignedDiv32, T::U32, T::U32, T::U32 )
OPCODE(SignedDiv64, T::U64, T::U64, T::U64 )
OPCODE(And32, T::U32, T::U32, T::U32 ) OPCODE(And32, T::U32, T::U32, T::U32 )
OPCODE(And64, T::U64, T::U64, T::U64 ) OPCODE(And64, T::U64, T::U64, T::U64 )
OPCODE(Eor32, T::U32, T::U32, T::U32 ) OPCODE(Eor32, T::U32, T::U32, T::U32 )