mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 00:11:24 +12:00
PPUJIT: Support exception based MMIO and reservations
This commit is contained in:
parent
bf1e29e227
commit
e7f278b5d2
3 changed files with 6024 additions and 6141 deletions
|
@ -2463,27 +2463,20 @@ void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) {
|
|||
}
|
||||
|
||||
void Compiler::LWARX(u32 rd, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
||||
|
||||
//auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false);
|
||||
//auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
||||
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
||||
|
||||
//resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32);
|
||||
//resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
||||
//SetGpr(rd, resv_val_i64);
|
||||
auto addr_i32 = m_ir_builder->CreateTrunc(addr_i64, m_ir_builder->getInt32Ty());
|
||||
auto val_i32_ptr = m_ir_builder->CreateAlloca(m_ir_builder->getInt32Ty());
|
||||
val_i32_ptr->setAlignment(4);
|
||||
Call<bool>("vm.reservation_acquire_no_cb", vm::reservation_acquire_no_cb, m_ir_builder->CreateBitCast(val_i32_ptr, m_ir_builder->getInt8PtrTy()), addr_i32, m_ir_builder->getInt32(4));
|
||||
auto val_i32 = (Value *)m_ir_builder->CreateLoad(val_i32_ptr);
|
||||
val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_i32);
|
||||
auto val_i64 = m_ir_builder->CreateZExt(val_i32, m_ir_builder->getInt64Ty());
|
||||
SetGpr(rd, val_i64);
|
||||
}
|
||||
|
||||
void Compiler::LDX(u32 rd, u32 ra, u32 rb) {
|
||||
|
@ -2741,25 +2734,19 @@ void Compiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) {
|
|||
}
|
||||
|
||||
void Compiler::LDARX(u32 rd, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
||||
|
||||
//auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false);
|
||||
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
||||
|
||||
//resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64);
|
||||
//SetGpr(rd, resv_val_i64);
|
||||
auto addr_i32 = m_ir_builder->CreateTrunc(addr_i64, m_ir_builder->getInt32Ty());
|
||||
auto val_i64_ptr = m_ir_builder->CreateAlloca(m_ir_builder->getInt64Ty());
|
||||
val_i64_ptr->setAlignment(8);
|
||||
Call<bool>("vm.reservation_acquire_no_cb", vm::reservation_acquire_no_cb, m_ir_builder->CreateBitCast(val_i64_ptr, m_ir_builder->getInt8PtrTy()), addr_i32, m_ir_builder->getInt32(8));
|
||||
auto val_i64 = (Value *)m_ir_builder->CreateLoad(val_i64_ptr);
|
||||
val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), val_i64);
|
||||
SetGpr(rd, val_i64);
|
||||
}
|
||||
|
||||
void Compiler::DCBF(u32 ra, u32 rb) {
|
||||
|
@ -2923,47 +2910,23 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) {
|
|||
}
|
||||
|
||||
void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
auto addr_i32 = m_ir_builder->CreateTrunc(addr_i64, m_ir_builder->getInt32Ty());
|
||||
auto rs_i32 = GetGpr(rs, 32);
|
||||
rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), rs_i32);
|
||||
auto rs_i32_ptr = m_ir_builder->CreateAlloca(m_ir_builder->getInt32Ty());
|
||||
rs_i32_ptr->setAlignment(4);
|
||||
m_ir_builder->CreateStore(rs_i32, rs_i32_ptr);
|
||||
auto success_i1 = Call<bool>("vm.reservation_update", vm::reservation_update, addr_i32, m_ir_builder->CreateBitCast(rs_i32_ptr, m_ir_builder->getInt8PtrTy()), m_ir_builder->getInt32(4));
|
||||
|
||||
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
|
||||
//auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
//m_ir_builder->SetInsertPoint(then_bb);
|
||||
//auto rs_i32 = GetGpr(rs, 32);
|
||||
//rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32);
|
||||
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
//auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||
//auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||
//auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8);
|
||||
|
||||
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
//auto cr_i32 = GetCr();
|
||||
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
//SetCr(cr_i32);
|
||||
//m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||
//m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
//m_ir_builder->SetInsertPoint(else_bb);
|
||||
//cr_i32 = GetCr();
|
||||
//cr_i32 = ClrBit(cr_i32, 2);
|
||||
//SetCr(cr_i32);
|
||||
//m_ir_builder->CreateBr(merge_bb);
|
||||
//m_ir_builder->SetInsertPoint(merge_bb);
|
||||
auto cr_i32 = GetCr();
|
||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
SetCr(cr_i32);
|
||||
}
|
||||
|
||||
void Compiler::STWX(u32 rs, u32 ra, u32 rb) {
|
||||
|
@ -3066,47 +3029,23 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) {
|
|||
}
|
||||
|
||||
void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
auto addr_i32 = m_ir_builder->CreateTrunc(addr_i64, m_ir_builder->getInt32Ty());
|
||||
auto rs_i64 = GetGpr(rs);
|
||||
rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), rs_i64);
|
||||
auto rs_i64_ptr = m_ir_builder->CreateAlloca(m_ir_builder->getInt64Ty());
|
||||
rs_i64_ptr->setAlignment(8);
|
||||
m_ir_builder->CreateStore(rs_i64, rs_i64_ptr);
|
||||
auto success_i1 = Call<bool>("vm.reservation_update", vm::reservation_update, addr_i32, m_ir_builder->CreateBitCast(rs_i64_ptr, m_ir_builder->getInt8PtrTy()), m_ir_builder->getInt32(8));
|
||||
|
||||
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
|
||||
//auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
//m_ir_builder->SetInsertPoint(then_bb);
|
||||
//auto rs_i64 = GetGpr(rs, 64);
|
||||
//rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64);
|
||||
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
//auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
//auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8);
|
||||
|
||||
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
//auto cr_i32 = GetCr();
|
||||
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
//SetCr(cr_i32);
|
||||
//m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||
//m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
//m_ir_builder->SetInsertPoint(else_bb);
|
||||
//cr_i32 = GetCr();
|
||||
//cr_i32 = ClrBit(cr_i32, 2);
|
||||
//SetCr(cr_i32);
|
||||
//m_ir_builder->CreateBr(merge_bb);
|
||||
//m_ir_builder->SetInsertPoint(merge_bb);
|
||||
auto cr_i32 = GetCr();
|
||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
SetCr(cr_i32);
|
||||
}
|
||||
|
||||
void Compiler::STBX(u32 rs, u32 ra, u32 rb) {
|
||||
|
@ -3271,7 +3210,7 @@ void Compiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) {
|
|||
}
|
||||
|
||||
void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
CompilationError("ECIWX");
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
|
@ -3431,7 +3370,7 @@ void Compiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) {
|
|||
}
|
||||
|
||||
void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) {
|
||||
throw __FUNCTION__;
|
||||
CompilationError("ECOWX");
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
|
@ -5526,92 +5465,26 @@ void Compiler::CreateBranch(llvm::Value * cmp_i1, llvm::Value * target_i32, bool
|
|||
}
|
||||
|
||||
Value * Compiler::ReadMemory(Value * addr_i64, u32 bits, u32 alignment, bool bswap, bool could_be_mmio) {
|
||||
if (bits != 32 || could_be_mmio == false) {
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getIntNTy(bits)->getPointerTo());
|
||||
auto val_ix = (Value *)m_ir_builder->CreateLoad(eaddr_ix_ptr, alignment);
|
||||
if (bits > 8 && bswap) {
|
||||
val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getIntNTy(bits)), val_ix);
|
||||
}
|
||||
|
||||
return val_ix;
|
||||
} else {
|
||||
static u32 next_basic_block_id = 0;
|
||||
|
||||
next_basic_block_id++;
|
||||
auto cmp_i1 = m_ir_builder->CreateICmpULT(addr_i64, m_ir_builder->getInt64(RAW_SPU_BASE_ADDR));
|
||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("then_%u", next_basic_block_id));
|
||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("else_%u", next_basic_block_id));
|
||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("merge_%u", next_basic_block_id));
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_i32_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||
auto val_then_i32 = (Value *)m_ir_builder->CreateAlignedLoad(eaddr_i32_ptr, alignment);
|
||||
if (bswap) {
|
||||
val_then_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_then_i32);
|
||||
}
|
||||
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(else_bb);
|
||||
auto val_else_i32 = Call<u32>("vm.read32", (u32(*)(u64))vm::read32, addr_i64);
|
||||
if (!bswap) {
|
||||
val_else_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_else_i32);
|
||||
}
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(merge_bb);
|
||||
auto phi = m_ir_builder->CreatePHI(m_ir_builder->getInt32Ty(), 2);
|
||||
phi->addIncoming(val_then_i32, then_bb);
|
||||
phi->addIncoming(val_else_i32, else_bb);
|
||||
return phi;
|
||||
addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF);
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getIntNTy(bits)->getPointerTo());
|
||||
auto val_ix = (Value *)m_ir_builder->CreateLoad(eaddr_ix_ptr, alignment);
|
||||
if (bits > 8 && bswap) {
|
||||
val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getIntNTy(bits)), val_ix);
|
||||
}
|
||||
|
||||
return val_ix;
|
||||
}
|
||||
|
||||
void Compiler::WriteMemory(Value * addr_i64, Value * val_ix, u32 alignment, bool bswap, bool could_be_mmio) {
|
||||
addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF);
|
||||
if (val_ix->getType()->getIntegerBitWidth() != 32 || could_be_mmio == false) {
|
||||
if (val_ix->getType()->getIntegerBitWidth() > 8 && bswap) {
|
||||
val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, val_ix->getType()), val_ix);
|
||||
}
|
||||
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, val_ix->getType()->getPointerTo());
|
||||
m_ir_builder->CreateAlignedStore(val_ix, eaddr_ix_ptr, alignment);
|
||||
} else {
|
||||
static u32 next_basic_block_id;
|
||||
|
||||
next_basic_block_id++;
|
||||
auto cmp_i1 = m_ir_builder->CreateICmpULT(addr_i64, m_ir_builder->getInt64(RAW_SPU_BASE_ADDR));
|
||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("then_%u", next_basic_block_id));
|
||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("else_%u", next_basic_block_id));
|
||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, fmt::Format("merge_%u", next_basic_block_id));
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
Value * val_then_i32 = val_ix;
|
||||
if (bswap) {
|
||||
val_then_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_then_i32);
|
||||
}
|
||||
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_i32_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||
m_ir_builder->CreateAlignedStore(val_then_i32, eaddr_i32_ptr, alignment);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(else_bb);
|
||||
Value * val_else_i32 = val_ix;
|
||||
if (!bswap) {
|
||||
val_else_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_else_i32);
|
||||
}
|
||||
|
||||
Call<void>("vm.write32", (void(*)(u32, u32))vm::write32, addr_i64, val_else_i32);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(merge_bb);
|
||||
if (val_ix->getType()->getIntegerBitWidth() > 8 && bswap) {
|
||||
val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, val_ix->getType()), val_ix);
|
||||
}
|
||||
|
||||
addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF);
|
||||
auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, val_ix->getType()->getPointerTo());
|
||||
m_ir_builder->CreateAlignedStore(val_ix, eaddr_ix_ptr, alignment);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -5630,6 +5503,8 @@ Type * Compiler::CppToLlvmType() {
|
|||
return m_ir_builder->getFloatTy();
|
||||
} else if (std::is_same<T, double>::value) {
|
||||
return m_ir_builder->getDoubleTy();
|
||||
} else if (std::is_same<T, bool>::value) {
|
||||
return m_ir_builder->getInt1Ty();
|
||||
} else if (std::is_pointer<T>::value) {
|
||||
return m_ir_builder->getInt8PtrTy();
|
||||
} else {
|
||||
|
|
|
@ -242,6 +242,11 @@ namespace vm
|
|||
return broken;
|
||||
}
|
||||
|
||||
bool reservation_acquire_no_cb(void* data, u32 addr, u32 size)
|
||||
{
|
||||
return reservation_acquire(data, addr, size);
|
||||
}
|
||||
|
||||
bool reservation_update(u32 addr, const void* data, u32 size)
|
||||
{
|
||||
assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128);
|
||||
|
|
|
@ -36,6 +36,9 @@ namespace vm
|
|||
bool reservation_break(u32 addr);
|
||||
// read memory and reserve it for further atomic update, return true if the previous reservation was broken
|
||||
bool reservation_acquire(void* data, u32 addr, u32 size, const std::function<void()>& callback = nullptr);
|
||||
// same as reservation_acquire but does not have the callback argument
|
||||
// used by the PPU LLVM JIT since creating a std::function object in LLVM IR is too complicated
|
||||
bool reservation_acquire_no_cb(void* data, u32 addr, u32 size);
|
||||
// attempt to atomically update reserved memory
|
||||
bool reservation_update(u32 addr, const void* data, u32 size);
|
||||
// for internal use
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue