llvm: Implement trap instructions

This commit is contained in:
Vincent Lejeune 2015-12-29 21:06:04 +01:00
parent 2da52d0309
commit 082815f93e
2 changed files with 101 additions and 4 deletions

View File

@ -362,6 +362,17 @@ static void wrapped_fast_stop(PPUThread &CPU)
CPU.fast_stop();
}
static void wrapped_trap(PPUThread &CPU, u32) noexcept {
try
{
throw EXCEPTION("trap");
}
catch (...)
{
CPU.pending_exception = std::current_exception();
}
}
std::pair<Executable, llvm::ExecutionEngine *> RecompilationEngine::compile(const std::string & name, u32 start_address, u32 instruction_count) {
std::unique_ptr<llvm::Module> module = Compiler::create_module(m_llvm_context);
@ -375,6 +386,7 @@ std::pair<Executable, llvm::ExecutionEngine *> RecompilationEngine::compile(cons
function_ptrs["get_timebased_time"] = reinterpret_cast<void*>(get_timebased_time);
function_ptrs["wrappedExecutePPUFuncByIndex"] = reinterpret_cast<void*>(wrappedExecutePPUFuncByIndex);
function_ptrs["wrappedDoSyscall"] = reinterpret_cast<void*>(wrappedDoSyscall);
function_ptrs["trap"] = reinterpret_cast<void*>(wrapped_trap);
#define REGISTER_FUNCTION_PTR(name) \
function_ptrs[#name] = reinterpret_cast<void*>(PPUInterpreter::name##_impl);

View File

@ -48,11 +48,67 @@ void Compiler::NOP() {
}
void Compiler::TDI(u32 to, u32 ra, s32 simm16) {
CompilationError("TDI");
llvm::Value *gpr_a = GetGpr(ra);
llvm::Value *cst_simm16 = m_ir_builder->getInt64(simm16);
llvm::Value *trap_condition = m_ir_builder->getFalse();
if (to & 0x10)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSLT(gpr_a, cst_simm16));
if (to & 0x8)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSGT(gpr_a, cst_simm16));
if (to & 0x4)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpEQ(gpr_a, cst_simm16));
if (to & 0x2)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpULT(gpr_a, cst_simm16));
if (to & 0x1)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpUGT(gpr_a, cst_simm16));
llvm::BasicBlock *trap_block = GetBasicBlockFromAddress(m_state.current_instruction_address, "trap_block");
llvm::BasicBlock *normal_execution = GetBasicBlockFromAddress(m_state.current_instruction_address, "normal_execution");
m_ir_builder->CreateCondBr(trap_condition, trap_block, normal_execution);
m_ir_builder->SetInsertPoint(trap_block);
Call<void>("trap");
m_ir_builder->CreateRet(m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException));
m_ir_builder->SetInsertPoint(normal_execution);
}
void Compiler::TWI(u32 to, u32 ra, s32 simm16) {
CompilationError("TWI");
llvm::Value *gpr_a = GetGpr(ra, 32);
llvm::Value *cst_simm16 = m_ir_builder->getInt32(simm16);
llvm::Value *trap_condition = m_ir_builder->getFalse();
if (to & 0x10)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSLT(gpr_a, cst_simm16));
if (to & 0x8)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSGT(gpr_a, cst_simm16));
if (to & 0x4)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpEQ(gpr_a, cst_simm16));
if (to & 0x2)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpULT(gpr_a, cst_simm16));
if (to & 0x1)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpUGT(gpr_a, cst_simm16));
llvm::BasicBlock *trap_block = GetBasicBlockFromAddress(m_state.current_instruction_address, "trap_block");
llvm::BasicBlock *normal_execution = GetBasicBlockFromAddress(m_state.current_instruction_address, "normal_execution");
m_ir_builder->CreateCondBr(trap_condition, trap_block, normal_execution);
m_ir_builder->SetInsertPoint(trap_block);
Call<void>("trap");
m_ir_builder->CreateRet(m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException));
m_ir_builder->SetInsertPoint(normal_execution);
}
void Compiler::MFVSCR(u32 vd) {
@ -2198,7 +2254,35 @@ void Compiler::CMP(u32 crfd, u32 l, u32 ra, u32 rb) {
}
void Compiler::TW(u32 to, u32 ra, u32 rb) {
CompilationError("TW");
llvm::Value *gpr_a = GetGpr(ra, 32);
llvm::Value *gpr_b = GetGpr(rb, 32);
llvm::Value *trap_condition = m_ir_builder->getFalse();
if (to & 0x10)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSLT(gpr_a, gpr_b));
if (to & 0x8)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpSGT(gpr_a, gpr_b));
if (to & 0x4)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpEQ(gpr_a, gpr_b));
if (to & 0x2)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpULT(gpr_a, gpr_b));
if (to & 0x1)
trap_condition = m_ir_builder->CreateOr(trap_condition,
m_ir_builder->CreateICmpUGT(gpr_a, gpr_b));
llvm::BasicBlock *trap_block = GetBasicBlockFromAddress(m_state.current_instruction_address, "trap_block");
llvm::BasicBlock *normal_execution = GetBasicBlockFromAddress(m_state.current_instruction_address, "normal_execution");
m_ir_builder->CreateCondBr(trap_condition, trap_block, normal_execution);
m_ir_builder->SetInsertPoint(trap_block);
Call<void>("trap");
m_ir_builder->CreateRet(m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException));
m_ir_builder->SetInsertPoint(normal_execution);
}
void Compiler::LVSL(u32 vd, u32 ra, u32 rb) {
@ -2555,7 +2639,8 @@ void Compiler::ANDC(u32 ra, u32 rs, u32 rb, u32 rc) {
}
void Compiler::TD(u32 to, u32 ra, u32 rb) {
CompilationError("TD");
Call<void>("trap");
m_ir_builder->CreateRet(m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException));
}
void Compiler::LVEWX(u32 vd, u32 ra, u32 rb) {