2014-09-15 16:16:53 +02:00
# include "stdafx.h"
# include "Utilities/Log.h"
# include "Emu/Cell/PPULLVMRecompiler.h"
# include "Emu/Memory/Memory.h"
# include "llvm/Support/TargetSelect.h"
# include "llvm/Support/Host.h"
# include "llvm/Support/ManagedStatic.h"
# include "llvm/Support/raw_ostream.h"
2014-09-17 11:57:45 +02:00
# include "llvm/CodeGen/MachineCodeInfo.h"
2014-09-15 16:16:53 +02:00
# include "llvm/ExecutionEngine/GenericValue.h"
# include "llvm/IR/Intrinsics.h"
2014-09-21 23:28:48 +02:00
# include "llvm/Support/FileSystem.h"
2014-09-15 16:35:18 +02:00
# include "llvm/Analysis/Passes.h"
2014-09-15 16:36:29 +02:00
# include "llvm/Analysis/TargetTransformInfo.h"
# include "llvm/Analysis/MemoryDependenceAnalysis.h"
# include "llvm/Analysis/LoopInfo.h"
# include "llvm/Analysis/ScalarEvolution.h"
# include "llvm/IR/Dominators.h"
# include "llvm/Transforms/Scalar.h"
# include "llvm/Transforms/Vectorize.h"
2014-10-08 22:04:17 +02:00
# include "llvm/MC/MCDisassembler.h"
2014-09-15 16:19:43 +02:00
2014-09-15 16:16:53 +02:00
using namespace llvm ;
2014-09-15 16:37:38 +02:00
u64 PPULLVMRecompiler : : s_rotate_mask [ 64 ] [ 64 ] ;
bool PPULLVMRecompiler : : s_rotate_mask_inited = false ;
2014-09-15 16:35:18 +02:00
PPULLVMRecompiler : : PPULLVMRecompiler ( )
: ThreadBase ( " PPULLVMRecompiler " )
2014-09-22 22:22:20 +02:00
, m_revision ( 0 ) {
2014-09-15 16:34:09 +02:00
InitializeNativeTarget ( ) ;
InitializeNativeTargetAsmPrinter ( ) ;
InitializeNativeTargetDisassembler ( ) ;
m_llvm_context = new LLVMContext ( ) ;
m_ir_builder = new IRBuilder < > ( * m_llvm_context ) ;
m_module = new llvm : : Module ( " Module " , * m_llvm_context ) ;
2014-09-15 16:36:29 +02:00
m_fpm = new FunctionPassManager ( m_module ) ;
2014-09-15 16:34:09 +02:00
EngineBuilder engine_builder ( m_module ) ;
engine_builder . setMCPU ( sys : : getHostCPUName ( ) ) ;
engine_builder . setEngineKind ( EngineKind : : JIT ) ;
engine_builder . setOptLevel ( CodeGenOpt : : Default ) ;
m_execution_engine = engine_builder . create ( ) ;
2014-09-15 16:36:29 +02:00
m_fpm - > add ( new DataLayoutPass ( m_module ) ) ;
m_fpm - > add ( createNoAAPass ( ) ) ;
m_fpm - > add ( createBasicAliasAnalysisPass ( ) ) ;
m_fpm - > add ( createNoTargetTransformInfoPass ( ) ) ;
m_fpm - > add ( createEarlyCSEPass ( ) ) ;
m_fpm - > add ( createTailCallEliminationPass ( ) ) ;
m_fpm - > add ( createReassociatePass ( ) ) ;
m_fpm - > add ( createInstructionCombiningPass ( ) ) ;
m_fpm - > add ( new DominatorTreeWrapperPass ( ) ) ;
m_fpm - > add ( new MemoryDependenceAnalysis ( ) ) ;
m_fpm - > add ( createGVNPass ( ) ) ;
m_fpm - > add ( createInstructionCombiningPass ( ) ) ;
m_fpm - > add ( new MemoryDependenceAnalysis ( ) ) ;
m_fpm - > add ( createDeadStoreEliminationPass ( ) ) ;
m_fpm - > add ( new LoopInfo ( ) ) ;
m_fpm - > add ( new ScalarEvolution ( ) ) ;
m_fpm - > add ( createSLPVectorizerPass ( ) ) ;
m_fpm - > add ( createInstructionCombiningPass ( ) ) ;
m_fpm - > add ( createCFGSimplificationPass ( ) ) ;
m_fpm - > doInitialization ( ) ;
2014-09-15 16:37:38 +02:00
if ( ! s_rotate_mask_inited ) {
InitRotateMask ( ) ;
s_rotate_mask_inited = true ;
}
2014-09-15 16:34:09 +02:00
}
2014-09-15 16:35:18 +02:00
PPULLVMRecompiler : : ~ PPULLVMRecompiler ( ) {
Stop ( ) ;
2014-09-15 16:34:09 +02:00
delete m_execution_engine ;
2014-09-15 16:36:29 +02:00
delete m_fpm ;
2014-09-15 16:34:09 +02:00
delete m_ir_builder ;
delete m_llvm_context ;
2014-09-15 16:16:53 +02:00
}
2014-09-22 22:22:20 +02:00
std : : pair < PPULLVMRecompiler : : Executable , u32 > PPULLVMRecompiler : : GetExecutable ( u32 address ) {
std : : lock_guard < std : : mutex > lock ( m_compiled_shared_lock ) ;
2014-09-18 13:29:49 +02:00
2014-09-22 22:22:20 +02:00
auto compiled = m_compiled_shared . lower_bound ( std : : make_pair ( address , 0 ) ) ;
if ( compiled ! = m_compiled_shared . end ( ) & & compiled - > first . first = = address ) {
compiled - > second . second + + ;
return std : : make_pair ( compiled - > second . first , compiled - > first . second ) ;
2014-09-15 16:35:18 +02:00
}
2014-09-22 22:22:20 +02:00
return std : : make_pair ( nullptr , 0 ) ;
2014-09-18 13:29:49 +02:00
}
2014-09-22 22:22:20 +02:00
void PPULLVMRecompiler : : ReleaseExecutable ( u32 address , u32 revision ) {
std : : lock_guard < std : : mutex > lock ( m_compiled_shared_lock ) ;
2014-09-18 13:29:49 +02:00
2014-09-22 22:22:20 +02:00
auto compiled = m_compiled_shared . find ( std : : make_pair ( address , revision ) ) ;
if ( compiled ! = m_compiled_shared . end ( ) ) {
compiled - > second . second - - ;
2014-09-18 13:29:49 +02:00
}
}
void PPULLVMRecompiler : : RequestCompilation ( u32 address ) {
2014-10-14 10:53:50 +02:00
{
std : : lock_guard < std : : mutex > lock ( m_uncompiled_shared_lock ) ;
m_uncompiled_shared . push_back ( address ) ;
}
2014-09-15 16:35:51 +02:00
if ( ! IsAlive ( ) ) {
Start ( ) ;
}
2014-09-15 16:35:18 +02:00
Notify ( ) ;
}
2014-09-22 22:22:20 +02:00
u32 PPULLVMRecompiler : : GetCurrentRevision ( ) {
2014-09-26 14:40:24 +02:00
return m_revision . load ( std : : memory_order_relaxed ) ;
2014-09-22 22:22:20 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : Task ( ) {
2014-09-22 22:22:20 +02:00
auto start = std : : chrono : : high_resolution_clock : : now ( ) ;
2014-09-15 16:35:51 +02:00
while ( ! TestDestroy ( ) & & ! Emu . IsStopped ( ) ) {
2014-09-22 22:22:20 +02:00
// Wait a few ms for something to happen
auto idling_start = std : : chrono : : high_resolution_clock : : now ( ) ;
WaitForAnySignal ( 250 ) ;
auto idling_end = std : : chrono : : high_resolution_clock : : now ( ) ;
m_idling_time + = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( idling_end - idling_start ) ;
2014-09-15 16:35:18 +02:00
2014-09-22 22:22:20 +02:00
// Update the set of blocks that have been hit with the set of blocks that have been requested for compilation.
{
std : : lock_guard < std : : mutex > lock ( m_uncompiled_shared_lock ) ;
for ( auto i = m_uncompiled_shared . begin ( ) ; i ! = m_uncompiled_shared . end ( ) ; i + + ) {
m_hit_blocks . insert ( * i ) ;
}
}
u32 num_compiled = 0 ;
2014-09-15 16:35:51 +02:00
while ( ! TestDestroy ( ) & & ! Emu . IsStopped ( ) ) {
2014-09-17 11:57:45 +02:00
u32 address ;
{
2014-09-22 22:22:20 +02:00
std : : lock_guard < std : : mutex > lock ( m_uncompiled_shared_lock ) ;
2014-09-17 11:57:45 +02:00
2014-09-22 22:22:20 +02:00
auto i = m_uncompiled_shared . begin ( ) ;
if ( i ! = m_uncompiled_shared . end ( ) ) {
2014-09-17 11:57:45 +02:00
address = * i ;
2014-09-22 22:22:20 +02:00
m_uncompiled_shared . erase ( i ) ;
2014-09-17 11:57:45 +02:00
} else {
break ;
}
2014-09-15 16:35:18 +02:00
}
2014-09-22 22:22:20 +02:00
m_hit_blocks . insert ( address ) ;
if ( NeedsCompiling ( address ) ) {
Compile ( address ) ;
num_compiled + + ;
}
2014-09-18 14:04:49 +02:00
}
2014-09-22 22:22:20 +02:00
if ( num_compiled = = 0 ) {
2014-09-18 14:04:49 +02:00
// If we get here, it means the recompilation thread is idling.
2014-09-22 22:22:20 +02:00
// We use this oppurtunity to optimize the code.
RemoveUnusedOldVersions ( ) ;
for ( auto i = m_compiled . begin ( ) ; i ! = m_compiled . end ( ) ; i + + ) {
if ( NeedsCompiling ( i - > first . first ) ) {
Compile ( i - > first . first ) ;
num_compiled + + ;
}
}
2014-09-15 16:35:18 +02:00
}
}
2014-09-15 16:34:09 +02:00
2014-09-15 16:35:51 +02:00
std : : chrono : : high_resolution_clock : : time_point end = std : : chrono : : high_resolution_clock : : now ( ) ;
2014-09-22 22:22:20 +02:00
m_total_time = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( end - start ) ;
2014-10-08 22:04:17 +02:00
std : : string error ;
raw_fd_ostream log_file ( " PPULLVMRecompiler.log " , error , sys : : fs : : F_Text ) ;
log_file < < " Total time = " < < m_total_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent compiling = " < < m_compilation_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent building IR = " < < m_ir_build_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent optimizing = " < < m_optimizing_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent translating = " < < m_translation_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent idling = " < < m_idling_time . count ( ) / 1000000 < < " ms \n " ;
log_file < < " Time spent doing misc tasks = " < < ( m_total_time . count ( ) - m_idling_time . count ( ) - m_compilation_time . count ( ) ) / 1000000 < < " ms \n " ;
log_file < < " Revision = " < < m_revision < < " \n " ;
log_file < < " \n Interpreter fallback stats: \n " ;
for ( auto i = m_interpreter_fallback_stats . begin ( ) ; i ! = m_interpreter_fallback_stats . end ( ) ; i + + ) {
log_file < < i - > first < < " = " < < i - > second < < " \n " ;
}
log_file < < " \n Disassembly: \n " ;
//auto disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
for ( auto i = m_compiled . begin ( ) ; i ! = m_compiled . end ( ) ; i + + ) {
log_file < < fmt : : Format ( " %s: Size = %u bytes, Number of instructions = %u \n " , i - > second . llvm_function - > getName ( ) . str ( ) . c_str ( ) , i - > second . size , i - > second . num_instructions ) ;
//uint8_t * fn_ptr = (uint8_t *)i->second.executable;
//for (size_t pc = 0; pc < i->second.size;) {
// char str[1024];
// auto size = LLVMDisasmInstruction(disassembler, fn_ptr + pc, i->second.size - pc, (uint64_t)(fn_ptr + pc), str, sizeof(str));
// log_file << str << '\n';
// pc += size;
//}
}
//LLVMDisasmDispose(disassembler);
//log_file << "\nLLVM IR:\n" << *m_module;
2014-09-22 22:22:20 +02:00
LOG_NOTICE ( PPU , " PPU LLVM compiler thread exiting. " ) ;
2014-09-15 16:35:51 +02:00
}
2014-09-09 23:30:53 +02:00
2014-09-15 16:35:51 +02:00
void PPULLVMRecompiler : : Decode ( const u32 code ) {
( * PPU_instr : : main_list ) ( this , code ) ;
2014-09-15 16:34:09 +02:00
}
2014-09-09 23:30:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : NULL_OP ( ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " NULL_OP " , & PPUInterpreter : : NULL_OP ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : NOP ( ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " NOP " , & PPUInterpreter : : NOP ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : TDI ( u32 to , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " TDI " , & PPUInterpreter : : TDI , to , ra , simm16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : TWI ( u32 to , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " TWI " , & PPUInterpreter : : TWI , to , ra , simm16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MFVSCR ( u32 vd ) {
2014-09-09 23:30:53 +02:00
auto vscr_i32 = GetVscr ( ) ;
2014-09-15 16:34:09 +02:00
auto vscr_i128 = m_ir_builder - > CreateZExt ( vscr_i32 , m_ir_builder - > getIntNTy ( 128 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , vscr_i128 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTVSCR ( u32 vb ) {
2014-09-15 16:19:43 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto vscr_i32 = m_ir_builder - > CreateExtractElement ( vb_v4i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
vscr_i32 = m_ir_builder - > CreateAnd ( vscr_i32 , 0x00010001 ) ;
2014-09-09 23:30:53 +02:00
SetVscr ( vscr_i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDCUW ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:16:53 +02:00
2014-10-18 22:27:54 +02:00
va_v4i32 = m_ir_builder - > CreateNot ( va_v4i32 ) ;
auto cmpv4i1 = m_ir_builder - > CreateICmpULT ( va_v4i32 , vb_v4i32 ) ;
auto cmpv4i32 = m_ir_builder - > CreateZExt ( cmpv4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , cmpv4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDFP ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
2014-09-15 16:34:09 +02:00
auto sum_v4f32 = m_ir_builder - > CreateFAdd ( va_v4f32 , vb_v4f32 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDSBS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_padds_b ) , va_v16i8 , vb_v16i8 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v16i8 ) ;
2014-09-15 16:16:53 +02:00
2014-09-15 16:19:43 +02:00
// TODO: Set VSCR.SAT
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDSHS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_padds_w ) , va_v8i16 , vb_v8i16 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v8i16 ) ;
2014-09-15 16:16:53 +02:00
2014-09-15 16:19:43 +02:00
// TODO: Set VSCR.SAT
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDSWS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:16:53 +02:00
2014-10-18 22:27:54 +02:00
// It looks like x86 does not have an instruction to add 32 bit intergers with signed/unsigned saturation.
2014-09-15 16:19:43 +02:00
// To implement add with saturation, we first determine what the result would be if the operation were to cause
// an overflow. If two -ve numbers are being added and cause an overflow, the result would be 0x80000000.
// If two +ve numbers are being added and cause an overflow, the result would be 0x7FFFFFFF. Addition of a -ve
// number and a +ve number cannot cause overflow. So the result in case of an overflow is 0x7FFFFFFF + sign bit
// of any one of the operands.
2014-10-19 21:46:35 +02:00
auto tmp1_v4i32 = m_ir_builder - > CreateLShr ( va_v4i32 , 31 ) ;
tmp1_v4i32 = m_ir_builder - > CreateAdd ( tmp1_v4i32 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 0x7FFFFFFF ) ) ) ;
auto tmp1_v16i8 = m_ir_builder - > CreateBitCast ( tmp1_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:16:53 +02:00
2014-09-15 16:19:43 +02:00
// Next, we find if the addition can actually result in an overflow. Since an overflow can only happen if the operands
2014-09-15 16:20:07 +02:00
// have the same sign, we bitwise XOR both the operands. If the sign bit of the result is 0 then the operands have the
// same sign and so may cause an overflow. We invert the result so that the sign bit is 1 when the operands have the
// same sign.
2014-10-19 21:46:35 +02:00
auto tmp2_v4i32 = m_ir_builder - > CreateXor ( va_v4i32 , vb_v4i32 ) ;
tmp2_v4i32 = m_ir_builder - > CreateNot ( tmp2_v4i32 ) ;
2014-09-15 16:16:53 +02:00
2014-09-15 16:19:43 +02:00
// Perform the sum.
2014-09-15 16:34:09 +02:00
auto sum_v4i32 = m_ir_builder - > CreateAdd ( va_v4i32 , vb_v4i32 ) ;
auto sum_v16i8 = m_ir_builder - > CreateBitCast ( sum_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:16:53 +02:00
2014-09-15 16:19:43 +02:00
// If an overflow occurs, then the sign of the sum will be different from the sign of the operands. So, we xor the
// result with one of the operands. The sign bit of the result will be 1 if the sign bit of the sum and the sign bit of the
2014-09-15 16:20:07 +02:00
// result is different. This result is again ANDed with tmp3 (the sign bit of tmp3 is 1 only if the operands have the same
2014-09-15 16:19:43 +02:00
// sign and so can cause an overflow).
2014-10-19 21:46:35 +02:00
auto tmp3_v4i32 = m_ir_builder - > CreateXor ( va_v4i32 , sum_v4i32 ) ;
tmp3_v4i32 = m_ir_builder - > CreateAnd ( tmp2_v4i32 , tmp3_v4i32 ) ;
tmp3_v4i32 = m_ir_builder - > CreateAShr ( tmp3_v4i32 , 31 ) ;
auto tmp3_v16i8 = m_ir_builder - > CreateBitCast ( tmp3_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:20:07 +02:00
// tmp4 is equal to 0xFFFFFFFF if an overflow occured and 0x00000000 otherwise.
2014-10-19 21:46:35 +02:00
auto res_v16i8 = m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pblendvb ) , sum_v16i8 , tmp1_v16i8 , tmp3_v16i8 ) ;
2014-09-15 16:20:07 +02:00
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
// TODO: Set SAT
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUBM ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v16i8 = m_ir_builder - > CreateAdd ( va_v16i8 , vb_v16i8 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUBS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_paddus_b ) , va_v16i8 , vb_v16i8 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v16i8 ) ;
2014-09-15 16:20:07 +02:00
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUHM ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v8i16 = m_ir_builder - > CreateAdd ( va_v8i16 , vb_v8i16 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v8i16 ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUHS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_paddus_w ) , va_v8i16 , vb_v8i16 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v8i16 ) ;
2014-09-15 16:20:07 +02:00
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUWM ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v4i32 = m_ir_builder - > CreateAdd ( va_v4i32 , vb_v4i32 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , sum_v4i32 ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VADDUWS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto sum_v4i32 = m_ir_builder - > CreateAdd ( va_v4i32 , vb_v4i32 ) ;
auto cmp_v4i1 = m_ir_builder - > CreateICmpULT ( sum_v4i32 , va_v4i32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto res_v4i32 = m_ir_builder - > CreateOr ( sum_v4i32 , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , res_v4i32 ) ;
// TODO: Set SAT
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAND ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:20:07 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto res_v4i32 = m_ir_builder - > CreateAnd ( va_v4i32 , vb_v4i32 ) ;
2014-09-15 16:20:07 +02:00
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VANDC ( u32 vd , u32 va , u32 vb ) {
2014-10-19 21:46:35 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
vb_v4i32 = m_ir_builder - > CreateNot ( vb_v4i32 ) ;
auto res_v4i32 = m_ir_builder - > CreateAnd ( va_v4i32 , vb_v4i32 ) ;
2014-09-15 16:20:07 +02:00
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGSB ( u32 vd , u32 va , u32 vb ) {
2014-10-19 21:46:35 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto va_v16i16 = m_ir_builder - > CreateSExt ( va_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto vb_v16i16 = m_ir_builder - > CreateSExt ( vb_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto sum_v16i16 = m_ir_builder - > CreateAdd ( va_v16i16 , vb_v16i16 ) ;
sum_v16i16 = m_ir_builder - > CreateAdd ( sum_v16i16 , m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt16 ( 1 ) ) ) ;
auto avg_v16i16 = m_ir_builder - > CreateAShr ( sum_v16i16 , 1 ) ;
auto avg_v16i8 = m_ir_builder - > CreateTrunc ( avg_v16i16 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGSH ( u32 vd , u32 va , u32 vb ) {
2014-10-19 21:46:35 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto va_v8i32 = m_ir_builder - > CreateSExt ( va_v8i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 8 ) ) ;
auto vb_v8i32 = m_ir_builder - > CreateSExt ( vb_v8i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 8 ) ) ;
auto sum_v8i32 = m_ir_builder - > CreateAdd ( va_v8i32 , vb_v8i32 ) ;
sum_v8i32 = m_ir_builder - > CreateAdd ( sum_v8i32 , m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt32 ( 1 ) ) ) ;
auto avg_v8i32 = m_ir_builder - > CreateAShr ( sum_v8i32 , 1 ) ;
auto avg_v8i16 = m_ir_builder - > CreateTrunc ( avg_v8i32 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 8 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGSW ( u32 vd , u32 va , u32 vb ) {
2014-10-19 21:46:35 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto va_v4i64 = m_ir_builder - > CreateSExt ( va_v4i32 , VectorType : : get ( m_ir_builder - > getInt64Ty ( ) , 4 ) ) ;
auto vb_v4i64 = m_ir_builder - > CreateSExt ( vb_v4i32 , VectorType : : get ( m_ir_builder - > getInt64Ty ( ) , 4 ) ) ;
auto sum_v4i64 = m_ir_builder - > CreateAdd ( va_v4i64 , vb_v4i64 ) ;
sum_v4i64 = m_ir_builder - > CreateAdd ( sum_v4i64 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt64 ( 1 ) ) ) ;
auto avg_v4i64 = m_ir_builder - > CreateAShr ( sum_v4i64 , 1 ) ;
auto avg_v4i32 = m_ir_builder - > CreateTrunc ( avg_v4i64 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v4i32 ) ;
}
2014-09-15 16:16:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGUB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto avg_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pavg_b ) , va_v16i8 , vb_v16i8 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGUH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:19:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto avg_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pavg_w ) , va_v8i16 , vb_v8i16 ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VAVGUW ( u32 vd , u32 va , u32 vb ) {
2014-10-19 21:46:35 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto va_v4i64 = m_ir_builder - > CreateZExt ( va_v4i32 , VectorType : : get ( m_ir_builder - > getInt64Ty ( ) , 4 ) ) ;
auto vb_v4i64 = m_ir_builder - > CreateZExt ( vb_v4i32 , VectorType : : get ( m_ir_builder - > getInt64Ty ( ) , 4 ) ) ;
auto sum_v4i64 = m_ir_builder - > CreateAdd ( va_v4i64 , vb_v4i64 ) ;
sum_v4i64 = m_ir_builder - > CreateAdd ( sum_v4i64 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt64 ( 1 ) ) ) ;
auto avg_v4i64 = m_ir_builder - > CreateLShr ( sum_v4i64 , 1 ) ;
auto avg_v4i32 = m_ir_builder - > CreateTrunc ( avg_v4i64 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:19:43 +02:00
SetVr ( vd , avg_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCFSX ( u32 vd , u32 uimm5 , u32 vb ) {
2014-09-02 11:41:32 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto res_v4f32 = m_ir_builder - > CreateSIToFP ( vb_v4i32 , VectorType : : get ( m_ir_builder - > getFloatTy ( ) , 4 ) ) ;
2014-09-15 16:16:53 +02:00
2014-09-02 11:41:32 +02:00
if ( uimm5 ) {
2014-10-19 21:46:35 +02:00
float scale = ( float ) ( ( u64 ) 1 < < uimm5 ) ;
res_v4f32 = m_ir_builder - > CreateFDiv ( res_v4f32 , m_ir_builder - > CreateVectorSplat ( 4 , ConstantFP : : get ( m_ir_builder - > getFloatTy ( ) , scale ) ) ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-02 11:41:32 +02:00
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCFUX ( u32 vd , u32 uimm5 , u32 vb ) {
2014-09-02 11:41:32 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto res_v4f32 = m_ir_builder - > CreateUIToFP ( vb_v4i32 , VectorType : : get ( m_ir_builder - > getFloatTy ( ) , 4 ) ) ;
2014-09-15 16:16:53 +02:00
2014-09-02 11:41:32 +02:00
if ( uimm5 ) {
2014-10-19 21:46:35 +02:00
float scale = ( float ) ( ( u64 ) 1 < < uimm5 ) ;
res_v4f32 = m_ir_builder - > CreateFDiv ( res_v4f32 , m_ir_builder - > CreateVectorSplat ( 4 , ConstantFP : : get ( m_ir_builder - > getFloatTy ( ) , scale ) ) ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-02 11:41:32 +02:00
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPBFP ( u32 vd , u32 va , u32 vb ) {
2014-09-02 11:41:32 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
2014-09-15 16:34:09 +02:00
auto cmp_gt_v4i1 = m_ir_builder - > CreateFCmpOGT ( va_v4f32 , vb_v4f32 ) ;
vb_v4f32 = m_ir_builder - > CreateFNeg ( vb_v4f32 ) ;
auto cmp_lt_v4i1 = m_ir_builder - > CreateFCmpOLT ( va_v4f32 , vb_v4f32 ) ;
auto cmp_gt_v4i32 = m_ir_builder - > CreateZExt ( cmp_gt_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto cmp_lt_v4i32 = m_ir_builder - > CreateZExt ( cmp_lt_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
cmp_gt_v4i32 = m_ir_builder - > CreateShl ( cmp_gt_v4i32 , 31 ) ;
cmp_lt_v4i32 = m_ir_builder - > CreateShl ( cmp_lt_v4i32 , 30 ) ;
auto res_v4i32 = m_ir_builder - > CreateOr ( cmp_gt_v4i32 , cmp_lt_v4i32 ) ;
2014-09-02 11:41:32 +02:00
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
2014-09-02 11:41:32 +02:00
// TODO: Implement NJ mode
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPBFP_ ( u32 vd , u32 va , u32 vb ) {
2014-09-02 11:41:32 +02:00
VCMPBFP ( vd , va , vb ) ;
2014-10-19 21:46:35 +02:00
auto vd_v16i8 = GetVrAsIntVec ( vd , 8 ) ;
u32 mask_v16i32 [ 16 ] = { 3 , 7 , 11 , 15 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
vd_v16i8 = m_ir_builder - > CreateShuffleVector ( vd_v16i8 , UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v16i32 ) ) ;
auto vd_v4i32 = m_ir_builder - > CreateBitCast ( vd_v16i8 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto vd_mask_i32 = m_ir_builder - > CreateExtractElement ( vd_v4i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
auto cmp_i1 = m_ir_builder - > CreateICmpEQ ( vd_mask_i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
2014-09-15 16:27:05 +02:00
SetCrField ( 6 , nullptr , nullptr , cmp_i1 , nullptr ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQFP ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
2014-09-15 16:33:06 +02:00
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateFCmpOEQ ( va_v4f32 , vb_v4f32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQFP_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
VCMPEQFP ( vd , va , vb ) ;
2014-09-15 16:26:55 +02:00
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v16i1 = m_ir_builder - > CreateICmpEQ ( va_v16i8 , vb_v16i8 ) ;
auto cmp_v16i8 = m_ir_builder - > CreateSExt ( cmp_v16i1 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:26:55 +02:00
SetVr ( vd , cmp_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUB_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPEQUB ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v8i1 = m_ir_builder - > CreateICmpEQ ( va_v8i16 , vb_v8i16 ) ;
auto cmp_v8i16 = m_ir_builder - > CreateSExt ( cmp_v8i1 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 8 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUH_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPEQUH ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUW ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateICmpEQ ( va_v4i32 , vb_v4i32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPEQUW_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPEQUW ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGEFP ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateFCmpOGE ( va_v4f32 , vb_v4f32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGEFP_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGEFP ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTFP ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateFCmpOGT ( va_v4f32 , vb_v4f32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTFP_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTFP ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v16i1 = m_ir_builder - > CreateICmpSGT ( va_v16i8 , vb_v16i8 ) ;
auto cmp_v16i8 = m_ir_builder - > CreateSExt ( cmp_v16i1 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:26:55 +02:00
SetVr ( vd , cmp_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSB_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTSB ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v8i1 = m_ir_builder - > CreateICmpSGT ( va_v8i16 , vb_v8i16 ) ;
auto cmp_v8i16 = m_ir_builder - > CreateSExt ( cmp_v8i1 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 8 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSH_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTSH ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSW ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateICmpSGT ( va_v4i32 , vb_v4i32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTSW_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTSW ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v16i1 = m_ir_builder - > CreateICmpUGT ( va_v16i8 , vb_v16i8 ) ;
auto cmp_v16i8 = m_ir_builder - > CreateSExt ( cmp_v16i1 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-09-15 16:26:55 +02:00
SetVr ( vd , cmp_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUB_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTUB ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v8i1 = m_ir_builder - > CreateICmpUGT ( va_v8i16 , vb_v8i16 ) ;
auto cmp_v8i16 = m_ir_builder - > CreateSExt ( cmp_v8i1 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 8 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUH_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTUH ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUW ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:15 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
2014-09-15 16:26:55 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
2014-09-15 16:34:09 +02:00
auto cmp_v4i1 = m_ir_builder - > CreateICmpUGT ( va_v4i32 , vb_v4i32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
2014-09-15 16:26:15 +02:00
SetVr ( vd , cmp_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCMPGTUW_ ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:26:55 +02:00
VCMPGTUW ( vd , va , vb ) ;
SetCr6AfterVectorCompare ( vd ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCTSXS ( u32 vd , u32 uimm5 , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VCTSXS " , & PPUInterpreter : : VCTSXS , vd , uimm5 , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:15 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VCTUXS ( u32 vd , u32 uimm5 , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VCTUXS " , & PPUInterpreter : : VCTUXS , vd , uimm5 , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VEXPTEFP ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VEXPTEFP " , & PPUInterpreter : : VEXPTEFP , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VLOGEFP ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VLOGEFP " , & PPUInterpreter : : VLOGEFP , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMADDFP ( u32 vd , u32 va , u32 vc , u32 vb ) {
2014-10-12 20:24:43 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto vc_v4f32 = GetVrAsFloatVec ( vc ) ;
2014-10-19 21:46:35 +02:00
auto res_v4f32 = m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , VectorType : : get ( m_ir_builder - > getFloatTy ( ) , 4 ) ) , va_v4f32 , vc_v4f32 , vb_v4f32 ) ;
2014-10-12 20:24:43 +02:00
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXFP ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto res_v4f32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse_max_ps ) , va_v4f32 , vb_v4f32 ) ;
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXSB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto res_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pmaxsb ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXSH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pmaxs_w ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXSW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pmaxsd ) , va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXUB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto res_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pmaxu_b ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXUH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pmaxuw ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMAXUW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pmaxud ) , va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMHADDSHS ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMHADDSHS " , & PPUInterpreter : : VMHADDSHS , vd , va , vb , vc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMHRADDSHS ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMHRADDSHS " , & PPUInterpreter : : VMHRADDSHS , vd , va , vb , vc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINFP ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto res_v4f32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse_min_ps ) , va_v4f32 , vb_v4f32 ) ;
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINSB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto res_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pminsb ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINSH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pmins_w ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINSW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pminsd ) , va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINUB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto res_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pminu_b ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINUH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pminuw ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMINUW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pminud ) , va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMLADDUHM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMLADDUHM " , & PPUInterpreter : : VMLADDUHM , vd , va , vb , vc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGHB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
u32 mask_v16i32 [ 16 ] = { 24 , 8 , 25 , 9 , 26 , 10 , 27 , 11 , 28 , 12 , 29 , 13 , 30 , 14 , 31 , 15 } ;
auto vd_v16i8 = m_ir_builder - > CreateShuffleVector ( va_v16i8 , vb_v16i8 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v16i32 ) ) ;
SetVr ( vd , vd_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGHH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
u32 mask_v8i32 [ 8 ] = { 12 , 4 , 13 , 5 , 14 , 6 , 15 , 7 } ;
auto vd_v8i16 = m_ir_builder - > CreateShuffleVector ( va_v8i16 , vb_v8i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v8i32 ) ) ;
SetVr ( vd , vd_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGHW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
u32 mask_v4i32 [ 4 ] = { 6 , 2 , 7 , 3 } ;
auto vd_v4i32 = m_ir_builder - > CreateShuffleVector ( va_v4i32 , vb_v4i32 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v4i32 ) ) ;
SetVr ( vd , vd_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGLB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
u32 mask_v16i32 [ 16 ] = { 16 , 0 , 17 , 1 , 18 , 2 , 19 , 3 , 20 , 4 , 21 , 5 , 22 , 6 , 23 , 7 } ;
auto vd_v16i8 = m_ir_builder - > CreateShuffleVector ( va_v16i8 , vb_v16i8 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v16i32 ) ) ;
SetVr ( vd , vd_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGLH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
u32 mask_v8i32 [ 8 ] = { 8 , 0 , 9 , 1 , 10 , 2 , 11 , 3 } ;
auto vd_v8i16 = m_ir_builder - > CreateShuffleVector ( va_v8i16 , vb_v8i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v8i32 ) ) ;
SetVr ( vd , vd_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMRGLW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
u32 mask_v4i32 [ 4 ] = { 4 , 0 , 5 , 1 } ;
auto vd_v4i32 = m_ir_builder - > CreateShuffleVector ( va_v4i32 , vb_v4i32 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v4i32 ) ) ;
SetVr ( vd , vd_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMMBM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto va_v16i16 = m_ir_builder - > CreateSExt ( va_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto vb_v16i16 = m_ir_builder - > CreateZExt ( vb_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto tmp_v16i16 = m_ir_builder - > CreateMul ( va_v16i16 , vb_v16i16 ) ;
auto undef_v16i16 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
u32 mask1_v4i32 [ 4 ] = { 0 , 4 , 8 , 12 } ;
auto tmp1_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask1_v4i32 ) ) ;
auto tmp1_v4i32 = m_ir_builder - > CreateSExt ( tmp1_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask2_v4i32 [ 4 ] = { 1 , 5 , 9 , 13 } ;
auto tmp2_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask2_v4i32 ) ) ;
auto tmp2_v4i32 = m_ir_builder - > CreateSExt ( tmp2_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask3_v4i32 [ 4 ] = { 2 , 6 , 10 , 14 } ;
auto tmp3_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask3_v4i32 ) ) ;
auto tmp3_v4i32 = m_ir_builder - > CreateSExt ( tmp3_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask4_v4i32 [ 4 ] = { 3 , 7 , 11 , 15 } ;
auto tmp4_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask4_v4i32 ) ) ;
auto tmp4_v4i32 = m_ir_builder - > CreateSExt ( tmp4_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto vc_v4i32 = GetVrAsIntVec ( vc , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateAdd ( tmp1_v4i32 , tmp2_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , tmp3_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , tmp4_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , vc_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
// TODO: Try to optimize with horizontal add
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMSHM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto vc_v4i32 = GetVrAsIntVec ( vc , 32 ) ;
2014-10-19 21:46:35 +02:00
auto res_v4i32 = ( Value * ) m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pmadd_wd ) , va_v8i16 , vb_v8i16 ) ;
2014-10-18 22:27:54 +02:00
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , vc_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMSHS ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMSUMSHS " , & PPUInterpreter : : VMSUMSHS , vd , va , vb , vc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:16:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMUBM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto va_v16i16 = m_ir_builder - > CreateZExt ( va_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto vb_v16i16 = m_ir_builder - > CreateZExt ( vb_v16i8 , VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
auto tmp_v16i16 = m_ir_builder - > CreateMul ( va_v16i16 , vb_v16i16 ) ;
auto undef_v16i16 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 16 ) ) ;
u32 mask1_v4i32 [ 4 ] = { 0 , 4 , 8 , 12 } ;
auto tmp1_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask1_v4i32 ) ) ;
auto tmp1_v4i32 = m_ir_builder - > CreateZExt ( tmp1_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask2_v4i32 [ 4 ] = { 1 , 5 , 9 , 13 } ;
auto tmp2_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask2_v4i32 ) ) ;
auto tmp2_v4i32 = m_ir_builder - > CreateZExt ( tmp2_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask3_v4i32 [ 4 ] = { 2 , 6 , 10 , 14 } ;
auto tmp3_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask3_v4i32 ) ) ;
auto tmp3_v4i32 = m_ir_builder - > CreateZExt ( tmp3_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
u32 mask4_v4i32 [ 4 ] = { 3 , 7 , 11 , 15 } ;
auto tmp4_v4i16 = m_ir_builder - > CreateShuffleVector ( tmp_v16i16 , undef_v16i16 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask4_v4i32 ) ) ;
auto tmp4_v4i32 = m_ir_builder - > CreateZExt ( tmp4_v4i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto vc_v4i32 = GetVrAsIntVec ( vc , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateAdd ( tmp1_v4i32 , tmp2_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , tmp3_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , tmp4_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , vc_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
// TODO: Try to optimize with horizontal add
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMUHM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto va_v8i32 = m_ir_builder - > CreateZExt ( va_v8i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 8 ) ) ;
auto vb_v8i32 = m_ir_builder - > CreateZExt ( vb_v8i16 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 8 ) ) ;
auto tmp_v8i32 = m_ir_builder - > CreateMul ( va_v8i32 , vb_v8i32 ) ;
auto undef_v8i32 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 8 ) ) ;
u32 mask1_v4i32 [ 4 ] = { 0 , 2 , 4 , 6 } ;
auto tmp1_v4i32 = m_ir_builder - > CreateShuffleVector ( tmp_v8i32 , undef_v8i32 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask1_v4i32 ) ) ;
u32 mask2_v4i32 [ 4 ] = { 1 , 3 , 5 , 7 } ;
auto tmp2_v4i32 = m_ir_builder - > CreateShuffleVector ( tmp_v8i32 , undef_v8i32 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask2_v4i32 ) ) ;
auto vc_v4i32 = GetVrAsIntVec ( vc , 32 ) ;
auto res_v4i32 = m_ir_builder - > CreateAdd ( tmp1_v4i32 , tmp2_v4i32 ) ;
res_v4i32 = m_ir_builder - > CreateAdd ( res_v4i32 , vc_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
// TODO: Try to optimize with horizontal add
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMSUMUHS ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMSUMUHS " , & PPUInterpreter : : VMSUMUHS , vd , va , vb , vc ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULESB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULESB " , & PPUInterpreter : : VMULESB , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULESH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULESH " , & PPUInterpreter : : VMULESH , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULEUB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULEUB " , & PPUInterpreter : : VMULEUB , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULEUH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULEUH " , & PPUInterpreter : : VMULEUH , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULOSB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULOSB " , & PPUInterpreter : : VMULOSB , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULOSH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULOSH " , & PPUInterpreter : : VMULOSH , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULOUB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULOUB " , & PPUInterpreter : : VMULOUB , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VMULOUH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VMULOUH " , & PPUInterpreter : : VMULOUH , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VNMSUBFP ( u32 vd , u32 va , u32 vc , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto vc_v4f32 = GetVrAsFloatVec ( vc ) ;
2014-10-19 21:46:35 +02:00
vc_v4f32 = m_ir_builder - > CreateFNeg ( vc_v4f32 ) ;
auto res_v4f32 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , VectorType : : get ( m_ir_builder - > getFloatTy ( ) , 4 ) ) , va_v4f32 , vc_v4f32 , vb_v4f32 ) ;
2014-10-18 22:27:54 +02:00
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VNOR ( u32 vd , u32 va , u32 vb ) {
2014-10-12 20:24:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateOr ( va_v8i16 , vb_v8i16 ) ;
res_v8i16 = m_ir_builder - > CreateNot ( res_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VOR ( u32 vd , u32 va , u32 vb ) {
2014-10-12 20:24:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateOr ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPERM ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-12 20:24:43 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto vc_v16i8 = GetVrAsIntVec ( vc , 8 ) ;
2014-10-19 21:46:35 +02:00
auto thrity_one_v16i8 = m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( 31 ) ) ;
vc_v16i8 = m_ir_builder - > CreateAnd ( vc_v16i8 , thrity_one_v16i8 ) ;
2014-10-12 20:24:43 +02:00
2014-10-19 21:46:35 +02:00
auto fifteen_v16i8 = m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( 15 ) ) ;
auto vc_le15_v16i8 = m_ir_builder - > CreateSub ( fifteen_v16i8 , vc_v16i8 ) ;
auto res_va_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_ssse3_pshuf_b_128 ) , va_v16i8 , vc_le15_v16i8 ) ;
2014-10-12 20:24:43 +02:00
2014-10-19 21:46:35 +02:00
auto vc_gt15_v16i8 = m_ir_builder - > CreateSub ( thrity_one_v16i8 , vc_v16i8 ) ;
auto cmp_i1 = m_ir_builder - > CreateICmpUGT ( vc_gt15_v16i8 , fifteen_v16i8 ) ;
2014-10-12 20:24:43 +02:00
auto cmp_i8 = m_ir_builder - > CreateSExt ( cmp_i1 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
vc_gt15_v16i8 = m_ir_builder - > CreateOr ( cmp_i8 , vc_gt15_v16i8 ) ;
auto res_vb_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_ssse3_pshuf_b_128 ) , vb_v16i8 , vc_gt15_v16i8 ) ;
auto res_v16i8 = m_ir_builder - > CreateOr ( res_vb_v16i8 , res_va_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKPX ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKPX " , & PPUInterpreter : : VPKPX , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKSHSS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKSHSS " , & PPUInterpreter : : VPKSHSS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKSHUS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKSHUS " , & PPUInterpreter : : VPKSHUS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKSWSS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKSWSS " , & PPUInterpreter : : VPKSWSS , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKSWUS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKSWUS " , & PPUInterpreter : : VPKSWUS , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKUHUM ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKUHUM " , & PPUInterpreter : : VPKUHUM , vd , va , vb ) ;
2014-09-15 16:28:38 +02:00
}
2014-09-15 16:16:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKUHUS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKUHUS " , & PPUInterpreter : : VPKUHUS , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKUWUM ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKUWUM " , & PPUInterpreter : : VPKUWUM , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VPKUWUS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VPKUWUS " , & PPUInterpreter : : VPKUWUS , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VREFP ( u32 vd , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto res_v4f32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse_rcp_ps ) , vb_v4f32 ) ;
SetVr ( vd , res_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRFIM ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRFIM " , & PPUInterpreter : : VRFIM , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRFIN ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRFIN " , & PPUInterpreter : : VRFIN , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRFIP ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRFIP " , & PPUInterpreter : : VRFIP , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRFIZ ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRFIZ " , & PPUInterpreter : : VRFIZ , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRLB ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRLB " , & PPUInterpreter : : VRLB , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRLH ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRLH " , & PPUInterpreter : : VRLH , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRLW ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRLW " , & PPUInterpreter : : VRLW , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VRSQRTEFP ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VRSQRTEFP " , & PPUInterpreter : : VRSQRTEFP , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSEL ( u32 vd , u32 va , u32 vb , u32 vc ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto vc_v4i32 = GetVrAsIntVec ( vc , 32 ) ;
vb_v4i32 = m_ir_builder - > CreateAnd ( vb_v4i32 , vc_v4i32 ) ;
vc_v4i32 = m_ir_builder - > CreateNot ( vc_v4i32 ) ;
va_v4i32 = m_ir_builder - > CreateAnd ( va_v4i32 , vc_v4i32 ) ;
auto vd_v4i32 = m_ir_builder - > CreateOr ( va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , vd_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSL ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_i128 = GetVr ( va ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto sh_i8 = m_ir_builder - > CreateExtractElement ( vb_v16i8 , m_ir_builder - > getInt8 ( 0 ) ) ;
sh_i8 = m_ir_builder - > CreateAnd ( sh_i8 , 0x7 ) ;
auto sh_i128 = m_ir_builder - > CreateZExt ( sh_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
va_i128 = m_ir_builder - > CreateShl ( va_i128 , sh_i128 ) ;
SetVr ( vd , va_i128 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSLB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
vb_v16i8 = m_ir_builder - > CreateAnd ( vb_v16i8 , m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( 0x7 ) ) ) ;
auto res_v16i8 = m_ir_builder - > CreateShl ( va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:16:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSLDOI ( u32 vd , u32 va , u32 vb , u32 sh ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
sh = 16 - sh ;
u32 mask_v16i32 [ 16 ] = { sh , sh + 1 , sh + 2 , sh + 3 , sh + 4 , sh + 5 , sh + 6 , sh + 7 , sh + 8 , sh + 9 , sh + 10 , sh + 11 , sh + 12 , sh + 13 , sh + 14 , sh + 15 } ;
auto vd_v16i8 = m_ir_builder - > CreateShuffleVector ( vb_v16i8 , va_v16i8 , ConstantDataVector : : get ( m_ir_builder - > getContext ( ) , mask_v16i32 ) ) ;
SetVr ( vd , vd_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSLH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
vb_v8i16 = m_ir_builder - > CreateAnd ( vb_v8i16 , m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt16 ( 0xF ) ) ) ;
auto res_v8i16 = m_ir_builder - > CreateShl ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSLO ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_i128 = GetVr ( va ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto sh_i8 = m_ir_builder - > CreateExtractElement ( vb_v16i8 , m_ir_builder - > getInt8 ( 0 ) ) ;
sh_i8 = m_ir_builder - > CreateAnd ( sh_i8 , 0x78 ) ;
auto sh_i128 = m_ir_builder - > CreateZExt ( sh_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
va_i128 = m_ir_builder - > CreateShl ( va_i128 , sh_i128 ) ;
SetVr ( vd , va_i128 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSLW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
vb_v4i32 = m_ir_builder - > CreateAnd ( vb_v4i32 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 0x1F ) ) ) ;
auto res_v4i32 = m_ir_builder - > CreateShl ( va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTB ( u32 vd , u32 uimm5 , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto undef_v16i8 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
auto mask_v16i32 = m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt32 ( 15 - uimm5 ) ) ;
auto res_v16i8 = m_ir_builder - > CreateShuffleVector ( vb_v16i8 , undef_v16i8 , mask_v16i32 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTH ( u32 vd , u32 uimm5 , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto undef_v8i16 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt16Ty ( ) , 8 ) ) ;
auto mask_v8i32 = m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt32 ( 7 - uimm5 ) ) ;
auto res_v8i16 = m_ir_builder - > CreateShuffleVector ( vb_v8i16 , undef_v8i16 , mask_v8i32 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTISB ( u32 vd , s32 simm5 ) {
2014-10-18 22:27:54 +02:00
auto vd_v16i8 = m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( ( s8 ) simm5 ) ) ;
SetVr ( vd , vd_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTISH ( u32 vd , s32 simm5 ) {
2014-10-18 22:27:54 +02:00
auto vd_v8i16 = m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt16 ( ( s16 ) simm5 ) ) ;
SetVr ( vd , vd_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTISW ( u32 vd , s32 simm5 ) {
2014-10-18 22:27:54 +02:00
auto vd_v4i32 = m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( ( s32 ) simm5 ) ) ;
SetVr ( vd , vd_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSPLTW ( u32 vd , u32 uimm5 , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto undef_v4i32 = UndefValue : : get ( VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto mask_v4i32 = m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 3 - uimm5 ) ) ;
auto res_v4i32 = m_ir_builder - > CreateShuffleVector ( vb_v4i32 , undef_v4i32 , mask_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSR ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_i128 = GetVr ( va ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto sh_i8 = m_ir_builder - > CreateExtractElement ( vb_v16i8 , m_ir_builder - > getInt8 ( 0 ) ) ;
sh_i8 = m_ir_builder - > CreateAnd ( sh_i8 , 0x7 ) ;
auto sh_i128 = m_ir_builder - > CreateZExt ( sh_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
va_i128 = m_ir_builder - > CreateLShr ( va_i128 , sh_i128 ) ;
SetVr ( vd , va_i128 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRAB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
vb_v16i8 = m_ir_builder - > CreateAnd ( vb_v16i8 , m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( 0x7 ) ) ) ;
auto res_v16i8 = m_ir_builder - > CreateAShr ( va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRAH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
vb_v8i16 = m_ir_builder - > CreateAnd ( vb_v8i16 , m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt16 ( 0xF ) ) ) ;
auto res_v8i16 = m_ir_builder - > CreateAShr ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRAW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
vb_v4i32 = m_ir_builder - > CreateAnd ( vb_v4i32 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 0x1F ) ) ) ;
auto res_v4i32 = m_ir_builder - > CreateAShr ( va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRB ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
vb_v16i8 = m_ir_builder - > CreateAnd ( vb_v16i8 , m_ir_builder - > CreateVectorSplat ( 16 , m_ir_builder - > getInt8 ( 0x7 ) ) ) ;
auto res_v16i8 = m_ir_builder - > CreateLShr ( va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , res_v16i8 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRH ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
vb_v8i16 = m_ir_builder - > CreateAnd ( vb_v8i16 , m_ir_builder - > CreateVectorSplat ( 8 , m_ir_builder - > getInt16 ( 0xF ) ) ) ;
auto res_v8i16 = m_ir_builder - > CreateLShr ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRO ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_i128 = GetVr ( va ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto sh_i8 = m_ir_builder - > CreateExtractElement ( vb_v16i8 , m_ir_builder - > getInt8 ( 0 ) ) ;
sh_i8 = m_ir_builder - > CreateAnd ( sh_i8 , 0x78 ) ;
auto sh_i128 = m_ir_builder - > CreateZExt ( sh_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
va_i128 = m_ir_builder - > CreateLShr ( va_i128 , sh_i128 ) ;
SetVr ( vd , va_i128 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSRW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
vb_v4i32 = m_ir_builder - > CreateAnd ( vb_v4i32 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 0x1F ) ) ) ;
auto res_v4i32 = m_ir_builder - > CreateLShr ( va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBCUW ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto cmpv4i1 = m_ir_builder - > CreateICmpUGE ( va_v4i32 , vb_v4i32 ) ;
auto cmpv4i32 = m_ir_builder - > CreateZExt ( cmpv4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
SetVr ( vd , cmpv4i32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBFP ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4f32 = GetVrAsFloatVec ( va ) ;
auto vb_v4f32 = GetVrAsFloatVec ( vb ) ;
auto diff_v4f32 = m_ir_builder - > CreateFSub ( va_v4f32 , vb_v4f32 ) ;
SetVr ( vd , diff_v4f32 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBSBS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto diff_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_psubs_b ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , diff_v16i8 ) ;
// TODO: Set VSCR.SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBSHS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto diff_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_psubs_w ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , diff_v8i16 ) ;
// TODO: Set VSCR.SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBSWS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
// See the comments for VADDSWS for a detailed description of how this works
// Find the result in case of an overflow
2014-10-19 21:46:35 +02:00
auto tmp1_v4i32 = m_ir_builder - > CreateLShr ( va_v4i32 , 31 ) ;
tmp1_v4i32 = m_ir_builder - > CreateAdd ( tmp1_v4i32 , m_ir_builder - > CreateVectorSplat ( 4 , m_ir_builder - > getInt32 ( 0x7FFFFFFF ) ) ) ;
auto tmp1_v16i8 = m_ir_builder - > CreateBitCast ( tmp1_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-10-18 22:27:54 +02:00
// Find the elements that can overflow (elements with opposite sign bits)
2014-10-19 21:46:35 +02:00
auto tmp2_v4i32 = m_ir_builder - > CreateXor ( va_v4i32 , vb_v4i32 ) ;
2014-10-18 22:27:54 +02:00
// Perform the sub
auto diff_v4i32 = m_ir_builder - > CreateSub ( va_v4i32 , vb_v4i32 ) ;
auto diff_v16i8 = m_ir_builder - > CreateBitCast ( diff_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
// Find the elements that overflowed
2014-10-19 21:46:35 +02:00
auto tmp3_v4i32 = m_ir_builder - > CreateXor ( va_v4i32 , diff_v4i32 ) ;
tmp3_v4i32 = m_ir_builder - > CreateAnd ( tmp2_v4i32 , tmp3_v4i32 ) ;
tmp3_v4i32 = m_ir_builder - > CreateAShr ( tmp3_v4i32 , 31 ) ;
auto tmp3_v16i8 = m_ir_builder - > CreateBitCast ( tmp3_v4i32 , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) ) ;
2014-10-18 22:27:54 +02:00
// tmp4 is equal to 0xFFFFFFFF if an overflow occured and 0x00000000 otherwise.
2014-10-19 21:46:35 +02:00
auto res_v16i8 = m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse41_pblendvb ) , diff_v16i8 , tmp1_v16i8 , tmp3_v16i8 ) ;
2014-10-18 22:27:54 +02:00
SetVr ( vd , res_v16i8 ) ;
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUBM ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto diff_v16i8 = m_ir_builder - > CreateSub ( va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , diff_v16i8 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUBS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v16i8 = GetVrAsIntVec ( va , 8 ) ;
auto vb_v16i8 = GetVrAsIntVec ( vb , 8 ) ;
auto diff_v16i8 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_psubus_b ) , va_v16i8 , vb_v16i8 ) ;
SetVr ( vd , diff_v16i8 ) ;
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUHM ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto diff_v8i16 = m_ir_builder - > CreateSub ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , diff_v8i16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUHS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto diff_v8i16 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_psubus_w ) , va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , diff_v8i16 ) ;
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUWM ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto diff_v4i32 = m_ir_builder - > CreateSub ( va_v4i32 , vb_v4i32 ) ;
SetVr ( vd , diff_v4i32 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUBUWS ( u32 vd , u32 va , u32 vb ) {
2014-10-18 22:27:54 +02:00
auto va_v4i32 = GetVrAsIntVec ( va , 32 ) ;
auto vb_v4i32 = GetVrAsIntVec ( vb , 32 ) ;
auto diff_v4i32 = m_ir_builder - > CreateSub ( va_v4i32 , vb_v4i32 ) ;
auto cmp_v4i1 = m_ir_builder - > CreateICmpULE ( diff_v4i32 , va_v4i32 ) ;
auto cmp_v4i32 = m_ir_builder - > CreateSExt ( cmp_v4i1 , VectorType : : get ( m_ir_builder - > getInt32Ty ( ) , 4 ) ) ;
auto res_v4i32 = m_ir_builder - > CreateAnd ( diff_v4i32 , cmp_v4i32 ) ;
SetVr ( vd , res_v4i32 ) ;
// TODO: Set SAT
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUMSWS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VSUMSWS " , & PPUInterpreter : : VSUMSWS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUM2SWS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VSUM2SWS " , & PPUInterpreter : : VSUM2SWS , vd , va , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUM4SBS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VSUM4SBS " , & PPUInterpreter : : VSUM4SBS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUM4SHS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VSUM4SHS " , & PPUInterpreter : : VSUM4SHS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VSUM4UBS ( u32 vd , u32 va , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VSUM4UBS " , & PPUInterpreter : : VSUM4UBS , vd , va , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKHPX ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKHPX " , & PPUInterpreter : : VUPKHPX , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKHSB ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKHSB " , & PPUInterpreter : : VUPKHSB , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKHSH ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKHSH " , & PPUInterpreter : : VUPKHSH , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKLPX ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKLPX " , & PPUInterpreter : : VUPKLPX , vd , vb ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKLSB ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKLSB " , & PPUInterpreter : : VUPKLSB , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VUPKLSH ( u32 vd , u32 vb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " VUPKLSH " , & PPUInterpreter : : VUPKLSH , vd , vb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : VXOR ( u32 vd , u32 va , u32 vb ) {
2014-10-12 20:24:43 +02:00
auto va_v8i16 = GetVrAsIntVec ( va , 16 ) ;
auto vb_v8i16 = GetVrAsIntVec ( vb , 16 ) ;
auto res_v8i16 = m_ir_builder - > CreateXor ( va_v8i16 , vb_v8i16 ) ;
SetVr ( vd , res_v8i16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULLI ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto res_i64 = m_ir_builder - > CreateMul ( ra_i64 , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) ) ;
SetGpr ( rd , res_i64 ) ;
//InterpreterCall("MULLI", &PPUInterpreter::MULLI, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBFIC ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
auto ra_i64 = GetGpr ( ra ) ;
2014-10-18 22:27:54 +02:00
ra_i64 = m_ir_builder - > CreateNeg ( ra_i64 ) ;
2014-10-19 21:46:35 +02:00
auto res_s = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : uadd_with_overflow , m_ir_builder - > getInt64Ty ( ) ) , ra_i64 , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) ) ;
2014-09-15 16:34:09 +02:00
auto diff_i64 = m_ir_builder - > CreateExtractValue ( res_s , { 0 } ) ;
auto carry_i1 = m_ir_builder - > CreateExtractValue ( res_s , { 1 } ) ;
SetGpr ( rd , diff_i64 ) ;
SetXerCa ( carry_i1 ) ;
//InterpreterCall("SUBFIC", &PPUInterpreter::SUBFIC, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CMPLI ( u32 crfd , u32 l , u32 ra , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
Value * ra_i64 ;
if ( l = = 0 ) {
ra_i64 = m_ir_builder - > CreateZExt ( GetGpr ( ra , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
} else {
ra_i64 = GetGpr ( ra ) ;
}
2014-09-15 16:26:55 +02:00
2014-09-15 16:34:09 +02:00
SetCrFieldUnsignedCmp ( crfd , ra_i64 , m_ir_builder - > getInt64 ( uimm16 ) ) ;
//InterpreterCall("CMPLI", &PPUInterpreter::CMPLI, crfd, l, ra, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CMPI ( u32 crfd , u32 l , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
Value * ra_i64 ;
if ( l = = 0 ) {
ra_i64 = m_ir_builder - > CreateSExt ( GetGpr ( ra , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
} else {
ra_i64 = GetGpr ( ra ) ;
}
2014-09-15 16:26:55 +02:00
2014-09-15 16:34:09 +02:00
SetCrFieldSignedCmp ( crfd , ra_i64 , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) ) ;
//InterpreterCall("CMPI", &PPUInterpreter::CMPI, crfd, l, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDIC ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
auto ra_i64 = GetGpr ( ra ) ;
2014-10-19 21:46:35 +02:00
auto res_s = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : uadd_with_overflow , m_ir_builder - > getInt64Ty ( ) ) , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) , ra_i64 ) ;
2014-09-15 16:34:09 +02:00
auto sum_i64 = m_ir_builder - > CreateExtractValue ( res_s , { 0 } ) ;
auto carry_i1 = m_ir_builder - > CreateExtractValue ( res_s , { 1 } ) ;
SetGpr ( rd , sum_i64 ) ;
SetXerCa ( carry_i1 ) ;
//InterpreterCall("ADDIC", &PPUInterpreter::ADDIC, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDIC_ ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
ADDIC ( rd , ra , simm16 ) ;
SetCrFieldSignedCmp ( 0 , GetGpr ( rd ) , m_ir_builder - > getInt64 ( 0 ) ) ;
//InterpreterCall("ADDIC_", &PPUInterpreter::ADDIC_, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDI ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:33:06 +02:00
if ( ra = = 0 ) {
2014-09-15 16:34:09 +02:00
SetGpr ( rd , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) ) ;
2014-09-15 16:33:06 +02:00
} else {
auto ra_i64 = GetGpr ( ra ) ;
2014-09-15 16:34:09 +02:00
auto sum_i64 = m_ir_builder - > CreateAdd ( ra_i64 , m_ir_builder - > getInt64 ( ( s64 ) simm16 ) ) ;
2014-09-15 16:33:06 +02:00
SetGpr ( rd , sum_i64 ) ;
}
2014-09-15 16:34:09 +02:00
//InterpreterCall("ADDI", &PPUInterpreter::ADDI, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDIS ( u32 rd , u32 ra , s32 simm16 ) {
2014-09-15 16:34:09 +02:00
if ( ra = = 0 ) {
SetGpr ( rd , m_ir_builder - > getInt64 ( ( s64 ) simm16 < < 16 ) ) ;
} else {
auto ra_i64 = GetGpr ( ra ) ;
auto sum_i64 = m_ir_builder - > CreateAdd ( ra_i64 , m_ir_builder - > getInt64 ( ( s64 ) simm16 < < 16 ) ) ;
SetGpr ( rd , sum_i64 ) ;
}
//InterpreterCall("ADDIS", &PPUInterpreter::ADDIS, rd, ra, simm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : BC ( u32 bo , u32 bi , s32 bd , u32 aa , u32 lk ) {
2014-09-22 22:22:20 +02:00
auto target_i64 = m_ir_builder - > getInt64 ( branchTarget ( aa ? 0 : m_current_instruction_address , bd ) ) ;
CreateBranch ( CheckBranchCondition ( bo , bi ) , target_i64 , lk ? true : false ) ;
//m_hit_branch_instruction = true;
//SetPc(m_ir_builder->getInt32(m_current_instruction_address));
//InterpreterCall("BC", &PPUInterpreter::BC, bo, bi, bd, aa, lk);
//SetPc(m_ir_builder->getInt32(m_current_instruction_address + 4));
//m_ir_builder->CreateRetVoid();
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SC ( u32 sc_code ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " SC " , & PPUInterpreter : : SC , sc_code ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : B ( s32 ll , u32 aa , u32 lk ) {
2014-09-22 22:22:20 +02:00
auto target_i64 = m_ir_builder - > getInt64 ( branchTarget ( aa ? 0 : m_current_instruction_address , ll ) ) ;
CreateBranch ( nullptr , target_i64 , lk ? true : false ) ;
//m_hit_branch_instruction = true;
//SetPc(m_ir_builder->getInt32(m_current_instruction_address));
//InterpreterCall("B", &PPUInterpreter::B, ll, aa, lk);
//m_ir_builder->CreateRetVoid();
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MCRF ( u32 crfd , u32 crfs ) {
2014-09-15 16:34:09 +02:00
if ( crfd ! = crfs ) {
auto cr_i32 = GetCr ( ) ;
auto crf_i32 = GetNibble ( cr_i32 , crfs ) ;
cr_i32 = SetNibble ( cr_i32 , crfd , crf_i32 ) ;
SetCr ( cr_i32 ) ;
}
//InterpreterCall("MCRF", &PPUInterpreter::MCRF, crfd, crfs);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : BCLR ( u32 bo , u32 bi , u32 bh , u32 lk ) {
2014-09-22 22:22:20 +02:00
auto lr_i64 = GetLr ( ) ;
lr_i64 = m_ir_builder - > CreateAnd ( lr_i64 , ~ 0x3ULL ) ;
CreateBranch ( CheckBranchCondition ( bo , bi ) , lr_i64 , lk ? true : false ) ;
//m_hit_branch_instruction = true;
//SetPc(m_ir_builder->getInt32(m_current_instruction_address));
//InterpreterCall("BCLR", &PPUInterpreter::BCLR, bo, bi, bh, lk);
//SetPc(m_ir_builder->getInt32(m_current_instruction_address + 4));
//m_ir_builder->CreateRetVoid();
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRNOR ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateOr ( ba_i32 , bb_i32 ) ;
res_i32 = m_ir_builder - > CreateXor ( res_i32 , 1 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRNOR", &PPUInterpreter::CRNOR, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRANDC ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateXor ( bb_i32 , 1 ) ;
res_i32 = m_ir_builder - > CreateAnd ( ba_i32 , res_i32 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRANDC", &PPUInterpreter::CRANDC, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ISYNC ( ) {
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_mfence ) ) ;
2014-09-26 14:40:24 +02:00
//InterpreterCall("ISYNC", &PPUInterpreter::ISYNC);
2014-09-15 16:34:09 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRXOR ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateXor ( ba_i32 , bb_i32 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRXOR", &PPUInterpreter::CRXOR, crbd, crba, crbb);
}
2014-10-25 22:53:55 +02:00
void PPULLVMRecompiler : : DCBI ( u32 ra , u32 rb ) {
InterpreterCall ( " DCBI " , & PPUInterpreter : : DCBI , ra , rb ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRNAND ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateAnd ( ba_i32 , bb_i32 ) ;
res_i32 = m_ir_builder - > CreateXor ( res_i32 , 1 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRNAND", &PPUInterpreter::CRNAND, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRAND ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateAnd ( ba_i32 , bb_i32 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRAND", &PPUInterpreter::CRAND, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CREQV ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateXor ( ba_i32 , bb_i32 ) ;
res_i32 = m_ir_builder - > CreateXor ( res_i32 , 1 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CREQV", &PPUInterpreter::CREQV, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CRORC ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateXor ( bb_i32 , 1 ) ;
res_i32 = m_ir_builder - > CreateOr ( ba_i32 , res_i32 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CRORC", &PPUInterpreter::CRORC, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CROR ( u32 crbd , u32 crba , u32 crbb ) {
2014-09-15 16:34:09 +02:00
auto cr_i32 = GetCr ( ) ;
auto ba_i32 = GetBit ( cr_i32 , crba ) ;
auto bb_i32 = GetBit ( cr_i32 , crbb ) ;
auto res_i32 = m_ir_builder - > CreateOr ( ba_i32 , bb_i32 ) ;
cr_i32 = SetBit ( cr_i32 , crbd , res_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("CROR", &PPUInterpreter::CROR, crbd, crba, crbb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : BCCTR ( u32 bo , u32 bi , u32 bh , u32 lk ) {
2014-09-22 22:22:20 +02:00
auto ctr_i64 = GetCtr ( ) ;
ctr_i64 = m_ir_builder - > CreateAnd ( ctr_i64 , ~ 0x3ULL ) ;
CreateBranch ( CheckBranchCondition ( bo , bi ) , ctr_i64 , lk ? true : false ) ;
//m_hit_branch_instruction = true;
//SetPc(m_ir_builder->getInt32(m_current_instruction_address));
//InterpreterCall("BCCTR", &PPUInterpreter::BCCTR, bo, bi, bh, lk);
//SetPc(m_ir_builder->getInt32(m_current_instruction_address + 4));
//m_ir_builder->CreateRetVoid();
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLWIMI ( u32 ra , u32 rs , u32 sh , u32 mb , u32 me , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rsh_i64 = m_ir_builder - > CreateShl ( rs_i64 , 32 ) ;
rs_i64 = m_ir_builder - > CreateOr ( rs_i64 , rsh_i64 ) ;
auto ra_i64 = GetGpr ( ra ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
u64 mask = s_rotate_mask [ 32 + mb ] [ 32 + me ] ;
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , mask ) ;
ra_i64 = m_ir_builder - > CreateAnd ( ra_i64 , ~ mask ) ;
res_i64 = m_ir_builder - > CreateOr ( res_i64 , ra_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLWIMI", &PPUInterpreter::RLWIMI, ra, rs, sh, mb, me, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLWINM ( u32 ra , u32 rs , u32 sh , u32 mb , u32 me , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rsh_i64 = m_ir_builder - > CreateShl ( rs_i64 , 32 ) ;
rs_i64 = m_ir_builder - > CreateOr ( rs_i64 , rsh_i64 ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ 32 + mb ] [ 32 + me ] ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLWINM", &PPUInterpreter::RLWINM, ra, rs, sh, mb, me, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLWNM ( u32 ra , u32 rs , u32 rb , u32 mb , u32 me , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rsh_i64 = m_ir_builder - > CreateShl ( rs_i64 , 32 ) ;
rs_i64 = m_ir_builder - > CreateOr ( rs_i64 , rsh_i64 ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto shl_i64 = m_ir_builder - > CreateAnd ( rb_i64 , 0x1F ) ;
auto shr_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 32 ) , shl_i64 ) ;
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , shr_i64 ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , shl_i64 ) ;
auto res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ 32 + mb ] [ 32 + me ] ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLWNM", &PPUInterpreter::RLWNM, ra, rs, rb, mb, me, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ORI ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateOr ( rs_i64 , uimm16 ) ;
SetGpr ( ra , res_i64 ) ;
//InterpreterCall("ORI", &PPUInterpreter::ORI, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ORIS ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateOr ( rs_i64 , ( u64 ) uimm16 < < 16 ) ;
SetGpr ( ra , res_i64 ) ;
//InterpreterCall("ORIS", &PPUInterpreter::ORIS, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : XORI ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateXor ( rs_i64 , uimm16 ) ;
SetGpr ( ra , res_i64 ) ;
//InterpreterCall("XORI", &PPUInterpreter::XORI, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : XORIS ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateXor ( rs_i64 , ( u64 ) uimm16 < < 16 ) ;
SetGpr ( ra , res_i64 ) ;
//InterpreterCall("XORIS", &PPUInterpreter::XORIS, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ANDI_ ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateAnd ( rs_i64 , uimm16 ) ;
SetGpr ( ra , res_i64 ) ;
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
//InterpreterCall("ANDI_", &PPUInterpreter::ANDI_, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ANDIS_ ( u32 ra , u32 rs , u32 uimm16 ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = m_ir_builder - > CreateAnd ( rs_i64 , ( u64 ) uimm16 < < 16 ) ;
SetGpr ( ra , res_i64 ) ;
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
//InterpreterCall("ANDIS_", &PPUInterpreter::ANDIS_, ra, rs, uimm16);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLDICL ( u32 ra , u32 rs , u32 sh , u32 mb , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ mb ] [ 63 ] ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLDICL", &PPUInterpreter::RLDICL, ra, rs, sh, mb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLDICR ( u32 ra , u32 rs , u32 sh , u32 me , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ 0 ] [ me ] ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLDICR", &PPUInterpreter::RLDICR, ra, rs, sh, me, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLDIC ( u32 ra , u32 rs , u32 sh , u32 mb , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ mb ] [ 63 - sh ] ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLDIC", &PPUInterpreter::RLDIC, ra, rs, sh, mb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLDIMI ( u32 ra , u32 rs , u32 sh , u32 mb , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto ra_i64 = GetGpr ( ra ) ;
auto res_i64 = rs_i64 ;
if ( sh ) {
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , 64 - sh ) ;
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , sh ) ;
res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
}
u64 mask = s_rotate_mask [ mb ] [ 63 - sh ] ;
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , mask ) ;
ra_i64 = m_ir_builder - > CreateAnd ( ra_i64 , ~ mask ) ;
res_i64 = m_ir_builder - > CreateOr ( res_i64 , ra_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLDIMI", &PPUInterpreter::RLDIMI, ra, rs, sh, mb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : RLDC_LR ( u32 ra , u32 rs , u32 rb , u32 m_eb , bool is_r , bool rc ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto shl_i64 = m_ir_builder - > CreateAnd ( rb_i64 , 0x3F ) ;
auto shr_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 64 ) , shl_i64 ) ;
2014-10-18 22:27:54 +02:00
auto resl_i64 = m_ir_builder - > CreateLShr ( rs_i64 , shr_i64 ) ;
2014-09-15 16:37:38 +02:00
auto resh_i64 = m_ir_builder - > CreateShl ( rs_i64 , shl_i64 ) ;
auto res_i64 = m_ir_builder - > CreateOr ( resh_i64 , resl_i64 ) ;
if ( is_r ) {
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ 0 ] [ m_eb ] ) ;
} else {
res_i64 = m_ir_builder - > CreateAnd ( res_i64 , s_rotate_mask [ m_eb ] [ 63 ] ) ;
}
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("RLDC_LR", &PPUInterpreter::RLDC_LR, ra, rs, rb, m_eb, is_r, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CMP ( u32 crfd , u32 l , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
Value * ra_i64 ;
Value * rb_i64 ;
if ( l = = 0 ) {
ra_i64 = m_ir_builder - > CreateSExt ( GetGpr ( ra , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
rb_i64 = m_ir_builder - > CreateSExt ( GetGpr ( rb , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
} else {
ra_i64 = GetGpr ( ra ) ;
rb_i64 = GetGpr ( rb ) ;
}
SetCrFieldSignedCmp ( crfd , ra_i64 , rb_i64 ) ;
//InterpreterCall("CMP", &PPUInterpreter::CMP, crfd, l, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : TW ( u32 to , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " TW " , & PPUInterpreter : : TW , to , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVSL ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
static const u128 s_lvsl_values [ ] = {
{ 0x08090A0B0C0D0E0F , 0x0001020304050607 } ,
{ 0x090A0B0C0D0E0F10 , 0x0102030405060708 } ,
{ 0x0A0B0C0D0E0F1011 , 0x0203040506070809 } ,
{ 0x0B0C0D0E0F101112 , 0x030405060708090A } ,
{ 0x0C0D0E0F10111213 , 0x0405060708090A0B } ,
{ 0x0D0E0F1011121314 , 0x05060708090A0B0C } ,
{ 0x0E0F101112131415 , 0x060708090A0B0C0D } ,
{ 0x0F10111213141516 , 0x0708090A0B0C0D0E } ,
{ 0x1011121314151617 , 0x08090A0B0C0D0E0F } ,
{ 0x1112131415161718 , 0x090A0B0C0D0E0F10 } ,
{ 0x1213141516171819 , 0x0A0B0C0D0E0F1011 } ,
{ 0x131415161718191A , 0x0B0C0D0E0F101112 } ,
{ 0x1415161718191A1B , 0x0C0D0E0F10111213 } ,
{ 0x15161718191A1B1C , 0x0D0E0F1011121314 } ,
{ 0x161718191A1B1C1D , 0x0E0F101112131415 } ,
{ 0x1718191A1B1C1D1E , 0x0F10111213141516 } ,
} ;
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xF ) ;
auto lvsl_values_v16i8_ptr = m_ir_builder - > CreateIntToPtr ( m_ir_builder - > getInt64 ( ( u64 ) s_lvsl_values ) , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) - > getPointerTo ( ) ) ;
lvsl_values_v16i8_ptr = m_ir_builder - > CreateGEP ( lvsl_values_v16i8_ptr , index_i64 ) ;
auto val_v16i8 = m_ir_builder - > CreateAlignedLoad ( lvsl_values_v16i8_ptr , 16 ) ;
SetVr ( vd , val_v16i8 ) ;
2014-10-16 11:58:57 +02:00
//InterpreterCall("LVSL", &PPUInterpreter::LVSL, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVEBX ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto val_i8 = ReadMemory ( addr_i64 , 8 ) ;
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 15 ) , index_i64 ) ;
auto vd_v16i8 = GetVrAsIntVec ( vd , 8 ) ;
vd_v16i8 = m_ir_builder - > CreateInsertElement ( vd_v16i8 , val_i8 , index_i64 ) ;
SetVr ( vd , vd_v16i8 ) ;
//InterpreterCall("LVEBX", &PPUInterpreter::LVEBX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBFC ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-10-18 22:27:54 +02:00
auto ra_i64 = GetGpr ( ra ) ;
ra_i64 = m_ir_builder - > CreateNeg ( ra_i64 ) ;
auto rb_i64 = GetGpr ( rb ) ;
2014-10-19 21:46:35 +02:00
auto res_s = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : uadd_with_overflow , m_ir_builder - > getInt64Ty ( ) ) , ra_i64 , rb_i64 ) ;
2014-10-18 22:27:54 +02:00
auto diff_i64 = m_ir_builder - > CreateExtractValue ( res_s , { 0 } ) ;
auto carry_i1 = m_ir_builder - > CreateExtractValue ( res_s , { 1 } ) ;
SetGpr ( rd , diff_i64 ) ;
SetXerCa ( carry_i1 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , diff_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
if ( oe ) {
// TODO: Implement this
}
//InterpreterCall("SUBFC", &PPUInterpreter::SUBFC, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDC ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-10-18 22:27:54 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
2014-10-19 21:46:35 +02:00
auto res_s = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : uadd_with_overflow , m_ir_builder - > getInt64Ty ( ) ) , ra_i64 , rb_i64 ) ;
2014-10-18 22:27:54 +02:00
auto sum_i64 = m_ir_builder - > CreateExtractValue ( res_s , { 0 } ) ;
auto carry_i1 = m_ir_builder - > CreateExtractValue ( res_s , { 1 } ) ;
SetGpr ( rd , sum_i64 ) ;
SetXerCa ( carry_i1 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , sum_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
if ( oe ) {
// TODO: Implement this
}
//InterpreterCall("ADDC", &PPUInterpreter::ADDC, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULHDU ( u32 rd , u32 ra , u32 rb , bool rc ) {
2014-10-16 11:58:57 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto ra_i128 = m_ir_builder - > CreateZExt ( ra_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto rb_i128 = m_ir_builder - > CreateZExt ( rb_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto prod_i128 = m_ir_builder - > CreateMul ( ra_i128 , rb_i128 ) ;
prod_i128 = m_ir_builder - > CreateLShr ( prod_i128 , 64 ) ;
auto prod_i64 = m_ir_builder - > CreateTrunc ( prod_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
2014-09-15 16:36:29 +02:00
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("MULHDU", &PPUInterpreter::MULHDU, rd, ra, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULHWU ( u32 rd , u32 ra , u32 rb , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i32 = GetGpr ( ra , 32 ) ;
auto rb_i32 = GetGpr ( rb , 32 ) ;
auto ra_i64 = m_ir_builder - > CreateZExt ( ra_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rb_i64 = m_ir_builder - > CreateZExt ( rb_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto prod_i64 = m_ir_builder - > CreateMul ( ra_i64 , rb_i64 ) ;
prod_i64 = m_ir_builder - > CreateLShr ( prod_i64 , 32 ) ;
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("MULHWU", &PPUInterpreter::MULHWU, rd, ra, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MFOCRF ( u32 a , u32 rd , u32 crm ) {
2014-09-18 13:29:49 +02:00
auto cr_i32 = GetCr ( ) ;
auto cr_i64 = m_ir_builder - > CreateZExt ( cr_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , cr_i64 ) ;
//InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWARX ( u32 rd , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
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 ( GetPPUState ( ) , ( 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 ( GetPPUState ( ) , ( 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 ) ;
2014-10-19 21:46:35 +02:00
resv_val_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt32Ty ( ) ) , resv_val_i32 ) ;
2014-10-18 22:27:54 +02:00
resv_val_i64 = m_ir_builder - > CreateZExt ( resv_val_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , resv_val_i64 ) ;
//InterpreterCall("LWARX", &PPUInterpreter::LWARX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LDX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LDX", &PPUInterpreter::LDX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWZX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 ) ;
//InterpreterCall("LWZX", &PPUInterpreter::LWZX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SLW ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x3F ) ;
auto rb_i64 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
auto res_i64 = m_ir_builder - > CreateShl ( rs_i64 , rb_i64 ) ;
auto res_i32 = m_ir_builder - > CreateTrunc ( res_i64 , m_ir_builder - > getInt32Ty ( ) ) ;
res_i64 = m_ir_builder - > CreateZExt ( res_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SLW", &PPUInterpreter::SLW, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CNTLZW ( u32 ra , u32 rs , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
2014-10-19 21:46:35 +02:00
auto res_i32 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : ctlz , m_ir_builder - > getInt32Ty ( ) ) , rs_i32 , m_ir_builder - > getInt1 ( false ) ) ;
2014-09-26 14:40:24 +02:00
auto res_i64 = m_ir_builder - > CreateZExt ( res_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("CNTLZW", &PPUInterpreter::CNTLZW, ra, rs, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SLD ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rs_i128 = m_ir_builder - > CreateZExt ( rs_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x7F ) ;
auto rb_i128 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto res_i128 = m_ir_builder - > CreateShl ( rs_i128 , rb_i128 ) ;
auto res_i64 = m_ir_builder - > CreateTrunc ( res_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SLD", &PPUInterpreter::SLD, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : AND ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateAnd ( rs_i64 , rb_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("AND", &PPUInterpreter::AND, ra, rs, rb, rc);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CMPL ( u32 crfd , u32 l , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
Value * ra_i64 ;
Value * rb_i64 ;
if ( l = = 0 ) {
ra_i64 = m_ir_builder - > CreateZExt ( GetGpr ( ra , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
rb_i64 = m_ir_builder - > CreateZExt ( GetGpr ( rb , 32 ) , m_ir_builder - > getInt64Ty ( ) ) ;
} else {
ra_i64 = GetGpr ( ra ) ;
rb_i64 = GetGpr ( rb ) ;
}
SetCrFieldUnsignedCmp ( crfd , ra_i64 , rb_i64 ) ;
//InterpreterCall("CMPL", &PPUInterpreter::CMPL, crfd, l, ra, rb);
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVSR ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
static const u128 s_lvsr_values [ ] = {
{ 0x18191A1B1C1D1E1F , 0x1011121314151617 } ,
{ 0x1718191A1B1C1D1E , 0x0F10111213141516 } ,
{ 0x161718191A1B1C1D , 0x0E0F101112131415 } ,
{ 0x15161718191A1B1C , 0x0D0E0F1011121314 } ,
{ 0x1415161718191A1B , 0x0C0D0E0F10111213 } ,
{ 0x131415161718191A , 0x0B0C0D0E0F101112 } ,
{ 0x1213141516171819 , 0x0A0B0C0D0E0F1011 } ,
{ 0x1112131415161718 , 0x090A0B0C0D0E0F10 } ,
{ 0x1011121314151617 , 0x08090A0B0C0D0E0F } ,
{ 0x0F10111213141516 , 0x0708090A0B0C0D0E } ,
{ 0x0E0F101112131415 , 0x060708090A0B0C0D } ,
{ 0x0D0E0F1011121314 , 0x05060708090A0B0C } ,
{ 0x0C0D0E0F10111213 , 0x0405060708090A0B } ,
{ 0x0B0C0D0E0F101112 , 0x030405060708090A } ,
{ 0x0A0B0C0D0E0F1011 , 0x0203040506070809 } ,
{ 0x090A0B0C0D0E0F10 , 0x0102030405060708 } ,
} ;
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xF ) ;
auto lvsr_values_v16i8_ptr = m_ir_builder - > CreateIntToPtr ( m_ir_builder - > getInt64 ( ( u64 ) s_lvsr_values ) , VectorType : : get ( m_ir_builder - > getInt8Ty ( ) , 16 ) - > getPointerTo ( ) ) ;
lvsr_values_v16i8_ptr = m_ir_builder - > CreateGEP ( lvsr_values_v16i8_ptr , index_i64 ) ;
auto val_v16i8 = m_ir_builder - > CreateAlignedLoad ( lvsr_values_v16i8_ptr , 16 ) ;
SetVr ( vd , val_v16i8 ) ;
2014-10-16 11:58:57 +02:00
//InterpreterCall("LVSR", &PPUInterpreter::LVSR, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:26:36 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVEHX ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFFEULL ) ;
2014-10-18 22:27:54 +02:00
auto val_i16 = ReadMemory ( addr_i64 , 16 , 2 ) ;
2014-10-16 11:58:57 +02:00
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateLShr ( index_i64 , 1 ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 7 ) , index_i64 ) ;
auto vd_v8i16 = GetVrAsIntVec ( vd , 16 ) ;
vd_v8i16 = m_ir_builder - > CreateInsertElement ( vd_v8i16 , val_i16 , index_i64 ) ;
SetVr ( vd , vd_v8i16 ) ;
//InterpreterCall("LVEHX", &PPUInterpreter::LVEHX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBF ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto diff_i64 = m_ir_builder - > CreateSub ( rb_i64 , ra_i64 ) ;
SetGpr ( rd , diff_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , diff_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
if ( oe ) {
// TODO: Implement this
}
//InterpreterCall("SUBF", &PPUInterpreter::SUBF, rd, ra, rb, oe, rc);
2014-09-15 16:34:09 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LDUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LDUX", &PPUInterpreter::LDUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DCBST ( u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
// TODO: Implement this
//InterpreterCall("DCBST", &PPUInterpreter::DCBST, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWZUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
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 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LWZUX", &PPUInterpreter::LWZUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : CNTLZD ( u32 ra , u32 rs , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i64 = GetGpr ( rs ) ;
2014-10-19 21:46:35 +02:00
auto res_i64 = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : ctlz , m_ir_builder - > getInt64Ty ( ) ) , rs_i64 , m_ir_builder - > getInt1 ( false ) ) ;
2014-09-26 14:40:24 +02:00
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("CNTLZD", &PPUInterpreter::CNTLZD, ra, rs, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ANDC ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ANDC " , & PPUInterpreter : : ANDC , ra , rs , rb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : TD ( u32 to , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " TD " , & PPUInterpreter : : TD , to , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVEWX ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFFCULL ) ;
2014-10-18 22:27:54 +02:00
auto val_i32 = ReadMemory ( addr_i64 , 32 , 4 ) ;
2014-10-16 11:58:57 +02:00
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateLShr ( index_i64 , 2 ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 3 ) , index_i64 ) ;
auto vd_v4i32 = GetVrAsIntVec ( vd , 32 ) ;
vd_v4i32 = m_ir_builder - > CreateInsertElement ( vd_v4i32 , val_i32 , index_i64 ) ;
SetVr ( vd , vd_v4i32 ) ;
//InterpreterCall("LVEWX", &PPUInterpreter::LVEWX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULHD ( u32 rd , u32 ra , u32 rb , bool rc ) {
2014-10-16 11:58:57 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto ra_i128 = m_ir_builder - > CreateSExt ( ra_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto rb_i128 = m_ir_builder - > CreateSExt ( rb_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto prod_i128 = m_ir_builder - > CreateMul ( ra_i128 , rb_i128 ) ;
prod_i128 = m_ir_builder - > CreateLShr ( prod_i128 , 64 ) ;
auto prod_i64 = m_ir_builder - > CreateTrunc ( prod_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
2014-09-15 16:36:29 +02:00
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("MULHD", &PPUInterpreter::MULHD, rd, ra, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULHW ( u32 rd , u32 ra , u32 rb , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i32 = GetGpr ( ra , 32 ) ;
auto rb_i32 = GetGpr ( rb , 32 ) ;
auto ra_i64 = m_ir_builder - > CreateSExt ( ra_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rb_i64 = m_ir_builder - > CreateSExt ( rb_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto prod_i64 = m_ir_builder - > CreateMul ( ra_i64 , rb_i64 ) ;
prod_i64 = m_ir_builder - > CreateAShr ( prod_i64 , 32 ) ;
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("MULHW", &PPUInterpreter::MULHW, rd, ra, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LDARX ( u32 rd , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
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 ( GetPPUState ( ) , ( 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 ( GetPPUState ( ) , ( 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 ) ;
2014-10-19 21:46:35 +02:00
resv_val_i64 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt64Ty ( ) ) , resv_val_i64 ) ;
2014-10-18 22:27:54 +02:00
SetGpr ( rd , resv_val_i64 ) ;
//InterpreterCall("LDARX", &PPUInterpreter::LDARX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DCBF ( u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
// TODO: Implement this
//InterpreterCall("DCBF", &PPUInterpreter::DCBF, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LBZX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i8 = ReadMemory ( addr_i64 , 8 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LBZX", &PPUInterpreter::LBZX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVX ( u32 vd , u32 ra , u32 rb ) {
2014-10-12 20:24:43 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFF0ULL ) ;
2014-10-18 22:27:54 +02:00
auto mem_i128 = ReadMemory ( addr_i64 , 128 , 16 ) ;
2014-10-12 20:24:43 +02:00
SetVr ( vd , mem_i128 ) ;
//InterpreterCall("LVX", &PPUInterpreter::LVX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : NEG ( u32 rd , u32 ra , u32 oe , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto diff_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 0 ) , ra_i64 ) ;
SetGpr ( rd , diff_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , diff_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
if ( oe ) {
// TODO: Implement this
}
//InterpreterCall("NEG", &PPUInterpreter::NEG, rd, ra, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LBZUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i8 = ReadMemory ( addr_i64 , 8 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LBZUX", &PPUInterpreter::LBZUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : NOR ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:36:29 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateOr ( rs_i64 , rb_i64 ) ;
res_i64 = m_ir_builder - > CreateXor ( res_i64 , ( s64 ) - 1 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("NOR", &PPUInterpreter::NOR, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVEBX ( u32 vs , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 15 ) , index_i64 ) ;
auto vs_v16i8 = GetVrAsIntVec ( vs , 8 ) ;
auto val_i8 = m_ir_builder - > CreateExtractElement ( vs_v16i8 , index_i64 ) ;
WriteMemory ( addr_i64 , val_i8 ) ;
//InterpreterCall("STVEBX", &PPUInterpreter::STVEBX, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBFE ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " SUBFE " , & PPUInterpreter : : SUBFE , rd , ra , rb , oe , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDE ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ADDE " , & PPUInterpreter : : ADDE , rd , ra , rb , oe , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTOCRF ( u32 l , u32 crm , u32 rs ) {
2014-09-18 13:29:49 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto cr_i32 = GetCr ( ) ;
u32 mask = 0 ;
for ( u32 i = 0 ; i < 8 ; i + + ) {
if ( crm & ( 1 < < i ) ) {
mask | = 0xF < < ( ( 7 - i ) * 4 ) ;
if ( l ) {
break ;
}
}
}
cr_i32 = m_ir_builder - > CreateAnd ( cr_i32 , ~ mask ) ;
rs_i32 = m_ir_builder - > CreateAnd ( rs_i32 , ~ mask ) ;
cr_i32 = m_ir_builder - > CreateOr ( cr_i32 , rs_i32 ) ;
SetCr ( cr_i32 ) ;
//InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STDX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 , 64 ) ) ;
//InterpreterCall("STDX", &PPUInterpreter::STDX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STWCX_ ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " STWCX_ " , & PPUInterpreter : : STWCX_ , rs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STWX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 ) ) ;
//InterpreterCall("STWX", &PPUInterpreter::STWX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVEHX ( u32 vs , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFFEULL ) ;
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateLShr ( index_i64 , 1 ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 7 ) , index_i64 ) ;
auto vs_v8i16 = GetVrAsIntVec ( vs , 16 ) ;
auto val_i16 = m_ir_builder - > CreateExtractElement ( vs_v8i16 , index_i64 ) ;
WriteMemory ( addr_i64 , val_i16 , 2 ) ;
//InterpreterCall("STVEHX", &PPUInterpreter::STVEHX, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STDUX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 64 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STDUX", &PPUInterpreter::STDUX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STWUX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 32 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STWUX", &PPUInterpreter::STWUX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVEWX ( u32 vs , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFFCULL ) ;
auto index_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xf ) ;
index_i64 = m_ir_builder - > CreateLShr ( index_i64 , 2 ) ;
index_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 3 ) , index_i64 ) ;
auto vs_v4i32 = GetVrAsIntVec ( vs , 32 ) ;
auto val_i32 = m_ir_builder - > CreateExtractElement ( vs_v4i32 , index_i64 ) ;
WriteMemory ( addr_i64 , val_i32 , 4 ) ;
//InterpreterCall("STVEWX", &PPUInterpreter::STVEWX, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDZE ( u32 rd , u32 ra , u32 oe , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto ca_i64 = GetXerCa ( ) ;
2014-10-19 21:46:35 +02:00
auto res_s = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : uadd_with_overflow , m_ir_builder - > getInt64Ty ( ) ) , ra_i64 , ca_i64 ) ;
2014-09-18 13:29:49 +02:00
auto sum_i64 = m_ir_builder - > CreateExtractValue ( res_s , { 0 } ) ;
auto carry_i1 = m_ir_builder - > CreateExtractValue ( res_s , { 1 } ) ;
SetGpr ( rd , sum_i64 ) ;
SetXerCa ( carry_i1 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , sum_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBFZE ( u32 rd , u32 ra , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " SUBFZE " , & PPUInterpreter : : SUBFZE , rd , ra , oe , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STDCX_ ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " STDCX_ " , & PPUInterpreter : : STDCX_ , rs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STBX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 , 8 ) ) ;
//InterpreterCall("STBX", &PPUInterpreter::STBX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVX ( u32 vs , u32 ra , u32 rb ) {
2014-10-12 20:24:43 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFF0ULL ) ;
2014-10-18 22:27:54 +02:00
WriteMemory ( addr_i64 , GetVr ( vs ) , 16 ) ;
2014-10-12 20:24:43 +02:00
//InterpreterCall("STVX", &PPUInterpreter::STVX, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SUBFME ( u32 rd , u32 ra , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " SUBFME " , & PPUInterpreter : : SUBFME , rd , ra , oe , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULLD ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto prod_i64 = m_ir_builder - > CreateMul ( ra_i64 , rb_i64 ) ;
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
//InterpreterCall("MULLD", &PPUInterpreter::MULLD, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADDME ( u32 rd , u32 ra , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ADDME " , & PPUInterpreter : : ADDME , rd , ra , oe , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MULLW ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:36:29 +02:00
auto ra_i32 = GetGpr ( ra , 32 ) ;
auto rb_i32 = GetGpr ( rb , 32 ) ;
auto ra_i64 = m_ir_builder - > CreateSExt ( ra_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rb_i64 = m_ir_builder - > CreateSExt ( rb_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto prod_i64 = m_ir_builder - > CreateMul ( ra_i64 , rb_i64 ) ;
SetGpr ( rd , prod_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , prod_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
//InterpreterCall("MULLW", &PPUInterpreter::MULLW, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DCBTST ( u32 ra , u32 rb , u32 th ) {
2014-10-16 11:58:57 +02:00
// TODO: Implement this
//InterpreterCall("DCBTST", &PPUInterpreter::DCBTST, ra, rb, th);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STBUX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 8 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STBUX", &PPUInterpreter::STBUX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ADD ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:34:09 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto sum_i64 = m_ir_builder - > CreateAdd ( ra_i64 , rb_i64 ) ;
SetGpr ( rd , sum_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , sum_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
if ( oe ) {
// TODO: Implement this
}
//InterpreterCall("ADD", &PPUInterpreter::ADD, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DCBT ( u32 ra , u32 rb , u32 th ) {
2014-10-16 11:58:57 +02:00
// TODO: Implement this using prefetch
//InterpreterCall("DCBT", &PPUInterpreter::DCBT, ra, rb, th);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHZX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LHZX", &PPUInterpreter::LHZX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : EQV ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " EQV " , & PPUInterpreter : : EQV , ra , rs , rb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ECIWX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ECIWX " , & PPUInterpreter : : ECIWX , rd , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHZUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LHZUX", &PPUInterpreter::LHZUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : XOR ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateXor ( rs_i64 , rb_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("XOR", &PPUInterpreter::XOR, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MFSPR ( u32 rd , u32 spr ) {
2014-09-15 16:37:38 +02:00
Value * rd_i64 ;
auto n = ( spr > > 5 ) | ( ( spr & 0x1f ) < < 5 ) ;
switch ( n ) {
case 0x001 :
rd_i64 = GetXer ( ) ;
break ;
case 0x008 :
rd_i64 = GetLr ( ) ;
break ;
case 0x009 :
rd_i64 = GetCtr ( ) ;
break ;
case 0x100 :
rd_i64 = GetUsprg0 ( ) ;
break ;
default :
assert ( 0 ) ;
break ;
}
SetGpr ( rd , rd_i64 ) ;
//InterpreterCall("MFSPR", &PPUInterpreter::MFSPR, rd, spr);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWAX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 - > CreateSExt ( mem_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LWAX", &PPUInterpreter::LWAX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DST ( u32 ra , u32 rb , u32 strm , u32 t ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " DST " , & PPUInterpreter : : DST , ra , rb , strm , t ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHAX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateSExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LHAX", &PPUInterpreter::LHAX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVXL ( u32 vd , u32 ra , u32 rb ) {
2014-10-12 20:24:43 +02:00
LVX ( vd , ra , rb ) ;
//InterpreterCall("LVXL", &PPUInterpreter::LVXL, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MFTB ( u32 rd , u32 spr ) {
2014-10-16 11:58:57 +02:00
static Function * s_get_time_fn = nullptr ;
if ( s_get_time_fn = = nullptr ) {
s_get_time_fn = ( Function * ) m_module - > getOrInsertFunction ( " get_time " , m_ir_builder - > getInt64Ty ( ) , nullptr ) ;
s_get_time_fn - > setCallingConv ( CallingConv : : X86_64_Win64 ) ;
m_execution_engine - > addGlobalMapping ( s_get_time_fn , ( void * ) get_time ) ;
}
auto tb_i64 = ( Value * ) m_ir_builder - > CreateCall ( s_get_time_fn ) ;
u32 n = ( spr > > 5 ) | ( ( spr & 0x1f ) < < 5 ) ;
if ( n = = 0x10D ) {
tb_i64 = m_ir_builder - > CreateLShr ( tb_i64 , 32 ) ;
}
SetGpr ( rd , tb_i64 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWAUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
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 - > CreateSExt ( mem_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LWAUX", &PPUInterpreter::LWAUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DSTST ( u32 ra , u32 rb , u32 strm , u32 t ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " DSTST " , & PPUInterpreter : : DSTST , ra , rb , strm , t ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHAUX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateSExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LHAUX", &PPUInterpreter::LHAUX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STHX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
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 , 16 ) ) ;
//InterpreterCall("STHX", &PPUInterpreter::STHX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ORC ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ORC " , & PPUInterpreter : : ORC , ra , rs , rb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ECOWX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ECOWX " , & PPUInterpreter : : ECOWX , rs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STHUX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 16 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STHUX", &PPUInterpreter::STHUX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : OR ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateOr ( rs_i64 , rb_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("OR", &PPUInterpreter::OR, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DIVDU ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:37:38 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateUDiv ( ra_i64 , rb_i64 ) ;
SetGpr ( rd , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
// TODO make sure an exception does not occur on divide by 0 and overflow
//InterpreterCall("DIVDU", &PPUInterpreter::DIVDU, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DIVWU ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:37:38 +02:00
auto ra_i32 = GetGpr ( ra , 32 ) ;
auto rb_i32 = GetGpr ( rb , 32 ) ;
auto res_i32 = m_ir_builder - > CreateUDiv ( ra_i32 , rb_i32 ) ;
auto res_i64 = m_ir_builder - > CreateZExt ( res_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
// TODO make sure an exception does not occur on divide by 0 and overflow
//InterpreterCall("DIVWU", &PPUInterpreter::DIVWU, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTSPR ( u32 spr , u32 rs ) {
2014-09-15 16:37:38 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto n = ( spr > > 5 ) | ( ( spr & 0x1f ) < < 5 ) ;
switch ( n ) {
case 0x001 :
SetXer ( rs_i64 ) ;
break ;
case 0x008 :
SetLr ( rs_i64 ) ;
break ;
case 0x009 :
SetCtr ( rs_i64 ) ;
break ;
case 0x100 :
SetUsprg0 ( rs_i64 ) ;
break ;
default :
assert ( 0 ) ;
break ;
}
//InterpreterCall("MTSPR", &PPUInterpreter::MTSPR, spr, rs);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:16:53 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : NAND ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " NAND " , & PPUInterpreter : : NAND , ra , rs , rb , rc ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVXL ( u32 vs , u32 ra , u32 rb ) {
2014-10-12 20:24:43 +02:00
STVX ( vs , ra , rb ) ;
//InterpreterCall("STVXL", &PPUInterpreter::STVXL, vs, ra, rb);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DIVD ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:37:38 +02:00
auto ra_i64 = GetGpr ( ra ) ;
auto rb_i64 = GetGpr ( rb ) ;
auto res_i64 = m_ir_builder - > CreateSDiv ( ra_i64 , rb_i64 ) ;
SetGpr ( rd , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
// TODO make sure an exception does not occur on divide by 0 and overflow
//InterpreterCall("DIVD", &PPUInterpreter::DIVD, rd, ra, rb, oe, rc);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DIVW ( u32 rd , u32 ra , u32 rb , u32 oe , bool rc ) {
2014-09-15 16:37:38 +02:00
auto ra_i32 = GetGpr ( ra , 32 ) ;
auto rb_i32 = GetGpr ( rb , 32 ) ;
auto res_i32 = m_ir_builder - > CreateSDiv ( ra_i32 , rb_i32 ) ;
auto res_i64 = m_ir_builder - > CreateZExt ( res_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
// TODO implement oe
// TODO make sure an exception does not occur on divide by 0 and overflow
//InterpreterCall("DIVW", &PPUInterpreter::DIVW, rd, ra, rb, oe, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVLX ( u32 vd , u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto eb_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xF ) ;
eb_i64 = m_ir_builder - > CreateShl ( eb_i64 , 3 ) ;
auto eb_i128 = m_ir_builder - > CreateZExt ( eb_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFF0ULL ) ;
2014-10-18 22:27:54 +02:00
auto mem_i128 = ReadMemory ( addr_i64 , 128 , 16 ) ;
2014-10-16 11:58:57 +02:00
mem_i128 = m_ir_builder - > CreateShl ( mem_i128 , eb_i128 ) ;
SetVr ( vd , mem_i128 ) ;
//InterpreterCall("LVLX", &PPUInterpreter::LVLX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LDBRX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
auto mem_i64 = ReadMemory ( addr_i64 , 64 , 0 , false ) ;
2014-09-15 16:34:09 +02:00
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LDBRX", &PPUInterpreter::LDBRX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LSWX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " LSWX " , & PPUInterpreter : : LSWX , rd , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWBRX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
auto mem_i32 = ReadMemory ( addr_i64 , 32 , 0 , false ) ;
2014-09-15 16:34:09 +02:00
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LWBRX", &PPUInterpreter::LWBRX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFSX ( u32 frd , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
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 ) ;
SetFpr ( frd , mem_i32 ) ;
//InterpreterCall("LFSX", &PPUInterpreter::LFSX, frd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRW ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x3F ) ;
auto rb_i64 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
auto res_i64 = m_ir_builder - > CreateLShr ( rs_i64 , rb_i64 ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SRW", &PPUInterpreter::SRW, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRD ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rs_i128 = m_ir_builder - > CreateZExt ( rs_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x7F ) ;
auto rb_i128 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto res_i128 = m_ir_builder - > CreateLShr ( rs_i128 , rb_i128 ) ;
auto res_i64 = m_ir_builder - > CreateTrunc ( res_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , res_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SRD", &PPUInterpreter::SRD, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVRX ( u32 vd , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto eb_i64 = m_ir_builder - > CreateSub ( m_ir_builder - > getInt64 ( 16 ) , addr_i64 ) ;
eb_i64 = m_ir_builder - > CreateAnd ( eb_i64 , 0xF ) ;
eb_i64 = m_ir_builder - > CreateShl ( eb_i64 , 3 ) ;
auto eb_i128 = m_ir_builder - > CreateZExt ( eb_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFFFFFFFFF0ULL ) ;
auto mem_i128 = ReadMemory ( addr_i64 , 128 , 16 ) ;
mem_i128 = m_ir_builder - > CreateLShr ( mem_i128 , eb_i128 ) ;
auto cmp_i1 = m_ir_builder - > CreateICmpNE ( eb_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto cmp_i128 = m_ir_builder - > CreateSExt ( cmp_i1 , m_ir_builder - > getIntNTy ( 128 ) ) ;
mem_i128 = m_ir_builder - > CreateAnd ( mem_i128 , cmp_i128 ) ;
SetVr ( vd , mem_i128 ) ;
//InterpreterCall("LVRX", &PPUInterpreter::LVRX, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LSWI ( u32 rd , u32 ra , u32 nb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = ra ? GetGpr ( ra ) : m_ir_builder - > getInt64 ( 0 ) ;
nb = nb ? nb : 32 ;
for ( u32 i = 0 ; i < nb ; i + = 4 ) {
auto val_i32 = ReadMemory ( addr_i64 , 32 , 0 , true , false ) ;
if ( i + 4 < = nb ) {
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( 4 ) ) ;
} else {
u32 mask = 0xFFFFFFFF < < ( ( 4 - ( nb - i ) ) * 8 ) ;
val_i32 = m_ir_builder - > CreateAnd ( val_i32 , mask ) ;
}
auto val_i64 = m_ir_builder - > CreateZExt ( val_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , val_i64 ) ;
rd = ( rd + 1 ) % 32 ;
}
//InterpreterCall("LSWI", &PPUInterpreter::LSWI, rd, ra, nb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFSUX ( u32 frd , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i32 = ReadMemory ( addr_i64 , 32 ) ;
SetFpr ( frd , mem_i32 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LFSUX", &PPUInterpreter::LFSUX, frd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SYNC ( u32 l ) {
2014-10-16 11:58:57 +02:00
m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_mfence ) ) ;
//InterpreterCall("SYNC", &PPUInterpreter::SYNC, l);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFDX ( u32 frd , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetFpr ( frd , mem_i64 ) ;
//InterpreterCall("LFDX", &PPUInterpreter::LFDX, frd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFDUX ( u32 frd , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetFpr ( frd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LFDUX", &PPUInterpreter::LFDUX, frd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVLX ( u32 vs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " STVLX " , & PPUInterpreter : : STVLX , vs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STSWX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " STSWX " , & PPUInterpreter : : STSWX , rs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STWBRX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
WriteMemory ( addr_i64 , GetGpr ( rs , 32 ) , 0 , false ) ;
2014-09-15 16:34:09 +02:00
//InterpreterCall("STWBRX", &PPUInterpreter::STWBRX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFSX ( u32 frs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto frs_i32 = m_ir_builder - > CreateBitCast ( GetFpr ( frs , 32 ) , m_ir_builder - > getInt32Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i32 ) ;
//InterpreterCall("STFSX", &PPUInterpreter::STFSX, frs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVRX ( u32 vs , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " STVRX " , & PPUInterpreter : : STVRX , vs , ra , rb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFSUX ( u32 frs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto frs_i32 = m_ir_builder - > CreateBitCast ( GetFpr ( frs , 32 ) , m_ir_builder - > getInt32Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i32 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STFSUX", &PPUInterpreter::STFSUX, frs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STSWI ( u32 rd , u32 ra , u32 nb ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = ra ? GetGpr ( ra ) : m_ir_builder - > getInt64 ( 0 ) ;
nb = nb ? nb : 32 ;
for ( u32 i = 0 ; i < nb ; i + = 4 ) {
auto val_i32 = GetGpr ( rd , 32 ) ;
if ( i + 4 < = nb ) {
WriteMemory ( addr_i64 , val_i32 , 0 , true , false ) ;
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( 4 ) ) ;
rd = ( rd + 1 ) % 32 ;
} else {
u32 n = nb - i ;
if ( n > = 2 ) {
auto val_i16 = m_ir_builder - > CreateLShr ( val_i32 , 16 ) ;
val_i16 = m_ir_builder - > CreateTrunc ( val_i16 , m_ir_builder - > getInt16Ty ( ) ) ;
WriteMemory ( addr_i64 , val_i16 ) ;
if ( n = = 3 ) {
auto val_i8 = m_ir_builder - > CreateLShr ( val_i32 , 8 ) ;
val_i8 = m_ir_builder - > CreateTrunc ( val_i8 , m_ir_builder - > getInt8Ty ( ) ) ;
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( 2 ) ) ;
WriteMemory ( addr_i64 , val_i8 ) ;
}
} else {
auto val_i8 = m_ir_builder - > CreateLShr ( val_i32 , 24 ) ;
val_i8 = m_ir_builder - > CreateTrunc ( val_i8 , m_ir_builder - > getInt8Ty ( ) ) ;
WriteMemory ( addr_i64 , val_i8 ) ;
}
}
}
//InterpreterCall("STSWI", &PPUInterpreter::STSWI, rd, ra, nb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFDX ( u32 frs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto frs_i64 = m_ir_builder - > CreateBitCast ( GetFpr ( frs ) , m_ir_builder - > getInt64Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i64 ) ;
//InterpreterCall("STFDX", &PPUInterpreter::STFDX, frs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFDUX ( u32 frs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto frs_i64 = m_ir_builder - > CreateBitCast ( GetFpr ( frs ) , m_ir_builder - > getInt64Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STFDUX", &PPUInterpreter::STFDUX, frs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVLXL ( u32 vd , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
LVLX ( vd , ra , rb ) ;
//InterpreterCall("LVLXL", &PPUInterpreter::LVLXL, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHBRX ( u32 rd , u32 ra , u32 rb ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
auto mem_i16 = ReadMemory ( addr_i64 , 16 , 0 , false ) ;
2014-09-15 16:34:09 +02:00
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LHBRX", &PPUInterpreter::LHBRX, rd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRAW ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
rs_i64 = m_ir_builder - > CreateShl ( rs_i64 , 32 ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x3F ) ;
auto rb_i64 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
auto res_i64 = m_ir_builder - > CreateAShr ( rs_i64 , rb_i64 ) ;
auto ra_i64 = m_ir_builder - > CreateAShr ( res_i64 , 32 ) ;
SetGpr ( ra , ra_i64 ) ;
auto res_i32 = m_ir_builder - > CreateTrunc ( res_i64 , m_ir_builder - > getInt32Ty ( ) ) ;
auto ca1_i1 = m_ir_builder - > CreateICmpSLT ( ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca2_i1 = m_ir_builder - > CreateICmpNE ( res_i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
auto ca_i1 = m_ir_builder - > CreateAnd ( ca1_i1 , ca2_i1 ) ;
SetXerCa ( ca_i1 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SRAW", &PPUInterpreter::SRAW, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRAD ( u32 ra , u32 rs , u32 rb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rs_i128 = m_ir_builder - > CreateZExt ( rs_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
rs_i128 = m_ir_builder - > CreateShl ( rs_i128 , 64 ) ;
auto rb_i8 = GetGpr ( rb , 8 ) ;
rb_i8 = m_ir_builder - > CreateAnd ( rb_i8 , 0x7F ) ;
auto rb_i128 = m_ir_builder - > CreateZExt ( rb_i8 , m_ir_builder - > getIntNTy ( 128 ) ) ;
auto res_i128 = m_ir_builder - > CreateAShr ( rs_i128 , rb_i128 ) ;
auto ra_i128 = m_ir_builder - > CreateAShr ( res_i128 , 64 ) ;
auto ra_i64 = m_ir_builder - > CreateTrunc ( ra_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , ra_i64 ) ;
auto res_i64 = m_ir_builder - > CreateTrunc ( res_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
auto ca1_i1 = m_ir_builder - > CreateICmpSLT ( ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca2_i1 = m_ir_builder - > CreateICmpNE ( res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca_i1 = m_ir_builder - > CreateAnd ( ca1_i1 , ca2_i1 ) ;
SetXerCa ( ca_i1 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("SRAD", &PPUInterpreter::SRAD, ra, rs, rb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LVRXL ( u32 vd , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
LVRX ( vd , ra , rb ) ;
//InterpreterCall("LVRXL", &PPUInterpreter::LVRXL, vd, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DSS ( u32 strm , u32 a ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " DSS " , & PPUInterpreter : : DSS , strm , a ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRAWI ( u32 ra , u32 rs , u32 sh , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateZExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
rs_i64 = m_ir_builder - > CreateShl ( rs_i64 , 32 ) ;
auto res_i64 = m_ir_builder - > CreateAShr ( rs_i64 , sh ) ;
auto ra_i64 = m_ir_builder - > CreateAShr ( res_i64 , 32 ) ;
SetGpr ( ra , ra_i64 ) ;
auto res_i32 = m_ir_builder - > CreateTrunc ( res_i64 , m_ir_builder - > getInt32Ty ( ) ) ;
auto ca1_i1 = m_ir_builder - > CreateICmpSLT ( ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca2_i1 = m_ir_builder - > CreateICmpNE ( res_i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
auto ca_i1 = m_ir_builder - > CreateAnd ( ca1_i1 , ca2_i1 ) ;
SetXerCa ( ca_i1 ) ;
2014-09-18 13:29:49 +02:00
2014-09-26 14:40:24 +02:00
if ( rc ) {
SetCrFieldSignedCmp ( 0 , ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
2014-09-18 13:29:49 +02:00
2014-09-26 14:40:24 +02:00
//InterpreterCall("SRAWI", &PPUInterpreter::SRAWI, ra, rs, sh, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRADI1 ( u32 ra , u32 rs , u32 sh , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rs_i64 = GetGpr ( rs ) ;
auto rs_i128 = m_ir_builder - > CreateZExt ( rs_i64 , m_ir_builder - > getIntNTy ( 128 ) ) ;
rs_i128 = m_ir_builder - > CreateShl ( rs_i128 , 64 ) ;
auto res_i128 = m_ir_builder - > CreateAShr ( rs_i128 , sh ) ;
auto ra_i128 = m_ir_builder - > CreateAShr ( res_i128 , 64 ) ;
auto ra_i64 = m_ir_builder - > CreateTrunc ( ra_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , ra_i64 ) ;
auto res_i64 = m_ir_builder - > CreateTrunc ( res_i128 , m_ir_builder - > getInt64Ty ( ) ) ;
auto ca1_i1 = m_ir_builder - > CreateICmpSLT ( ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca2_i1 = m_ir_builder - > CreateICmpNE ( res_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
auto ca_i1 = m_ir_builder - > CreateAnd ( ca1_i1 , ca2_i1 ) ;
SetXerCa ( ca_i1 ) ;
2014-09-18 13:29:49 +02:00
2014-09-26 14:40:24 +02:00
if ( rc ) {
SetCrFieldSignedCmp ( 0 , ra_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
2014-09-18 13:29:49 +02:00
2014-09-26 14:40:24 +02:00
//InterpreterCall("SRADI1", &PPUInterpreter::SRADI1, ra, rs, sh, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SRADI2 ( u32 ra , u32 rs , u32 sh , bool rc ) {
2014-09-26 14:40:24 +02:00
SRADI1 ( ra , rs , sh , rc ) ;
//InterpreterCall("SRADI2", &PPUInterpreter::SRADI2, ra, rs, sh, rc);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:19:43 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : EIEIO ( ) {
2014-09-26 14:40:24 +02:00
m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_mfence ) ) ;
//InterpreterCall("EIEIO", &PPUInterpreter::EIEIO);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVLXL ( u32 vs , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
STVLX ( vs , ra , rb ) ;
//InterpreterCall("STVLXL", &PPUInterpreter::STVLXL, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STHBRX ( u32 rs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
2014-10-18 22:27:54 +02:00
WriteMemory ( addr_i64 , GetGpr ( rs , 16 ) , 0 , false ) ;
2014-09-15 16:37:38 +02:00
//InterpreterCall("STHBRX", &PPUInterpreter::STHBRX, rs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : EXTSH ( u32 ra , u32 rs , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i16 = GetGpr ( rs , 16 ) ;
auto rs_i64 = m_ir_builder - > CreateSExt ( rs_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , rs_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , rs_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("EXTSH", &PPUInterpreter::EXTSH, ra, rs, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STVRXL ( u32 vs , u32 ra , u32 rb ) {
2014-10-18 22:27:54 +02:00
STVRX ( vs , ra , rb ) ;
//InterpreterCall("STVRXL", &PPUInterpreter::STVRXL, vs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : EXTSB ( u32 ra , u32 rs , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i8 = GetGpr ( rs , 8 ) ;
auto rs_i64 = m_ir_builder - > CreateSExt ( rs_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , rs_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , rs_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("EXTSB", &PPUInterpreter::EXTSB, ra, rs, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFIWX ( u32 frs , u32 ra , u32 rb ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto frs_i64 = m_ir_builder - > CreateBitCast ( GetFpr ( frs ) , m_ir_builder - > getInt64Ty ( ) ) ;
auto frs_i32 = m_ir_builder - > CreateTrunc ( frs_i64 , m_ir_builder - > getInt32Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i32 ) ;
//InterpreterCall("STFIWX", &PPUInterpreter::STFIWX, frs, ra, rb);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : EXTSW ( u32 ra , u32 rs , bool rc ) {
2014-09-15 16:34:09 +02:00
auto rs_i32 = GetGpr ( rs , 32 ) ;
auto rs_i64 = m_ir_builder - > CreateSExt ( rs_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( ra , rs_i64 ) ;
if ( rc ) {
SetCrFieldSignedCmp ( 0 , rs_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
}
//InterpreterCall("EXTSW", &PPUInterpreter::EXTSW, ra, rs, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : ICBI ( u32 ra , u32 rs ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " ICBI " , & PPUInterpreter : : ICBI , ra , rs ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : DCBZ ( u32 ra , u32 rb ) {
2014-10-16 11:58:57 +02:00
auto addr_i64 = GetGpr ( rb ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , ~ ( 127ULL ) ) ;
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( ( u64 ) vm : : get_ptr < u8 > ( 0 ) ) ) ;
auto addr_i8_ptr = m_ir_builder - > CreateIntToPtr ( addr_i64 , m_ir_builder - > getInt8PtrTy ( ) ) ;
std : : vector < Type * > types = { ( Type * ) m_ir_builder - > getInt8PtrTy ( ) , ( Type * ) m_ir_builder - > getInt32Ty ( ) } ;
m_ir_builder - > CreateCall5 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : memset , types ) ,
addr_i8_ptr , m_ir_builder - > getInt8 ( 0 ) , m_ir_builder - > getInt32 ( 128 ) , m_ir_builder - > getInt32 ( 128 ) , m_ir_builder - > getInt1 ( true ) ) ;
//InterpreterCall("DCBZ", &PPUInterpreter::DCBZ, ra, rb);L
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWZ ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
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 ) ;
//InterpreterCall("LWZ", &PPUInterpreter::LWZ, rd, ra, d);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWZU ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
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 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LWZU", &PPUInterpreter::LWZU, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LBZ ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i8 = ReadMemory ( addr_i64 , 8 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LBZ", &PPUInterpreter::LBZ, rd, ra, d);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LBZU ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i8 = ReadMemory ( addr_i64 , 8 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i8 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LBZU", &PPUInterpreter::LBZU, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STW ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
WriteMemory ( addr_i64 , GetGpr ( rs , 32 ) ) ;
//InterpreterCall("STW", &PPUInterpreter::STW, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STWU ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 32 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STWU", &PPUInterpreter::STWU, rs, ra, d);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STB ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
WriteMemory ( addr_i64 , GetGpr ( rs , 8 ) ) ;
//InterpreterCall("STB", &PPUInterpreter::STB, rs, ra, d);
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STBU ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 8 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STBU", &PPUInterpreter::STBU, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHZ ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LHZ", &PPUInterpreter::LHZ, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHZU ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateZExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LHZU", &PPUInterpreter::LHZU, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHA ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateSExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LHA", &PPUInterpreter::LHA, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LHAU ( u32 rd , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i16 = ReadMemory ( addr_i64 , 16 ) ;
auto mem_i64 = m_ir_builder - > CreateSExt ( mem_i16 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LHAU", &PPUInterpreter::LHAU, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STH ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
WriteMemory ( addr_i64 , GetGpr ( rs , 16 ) ) ;
//InterpreterCall("STH", &PPUInterpreter::STH, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STHU ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 16 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STHU", &PPUInterpreter::STHU, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LMW ( u32 rd , u32 ra , s32 d ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , GetGpr ( ra ) ) ;
}
for ( u32 i = rd ; i < 32 ; i + + ) {
auto val_i32 = ReadMemory ( addr_i64 , 32 ) ;
auto val_i64 = m_ir_builder - > CreateZExt ( val_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( i , val_i64 ) ;
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( 4 ) ) ;
}
//InterpreterCall("LMW", &PPUInterpreter::LMW, rd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STMW ( u32 rs , u32 ra , s32 d ) {
2014-10-18 22:27:54 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , GetGpr ( ra ) ) ;
}
for ( u32 i = rs ; i < 32 ; i + + ) {
auto val_i32 = GetGpr ( i , 32 ) ;
WriteMemory ( addr_i64 , val_i32 ) ;
addr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( 4 ) ) ;
}
//InterpreterCall("STMW", &PPUInterpreter::STMW, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFS ( u32 frd , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i32 = ReadMemory ( addr_i64 , 32 ) ;
SetFpr ( frd , mem_i32 ) ;
//InterpreterCall("LFS", &PPUInterpreter::LFS, frd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFSU ( u32 frd , u32 ra , s32 ds ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i32 = ReadMemory ( addr_i64 , 32 ) ;
SetFpr ( frd , mem_i32 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LFSU", &PPUInterpreter::LFSU, frd, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFD ( u32 frd , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetFpr ( frd , mem_i64 ) ;
//InterpreterCall("LFD", &PPUInterpreter::LFD, frd, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LFDU ( u32 frd , u32 ra , s32 ds ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetFpr ( frd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LFDU", &PPUInterpreter::LFDU, frd, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFS ( u32 frs , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto frs_i32 = m_ir_builder - > CreateBitCast ( GetFpr ( frs , 32 ) , m_ir_builder - > getInt32Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i32 ) ;
//InterpreterCall("STFS", &PPUInterpreter::STFS, frs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFSU ( u32 frs , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto frs_i32 = m_ir_builder - > CreateBitCast ( GetFpr ( frs , 32 ) , m_ir_builder - > getInt32Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i32 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STFSU", &PPUInterpreter::STFSU, frs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFD ( u32 frs , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto frs_i64 = m_ir_builder - > CreateBitCast ( GetFpr ( frs ) , m_ir_builder - > getInt64Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i64 ) ;
//InterpreterCall("STFD", &PPUInterpreter::STFD, frs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STFDU ( u32 frs , u32 ra , s32 d ) {
2014-09-15 16:37:38 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto frs_i64 = m_ir_builder - > CreateBitCast ( GetFpr ( frs ) , m_ir_builder - > getInt64Ty ( ) ) ;
WriteMemory ( addr_i64 , frs_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STFDU", &PPUInterpreter::STFDU, frs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LD ( u32 rd , u32 ra , s32 ds ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LD", &PPUInterpreter::LD, rd, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LDU ( u32 rd , u32 ra , s32 ds ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
auto mem_i64 = ReadMemory ( addr_i64 , 64 ) ;
SetGpr ( rd , mem_i64 ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("LDU", &PPUInterpreter::LDU, rd, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : LWA ( u32 rd , u32 ra , s32 ds ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
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 - > CreateSExt ( mem_i32 , m_ir_builder - > getInt64Ty ( ) ) ;
SetGpr ( rd , mem_i64 ) ;
//InterpreterCall("LWA", &PPUInterpreter::LWA, rd, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FDIVS ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFDiv ( ra_f64 , rb_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
//InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FSUBS ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFSub ( ra_f64 , rb_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FSUBS", &PPUInterpreter::FSUBS, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FADDS ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFAdd ( ra_f64 , rb_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
//InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FSQRTS ( u32 frd , u32 frb , bool rc ) {
2014-10-21 16:20:52 +02:00
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : sqrt , m_ir_builder - > getDoubleTy ( ) ) , rb_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FSQRTS", &PPUInterpreter::FSQRTS, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FRES ( u32 frd , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FRES " , & PPUInterpreter : : FRES , frd , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMULS ( u32 frd , u32 fra , u32 frc , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rc_f64 = GetFpr ( frc ) ;
auto res_f64 = m_ir_builder - > CreateFMul ( ra_f64 , rc_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
//InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMADDS ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-09-26 14:40:24 +02:00
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
2014-09-18 13:29:49 +02:00
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMSUBS ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
rb_f64 = m_ir_builder - > CreateFNeg ( rb_f64 ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-09-26 14:40:24 +02:00
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
2014-10-12 20:24:43 +02:00
//InterpreterCall("FMSUBS", &PPUInterpreter::FMSUBS, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNMSUBS ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
rb_f64 = m_ir_builder - > CreateFNeg ( rb_f64 ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
res_f64 = m_ir_builder - > CreateFNeg ( res_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FNMSUBS", &PPUInterpreter::FNMSUBS, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNMADDS ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
res_f64 = m_ir_builder - > CreateFNeg ( res_f64 ) ;
auto res_f32 = m_ir_builder - > CreateFPTrunc ( res_f64 , m_ir_builder - > getFloatTy ( ) ) ;
res_f64 = m_ir_builder - > CreateFPExt ( res_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FNMADDS", &PPUInterpreter::FNMADDS, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STD ( u32 rs , u32 ra , s32 d ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) d ) ;
if ( ra ) {
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
}
WriteMemory ( addr_i64 , GetGpr ( rs , 64 ) ) ;
//InterpreterCall("STD", &PPUInterpreter::STD, rs, ra, d);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : STDU ( u32 rs , u32 ra , s32 ds ) {
2014-09-15 16:34:09 +02:00
auto addr_i64 = ( Value * ) m_ir_builder - > getInt64 ( ( s64 ) ds ) ;
auto ra_i64 = GetGpr ( ra ) ;
addr_i64 = m_ir_builder - > CreateAdd ( ra_i64 , addr_i64 ) ;
WriteMemory ( addr_i64 , GetGpr ( rs , 64 ) ) ;
SetGpr ( ra , addr_i64 ) ;
//InterpreterCall("STDU", &PPUInterpreter::STDU, rs, ra, ds);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTFSB1 ( u32 crbd , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MTFSB1 " , & PPUInterpreter : : MTFSB1 , crbd , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MCRFS ( u32 crbd , u32 crbs ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MCRFS " , & PPUInterpreter : : MCRFS , crbd , crbs ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTFSB0 ( u32 crbd , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MTFSB0 " , & PPUInterpreter : : MTFSB0 , crbd , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTFSFI ( u32 crfd , u32 i , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MTFSFI " , & PPUInterpreter : : MTFSFI , crfd , i , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MFFS ( u32 frd , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MFFS " , & PPUInterpreter : : MFFS , frd , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : MTFSF ( u32 flm , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " MTFSF " , & PPUInterpreter : : MTFSF , flm , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCMPU ( u32 crfd , u32 fra , u32 frb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FCMPU " , & PPUInterpreter : : FCMPU , crfd , fra , frb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FRSP ( u32 frd , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
InterpreterCall ( " FRSP " , & PPUInterpreter : : FRSP , frd , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCTIW ( u32 frd , u32 frb , bool rc ) {
2014-10-23 18:46:04 +02:00
auto rb_f64 = GetFpr ( frb ) ;
auto res_i32 = m_ir_builder - > CreateFPToSI ( rb_f64 , m_ir_builder - > getInt32Ty ( ) ) ;
SetFpr ( frd , res_i32 ) ;
// TODO: Set flags / Handle NaN / Implement Saturation
//InterpreterCall("FCTIW", &PPUInterpreter::FCTIW, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCTIWZ ( u32 frd , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FCTIWZ " , & PPUInterpreter : : FCTIWZ , frd , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FDIV ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFDiv ( ra_f64 , rb_f64 ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FSUB ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFSub ( ra_f64 , rb_f64 ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FADD ( u32 frd , u32 fra , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = m_ir_builder - > CreateFAdd ( ra_f64 , rb_f64 ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-15 16:37:38 +02:00
2014-09-18 13:29:49 +02:00
// TODO: Set flags
//InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FSQRT ( u32 frd , u32 frb , bool rc ) {
2014-10-21 16:20:52 +02:00
auto rb_f64 = GetFpr ( frb ) ;
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : sqrt , m_ir_builder - > getDoubleTy ( ) ) , rb_f64 ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FSQRT", &PPUInterpreter::FSQRT, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FSEL ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FSEL " , & PPUInterpreter : : FSEL , frd , fra , frc , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMUL ( u32 frd , u32 fra , u32 frc , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rc_f64 = GetFpr ( frc ) ;
auto res_f64 = m_ir_builder - > CreateFMul ( ra_f64 , rc_f64 ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FRSQRTE ( u32 frd , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FRSQRTE " , & PPUInterpreter : : FRSQRTE , frd , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMSUB ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
rb_f64 = m_ir_builder - > CreateFNeg ( rb_f64 ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-09-26 14:40:24 +02:00
SetFpr ( frd , res_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
2014-09-26 14:40:24 +02:00
//InterpreterCall("FMSUB", &PPUInterpreter::FMSUB, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMADD ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-09-18 13:29:49 +02:00
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNMSUB ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
2014-10-19 21:46:35 +02:00
rc_f64 = m_ir_builder - > CreateFNeg ( rc_f64 ) ;
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FNMSUB", &PPUInterpreter::FNMSUB, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNMADD ( u32 frd , u32 fra , u32 frc , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto ra_f64 = GetFpr ( fra ) ;
auto rb_f64 = GetFpr ( frb ) ;
auto rc_f64 = GetFpr ( frc ) ;
2014-10-19 21:46:35 +02:00
rb_f64 = m_ir_builder - > CreateFNeg ( rb_f64 ) ;
rc_f64 = m_ir_builder - > CreateFNeg ( rc_f64 ) ;
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall3 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fmuladd , m_ir_builder - > getDoubleTy ( ) ) , ra_f64 , rc_f64 , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FNMADD", &PPUInterpreter::FNMADD, frd, fra, frc, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCMPO ( u32 crfd , u32 fra , u32 frb ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FCMPO " , & PPUInterpreter : : FCMPO , crfd , fra , frb ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNEG ( u32 frd , u32 frb , bool rc ) {
2014-09-26 14:40:24 +02:00
auto rb_f64 = GetFpr ( frb ) ;
rb_f64 = m_ir_builder - > CreateFNeg ( rb_f64 ) ;
SetFpr ( frd , rb_f64 ) ;
2014-09-18 13:29:49 +02:00
// TODO: Set flags
2014-09-26 14:40:24 +02:00
//InterpreterCall("FNEG", &PPUInterpreter::FNEG, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FMR ( u32 frd , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
SetFpr ( frd , GetFpr ( frb ) ) ;
// TODO: Set flags
//InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FNABS ( u32 frd , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto rb_f64 = GetFpr ( frb ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fabs , m_ir_builder - > getDoubleTy ( ) ) , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
res_f64 = m_ir_builder - > CreateFNeg ( res_f64 ) ;
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FNABS", &PPUInterpreter::FNABS, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FABS ( u32 frd , u32 frb , bool rc ) {
2014-10-12 20:24:43 +02:00
auto rb_f64 = GetFpr ( frb ) ;
2014-10-19 21:46:35 +02:00
auto res_f64 = ( Value * ) m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : fabs , m_ir_builder - > getDoubleTy ( ) ) , rb_f64 ) ;
2014-10-12 20:24:43 +02:00
SetFpr ( frd , res_f64 ) ;
// TODO: Set flags
//InterpreterCall("FABS", &PPUInterpreter::FABS, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCTID ( u32 frd , u32 frb , bool rc ) {
2014-10-23 18:46:04 +02:00
auto rb_f64 = GetFpr ( frb ) ;
auto res_i64 = m_ir_builder - > CreateFPToSI ( rb_f64 , m_ir_builder - > getInt64Ty ( ) ) ;
SetFpr ( frd , res_i64 ) ;
// TODO: Set flags / Handle NaN / Implement Saturation
//InterpreterCall("FCTID", &PPUInterpreter::FCTID, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCTIDZ ( u32 frd , u32 frb , bool rc ) {
2014-09-15 16:34:09 +02:00
InterpreterCall ( " FCTIDZ " , & PPUInterpreter : : FCTIDZ , frd , frb , rc ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : FCFID ( u32 frd , u32 frb , bool rc ) {
2014-09-18 13:29:49 +02:00
auto rb_i64 = GetFpr ( frb , 64 , true ) ;
auto res_f64 = m_ir_builder - > CreateSIToFP ( rb_i64 , m_ir_builder - > getDoubleTy ( ) ) ;
SetFpr ( frd , res_f64 ) ;
2014-09-22 22:22:20 +02:00
// TODO: Set flags
2014-09-18 13:29:49 +02:00
//InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc);
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : UNK ( const u32 code , const u32 opcode , const u32 gcode ) {
2014-09-15 16:34:09 +02:00
//InterpreterCall("UNK", &PPUInterpreter::UNK, code, opcode, gcode);
2014-09-15 16:19:43 +02:00
}
2014-09-22 22:22:20 +02:00
BasicBlock * PPULLVMRecompiler : : GetBlockInFunction ( u32 address , Function * function , bool create_if_not_exist ) {
auto block_name = fmt : : Format ( " instr_0x%X " , address ) ;
BasicBlock * block = nullptr ;
for ( auto i = function - > getBasicBlockList ( ) . begin ( ) ; i ! = function - > getBasicBlockList ( ) . end ( ) ; i + + ) {
if ( i - > getName ( ) = = block_name ) {
block = & ( * i ) ;
break ;
}
}
if ( ! block & & create_if_not_exist ) {
block = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , block_name , function ) ;
}
return block ;
}
2014-09-17 11:57:45 +02:00
void PPULLVMRecompiler : : Compile ( u32 address ) {
2014-09-22 22:22:20 +02:00
auto compilation_start = std : : chrono : : high_resolution_clock : : now ( ) ;
// Get the revision number for this section
u32 revision = 0 ;
auto compiled = m_compiled . lower_bound ( std : : make_pair ( address , 0 ) ) ;
if ( compiled ! = m_compiled . end ( ) & & compiled - > first . first = = address ) {
revision = ~ ( compiled - > first . second ) ;
revision + + ;
}
auto ir_build_start = std : : chrono : : high_resolution_clock : : now ( ) ;
// Create a function for this section
auto function_name = fmt : : Format ( " fn_0x%X_%u " , address , revision ) ;
m_current_function = ( Function * ) m_module - > getOrInsertFunction ( function_name , m_ir_builder - > getVoidTy ( ) ,
m_ir_builder - > getInt8PtrTy ( ) /*ppu_state*/ ,
m_ir_builder - > getInt8PtrTy ( ) /*interpreter*/ , nullptr ) ;
m_current_function - > setCallingConv ( CallingConv : : X86_64_Win64 ) ;
auto arg_i = m_current_function - > arg_begin ( ) ;
arg_i - > setName ( " ppu_state " ) ;
( + + arg_i ) - > setName ( " interpreter " ) ;
// Add an entry block that branches to the first instruction
m_ir_builder - > SetInsertPoint ( BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " entry " , m_current_function ) ) ;
m_ir_builder - > CreateBr ( GetBlockInFunction ( address , m_current_function , true ) ) ;
// Convert each block in this section to LLVM IR
m_num_instructions = 0 ;
m_current_function_uncompiled_blocks_list . clear ( ) ;
m_current_function_unhit_blocks_list . clear ( ) ;
m_current_function_uncompiled_blocks_list . push_back ( address ) ;
while ( ! m_current_function_uncompiled_blocks_list . empty ( ) ) {
m_current_instruction_address = m_current_function_uncompiled_blocks_list . front ( ) ;
auto block = GetBlockInFunction ( m_current_instruction_address , m_current_function , true ) ;
m_hit_branch_instruction = false ;
2014-09-15 16:35:51 +02:00
m_ir_builder - > SetInsertPoint ( block ) ;
2014-09-22 22:22:20 +02:00
m_current_function_uncompiled_blocks_list . pop_front ( ) ;
2014-09-15 16:35:51 +02:00
while ( ! m_hit_branch_instruction ) {
2014-09-22 22:22:20 +02:00
if ( ! block - > getInstList ( ) . empty ( ) ) {
break ;
}
u32 instr = vm : : read32 ( m_current_instruction_address ) ;
2014-09-15 16:35:51 +02:00
Decode ( instr ) ;
2014-09-22 22:22:20 +02:00
m_num_instructions + + ;
2014-09-15 16:35:51 +02:00
2014-09-22 22:22:20 +02:00
m_current_instruction_address + = 4 ;
if ( ! m_hit_branch_instruction ) {
block = GetBlockInFunction ( m_current_instruction_address , m_current_function , true ) ;
m_ir_builder - > CreateBr ( block ) ;
m_ir_builder - > SetInsertPoint ( block ) ;
}
2014-09-15 16:35:51 +02:00
}
2014-09-22 22:22:20 +02:00
}
2014-09-15 16:35:51 +02:00
2014-09-22 22:22:20 +02:00
auto ir_build_end = std : : chrono : : high_resolution_clock : : now ( ) ;
m_ir_build_time + = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( ir_build_end - ir_build_start ) ;
// Optimize this function
auto optimize_start = std : : chrono : : high_resolution_clock : : now ( ) ;
m_fpm - > run ( * m_current_function ) ;
auto optimize_end = std : : chrono : : high_resolution_clock : : now ( ) ;
m_optimizing_time + = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( optimize_end - optimize_start ) ;
// Translate to machine code
auto translate_start = std : : chrono : : high_resolution_clock : : now ( ) ;
MachineCodeInfo mci ;
m_execution_engine - > runJITOnFunction ( m_current_function , & mci ) ;
auto translate_end = std : : chrono : : high_resolution_clock : : now ( ) ;
m_translation_time + = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( translate_end - translate_start ) ;
// Add the executable to private and shared data stores
ExecutableInfo executable_info ;
executable_info . executable = ( Executable ) mci . address ( ) ;
executable_info . size = mci . size ( ) ;
executable_info . num_instructions = m_num_instructions ;
executable_info . unhit_blocks_list = std : : move ( m_current_function_unhit_blocks_list ) ;
executable_info . llvm_function = m_current_function ;
m_compiled [ std : : make_pair ( address , ~ revision ) ] = executable_info ;
{
std : : lock_guard < std : : mutex > lock ( m_compiled_shared_lock ) ;
m_compiled_shared [ std : : make_pair ( address , ~ revision ) ] = std : : make_pair ( executable_info . executable , 0 ) ;
}
2014-10-12 20:24:43 +02:00
if ( revision ) {
m_revision . fetch_add ( 1 , std : : memory_order_relaxed ) ;
}
2014-09-22 22:22:20 +02:00
auto compilation_end = std : : chrono : : high_resolution_clock : : now ( ) ;
m_compilation_time + = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( compilation_end - compilation_start ) ;
}
void PPULLVMRecompiler : : RemoveUnusedOldVersions ( ) {
u32 num_removed = 0 ;
u32 prev_address = 0 ;
for ( auto i = m_compiled . begin ( ) ; i ! = m_compiled . end ( ) ; i + + ) {
u32 current_address = i - > first . first ;
if ( prev_address = = current_address ) {
bool erase_this_entry = false ;
{
std : : lock_guard < std : : mutex > lock ( m_compiled_shared_lock ) ;
auto j = m_compiled_shared . find ( i - > first ) ;
if ( j - > second . second = = 0 ) {
m_compiled_shared . erase ( j ) ;
erase_this_entry = true ;
}
}
if ( erase_this_entry ) {
auto tmp = i ;
i - - ;
m_execution_engine - > freeMachineCodeForFunction ( tmp - > second . llvm_function ) ;
tmp - > second . llvm_function - > eraseFromParent ( ) ;
m_compiled . erase ( tmp ) ;
num_removed + + ;
}
2014-09-17 11:57:45 +02:00
}
2014-09-22 22:22:20 +02:00
prev_address = current_address ;
}
if ( num_removed > 0 ) {
LOG_NOTICE ( PPU , " Removed %u old versions " , num_removed ) ;
2014-09-17 11:57:45 +02:00
}
2014-09-22 22:22:20 +02:00
}
bool PPULLVMRecompiler : : NeedsCompiling ( u32 address ) {
auto i = m_compiled . lower_bound ( std : : make_pair ( address , 0 ) ) ;
if ( i ! = m_compiled . end ( ) & & i - > first . first = = address ) {
if ( i - > second . num_instructions > = 300 ) {
// This section has reached its limit. Don't allow further expansion.
return false ;
}
// If any of the unhit blocks in this function have been hit, then recompile this section
2014-10-08 22:04:17 +02:00
for ( auto j = i - > second . unhit_blocks_list . begin ( ) ; j ! = i - > second . unhit_blocks_list . end ( ) ; j + + ) {
2014-09-22 22:22:20 +02:00
if ( m_hit_blocks . find ( * j ) ! = m_hit_blocks . end ( ) ) {
return true ;
}
}
2014-09-15 16:35:51 +02:00
2014-09-22 22:22:20 +02:00
return false ;
} else {
// This section has not been encountered before
return true ;
}
2014-09-15 16:35:51 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetPPUState ( ) {
2014-09-22 22:22:20 +02:00
return m_current_function - > arg_begin ( ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetInterpreter ( ) {
2014-09-22 22:22:20 +02:00
auto i = m_current_function - > arg_begin ( ) ;
2014-09-15 16:34:09 +02:00
i + + ;
return i ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetBit ( Value * val , u32 n ) {
2014-09-15 16:27:05 +02:00
Value * bit ;
2014-09-18 14:04:49 +02:00
# ifdef PPU_LLVM_RECOMPILER_USE_BMI
2014-09-15 16:27:05 +02:00
if ( val - > getType ( ) - > isIntegerTy ( 32 ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_bmi_pext_32 ) , val , m_ir_builder - > getInt32 ( 1 < < ( 31 - n ) ) ) ;
2014-09-15 16:27:05 +02:00
} else if ( val - > getType ( ) - > isIntegerTy ( 64 ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_bmi_pext_64 ) , val , m_ir_builder - > getInt64 ( ( u64 ) 1 < < ( 63 - n ) ) ) ;
2014-09-15 16:27:05 +02:00
} else {
2014-09-18 14:04:49 +02:00
# endif
2014-09-15 16:27:05 +02:00
if ( val - > getType ( ) - > getIntegerBitWidth ( ) ! = ( n + 1 ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateLShr ( val , val - > getType ( ) - > getIntegerBitWidth ( ) - n - 1 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-22 22:22:20 +02:00
bit = m_ir_builder - > CreateAnd ( bit , 1 ) ;
2014-09-18 14:04:49 +02:00
# ifdef PPU_LLVM_RECOMPILER_USE_BMI
2014-09-15 16:27:05 +02:00
}
2014-09-18 14:04:49 +02:00
# endif
2014-09-15 16:27:05 +02:00
return bit ;
2014-09-15 16:26:36 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : ClrBit ( Value * val , u32 n ) {
2014-09-15 16:34:09 +02:00
return m_ir_builder - > CreateAnd ( val , ~ ( ( u64 ) 1 < < ( val - > getType ( ) - > getIntegerBitWidth ( ) - n - 1 ) ) ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : SetBit ( Value * val , u32 n , Value * bit , bool doClear ) {
2014-09-15 16:27:05 +02:00
if ( doClear ) {
val = ClrBit ( val , n ) ;
}
if ( bit - > getType ( ) - > getIntegerBitWidth ( ) < val - > getType ( ) - > getIntegerBitWidth ( ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateZExt ( bit , val - > getType ( ) ) ;
2014-09-15 16:27:05 +02:00
} else if ( bit - > getType ( ) - > getIntegerBitWidth ( ) > val - > getType ( ) - > getIntegerBitWidth ( ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateTrunc ( bit , val - > getType ( ) ) ;
2014-09-15 16:27:05 +02:00
}
if ( val - > getType ( ) - > getIntegerBitWidth ( ) ! = ( n + 1 ) ) {
2014-09-15 16:34:09 +02:00
bit = m_ir_builder - > CreateShl ( bit , bit - > getType ( ) - > getIntegerBitWidth ( ) - n - 1 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:34:09 +02:00
return m_ir_builder - > CreateOr ( val , bit ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetNibble ( Value * val , u32 n ) {
2014-09-15 16:27:05 +02:00
Value * nibble ;
2014-09-18 14:04:49 +02:00
# ifdef PPU_LLVM_RECOMPILER_USE_BMI
2014-09-15 16:27:05 +02:00
if ( val - > getType ( ) - > isIntegerTy ( 32 ) ) {
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_bmi_pext_32 ) , val , m_ir_builder - > getInt32 ( ( u64 ) 0xF < < ( ( 7 - n ) * 4 ) ) ) ;
2014-09-15 16:27:05 +02:00
} else if ( val - > getType ( ) - > isIntegerTy ( 64 ) ) {
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateCall2 ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_bmi_pext_64 ) , val , m_ir_builder - > getInt64 ( ( u64 ) 0xF < < ( ( 15 - n ) * 4 ) ) ) ;
2014-09-15 16:27:05 +02:00
} else {
2014-09-18 14:04:49 +02:00
# endif
2014-09-15 16:27:05 +02:00
if ( ( val - > getType ( ) - > getIntegerBitWidth ( ) > > 2 ) ! = ( n + 1 ) ) {
2014-09-26 14:40:24 +02:00
val = m_ir_builder - > CreateLShr ( val , ( ( ( val - > getType ( ) - > getIntegerBitWidth ( ) > > 2 ) - 1 ) - n ) * 4 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateAnd ( val , 0xF ) ;
2014-09-18 14:04:49 +02:00
# ifdef PPU_LLVM_RECOMPILER_USE_BMI
2014-09-15 16:27:05 +02:00
}
2014-09-18 14:04:49 +02:00
# endif
2014-09-15 16:27:05 +02:00
return nibble ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : ClrNibble ( Value * val , u32 n ) {
2014-09-15 16:34:09 +02:00
return m_ir_builder - > CreateAnd ( val , ~ ( ( u64 ) 0xF < < ( ( ( ( val - > getType ( ) - > getIntegerBitWidth ( ) > > 2 ) - 1 ) - n ) * 4 ) ) ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : SetNibble ( Value * val , u32 n , Value * nibble , bool doClear ) {
2014-09-15 16:27:05 +02:00
if ( doClear ) {
val = ClrNibble ( val , n ) ;
}
2014-09-15 16:26:55 +02:00
2014-09-15 16:27:05 +02:00
if ( nibble - > getType ( ) - > getIntegerBitWidth ( ) < val - > getType ( ) - > getIntegerBitWidth ( ) ) {
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateZExt ( nibble , val - > getType ( ) ) ;
2014-09-15 16:27:05 +02:00
} else if ( nibble - > getType ( ) - > getIntegerBitWidth ( ) > val - > getType ( ) - > getIntegerBitWidth ( ) ) {
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateTrunc ( nibble , val - > getType ( ) ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:27:05 +02:00
if ( ( val - > getType ( ) - > getIntegerBitWidth ( ) > > 2 ) ! = ( n + 1 ) ) {
2014-09-15 16:34:09 +02:00
nibble = m_ir_builder - > CreateShl ( nibble , ( ( ( val - > getType ( ) - > getIntegerBitWidth ( ) > > 2 ) - 1 ) - n ) * 4 ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:34:09 +02:00
return m_ir_builder - > CreateOr ( val , nibble ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : SetNibble ( Value * val , u32 n , Value * b0 , Value * b1 , Value * b2 , Value * b3 , bool doClear ) {
2014-09-15 16:27:05 +02:00
if ( doClear ) {
val = ClrNibble ( val , n ) ;
}
if ( b0 ) {
val = SetBit ( val , n * 4 , b0 , false ) ;
}
if ( b1 ) {
val = SetBit ( val , ( n * 4 ) + 1 , b1 , false ) ;
}
if ( b2 ) {
val = SetBit ( val , ( n * 4 ) + 2 , b2 , false ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:27:05 +02:00
if ( b3 ) {
val = SetBit ( val , ( n * 4 ) + 3 , b3 , false ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:27:05 +02:00
return val ;
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetPc ( ) {
auto pc_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , PC ) ) ;
2014-09-17 11:57:45 +02:00
auto pc_i32_ptr = m_ir_builder - > CreateBitCast ( pc_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( pc_i32_ptr , 4 ) ;
2014-09-09 23:30:53 +02:00
}
2014-09-22 22:22:20 +02:00
void PPULLVMRecompiler : : SetPc ( Value * val_ix ) {
2014-09-15 16:35:18 +02:00
auto pc_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , PC ) ) ;
2014-09-17 11:57:45 +02:00
auto pc_i32_ptr = m_ir_builder - > CreateBitCast ( pc_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-09-22 22:22:20 +02:00
auto val_i32 = m_ir_builder - > CreateZExtOrTrunc ( val_ix , m_ir_builder - > getInt32Ty ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i32 , pc_i32_ptr , 4 ) ;
2014-09-09 23:30:53 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetGpr ( u32 r , u32 num_bits ) {
auto r_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , GPR [ r ] ) ) ;
2014-09-15 16:34:09 +02:00
auto r_ix_ptr = m_ir_builder - > CreateBitCast ( r_i8_ptr , m_ir_builder - > getIntNTy ( num_bits ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( r_ix_ptr , 8 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetGpr ( u32 r , Value * val_x64 ) {
auto r_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , GPR [ r ] ) ) ;
2014-09-15 16:34:09 +02:00
auto r_i64_ptr = m_ir_builder - > CreateBitCast ( r_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
auto val_i64 = m_ir_builder - > CreateBitCast ( val_x64 , m_ir_builder - > getInt64Ty ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i64 , r_i64_ptr , 8 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetCr ( ) {
auto cr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , CR ) ) ;
2014-09-15 16:34:09 +02:00
auto cr_i32_ptr = m_ir_builder - > CreateBitCast ( cr_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( cr_i32_ptr , 4 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetCrField ( u32 n ) {
2014-09-15 16:27:05 +02:00
return GetNibble ( GetCr ( ) , n ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCr ( Value * val_x32 ) {
2014-09-15 16:34:09 +02:00
auto val_i32 = m_ir_builder - > CreateBitCast ( val_x32 , m_ir_builder - > getInt32Ty ( ) ) ;
2014-09-15 16:35:18 +02:00
auto cr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , CR ) ) ;
2014-09-15 16:34:09 +02:00
auto cr_i32_ptr = m_ir_builder - > CreateBitCast ( cr_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i32 , cr_i32_ptr , 4 ) ;
2014-09-15 16:27:05 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCrField ( u32 n , Value * field ) {
2014-09-15 16:27:05 +02:00
SetCr ( SetNibble ( GetCr ( ) , n , field ) ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCrField ( u32 n , Value * b0 , Value * b1 , Value * b2 , Value * b3 ) {
2014-09-15 16:27:05 +02:00
SetCr ( SetNibble ( GetCr ( ) , n , b0 , b1 , b2 , b3 ) ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCrFieldSignedCmp ( u32 n , Value * a , Value * b ) {
2014-09-15 16:34:09 +02:00
auto lt_i1 = m_ir_builder - > CreateICmpSLT ( a , b ) ;
auto gt_i1 = m_ir_builder - > CreateICmpSGT ( a , b ) ;
auto eq_i1 = m_ir_builder - > CreateICmpEQ ( a , b ) ;
2014-09-15 16:27:05 +02:00
auto cr_i32 = GetCr ( ) ;
cr_i32 = SetNibble ( cr_i32 , n , lt_i1 , gt_i1 , eq_i1 , GetXerSo ( ) ) ;
2014-09-15 16:26:55 +02:00
SetCr ( cr_i32 ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCrFieldUnsignedCmp ( u32 n , Value * a , Value * b ) {
2014-09-15 16:34:09 +02:00
auto lt_i1 = m_ir_builder - > CreateICmpULT ( a , b ) ;
auto gt_i1 = m_ir_builder - > CreateICmpUGT ( a , b ) ;
auto eq_i1 = m_ir_builder - > CreateICmpEQ ( a , b ) ;
2014-09-15 16:27:05 +02:00
auto cr_i32 = GetCr ( ) ;
cr_i32 = SetNibble ( cr_i32 , n , lt_i1 , gt_i1 , eq_i1 , GetXerSo ( ) ) ;
SetCr ( cr_i32 ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetCr6AfterVectorCompare ( u32 vr ) {
2014-09-15 16:26:55 +02:00
auto vr_v16i8 = GetVrAsIntVec ( vr , 8 ) ;
2014-09-15 16:34:09 +02:00
auto vr_mask_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : x86_sse2_pmovmskb_128 ) , vr_v16i8 ) ;
auto cmp0_i1 = m_ir_builder - > CreateICmpEQ ( vr_mask_i32 , m_ir_builder - > getInt32 ( 0 ) ) ;
auto cmp1_i1 = m_ir_builder - > CreateICmpEQ ( vr_mask_i32 , m_ir_builder - > getInt32 ( 0xFFFF ) ) ;
2014-09-15 16:27:05 +02:00
auto cr_i32 = GetCr ( ) ;
cr_i32 = SetNibble ( cr_i32 , 6 , cmp1_i1 , nullptr , cmp0_i1 , nullptr ) ;
SetCr ( cr_i32 ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:37:38 +02:00
Value * PPULLVMRecompiler : : GetLr ( ) {
auto lr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , LR ) ) ;
auto lr_i64_ptr = m_ir_builder - > CreateBitCast ( lr_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( lr_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
void PPULLVMRecompiler : : SetLr ( Value * val_x64 ) {
auto val_i64 = m_ir_builder - > CreateBitCast ( val_x64 , m_ir_builder - > getInt64Ty ( ) ) ;
auto lr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , LR ) ) ;
auto lr_i64_ptr = m_ir_builder - > CreateBitCast ( lr_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i64 , lr_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
Value * PPULLVMRecompiler : : GetCtr ( ) {
auto ctr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , CTR ) ) ;
auto ctr_i64_ptr = m_ir_builder - > CreateBitCast ( ctr_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( ctr_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
void PPULLVMRecompiler : : SetCtr ( Value * val_x64 ) {
auto val_i64 = m_ir_builder - > CreateBitCast ( val_x64 , m_ir_builder - > getInt64Ty ( ) ) ;
auto ctr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , CTR ) ) ;
auto ctr_i64_ptr = m_ir_builder - > CreateBitCast ( ctr_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i64 , ctr_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetXer ( ) {
auto xer_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , XER ) ) ;
2014-09-15 16:34:09 +02:00
auto xer_i64_ptr = m_ir_builder - > CreateBitCast ( xer_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( xer_i64_ptr , 8 ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetXerCa ( ) {
2014-09-15 16:27:05 +02:00
return GetBit ( GetXer ( ) , 34 ) ;
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetXerSo ( ) {
2014-09-15 16:27:05 +02:00
return GetBit ( GetXer ( ) , 32 ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetXer ( Value * val_x64 ) {
2014-09-15 16:34:09 +02:00
auto val_i64 = m_ir_builder - > CreateBitCast ( val_x64 , m_ir_builder - > getInt64Ty ( ) ) ;
2014-09-15 16:35:18 +02:00
auto xer_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , XER ) ) ;
2014-09-15 16:34:09 +02:00
auto xer_i64_ptr = m_ir_builder - > CreateBitCast ( xer_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i64 , xer_i64_ptr , 8 ) ;
2014-09-15 16:26:55 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetXerCa ( Value * ca ) {
2014-09-15 16:27:05 +02:00
auto xer_i64 = GetXer ( ) ;
xer_i64 = SetBit ( xer_i64 , 34 , ca ) ;
SetXer ( xer_i64 ) ;
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetXerSo ( Value * so ) {
2014-09-15 16:26:55 +02:00
auto xer_i64 = GetXer ( ) ;
2014-09-15 16:27:05 +02:00
xer_i64 = SetBit ( xer_i64 , 32 , so ) ;
2014-09-15 16:26:55 +02:00
SetXer ( xer_i64 ) ;
2014-09-15 16:26:36 +02:00
}
2014-09-15 16:37:38 +02:00
Value * PPULLVMRecompiler : : GetUsprg0 ( ) {
auto usrpg0_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , USPRG0 ) ) ;
auto usprg0_i64_ptr = m_ir_builder - > CreateBitCast ( usrpg0_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( usprg0_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
void PPULLVMRecompiler : : SetUsprg0 ( Value * val_x64 ) {
auto val_i64 = m_ir_builder - > CreateBitCast ( val_x64 , m_ir_builder - > getInt64Ty ( ) ) ;
auto usprg0_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , USPRG0 ) ) ;
auto usprg0_i64_ptr = m_ir_builder - > CreateBitCast ( usprg0_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i64 , usprg0_i64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
2014-09-18 13:29:49 +02:00
Value * PPULLVMRecompiler : : GetFpr ( u32 r , u32 bits , bool as_int ) {
auto r_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , FPR [ r ] ) ) ;
if ( ! as_int ) {
auto r_f64_ptr = m_ir_builder - > CreateBitCast ( r_i8_ptr , m_ir_builder - > getDoubleTy ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
auto r_f64 = m_ir_builder - > CreateAlignedLoad ( r_f64_ptr , 8 ) ;
2014-09-18 13:29:49 +02:00
if ( bits = = 32 ) {
return m_ir_builder - > CreateFPTrunc ( r_f64 , m_ir_builder - > getFloatTy ( ) ) ;
} else {
return r_f64 ;
}
2014-09-15 16:37:38 +02:00
} else {
2014-09-18 13:29:49 +02:00
auto r_i64_ptr = m_ir_builder - > CreateBitCast ( r_i8_ptr , m_ir_builder - > getInt64Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
auto r_i64 = m_ir_builder - > CreateAlignedLoad ( r_i64_ptr , 8 ) ;
2014-09-18 13:29:49 +02:00
if ( bits = = 32 ) {
return m_ir_builder - > CreateTrunc ( r_i64 , m_ir_builder - > getInt32Ty ( ) ) ;
} else {
return r_i64 ;
}
2014-09-15 16:37:38 +02:00
}
}
void PPULLVMRecompiler : : SetFpr ( u32 r , Value * val ) {
auto r_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , FPR [ r ] ) ) ;
auto r_f64_ptr = m_ir_builder - > CreateBitCast ( r_i8_ptr , m_ir_builder - > getDoubleTy ( ) - > getPointerTo ( ) ) ;
Value * val_f64 ;
if ( val - > getType ( ) - > isDoubleTy ( ) | | val - > getType ( ) - > isIntegerTy ( 64 ) ) {
val_f64 = m_ir_builder - > CreateBitCast ( val , m_ir_builder - > getDoubleTy ( ) ) ;
} else if ( val - > getType ( ) - > isFloatTy ( ) | | val - > getType ( ) - > isIntegerTy ( 32 ) ) {
auto val_f32 = m_ir_builder - > CreateBitCast ( val , m_ir_builder - > getFloatTy ( ) ) ;
val_f64 = m_ir_builder - > CreateFPExt ( val_f32 , m_ir_builder - > getDoubleTy ( ) ) ;
} else {
assert ( 0 ) ;
}
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_f64 , r_f64_ptr , 8 ) ;
2014-09-15 16:37:38 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetVscr ( ) {
auto vscr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VSCR ) ) ;
2014-09-15 16:34:09 +02:00
auto vscr_i32_ptr = m_ir_builder - > CreateBitCast ( vscr_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( vscr_i32_ptr , 4 ) ;
2014-09-09 23:30:53 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetVscr ( Value * val_x32 ) {
2014-09-15 16:34:09 +02:00
auto val_i32 = m_ir_builder - > CreateBitCast ( val_x32 , m_ir_builder - > getInt32Ty ( ) ) ;
2014-09-15 16:35:18 +02:00
auto vscr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VSCR ) ) ;
2014-09-15 16:34:09 +02:00
auto vscr_i32_ptr = m_ir_builder - > CreateBitCast ( vscr_i8_ptr , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i32 , vscr_i32_ptr , 4 ) ;
2014-09-09 23:30:53 +02:00
}
2014-10-12 20:24:43 +02:00
Value * PPULLVMRecompiler : : GetVr ( u32 vr ) {
auto vr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VPR [ vr ] ) ) ;
auto vr_i128_ptr = m_ir_builder - > CreateBitCast ( vr_i8_ptr , m_ir_builder - > getIntNTy ( 128 ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( vr_i128_ptr , 16 ) ;
2014-10-12 20:24:43 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetVrAsIntVec ( u32 vr , u32 vec_elt_num_bits ) {
auto vr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VPR [ vr ] ) ) ;
2014-09-15 16:34:09 +02:00
auto vr_i128_ptr = m_ir_builder - > CreateBitCast ( vr_i8_ptr , m_ir_builder - > getIntNTy ( 128 ) - > getPointerTo ( ) ) ;
auto vr_vec_ptr = m_ir_builder - > CreateBitCast ( vr_i128_ptr , VectorType : : get ( m_ir_builder - > getIntNTy ( vec_elt_num_bits ) , 128 / vec_elt_num_bits ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( vr_vec_ptr , 16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetVrAsFloatVec ( u32 vr ) {
auto vr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VPR [ vr ] ) ) ;
2014-09-15 16:34:09 +02:00
auto vr_i128_ptr = m_ir_builder - > CreateBitCast ( vr_i8_ptr , m_ir_builder - > getIntNTy ( 128 ) - > getPointerTo ( ) ) ;
auto vr_v4f32_ptr = m_ir_builder - > CreateBitCast ( vr_i128_ptr , VectorType : : get ( m_ir_builder - > getFloatTy ( ) , 4 ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( vr_v4f32_ptr , 16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : GetVrAsDoubleVec ( u32 vr ) {
auto vr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VPR [ vr ] ) ) ;
2014-09-15 16:34:09 +02:00
auto vr_i128_ptr = m_ir_builder - > CreateBitCast ( vr_i8_ptr , m_ir_builder - > getIntNTy ( 128 ) - > getPointerTo ( ) ) ;
auto vr_v2f64_ptr = m_ir_builder - > CreateBitCast ( vr_i128_ptr , VectorType : : get ( m_ir_builder - > getDoubleTy ( ) , 2 ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
return m_ir_builder - > CreateAlignedLoad ( vr_v2f64_ptr , 16 ) ;
2014-09-15 16:19:43 +02:00
}
2014-09-15 16:35:18 +02:00
void PPULLVMRecompiler : : SetVr ( u32 vr , Value * val_x128 ) {
auto vr_i8_ptr = m_ir_builder - > CreateConstGEP1_32 ( GetPPUState ( ) , ( unsigned int ) offsetof ( PPUThread , VPR [ vr ] ) ) ;
2014-09-15 16:34:09 +02:00
auto vr_i128_ptr = m_ir_builder - > CreateBitCast ( vr_i8_ptr , m_ir_builder - > getIntNTy ( 128 ) - > getPointerTo ( ) ) ;
auto val_i128 = m_ir_builder - > CreateBitCast ( val_x128 , m_ir_builder - > getIntNTy ( 128 ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_i128 , vr_i128_ptr , 16 ) ;
2014-09-15 16:16:53 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-22 22:22:20 +02:00
Value * PPULLVMRecompiler : : CheckBranchCondition ( u32 bo , u32 bi ) {
bool bo0 = bo & 0x10 ? true : false ;
bool bo1 = bo & 0x08 ? true : false ;
bool bo2 = bo & 0x04 ? true : false ;
bool bo3 = bo & 0x02 ? true : false ;
auto ctr_i64 = GetCtr ( ) ;
if ( ! bo2 ) {
ctr_i64 = m_ir_builder - > CreateSub ( ctr_i64 , m_ir_builder - > getInt64 ( 1 ) ) ;
SetCtr ( ctr_i64 ) ;
}
Value * ctr_ok_i1 = nullptr ;
if ( ! bo2 ) {
// TODO: Check if we should compare all bits or just the lower 32 bits. This depends on MSR[SF]. Not sure what it is for PS3.
ctr_ok_i1 = m_ir_builder - > CreateICmpNE ( ctr_i64 , m_ir_builder - > getInt64 ( 0 ) ) ;
if ( bo3 ) {
ctr_ok_i1 = m_ir_builder - > CreateXor ( ctr_ok_i1 , m_ir_builder - > getInt1 ( bo3 ) ) ;
}
}
Value * cond_ok_i1 = nullptr ;
if ( ! bo0 ) {
auto cr_bi_i32 = GetBit ( GetCr ( ) , bi ) ;
cond_ok_i1 = m_ir_builder - > CreateTrunc ( cr_bi_i32 , m_ir_builder - > getInt1Ty ( ) ) ;
if ( ! bo1 ) {
cond_ok_i1 = m_ir_builder - > CreateXor ( cond_ok_i1 , m_ir_builder - > getInt1 ( ! bo1 ) ) ;
}
}
Value * cmp_i1 = nullptr ;
if ( ctr_ok_i1 & & cond_ok_i1 ) {
cmp_i1 = m_ir_builder - > CreateAnd ( ctr_ok_i1 , cond_ok_i1 ) ;
} else if ( ctr_ok_i1 ) {
cmp_i1 = ctr_ok_i1 ;
} else if ( cond_ok_i1 ) {
cmp_i1 = cond_ok_i1 ;
}
return cmp_i1 ;
}
void PPULLVMRecompiler : : CreateBranch ( llvm : : Value * cmp_i1 , llvm : : Value * target_i64 , bool lk ) {
if ( lk ) {
SetLr ( m_ir_builder - > getInt64 ( m_current_instruction_address + 4 ) ) ;
}
auto current_block = m_ir_builder - > GetInsertBlock ( ) ;
BasicBlock * target_block = nullptr ;
if ( dyn_cast < ConstantInt > ( target_i64 ) ) {
// Target address is an immediate value.
u32 target_address = ( u32 ) ( dyn_cast < ConstantInt > ( target_i64 ) - > getLimitedValue ( ) ) ;
target_block = GetBlockInFunction ( target_address , m_current_function ) ;
if ( ! target_block ) {
target_block = GetBlockInFunction ( target_address , m_current_function , true ) ;
2014-10-08 22:04:17 +02:00
if ( ( m_hit_blocks . find ( target_address ) ! = m_hit_blocks . end ( ) | | ! cmp_i1 ) & & m_num_instructions < 300 ) {
2014-09-22 22:22:20 +02:00
// Target block has either been hit or this is an unconditional branch.
m_current_function_uncompiled_blocks_list . push_back ( target_address ) ;
m_hit_blocks . insert ( target_address ) ;
} else {
// Target block has not been encountered yet and this is not an unconditional branch
m_ir_builder - > SetInsertPoint ( target_block ) ;
SetPc ( target_i64 ) ;
m_ir_builder - > CreateRetVoid ( ) ;
m_current_function_unhit_blocks_list . push_back ( target_address ) ;
}
}
} else {
// Target addres is in a register
target_block = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function ) ;
m_ir_builder - > SetInsertPoint ( target_block ) ;
SetPc ( target_i64 ) ;
m_ir_builder - > CreateRetVoid ( ) ;
}
if ( cmp_i1 ) {
// Conditional branch
auto next_block = GetBlockInFunction ( m_current_instruction_address + 4 , m_current_function ) ;
if ( ! next_block ) {
next_block = GetBlockInFunction ( m_current_instruction_address + 4 , m_current_function , true ) ;
if ( m_hit_blocks . find ( m_current_instruction_address + 4 ) ! = m_hit_blocks . end ( ) & & m_num_instructions < 300 ) {
// Next block has already been hit.
m_current_function_uncompiled_blocks_list . push_back ( m_current_instruction_address + 4 ) ;
} else {
// Next block has not been encountered yet
m_ir_builder - > SetInsertPoint ( next_block ) ;
SetPc ( m_ir_builder - > getInt32 ( m_current_instruction_address + 4 ) ) ;
m_ir_builder - > CreateRetVoid ( ) ;
m_current_function_unhit_blocks_list . push_back ( m_current_instruction_address + 4 ) ;
}
}
m_ir_builder - > SetInsertPoint ( current_block ) ;
m_ir_builder - > CreateCondBr ( cmp_i1 , target_block , next_block ) ;
} else {
// Unconditional branch
m_ir_builder - > SetInsertPoint ( current_block ) ;
m_ir_builder - > CreateBr ( target_block ) ;
}
m_hit_branch_instruction = true ;
}
2014-10-18 22:27:54 +02:00
Value * PPULLVMRecompiler : : ReadMemory ( Value * addr_i64 , u32 bits , u32 alignment , bool bswap , bool could_be_mmio ) {
if ( bits ! = 32 | | could_be_mmio = = false ) {
2014-10-16 11:58:57 +02:00
auto eaddr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( ( u64 ) vm : : get_ptr < u8 > ( 0 ) ) ) ;
2014-09-15 16:34:09 +02:00
auto eaddr_ix_ptr = m_ir_builder - > CreateIntToPtr ( eaddr_i64 , m_ir_builder - > getIntNTy ( bits ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
auto val_ix = ( Value * ) m_ir_builder - > CreateLoad ( eaddr_ix_ptr , alignment ) ;
2014-09-15 16:34:09 +02:00
if ( bits > 8 & & bswap ) {
2014-10-19 21:46:35 +02:00
val_ix = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getIntNTy ( bits ) ) , val_ix ) ;
2014-09-15 16:34:09 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:34:09 +02:00
return val_ix ;
} else {
2014-09-22 22:22:20 +02:00
BasicBlock * next_block = nullptr ;
for ( auto i = m_current_function - > begin ( ) ; i ! = m_current_function - > end ( ) ; i + + ) {
if ( & ( * i ) = = m_ir_builder - > GetInsertBlock ( ) ) {
i + + ;
if ( i ! = m_current_function - > end ( ) ) {
next_block = & ( * i ) ;
}
break ;
}
}
2014-09-15 16:34:09 +02:00
auto cmp_i1 = m_ir_builder - > CreateICmpULT ( addr_i64 , m_ir_builder - > getInt64 ( RAW_SPU_BASE_ADDR ) ) ;
2014-09-22 22:22:20 +02:00
auto then_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
auto else_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
auto merge_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateCondBr ( cmp_i1 , then_bb , else_bb ) ;
m_ir_builder - > SetInsertPoint ( then_bb ) ;
2014-10-16 11:58:57 +02:00
auto eaddr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( ( u64 ) vm : : get_ptr < u8 > ( 0 ) ) ) ;
2014-09-15 16:34:09 +02:00
auto eaddr_i32_ptr = m_ir_builder - > CreateIntToPtr ( eaddr_i64 , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
auto val_then_i32 = ( Value * ) m_ir_builder - > CreateAlignedLoad ( eaddr_i32_ptr , alignment ) ;
2014-09-15 16:34:09 +02:00
if ( bswap ) {
2014-10-19 21:46:35 +02:00
val_then_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt32Ty ( ) ) , val_then_i32 ) ;
2014-09-15 16:34:09 +02:00
}
2014-09-15 16:28:38 +02:00
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateBr ( merge_bb ) ;
2014-09-15 16:28:38 +02:00
2014-09-15 16:34:09 +02:00
m_ir_builder - > SetInsertPoint ( else_bb ) ;
2014-09-17 11:57:45 +02:00
auto val_else_i32 = Call < u32 > ( " vm_read32 " , ( u32 ( * ) ( u64 ) ) vm : : read32 , addr_i64 ) ;
2014-09-15 16:34:09 +02:00
if ( ! bswap ) {
2014-10-19 21:46:35 +02:00
val_else_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt32Ty ( ) ) , val_else_i32 ) ;
2014-09-15 16:34:09 +02:00
}
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 ;
}
}
2014-10-18 22:27:54 +02:00
void PPULLVMRecompiler : : WriteMemory ( Value * addr_i64 , Value * val_ix , u32 alignment , bool bswap , bool could_be_mmio ) {
2014-09-17 11:57:45 +02:00
addr_i64 = m_ir_builder - > CreateAnd ( addr_i64 , 0xFFFFFFFF ) ;
2014-10-18 22:27:54 +02:00
if ( val_ix - > getType ( ) - > getIntegerBitWidth ( ) ! = 32 | | could_be_mmio = = false ) {
2014-09-15 16:34:09 +02:00
if ( val_ix - > getType ( ) - > getIntegerBitWidth ( ) > 8 & & bswap ) {
2014-10-19 21:46:35 +02:00
val_ix = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , val_ix - > getType ( ) ) , val_ix ) ;
2014-09-15 16:34:09 +02:00
}
2014-10-16 11:58:57 +02:00
auto eaddr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( ( u64 ) vm : : get_ptr < u8 > ( 0 ) ) ) ;
2014-09-15 16:34:09 +02:00
auto eaddr_ix_ptr = m_ir_builder - > CreateIntToPtr ( eaddr_i64 , val_ix - > getType ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_ix , eaddr_ix_ptr , alignment ) ;
2014-09-15 16:34:09 +02:00
} else {
2014-09-22 22:22:20 +02:00
BasicBlock * next_block = nullptr ;
for ( auto i = m_current_function - > begin ( ) ; i ! = m_current_function - > end ( ) ; i + + ) {
if ( & ( * i ) = = m_ir_builder - > GetInsertBlock ( ) ) {
i + + ;
if ( i ! = m_current_function - > end ( ) ) {
next_block = & ( * i ) ;
}
break ;
}
}
2014-09-15 16:34:09 +02:00
auto cmp_i1 = m_ir_builder - > CreateICmpULT ( addr_i64 , m_ir_builder - > getInt64 ( RAW_SPU_BASE_ADDR ) ) ;
2014-09-22 22:22:20 +02:00
auto then_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
auto else_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
auto merge_bb = BasicBlock : : Create ( m_ir_builder - > getContext ( ) , " " , m_current_function , next_block ) ;
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateCondBr ( cmp_i1 , then_bb , else_bb ) ;
m_ir_builder - > SetInsertPoint ( then_bb ) ;
2014-09-17 11:57:45 +02:00
Value * val_then_i32 = val_ix ;
2014-09-15 16:34:09 +02:00
if ( bswap ) {
2014-10-19 21:46:35 +02:00
val_then_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt32Ty ( ) ) , val_then_i32 ) ;
2014-09-15 16:34:09 +02:00
}
2014-10-16 11:58:57 +02:00
auto eaddr_i64 = m_ir_builder - > CreateAdd ( addr_i64 , m_ir_builder - > getInt64 ( ( u64 ) vm : : get_ptr < u8 > ( 0 ) ) ) ;
2014-09-15 16:34:09 +02:00
auto eaddr_i32_ptr = m_ir_builder - > CreateIntToPtr ( eaddr_i64 , m_ir_builder - > getInt32Ty ( ) - > getPointerTo ( ) ) ;
2014-10-18 22:27:54 +02:00
m_ir_builder - > CreateAlignedStore ( val_then_i32 , eaddr_i32_ptr , alignment ) ;
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateBr ( merge_bb ) ;
m_ir_builder - > SetInsertPoint ( else_bb ) ;
2014-09-17 11:57:45 +02:00
Value * val_else_i32 = val_ix ;
2014-09-15 16:34:09 +02:00
if ( ! bswap ) {
2014-10-19 21:46:35 +02:00
val_else_i32 = m_ir_builder - > CreateCall ( Intrinsic : : getDeclaration ( m_module , Intrinsic : : bswap , m_ir_builder - > getInt32Ty ( ) ) , val_else_i32 ) ;
2014-09-15 16:34:09 +02:00
}
2014-09-17 11:57:45 +02:00
Call < void > ( " vm_write32 " , ( void ( * ) ( u64 , u32 ) ) vm : : write32 , addr_i64 , val_else_i32 ) ;
2014-09-15 16:34:09 +02:00
m_ir_builder - > CreateBr ( merge_bb ) ;
m_ir_builder - > SetInsertPoint ( merge_bb ) ;
}
}
template < class Func , class . . . Args >
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : InterpreterCall ( const char * name , Func function , Args . . . args ) {
2014-09-15 16:34:09 +02:00
auto i = m_interpreter_fallback_stats . find ( name ) ;
if ( i = = m_interpreter_fallback_stats . end ( ) ) {
i = m_interpreter_fallback_stats . insert ( m_interpreter_fallback_stats . end ( ) , std : : make_pair < std : : string , u64 > ( name , 0 ) ) ;
2014-09-15 16:28:38 +02:00
}
2014-09-15 16:33:06 +02:00
i - > second + + ;
2014-09-15 16:34:09 +02:00
2014-09-17 11:57:45 +02:00
return Call < void > ( name , function , GetInterpreter ( ) , m_ir_builder - > getInt32 ( args ) . . . ) ;
2014-09-15 16:34:09 +02:00
}
template < class T >
2014-09-15 16:35:18 +02:00
Type * PPULLVMRecompiler : : CppToLlvmType ( ) {
2014-09-15 16:34:09 +02:00
if ( std : : is_void < T > : : value ) {
return m_ir_builder - > getVoidTy ( ) ;
} else if ( std : : is_same < T , long long > : : value | | std : : is_same < T , unsigned long long > : : value ) {
return m_ir_builder - > getInt64Ty ( ) ;
} else if ( std : : is_same < T , int > : : value | | std : : is_same < T , unsigned int > : : value ) {
return m_ir_builder - > getInt32Ty ( ) ;
} else if ( std : : is_same < T , short > : : value | | std : : is_same < T , unsigned short > : : value ) {
return m_ir_builder - > getInt16Ty ( ) ;
} else if ( std : : is_same < T , char > : : value | | std : : is_same < T , unsigned char > : : value ) {
2014-09-26 14:40:24 +02:00
return m_ir_builder - > getInt8Ty ( ) ;
2014-09-15 16:34:09 +02:00
} else if ( std : : is_same < T , float > : : value ) {
return m_ir_builder - > getFloatTy ( ) ;
} else if ( std : : is_same < T , double > : : value ) {
return m_ir_builder - > getDoubleTy ( ) ;
} else if ( std : : is_pointer < T > : : value ) {
return m_ir_builder - > getInt8PtrTy ( ) ;
} else {
assert ( 0 ) ;
}
return nullptr ;
2014-09-15 16:28:38 +02:00
}
2014-09-17 11:57:45 +02:00
template < class ReturnType , class Func , class . . . Args >
2014-09-15 16:35:18 +02:00
Value * PPULLVMRecompiler : : Call ( const char * name , Func function , Args . . . args ) {
2014-09-15 16:34:09 +02:00
auto fn = m_module - > getFunction ( name ) ;
if ( ! fn ) {
std : : vector < Type * > fn_args_type = { args - > getType ( ) . . . } ;
auto fn_type = FunctionType : : get ( CppToLlvmType < ReturnType > ( ) , fn_args_type , false ) ;
fn = cast < Function > ( m_module - > getOrInsertFunction ( name , fn_type ) ) ;
fn - > setCallingConv ( CallingConv : : X86_64_Win64 ) ;
m_execution_engine - > addGlobalMapping ( fn , ( void * & ) function ) ;
}
std : : vector < Value * > fn_args = { args . . . } ;
return m_ir_builder - > CreateCall ( fn , fn_args ) ;
}
2014-09-15 16:37:38 +02:00
void PPULLVMRecompiler : : InitRotateMask ( ) {
for ( u32 mb = 0 ; mb < 64 ; mb + + ) {
for ( u32 me = 0 ; me < 64 ; me + + ) {
u64 mask = ( ( u64 ) - 1 > > mb ) ^ ( ( me > = 63 ) ? 0 : ( u64 ) - 1 > > ( me + 1 ) ) ;
s_rotate_mask [ mb ] [ me ] = mb > me ? ~ mask : mask ;
}
}
}
2014-09-15 16:35:18 +02:00
u32 PPULLVMEmulator : : s_num_instances = 0 ;
std : : mutex PPULLVMEmulator : : s_recompiler_mutex ;
PPULLVMRecompiler * PPULLVMEmulator : : s_recompiler = nullptr ;
PPULLVMEmulator : : PPULLVMEmulator ( PPUThread & ppu )
2014-09-15 16:34:09 +02:00
: m_ppu ( ppu )
2014-09-15 16:35:18 +02:00
, m_interpreter ( new PPUInterpreter ( ppu ) )
2014-10-08 22:04:17 +02:00
, m_decoder ( m_interpreter )
, m_last_instr_was_branch ( true )
, m_last_cache_clear_time ( std : : chrono : : high_resolution_clock : : now ( ) )
, m_recompiler_revision ( 0 ) {
2014-09-15 16:35:18 +02:00
std : : lock_guard < std : : mutex > lock ( s_recompiler_mutex ) ;
s_num_instances + + ;
if ( ! s_recompiler ) {
s_recompiler = new PPULLVMRecompiler ( ) ;
2014-10-19 22:18:05 +02:00
s_recompiler - > RunAllTests ( & m_ppu , m_interpreter ) ;
2014-09-15 16:35:18 +02:00
}
2014-09-15 16:28:38 +02:00
}
2014-09-15 16:35:18 +02:00
PPULLVMEmulator : : ~ PPULLVMEmulator ( ) {
2014-10-08 22:04:17 +02:00
for ( auto iter = m_address_to_executable . begin ( ) ; iter ! = m_address_to_executable . end ( ) ; iter + + ) {
s_recompiler - > ReleaseExecutable ( iter - > first , iter - > second . revision ) ;
}
2014-09-15 16:35:18 +02:00
std : : lock_guard < std : : mutex > lock ( s_recompiler_mutex ) ;
2014-09-15 16:34:09 +02:00
2014-09-15 16:35:18 +02:00
s_num_instances - - ;
if ( s_recompiler & & s_num_instances = = 0 ) {
delete s_recompiler ;
s_recompiler = nullptr ;
}
2014-09-15 16:28:38 +02:00
}
2014-09-17 11:57:45 +02:00
u8 PPULLVMEmulator : : DecodeMemory ( const u32 address ) {
2014-10-08 22:04:17 +02:00
auto now = std : : chrono : : high_resolution_clock : : now ( ) ;
2014-09-22 22:22:20 +02:00
2014-10-08 22:04:17 +02:00
if ( std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( now - m_last_cache_clear_time ) . count ( ) > 1000 ) {
2014-10-14 10:53:50 +02:00
bool clear_all = false ;
2014-09-22 22:22:20 +02:00
u32 revision = s_recompiler - > GetCurrentRevision ( ) ;
2014-10-08 22:04:17 +02:00
if ( m_recompiler_revision ! = revision ) {
m_recompiler_revision = revision ;
2014-10-14 10:53:50 +02:00
clear_all = true ;
2014-09-22 22:22:20 +02:00
}
for ( auto iter = m_address_to_executable . begin ( ) ; iter ! = m_address_to_executable . end ( ) ; ) {
auto tmp = iter ;
iter + + ;
if ( tmp - > second . num_hits = = 0 | | clear_all ) {
m_address_to_executable . erase ( tmp ) ;
s_recompiler - > ReleaseExecutable ( tmp - > first , tmp - > second . revision ) ;
} else {
tmp - > second . num_hits = 0 ;
}
}
2014-10-08 22:04:17 +02:00
m_last_cache_clear_time = now ;
2014-09-22 22:22:20 +02:00
}
auto address_to_executable_iter = m_address_to_executable . find ( address ) ;
if ( address_to_executable_iter = = m_address_to_executable . end ( ) ) {
auto executable_and_revision = s_recompiler - > GetExecutable ( address ) ;
if ( executable_and_revision . first ) {
ExecutableInfo executable_info ;
executable_info . executable = executable_and_revision . first ;
executable_info . revision = executable_and_revision . second ;
executable_info . num_hits = 0 ;
address_to_executable_iter = m_address_to_executable . insert ( m_address_to_executable . end ( ) , std : : make_pair ( address , executable_info ) ) ;
m_uncompiled . erase ( address ) ;
2014-09-18 13:29:49 +02:00
} else {
2014-10-08 22:04:17 +02:00
if ( m_last_instr_was_branch ) {
2014-09-22 22:22:20 +02:00
auto uncompiled_iter = m_uncompiled . find ( address ) ;
if ( uncompiled_iter ! = m_uncompiled . end ( ) ) {
uncompiled_iter - > second + + ;
if ( ( uncompiled_iter - > second % 1000 ) = = 0 ) {
2014-09-18 13:29:49 +02:00
s_recompiler - > RequestCompilation ( address ) ;
}
} else {
2014-09-22 22:22:20 +02:00
m_uncompiled [ address ] = 0 ;
2014-09-18 13:29:49 +02:00
}
}
}
2014-09-15 16:35:18 +02:00
}
2014-09-22 22:22:20 +02:00
u8 ret = 0 ;
if ( address_to_executable_iter ! = m_address_to_executable . end ( ) ) {
2014-10-16 11:58:57 +02:00
address_to_executable_iter - > second . executable ( & m_ppu , m_interpreter ) ;
2014-09-22 22:22:20 +02:00
address_to_executable_iter - > second . num_hits + + ;
2014-10-08 22:04:17 +02:00
m_last_instr_was_branch = true ;
2014-09-15 16:35:18 +02:00
} else {
2014-09-22 22:22:20 +02:00
ret = m_decoder . DecodeMemory ( address ) ;
2014-10-08 22:04:17 +02:00
m_last_instr_was_branch = m_ppu . m_is_branch ;
2014-09-15 16:35:18 +02:00
}
2014-09-22 22:22:20 +02:00
return ret ;
2014-09-15 16:28:38 +02:00
}