PPU LLVM recompiler: Implement more instructions

This commit is contained in:
S Gopal Rajagopal 2014-11-26 00:53:24 +05:30
parent 631675fdd6
commit 205e1d88b3
2 changed files with 62 additions and 34 deletions

View file

@ -1778,7 +1778,21 @@ void Compiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) {
} }
void Compiler::SC(u32 sc_code) { void Compiler::SC(u32 sc_code) {
InterpreterCall("SC", &PPUInterpreter::SC, sc_code); switch (sc_code) {
case 2:
Call<void>("SysCalls.DoSyscall", SysCalls::DoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11));
break;
case 3:
Call<void>("StaticFuncManager.StaticExecute", &StaticFuncManager::StaticExecute,
m_ir_builder->getInt64((u64)&Emu.GetSFuncManager()), m_state.args[CompileTaskState::Args::State], GetGpr(11, 32));
break;
case 4:
Call<void>("PPUThread.FastStop", &PPUThread::FastStop, m_state.args[CompileTaskState::Args::State]);
break;
default:
CompilationError(fmt::Format("SC %u", sc_code));
break;
}
} }
void Compiler::B(s32 ll, u32 aa, u32 lk) { void Compiler::B(s32 ll, u32 aa, u32 lk) {
@ -2955,7 +2969,15 @@ void Compiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) {
} }
void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) { void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) {
InterpreterCall("ECIWX", &PPUInterpreter::ECIWX, rd, ra, rb); auto addr_i64 = GetGpr(rb);
if (ra) {
auto ra_i64 = GetGpr(ra);
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
}
auto mem_i32 = ReadMemory(addr_i64, 32);
auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty());
SetGpr(rd, mem_i64);
} }
void Compiler::LHZUX(u32 rd, u32 ra, u32 rb) { void Compiler::LHZUX(u32 rd, u32 ra, u32 rb) {
@ -3106,7 +3128,13 @@ void Compiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) {
} }
void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) { void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) {
InterpreterCall("ECOWX", &PPUInterpreter::ECOWX, rs, ra, rb); auto addr_i64 = GetGpr(rb);
if (ra) {
auto ra_i64 = GetGpr(ra);
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
}
WriteMemory(addr_i64, GetGpr(rs, 32));
} }
void Compiler::STHUX(u32 rs, u32 ra, u32 rb) { void Compiler::STHUX(u32 rs, u32 ra, u32 rb) {
@ -4215,8 +4243,8 @@ void Compiler::FRSP(u32 frd, u32 frb, bool rc) {
void Compiler::FCTIW(u32 frd, u32 frb, bool rc) { void Compiler::FCTIW(u32 frd, u32 frb, bool rc) {
auto rb_f64 = GetFpr(frb); auto rb_f64 = GetFpr(frb);
auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFF)); auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 2147483647.0));
auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648)); auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648.0));
auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty()); auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty());
auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty()); auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty());
res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64); res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64);
@ -4229,26 +4257,24 @@ void Compiler::FCTIW(u32 frd, u32 frb, bool rc) {
} }
// TODO: Set flags / Implement rounding modes // TODO: Set flags / Implement rounding modes
//InterpreterCall("FCTIW", &PPUInterpreter::FCTIWZ, frd, frb, rc);
} }
void Compiler::FCTIWZ(u32 frd, u32 frb, bool rc) { void Compiler::FCTIWZ(u32 frd, u32 frb, bool rc) {
//auto rb_f64 = GetFpr(frb); auto rb_f64 = GetFpr(frb);
//auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFF)); auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 2147483647.0));
//auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648)); auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648.0));
//auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty()); auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty());
//auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty()); auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty());
//res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64); res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64);
//res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x80000000), res_i64); res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x80000000), res_i64);
//SetFpr(frd, res_i64); SetFpr(frd, res_i64);
//if (rc) { if (rc) {
// // TODO: Implement this // TODO: Implement this
// CompilationError("FCTIWZ."); CompilationError("FCTIWZ.");
//} }
// TODO: Set flags // TODO: Set flags
InterpreterCall("FCTIWZ", &PPUInterpreter::FCTIWZ, frd, frb, rc);
} }
void Compiler::FDIV(u32 frd, u32 fra, u32 frb, bool rc) { void Compiler::FDIV(u32 frd, u32 fra, u32 frb, bool rc) {
@ -4478,8 +4504,8 @@ void Compiler::FABS(u32 frd, u32 frb, bool rc) {
void Compiler::FCTID(u32 frd, u32 frb, bool rc) { void Compiler::FCTID(u32 frd, u32 frb, bool rc) {
auto rb_f64 = GetFpr(frb); auto rb_f64 = GetFpr(frb);
auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFFFFFFFFFFll)); auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 9223372036854775807.0));
auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808ll)); auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808.0));
auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty()); auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty());
res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64); res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64);
res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64); res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64);
@ -4491,25 +4517,23 @@ void Compiler::FCTID(u32 frd, u32 frb, bool rc) {
} }
// TODO: Set flags / Implement rounding modes // TODO: Set flags / Implement rounding modes
//InterpreterCall("FCTIDZ", &PPUInterpreter::FCTID, frd, frb, rc);
} }
void Compiler::FCTIDZ(u32 frd, u32 frb, bool rc) { void Compiler::FCTIDZ(u32 frd, u32 frb, bool rc) {
//auto rb_f64 = GetFpr(frb); auto rb_f64 = GetFpr(frb);
//auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFFFFFFFFFFll)); auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 9223372036854775807.0));
//auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808ll)); auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808.0));
//auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty()); auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty());
//res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64); res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64);
//res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64); res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64);
//SetFpr(frd, res_i64); SetFpr(frd, res_i64);
//if (rc) { if (rc) {
// // TODO: Implement this // TODO: Implement this
// CompilationError("FCTIDZ."); CompilationError("FCTIDZ.");
//} }
// TODO: Set flags // TODO: Set flags
InterpreterCall("FCTIDZ", &PPUInterpreter::FCTIDZ, frd, frb, rc);
} }
void Compiler::FCFID(u32 frd, u32 frb, bool rc) { void Compiler::FCFID(u32 frd, u32 frb, bool rc) {

View file

@ -703,6 +703,8 @@ void Compiler::RunAllTests() {
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0);
@ -789,6 +791,8 @@ void Compiler::RunAllTests() {
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000);