forked from eden-emu/eden
[dynarmic] pre-LZCNT count leading zeroes (integer)
This commit is contained in:
parent
edbce61fa9
commit
16583284e0
2 changed files with 50 additions and 10 deletions
|
@ -1568,14 +1568,14 @@ void EmitX64::EmitCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) {
|
|||
} else {
|
||||
const Xbyak::Reg32 source = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32();
|
||||
const Xbyak::Reg32 temp = ctx.reg_alloc.ScratchGpr().cvt32();
|
||||
|
||||
// The result of a bsr of zero is undefined, but zf is set after it.
|
||||
code.bsr(result, source);
|
||||
code.mov(source, 0xFFFFFFFF);
|
||||
code.cmovz(result, source);
|
||||
code.neg(result);
|
||||
code.add(result, 31);
|
||||
|
||||
code.mov(temp, 32);
|
||||
code.xor_(result, 31);
|
||||
code.test(source, source);
|
||||
code.cmove(result, temp);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
}
|
||||
|
@ -1592,14 +1592,14 @@ void EmitX64::EmitCountLeadingZeros64(EmitContext& ctx, IR::Inst* inst) {
|
|||
} else {
|
||||
const Xbyak::Reg64 source = ctx.reg_alloc.UseScratchGpr(args[0]).cvt64();
|
||||
const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr().cvt64();
|
||||
const Xbyak::Reg64 temp = ctx.reg_alloc.ScratchGpr().cvt64();
|
||||
|
||||
// The result of a bsr of zero is undefined, but zf is set after it.
|
||||
code.bsr(result, source);
|
||||
code.mov(source.cvt32(), 0xFFFFFFFF);
|
||||
code.cmovz(result.cvt32(), source.cvt32());
|
||||
code.neg(result.cvt32());
|
||||
code.add(result.cvt32(), 63);
|
||||
|
||||
code.mov(temp.cvt32(), 64);
|
||||
code.xor_(result.cvt32(), 63);
|
||||
code.test(source, source);
|
||||
code.cmove(result.cvt32(), temp.cvt32());
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
}
|
||||
|
|
40
externals/dynarmic/tests/A64/a64.cpp
vendored
40
externals/dynarmic/tests/A64/a64.cpp
vendored
|
@ -2345,3 +2345,43 @@ TEST_CASE("A64: RBIT{16b}", "[a64]") {
|
|||
REQUIRE(jit.GetVector(2)[0] == 0xcafedead);
|
||||
REQUIRE(jit.GetVector(2)[1] == 0xbabebeef);
|
||||
}
|
||||
|
||||
TEST_CASE("A64: CLZ{X}", "[a64]") {
|
||||
A64TestEnv env;
|
||||
A64::UserConfig conf{};
|
||||
conf.callbacks = &env;
|
||||
A64::Jit jit{conf};
|
||||
env.code_mem.emplace_back(0xdac01060); // clz x0, x3
|
||||
env.code_mem.emplace_back(0xdac01081); // clz x1, x4
|
||||
env.code_mem.emplace_back(0xdac010a2); // clz x2, x5
|
||||
env.code_mem.emplace_back(0x14000000); // b .
|
||||
jit.SetRegister(3, 0xfffffffffffffff0);
|
||||
jit.SetRegister(4, 0x0fffffff0ffffff0);
|
||||
jit.SetRegister(5, 0x07fffffeffeffef0);
|
||||
jit.SetPC(0); // at _start
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
REQUIRE(jit.GetRegister(0) == 0);
|
||||
REQUIRE(jit.GetRegister(1) == 4);
|
||||
REQUIRE(jit.GetRegister(2) == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("A64: CLZ{W}", "[a64]") {
|
||||
A64TestEnv env;
|
||||
A64::UserConfig conf{};
|
||||
conf.callbacks = &env;
|
||||
A64::Jit jit{conf};
|
||||
env.code_mem.emplace_back(0x5ac01060); // clz w0, w3
|
||||
env.code_mem.emplace_back(0x5ac01081); // clz w1, w4
|
||||
env.code_mem.emplace_back(0x5ac010a2); // clz w2, w5
|
||||
env.code_mem.emplace_back(0x14000000); // b .
|
||||
jit.SetRegister(3, 0xffff1110);
|
||||
jit.SetRegister(4, 0x0fff1110);
|
||||
jit.SetRegister(5, 0x07fffffe);
|
||||
jit.SetPC(0); // at _start
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
REQUIRE(jit.GetRegister(0) == 0);
|
||||
REQUIRE(jit.GetRegister(1) == 4);
|
||||
REQUIRE(jit.GetRegister(2) == 5);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue