@@ -266,7 +266,7 @@ Function* PPUTranslator::Translate(const ppu_function& info)
266
266
if (!m_ir->GetInsertBlock ()->getTerminator ())
267
267
{
268
268
FlushRegisters ();
269
- CallFunction (m_addr);
269
+ CallFunction (m_addr, nullptr , m_ir-> GetInsertBlock () );
270
270
}
271
271
}
272
272
@@ -354,7 +354,7 @@ Value* PPUTranslator::RotateLeft(Value* arg, Value* n)
354
354
return m_ir->CreateOr (m_ir->CreateShl (arg, m_ir->CreateAnd (n, mask)), m_ir->CreateLShr (arg, m_ir->CreateAnd (m_ir->CreateNeg (n), mask)));
355
355
}
356
356
357
- void PPUTranslator::CallFunction (u64 target, Value* indirect)
357
+ void PPUTranslator::CallFunction (u64 target, Value* indirect, BasicBlock* prev_block )
358
358
{
359
359
const auto type = m_function->getFunctionType ();
360
360
const auto block = m_ir->GetInsertBlock ();
@@ -372,21 +372,27 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
372
372
373
373
if (_target >= caddr && _target <= cend)
374
374
{
375
- std::unordered_set<u64> passed_targets{_target} ;
375
+ std::unordered_set<u64> passed_targets;
376
376
377
377
u32 target_last = _target;
378
378
379
379
// Try to follow unconditional branches as long as there is no infinite loop
380
- while (target_last != _target )
380
+ while (target_last != m_addr + base )
381
381
{
382
+ if (passed_targets.empty ())
383
+ {
384
+ passed_targets.emplace (_target);
385
+ passed_targets.emplace (m_addr + base);
386
+ }
387
+
382
388
const ppu_opcode_t op{*ensure (m_info.get_ptr <u32>(target_last))};
383
389
const ppu_itype::type itype = g_ppu_itype.decode (op.opcode );
384
390
385
391
if (((itype == ppu_itype::BC && (op.bo & 0x14 ) == 0x14 ) || itype == ppu_itype::B) && !op.lk )
386
392
{
387
393
const u32 new_target = (op.aa ? 0 : target_last) + (itype == ppu_itype::B ? +op.bt24 : +op.bt14 );
388
394
389
- if (target_last >= caddr && target_last <= cend)
395
+ if (new_target >= caddr && new_target <= cend)
390
396
{
391
397
if (passed_targets.emplace (new_target).second )
392
398
{
@@ -401,11 +407,21 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
401
407
402
408
// Odd destination
403
409
}
404
- else if (itype == ppu_itype::BCLR && (op.bo & 0x14 ) == 0x14 && !op.lk )
410
+ else if (itype == ppu_itype::BCLR && (op.bo & 0x14 ) == 0x14 && !op.lk && (prev_block || m_lr) )
405
411
{
406
412
// Special case: empty function
407
413
// In this case the branch can be treated as BCLR because previous CIA does not matter
408
- indirect = RegLoad (m_lr);
414
+ indirect = m_lr;
415
+
416
+ if (!indirect)
417
+ {
418
+ // Emit register load in the beginning of the common block
419
+ m_ir->SetInsertPoint (prev_block, prev_block->getFirstInsertionPt ());
420
+ indirect = RegLoad (m_lr);
421
+
422
+ // Restore current insert point
423
+ m_ir->SetInsertPoint (block);
424
+ }
409
425
}
410
426
411
427
break ;
@@ -629,7 +645,7 @@ Value* PPUTranslator::Trunc(Value* value, Type* type)
629
645
return type != value->getType () ? m_ir->CreateTrunc (value, type) : value;
630
646
}
631
647
632
- void PPUTranslator::UseCondition (MDNode* hint, Value* cond)
648
+ void PPUTranslator::UseCondition (MDNode* hint, Value* cond, BasicBlock* prev_block )
633
649
{
634
650
FlushRegisters ();
635
651
@@ -639,7 +655,7 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
639
655
const auto next = BasicBlock::Create (m_context, " __next" , m_function);
640
656
m_ir->CreateCondBr (cond, local, next, hint);
641
657
m_ir->SetInsertPoint (next);
642
- CallFunction (m_addr + 4 );
658
+ CallFunction (m_addr + 4 , nullptr , prev_block );
643
659
m_ir->SetInsertPoint (local);
644
660
}
645
661
}
@@ -2024,19 +2040,22 @@ void PPUTranslator::BC(ppu_opcode_t op)
2024
2040
const s32 bt14 = op.bt14 ; // Workaround for VS 16.5
2025
2041
const u64 target = (op.aa ? 0 : m_addr) + bt14;
2026
2042
2043
+ const auto block = m_ir->GetInsertBlock ();
2044
+
2027
2045
if (op.aa && m_reloc)
2028
2046
{
2029
2047
CompilationError (" Branch with absolute address" );
2030
2048
}
2031
2049
2032
2050
if (op.lk )
2033
2051
{
2034
- m_ir->CreateStore (GetAddr (+4 ), m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2052
+ m_lr = GetAddr (+4 );
2053
+ m_ir->CreateStore (m_lr, m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2035
2054
}
2036
2055
2037
- UseCondition (CheckBranchProbability (op.bo ), CheckBranchCondition (op.bo , op.bi ));
2056
+ UseCondition (CheckBranchProbability (op.bo ), CheckBranchCondition (op.bo , op.bi ), block );
2038
2057
2039
- CallFunction (target);
2058
+ CallFunction (target, nullptr , block );
2040
2059
}
2041
2060
2042
2061
void PPUTranslator::SC (ppu_opcode_t op)
@@ -2074,6 +2093,8 @@ void PPUTranslator::B(ppu_opcode_t op)
2074
2093
const s32 bt24 = op.bt24 ; // Workaround for VS 16.5
2075
2094
const u64 target = (op.aa ? 0 : m_addr) + bt24;
2076
2095
2096
+ const auto block = m_ir->GetInsertBlock ();
2097
+
2077
2098
if (op.aa && m_reloc)
2078
2099
{
2079
2100
CompilationError (" Branch with absolute address" );
@@ -2085,7 +2106,7 @@ void PPUTranslator::B(ppu_opcode_t op)
2085
2106
}
2086
2107
2087
2108
FlushRegisters ();
2088
- CallFunction (target);
2109
+ CallFunction (target, nullptr , block );
2089
2110
}
2090
2111
2091
2112
void PPUTranslator::MCRF (ppu_opcode_t op)
@@ -2103,7 +2124,8 @@ void PPUTranslator::BCLR(ppu_opcode_t op)
2103
2124
2104
2125
if (op.lk )
2105
2126
{
2106
- m_ir->CreateStore (GetAddr (+4 ), m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2127
+ m_lr = GetAddr (+4 );
2128
+ m_ir->CreateStore (m_lr, m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2107
2129
}
2108
2130
2109
2131
UseCondition (CheckBranchProbability (op.bo ), CheckBranchCondition (op.bo , op.bi ));
@@ -2166,7 +2188,8 @@ void PPUTranslator::BCCTR(ppu_opcode_t op)
2166
2188
2167
2189
if (op.lk )
2168
2190
{
2169
- m_ir->CreateStore (GetAddr (+4 ), m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2191
+ m_lr = GetAddr (+4 );
2192
+ m_ir->CreateStore (m_lr, m_ir->CreateStructGEP (m_thread_type, m_thread, static_cast <uint >(&m_lr - m_locals)));
2170
2193
}
2171
2194
2172
2195
UseCondition (CheckBranchProbability (op.bo | 0x4 ), CheckBranchCondition (op.bo | 0x4 , op.bi ));
0 commit comments