Bug Summary

File:/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
Location:line 735, column 3
Description:Value stored to 'unniceSize' is never read

Annotated Source Code

1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <string>
6#include <queue>
7
8#include "StringUtil.h"
9#include "Interpreter/Interpreter.h"
10#include "../HW/Memmap.h"
11#include "JitInterface.h"
12#include "PPCTables.h"
13#include "PPCSymbolDB.h"
14#include "SignatureDB.h"
15#include "PPCAnalyst.h"
16#include "../ConfigManager.h"
17#include "../GeckoCode.h"
18
19// Analyzes PowerPC code in memory to find functions
20// After running, for each function we will know what functions it calls
21// and what functions calls it. That is, we will have an incomplete call graph,
22// but only missing indirect branches.
23
24// The results of this analysis is displayed in the code browsing sections at the bottom left
25// of the disassembly window (debugger).
26
27// It is also useful for finding function boundaries so that we can find, fingerprint and detect library functions.
28// We don't do this much currently. Only for the special case Super Monkey Ball.
29
30namespace PPCAnalyst {
31
32using namespace std;
33
34static const int CODEBUFFER_SIZE = 32000;
35// 0 does not perform block merging
36static const int FUNCTION_FOLLOWING_THRESHOLD = 16;
37
38CodeBuffer::CodeBuffer(int size)
39{
40 codebuffer = new PPCAnalyst::CodeOp[size];
41 size_ = size;
42}
43
44CodeBuffer::~CodeBuffer()
45{
46 delete[] codebuffer;
47}
48
49void AnalyzeFunction2(Symbol &func);
50u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc);
51
52#define INVALID_TARGET((u32)-1) ((u32)-1)
53
54u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc)
55{
56 switch (instr.OPCD)
57 {
58 case 18://branch instruction
59 {
60 u32 target = SignExt26(instr.LI<<2);
61 if (!instr.AA)
62 target += pc;
63
64 return target;
65 }
66 default:
67 return INVALID_TARGET((u32)-1);
68 }
69}
70
71//To find the size of each found function, scan
72//forward until we hit blr. In the meantime, collect information
73//about which functions this function calls.
74//Also collect which internal branch goes the farthest
75//If any one goes farther than the blr, assume that there is more than
76//one blr, and keep scanning.
77
78bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size)
79{
80 if (!func.name.size())
81 func.name = StringFromFormat("zz_%07x_", startAddr & 0x0FFFFFF);
82 if (func.analyzed >= 1)
83 return true; // No error, just already did it.
84
85 func.calls.clear();
86 func.callers.clear();
87 func.size = 0;
88 func.flags = FFLAG_LEAF;
89 u32 addr = startAddr;
90
91 u32 farthestInternalBranchTarget = startAddr;
92 int numInternalBranches = 0;
93 while (true)
94 {
95 func.size += 4;
96 if (func.size >= CODEBUFFER_SIZE * 4) //weird
97 return false;
98
99 UGeckoInstruction instr = (UGeckoInstruction)Memory::ReadUnchecked_U32(addr);
100 if (max_size && func.size > max_size)
101 {
102 func.address = startAddr;
103 func.analyzed = 1;
104 func.hash = SignatureDB::ComputeCodeChecksum(startAddr, addr);
105 if (numInternalBranches == 0)
106 func.flags |= FFLAG_STRAIGHT;
107 return true;
108 }
109 if (PPCTables::IsValidInstruction(instr))
110 {
111 if (instr.hex == 0x4e800020) //4e800021 is blrl, not the end of a function
112 {
113 //BLR
114 if (farthestInternalBranchTarget > addr)
115 {
116 //bah, not this one, continue..
117 }
118 else
119 {
120 //a final blr!
121 //We're done! Looks like we have a neat valid function. Perfect.
122 //Let's calc the checksum and get outta here
123 func.address = startAddr;
124 func.analyzed = 1;
125 func.hash = SignatureDB::ComputeCodeChecksum(startAddr, addr);
126 if (numInternalBranches == 0)
127 func.flags |= FFLAG_STRAIGHT;
128 return true;
129 }
130 }
131 /*
132 else if ((instr.hex & 0xFC000000) == (0x4b000000 & 0xFC000000) && !instr.LK) {
133 u32 target = addr + SignExt26(instr.LI << 2);
134 if (target < startAddr || (max_size && target > max_size+startAddr))
135 {
136 //block ends by branching away. We're done!
137 func.size *= 4; // into bytes
138 func.address = startAddr;
139 func.analyzed = 1;
140 func.hash = SignatureDB::ComputeCodeChecksum(startAddr, addr);
141 if (numInternalBranches == 0)
142 func.flags |= FFLAG_STRAIGHT;
143 return true;
144 }
145 }*/
146 else if (instr.hex == 0x4e800021 || instr.hex == 0x4e800420 || instr.hex == 0x4e800421)
147 {
148 func.flags &= ~FFLAG_LEAF;
149 func.flags |= FFLAG_EVIL;
150 }
151 else if (instr.hex == 0x4c000064)
152 {
153 func.flags &= ~FFLAG_LEAF;
154 func.flags |= FFLAG_RFI;
155 }
156 else
157 {
158 if (instr.OPCD == 16)
159 {
160 u32 target = SignExt16(instr.BD << 2);
161
162 if (!instr.AA)
163 target += addr;
164
165 if (target > farthestInternalBranchTarget && !instr.LK)
166 {
167 farthestInternalBranchTarget = target;
168 }
169 numInternalBranches++;
170 }
171 else
172 {
173 u32 target = EvaluateBranchTarget(instr, addr);
174 if (target != INVALID_TARGET((u32)-1) && instr.LK)
175 {
176 //we found a branch-n-link!
177 func.calls.push_back(SCall(target,addr));
178 func.flags &= ~FFLAG_LEAF;
179 }
180 }
181 }
182 }
183 else
184 {
185 return false;
186 }
187 addr += 4;
188 }
189}
190
191
192// Second pass analysis, done after the first pass is done for all functions
193// so we have more information to work with
194void AnalyzeFunction2(Symbol *func)
195{
196 u32 flags = func->flags;
197
198 bool nonleafcall = false;
199 for (size_t i = 0; i < func->calls.size(); i++)
200 {
201 SCall c = func->calls[i];
202 Symbol *called_func = g_symbolDB.GetSymbolFromAddr(c.function);
203 if (called_func && (called_func->flags & FFLAG_LEAF) == 0)
204 {
205 nonleafcall = true;
206 break;
207 }
208 }
209
210 if (nonleafcall && !(flags & FFLAG_EVIL) && !(flags & FFLAG_RFI))
211 flags |= FFLAG_ONLYCALLSNICELEAFS;
212
213 func->flags = flags;
214}
215
216// IMPORTANT - CURRENTLY ASSUMES THAT A IS A COMPARE
217bool CanSwapAdjacentOps(const CodeOp &a, const CodeOp &b)
218{
219 const GekkoOPInfo *b_info = b.opinfo;
220 int b_flags = b_info->flags;
221 if (b_flags & (FL_SET_CRx | FL_ENDBLOCK | FL_TIMER | FL_EVIL))
222 return false;
223 if ((b_flags & (FL_RC_BIT | FL_RC_BIT_F)) && (b.inst.hex & 1))
224 return false;
225
226 switch (b.inst.OPCD)
227 {
228 case 16:
229 case 18:
230 //branches. Do not swap.
231 case 17: //sc
232 case 46: //lmw
233 case 19: //table19 - lots of tricky stuff
234 return false;
235 }
236
237 // For now, only integer ops acceptable. Any instruction which can raise an
238 // interrupt is *not* a possible swap candidate: see [1] for an example of
239 // a crash caused by this error.
240 //
241 // [1] https://code.google.com/p/dolphin-emu/issues/detail?id=5864#c7
242 if (b_info->type != OPTYPE_INTEGER)
243 return false;
244
245 // Check that we have no register collisions.
246 // That is, check that none of b's outputs matches any of a's inputs,
247 // and that none of a's outputs matches any of b's inputs.
248 // The latter does not apply if a is a cmp, of course, but doesn't hurt to check.
249 for (int j = 0; j < 3; j++)
250 {
251 int regInA = a.regsIn[j];
252 int regInB = b.regsIn[j];
253 if (regInA >= 0 &&
254 (b.regsOut[0] == regInA ||
255 b.regsOut[1] == regInA))
256 {
257 // reg collision! don't swap
258 return false;
259 }
260 if (regInB >= 0 &&
261 (a.regsOut[0] == regInB ||
262 a.regsOut[1] == regInB))
263 {
264 // reg collision! don't swap
265 return false;
266 }
267 }
268
269 return true;
270}
271
272// Does not yet perform inlining - although there are plans for that.
273// Returns the exit address of the next PC
274u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
275 BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer,
276 int blockSize, u32* merged_addresses,
277 int capacity_of_merged_addresses, int& size_of_merged_addresses)
278{
279 if (capacity_of_merged_addresses < FUNCTION_FOLLOWING_THRESHOLD) {
280 PanicAlert("Capacity of merged_addresses is too small!")MsgAlert(false, WARNING, "Capacity of merged_addresses is too small!"
)
;
281 }
282 std::fill_n(merged_addresses, capacity_of_merged_addresses, 0);
283 merged_addresses[0] = address;
284 size_of_merged_addresses = 1;
285
286 memset(st, 0, sizeof(*st));
287
288 // Disabled the following optimization in preference of FAST_ICACHE
289 //UGeckoInstruction previnst = Memory::Read_Opcode_JIT_LC(address - 4);
290 //if (previnst.hex == 0x4e800020)
291 // st->isFirstBlockOfFunction = true;
292
293 gpa->any = true;
294 fpa->any = false;
295
296 for (int i = 0; i < 32; i++)
297 {
298 gpa->firstRead[i] = -1;
299 gpa->firstWrite[i] = -1;
300 gpa->numReads[i] = 0;
301 gpa->numWrites[i] = 0;
302 }
303
304 u32 blockstart = address;
305 int maxsize = blockSize;
306
307 int num_inst = 0;
308 int numFollows = 0;
309 int numCycles = 0;
310
311 CodeOp *code = buffer->codebuffer;
312 bool foundExit = false;
313
314 u32 returnAddress = 0;
315
316 // Used for Gecko CST1 code. (See GeckoCode/GeckoCode.h)
317 // We use std::queue but it is not so slow
318 // because cst1_instructions does not allocate memory so many times.
319 std::queue<UGeckoInstruction> cst1_instructions;
320 const std::map<u32, std::vector<u32> >& inserted_asm_codes =
321 Gecko::GetInsertedAsmCodes();
322
323 // Do analysis of the code, look for dependencies etc
324 int numSystemInstructions = 0;
325 for (int i = 0; i < maxsize; i++)
326 {
327 UGeckoInstruction inst;
328
329 if (!cst1_instructions.empty())
330 {
331 // If the Gecko CST1 instruction queue is not empty,
332 // we consume the first instruction.
333 inst = UGeckoInstruction(cst1_instructions.front());
334 cst1_instructions.pop();
335 address -= 4;
336
337 }
338 else
339 {
340 // If the address is the insertion point of Gecko CST1 code,
341 // we push the code into the instruction queue and
342 // consume the first instruction.
343 std::map<u32, std::vector<u32> >::const_iterator it =
344 inserted_asm_codes.find(address);
345 if (it != inserted_asm_codes.end())
346 {
347 const std::vector<u32>& codes = it->second;
348 for (std::vector<u32>::const_iterator itCur = codes.begin(),
349 itEnd = codes.end(); itCur != itEnd; ++itCur)
350 {
351 cst1_instructions.push(*itCur);
352 }
353 inst = UGeckoInstruction(cst1_instructions.front());
354 cst1_instructions.pop();
355
356 }
357 else
358 {
359 inst = JitInterface::Read_Opcode_JIT(address);
360 }
361 }
362
363 if (inst.hex != 0)
364 {
365 num_inst++;
366 memset(&code[i], 0, sizeof(CodeOp));
367 GekkoOPInfo *opinfo = GetOpInfo(inst);
368 code[i].opinfo = opinfo;
369 // FIXME: code[i].address may not be correct due to CST1 code.
370 code[i].address = address;
371 code[i].inst = inst;
372 code[i].branchTo = -1;
373 code[i].branchToIndex = -1;
374 code[i].skip = false;
375 numCycles += opinfo->numCyclesMinusOne + 1;
376
377 code[i].wantsCR0 = false;
378 code[i].wantsCR1 = false;
379 code[i].wantsPS1 = false;
380
381 int flags = opinfo->flags;
382
383 if (flags & FL_USE_FPU)
384 fpa->any = true;
385
386 if (flags & FL_TIMER)
387 gpa->anyTimer = true;
388
389 // Does the instruction output CR0?
390 if (flags & FL_RC_BIT)
391 code[i].outputCR0 = inst.hex & 1; //todo fix
392 else if ((flags & FL_SET_CRn) && inst.CRFD == 0)
393 code[i].outputCR0 = true;
394 else
395 code[i].outputCR0 = (flags & FL_SET_CR0) ? true : false;
396
397 // Does the instruction output CR1?
398 if (flags & FL_RC_BIT_F)
399 code[i].outputCR1 = inst.hex & 1; //todo fix
400 else if ((flags & FL_SET_CRn) && inst.CRFD == 1)
401 code[i].outputCR1 = true;
402 else
403 code[i].outputCR1 = (flags & FL_SET_CR1) ? true : false;
404
405 int numOut = 0;
406 int numIn = 0;
407 if (flags & FL_OUT_A)
408 {
409 code[i].regsOut[numOut++] = inst.RA;
410 gpa->SetOutputRegister(inst.RA, i);
411 }
412 if (flags & FL_OUT_D)
413 {
414 code[i].regsOut[numOut++] = inst.RD;
415 gpa->SetOutputRegister(inst.RD, i);
416 }
417 if (flags & FL_OUT_S)
418 {
419 code[i].regsOut[numOut++] = inst.RS;
420 gpa->SetOutputRegister(inst.RS, i);
421 }
422 if ((flags & FL_IN_A) || ((flags & FL_IN_A0) && inst.RA != 0))
423 {
424 code[i].regsIn[numIn++] = inst.RA;
425 gpa->SetInputRegister(inst.RA, i);
426 }
427 if (flags & FL_IN_B)
428 {
429 code[i].regsIn[numIn++] = inst.RB;
430 gpa->SetInputRegister(inst.RB, i);
431 }
432 if (flags & FL_IN_C)
433 {
434 code[i].regsIn[numIn++] = inst.RC;
435 gpa->SetInputRegister(inst.RC, i);
436 }
437 if (flags & FL_IN_S)
438 {
439 code[i].regsIn[numIn++] = inst.RS;
440 gpa->SetInputRegister(inst.RS, i);
441 }
442
443 // Set remaining register slots as unused (-1)
444 for (int j = numIn; j < 3; j++)
445 code[i].regsIn[j] = -1;
446 for (int j = numOut; j < 2; j++)
447 code[i].regsOut[j] = -1;
448 for (int j = 0; j < 3; j++)
449 code[i].fregsIn[j] = -1;
450 code[i].fregOut = -1;
451
452 switch (opinfo->type)
453 {
454 case OPTYPE_INTEGER:
455 case OPTYPE_LOAD:
456 case OPTYPE_STORE:
457 case OPTYPE_LOADFP:
458 case OPTYPE_STOREFP:
459 break;
460 case OPTYPE_FPU:
461 break;
462 case OPTYPE_BRANCH:
463 if (code[i].inst.hex == 0x4e800020)
464 {
465 // For analysis purposes, we can assume that blr eats flags.
466 code[i].outputCR0 = true;
467 code[i].outputCR1 = true;
468 }
469 break;
470 case OPTYPE_SYSTEM:
471 case OPTYPE_SYSTEMFP:
472 numSystemInstructions++;
473 break;
474 }
475
476 bool follow = false;
477 u32 destination = 0;
478 if (inst.OPCD == 18 && blockSize > 1)
479 {
480 //Is bx - should we inline? yes!
481 if (inst.AA)
482 destination = SignExt26(inst.LI << 2);
483 else
484 destination = address + SignExt26(inst.LI << 2);
485 if (destination != blockstart)
486 follow = true;
487 }
488 else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
489 (inst.BO & (1 << 4)) && (inst.BO & (1 << 2)) &&
490 returnAddress != 0)
491 {
492 // bclrx with unconditional branch = return
493 follow = true;
494 destination = returnAddress;
495 returnAddress = 0;
496
497 if (inst.LK)
498 returnAddress = address + 4;
499 }
500 else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
501 {
502 // mtspr
503 const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
504 if (index == SPR_LR) {
505 // We give up to follow the return address
506 // because we have to check the register usage.
507 returnAddress = 0;
508 }
509 }
510
511 if (follow)
512 numFollows++;
513 // TODO: Find the optimal value for FUNCTION_FOLLOWING_THRESHOLD.
514 // If it is small, the performance will be down.
515 // If it is big, the size of generated code will be big and
516 // cache clearning will happen many times.
517 // TODO: Investivate the reason why
518 // "0" is fastest in some games, MP2 for example.
519 if (numFollows > FUNCTION_FOLLOWING_THRESHOLD)
520 follow = false;
521
522 if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMergeBlocks) {
523 follow = false;
524 }
525
526 if (!follow)
527 {
528 if (opinfo->flags & FL_ENDBLOCK) //right now we stop early
529 {
530 foundExit = true;
531 break;
532 }
533 address += 4;
534 }
535 else
536 {
537 // We don't "code[i].skip = true" here
538 // because bx may store a certain value to the link register.
539 // Instead, we skip a part of bx in Jit**::bx().
540 address = destination;
541 merged_addresses[size_of_merged_addresses++] = address;
542 }
543 }
544 else
545 {
546 // ISI exception or other critical memory exception occurred (game over)
547 break;
548 }
549 }
550 st->numCycles = numCycles;
551
552 // Instruction Reordering Pass
553 if (num_inst > 1)
554 {
555 // Bubble down compares towards branches, so that they can be merged.
556 // -2: -1 for the pair, -1 for not swapping with the final instruction which is probably the branch.
557 for (int i = 0; i < num_inst - 2; i++)
558 {
559 CodeOp &a = code[i];
560 CodeOp &b = code[i + 1];
561 // All integer compares can be reordered.
562 if ((a.inst.OPCD == 10 || a.inst.OPCD == 11) ||
563 (a.inst.OPCD == 31 && (a.inst.SUBOP10 == 0 || a.inst.SUBOP10 == 32)))
564 {
565 // Got a compare instruction.
566 if (CanSwapAdjacentOps(a, b)) {
567 // Alright, let's bubble it down!
568 CodeOp c = a;
569 a = b;
570 b = c;
571 }
572 }
573 }
574 }
575
576 if (!foundExit && num_inst > 0)
577 {
578 // A broken block is a block that does not end in a branch
579 broken_block = true;
580 }
581
582 // Scan for CR0 dependency
583 // assume next block wants CR0 to be safe
584 bool wantsCR0 = true;
585 bool wantsCR1 = true;
586 bool wantsPS1 = true;
587 for (int i = num_inst - 1; i >= 0; i--)
588 {
589 if (code[i].outputCR0)
590 wantsCR0 = false;
591 if (code[i].outputCR1)
592 wantsCR1 = false;
593 if (code[i].outputPS1)
594 wantsPS1 = false;
595 wantsCR0 |= code[i].wantsCR0;
596 wantsCR1 |= code[i].wantsCR1;
597 wantsPS1 |= code[i].wantsPS1;
598 code[i].wantsCR0 = wantsCR0;
599 code[i].wantsCR1 = wantsCR1;
600 code[i].wantsPS1 = wantsPS1;
601 }
602
603 *realsize = num_inst;
604 // ...
605 return address;
606}
607
608
609// Most functions that are relevant to analyze should be
610// called by another function. Therefore, let's scan the
611// entire space for bl operations and find what functions
612// get called.
613void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, SymbolDB *func_db)
614{
615 for (u32 addr = startAddr; addr < endAddr; addr+=4)
616 {
617 UGeckoInstruction instr = (UGeckoInstruction)Memory::ReadUnchecked_U32(addr);
618
619 if (PPCTables::IsValidInstruction(instr))
620 {
621 switch (instr.OPCD)
622 {
623 case 18://branch instruction
624 {
625 if (instr.LK) //bl
626 {
627 u32 target = SignExt26(instr.LI << 2);
628 if (!instr.AA)
629 target += addr;
630 if (Memory::IsRAMAddress(target))
631 {
632 func_db->AddFunction(target);
633 }
634 }
635 }
636 break;
637 default:
638 break;
639 }
640 }
641 }
642}
643
644void FindFunctionsAfterBLR(PPCSymbolDB *func_db)
645{
646 vector<u32> funcAddrs;
647
648 for (PPCSymbolDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); ++iter)
649 funcAddrs.push_back(iter->second.address + iter->second.size);
650
651 for (vector<u32>::iterator iter = funcAddrs.begin(); iter != funcAddrs.end(); ++iter)
652 {
653 u32 location = *iter;
654 while (true)
655 {
656 if (PPCTables::IsValidInstruction(Memory::Read_Instruction(location)))
657 {
658 //check if this function is already mapped
659 Symbol *f = func_db->AddFunction(location);
660 if (!f)
661 break;
662 else
663 location += f->size;
664 }
665 else
666 break;
667 }
668 }
669}
670
671void FindFunctions(u32 startAddr, u32 endAddr, PPCSymbolDB *func_db)
672{
673 //Step 1: Find all functions
674 FindFunctionsFromBranches(startAddr, endAddr, func_db);
675 FindFunctionsAfterBLR(func_db);
676
677 //Step 2:
678 func_db->FillInCallers();
679
680 int numLeafs = 0, numNice = 0, numUnNice = 0;
681 int numTimer = 0, numRFI = 0, numStraightLeaf = 0;
682 int leafSize = 0, niceSize = 0, unniceSize = 0;
683 for (PPCSymbolDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); ++iter)
684 {
685 if (iter->second.address == 4)
686 {
687 WARN_LOG(OSHLE, "Weird function")do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 687, "Weird function"); } } while (0)
;
688 continue;
689 }
690 AnalyzeFunction2(&(iter->second));
691 Symbol &f = iter->second;
692 if (f.name.substr(0, 3) == "zzz")
693 {
694 if (f.flags & FFLAG_LEAF)
695 f.name += "_leaf";
696 if (f.flags & FFLAG_STRAIGHT)
697 f.name += "_straight";
698 }
699 if (f.flags & FFLAG_LEAF)
700 {
701 numLeafs++;
702 leafSize += f.size;
703 }
704 else if (f.flags & FFLAG_ONLYCALLSNICELEAFS)
705 {
706 numNice++;
707 niceSize += f.size;
708 }
709 else
710 {
711 numUnNice++;
712 unniceSize += f.size;
713 }
714
715 if (f.flags & FFLAG_TIMERINSTRUCTIONS)
716 numTimer++;
717 if (f.flags & FFLAG_RFI)
718 numRFI++;
719 if ((f.flags & FFLAG_STRAIGHT) && (f.flags & FFLAG_LEAF))
720 numStraightLeaf++;
721 }
722 if (numLeafs == 0)
723 leafSize = 0;
724 else
725 leafSize /= numLeafs;
726
727 if (numNice == 0)
728 niceSize = 0;
729 else
730 niceSize /= numNice;
731
732 if (numUnNice == 0)
733 unniceSize = 0;
734 else
735 unniceSize /= numUnNice;
Value stored to 'unniceSize' is never read
736
737 INFO_LOG(OSHLE, "Functions analyzed. %i leafs, %i nice, %i unnice."do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 739, "Functions analyzed. %i leafs, %i nice, %i unnice." "%i timer, %i rfi. %i are branchless leafs."
, numLeafs, numNice, numUnNice, numTimer, numRFI, numStraightLeaf
); } } while (0)
738 "%i timer, %i rfi. %i are branchless leafs.", numLeafs,do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 739, "Functions analyzed. %i leafs, %i nice, %i unnice." "%i timer, %i rfi. %i are branchless leafs."
, numLeafs, numNice, numUnNice, numTimer, numRFI, numStraightLeaf
); } } while (0)
739 numNice, numUnNice, numTimer, numRFI, numStraightLeaf)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 739, "Functions analyzed. %i leafs, %i nice, %i unnice." "%i timer, %i rfi. %i are branchless leafs."
, numLeafs, numNice, numUnNice, numTimer, numRFI, numStraightLeaf
); } } while (0)
;
740 INFO_LOG(OSHLE, "Average size: %i (leaf), %i (nice), %i(unnice)",do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 741, "Average size: %i (leaf), %i (nice), %i(unnice)", leafSize
, niceSize, unniceSize); } } while (0)
741 leafSize, niceSize, unniceSize)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::OSHLE, "/home/anal/dolphin-emu/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp"
, 741, "Average size: %i (leaf), %i (nice), %i(unnice)", leafSize
, niceSize, unniceSize); } } while (0)
;
742}
743
744} // namespace