120 changes: 120 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitArmIL/JitILAsm.cpp
@@ -0,0 +1,120 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "../../HW/Memmap.h"

#include "../PowerPC.h"
#include "../../CoreTiming.h"
#include "MemoryUtil.h"

#include "JitIL.h"
#include "../JitCommon/JitCache.h"

#include "../../HW/GPFifo.h"
#include "../../Core.h"

#include "JitILAsm.h"
#include "ArmEmitter.h"

JitArmILAsmRoutineManager armil_asm_routines;
void JitArmILAsmRoutineManager::Generate()
{
enterCode = GetCodePtr();
PUSH(9, R4, R5, R6, R7, R8, R9, R10, R11, _LR);
// Take care to 8-byte align stack for function calls.
// We are misaligned here because of an odd number of args for PUSH.
// It's not like x86 where you need to account for an extra 4 bytes
// consumed by CALL.
SUB(_SP, _SP, 4);

MOVI2R(R0, (u32)&CoreTiming::downcount);
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);

FixupBranch skipToRealDispatcher = B();
dispatcher = GetCodePtr();
printf("ILDispatcher is %p\n", dispatcher);

// Downcount Check
// The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!!
FixupBranch bail = B_CC(CC_MI);

SetJumpTarget(skipToRealDispatcher);
dispatcherNoCheck = GetCodePtr();

// This block of code gets the address of the compiled block of code
// It runs though to the compiling portion if it isn't found
LDR(R12, R9, PPCSTATE_OFF(pc));// Load the current PC into R12

Operand2 iCacheMask = Operand2(0xE, 2); // JIT_ICACHE_MASK
BIC(R12, R12, iCacheMask); // R12 contains PC & JIT_ICACHE_MASK here.

MOVI2R(R14, (u32)jit->GetBlockCache()->iCache);

LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
// R12 Confirmed this is the correct iCache Location loaded.
TST(R12, 0x80); // Test to see if it is a JIT block.

SetCC(CC_EQ);
// Success, it is our Jitblock.
MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
// LDR R14 right here to get CodePointers()[0] pointer.
LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
LDR(R14, R14, R12); // Load the block address in to R14

B(R14);
// No need to jump anywhere after here, the block will go back to dispatcher start
SetCC();

// If we get to this point, that means that we don't have the block cached to execute
// So call ArmJit to compile the block and then execute it.
MOVI2R(R14, (u32)&Jit);
BL(R14);

B(dispatcherNoCheck);

// fpException()
// Floating Point Exception Check, Jumped to if false
fpException = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(Exceptions));
ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
STR(R0, R9, PPCSTATE_OFF(Exceptions));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
B(dispatcher);

SetJumpTarget(bail);
doTiming = GetCodePtr();
// XXX: In JIT64, Advance() gets called /after/ the exception checking
// once it jumps back to the start of outerLoop
QuickCallFunction(R14, (void*)&CoreTiming::Advance);

// Does exception checking
testExceptions = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
// Check the state pointer to see if we are exiting
// Gets checked on every exception check
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
MVN(R1, 0);
LDR(R0, R0);
TST(R0, R1);
FixupBranch Exit = B_CC(CC_NEQ);

B(dispatcher);

SetJumpTarget(Exit);

ADD(_SP, _SP, 4);

POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns

GenerateCommon();

FlushIcache();
}

32 changes: 32 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitArmIL/JitILAsm.h
@@ -0,0 +1,32 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#ifndef _JITARMILASM_H
#define _JITARMILASM_H
#include "ArmEmitter.h"
#include "../JitCommon/JitAsmCommon.h"
using namespace ArmGen;
class JitArmILAsmRoutineManager : public CommonAsmRoutinesBase, public ARMXCodeBlock
{
private:
void Generate();
void GenerateCommon() {}

public:
void Init() {
AllocCodeSpace(8192);
Generate();
WriteProtect();
}

void Shutdown() {
FreeCodeSpace();
}
};

extern JitArmILAsmRoutineManager armil_asm_routines;

#endif


169 changes: 169 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Branch.cpp
@@ -0,0 +1,169 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"

#include "../../ConfigManager.h"
#include "../PowerPC.h"
#include "../PPCTables.h"

#include "JitIL.h"

#include "../../HW/Memmap.h"

#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return;
//#define NORMALBRANCH_START

void JitArmIL::bx(UGeckoInstruction inst)
{
//NORMALBRANCH_START
INSTRUCTION_START;

// We must always process the following sentence
// even if the blocks are merged by PPCAnalyst::Flatten().
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));

// If this is not the last instruction of a block,
// we will skip the rest process.
// Because PPCAnalyst::Flatten() merged the blocks.
if (!js.isLastInstruction) {
return;
}

u32 destination;
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = js.compilerPC + SignExt26(inst.LI << 2);

if (destination == js.compilerPC) {
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}

ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) {
IREmitter::InstLoc CRTest = 0, CTRTest = 0;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
CRTest = ibuild.EmitXor(CRCmp, CRTest);
}

if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
if (inst.BO & 2) {
CTRTest = ibuild.EmitICmpEq(c,
ibuild.EmitIntConst(0));
} else {
CTRTest = c;
}
}

IREmitter::InstLoc Test = CRTest;
if (CTRTest) {
if (Test)
Test = ibuild.EmitAnd(Test, CTRTest);
else
Test = CTRTest;
}

if (!Test) {
Test = ibuild.EmitIntConst(1);
}
return Test;
}

void JitArmIL::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START

if (!js.isLastInstruction &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
return;
}

if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
void JitArmIL::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
ibuild.EmitStoreLink(
ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc Test = TestBranch(ibuild, inst);

u32 destination;
if(inst.AA)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);

if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
)
{
ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination));
}
else
{
ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination));
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}

void JitArmIL::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
}
IREmitter::InstLoc test;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
test = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
test = ibuild.EmitXor(test, CRCmp);
} else {
test = ibuild.EmitIntConst(1);
}
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc destination = ibuild.EmitLoadCTR();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}

489 changes: 489 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.h
@@ -0,0 +1,16 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#ifndef JITARMIL_TABLES_H
#define JITARMIL_TABLES_H

#include "../Gekko.h"
#include "../PPCTables.h"

namespace JitArmILTables
{
void CompileInstruction(PPCAnalyst::CodeOp & op);
void InitTables();
}
#endif
26 changes: 9 additions & 17 deletions Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp
Expand Up @@ -2,23 +2,12 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "x64ABI.h"
#include "CPUDetect.h"
#include "x64Emitter.h"

#include "../../HW/Memmap.h"
#include "JitAsmCommon.h"
#include "JitBase.h"

#include "../PowerPC.h"
#include "../../CoreTiming.h"
#include "CPUDetect.h"
#include "MemoryUtil.h"

#include "x64ABI.h"
#include "../JitCommon/JitCache.h"

#include "../../HW/GPFifo.h"
#include "../../Core.h"
#include "JitAsmCommon.h"
#include "JitBase.h"

#define QUANTIZED_REGS_TO_SAVE (ABI_ALL_CALLEE_SAVED & ~((1 << RAX) | (1 << RCX) | (1 << RDX) | \
(1 << XMM0) | (1 << XMM1)))
Expand Down Expand Up @@ -150,7 +139,8 @@ static void WriteDual32(u32 address)
}

// See comment in header for in/outs.
void CommonAsmRoutines::GenQuantizedStores() {
void CommonAsmRoutines::GenQuantizedStores()
{
const u8* storePairedIllegal = AlignCode4();
UD2();
const u8* storePairedFloat = AlignCode4();
Expand Down Expand Up @@ -289,7 +279,8 @@ void CommonAsmRoutines::GenQuantizedStores() {
}

// See comment in header for in/outs.
void CommonAsmRoutines::GenQuantizedSingleStores() {
void CommonAsmRoutines::GenQuantizedSingleStores()
{
const u8* storeSingleIllegal = AlignCode4();
UD2();

Expand Down Expand Up @@ -365,7 +356,8 @@ void CommonAsmRoutines::GenQuantizedSingleStores() {
singleStoreQuantized[7] = storeSingleS16;
}

void CommonAsmRoutines::GenQuantizedLoads() {
void CommonAsmRoutines::GenQuantizedLoads()
{
const u8* loadPairedIllegal = AlignCode4();
UD2();

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h
Expand Up @@ -5,7 +5,7 @@
#ifndef _JITASMCOMMON_H
#define _JITASMCOMMON_H

#include "../JitCommon/Jit_Util.h"
#include "Jit_Util.h"

class CommonAsmRoutinesBase {
public:
Expand Down
10 changes: 2 additions & 8 deletions Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp
Expand Up @@ -6,14 +6,8 @@

#include "Common.h"
#include "disasm.h"
#include "../JitCommon/JitBase.h"
#include "../JitCommon/JitBackpatch.h"

#include "../../HW/Memmap.h"

#include "x64Emitter.h"
#include "x64ABI.h"
#include "x64Analyzer.h"
#include "JitBase.h"
#include "JitBackpatch.h"

#include "StringUtil.h"
#ifdef _WIN32
Expand Down
16 changes: 15 additions & 1 deletion Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h
Expand Up @@ -107,6 +107,19 @@
#define CTX_R15 gregs[REG_R15]
#define CTX_RIP gregs[REG_RIP]
#elif defined(_M_IX86)
#ifdef ANDROID
#include <asm/sigcontext.h>
typedef sigcontext SContext;
#define CTX_EAX eax
#define CTX_EBX ebx
#define CTX_ECX ecx
#define CTX_EDX edx
#define CTX_EDI edi
#define CTX_ESI esi
#define CTX_EBP ebp
#define CTX_ESP esp
#define CTX_EIP eip
#else
#include <ucontext.h>
typedef mcontext_t SContext;
#define CTX_EAX gregs[REG_EAX]
Expand All @@ -118,12 +131,13 @@
#define CTX_EBP gregs[REG_EBP]
#define CTX_ESP gregs[REG_ESP]
#define CTX_EIP gregs[REG_EIP]
#endif
#elif defined(_M_ARM)
// Add others if required.
typedef struct sigcontext SContext;
#define CTX_PC arm_pc
#else
#error No context definition for OS
#warning No context definition for OS
#endif
#elif defined(__NetBSD__)
#include <ucontext.h>
Expand Down
18 changes: 13 additions & 5 deletions Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h
Expand Up @@ -9,16 +9,24 @@
//#define JIT_LOG_GPR // Enables logging of the PPC general purpose regs
//#define JIT_LOG_FPR // Enables logging of the PPC floating point regs

#include "../CPUCoreBase.h"
#include "JitAsmCommon.h"
#include "JitCache.h"
#include "Jit_Util.h" // for EmuCodeBlock
#include "Jit_Util.h" // for EmuCodeBlock
#include "JitBackpatch.h" // for EmuCodeBlock
#include "JitAsmCommon.h"
#include "x64ABI.h"
#include "x64Analyzer.h"
#include "x64Emitter.h"
#include "../CPUCoreBase.h"
#include "../PowerPC.h"
#include "../PPCAnalyst.h"
#include "../PPCTables.h"
#include "../../Core.h"
#include "../../CoreTiming.h"
#include "../../HW/GPFifo.h"
#include "../../HW/Memmap.h"

#include <set>

#define JIT_OPCODE 0

class JitBase : public CPUCoreBase
{
protected:
Expand Down
116 changes: 14 additions & 102 deletions Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp
Expand Up @@ -15,21 +15,11 @@
#include <windows.h>
#endif

#include "../../Core.h"
#include "JitBase.h"
#include "MemoryUtil.h"
#include "disasm.h"

#include "../../HW/Memmap.h"
#include "../JitInterface.h"
#include "../../CoreTiming.h"

#include "../PowerPC.h"
#include "../PPCTables.h"
#include "../PPCAnalyst.h"

#include "JitCache.h"
#include "JitBase.h"

#include "disasm.h"

#if defined USE_OPROFILE && USE_OPROFILE
#include <opagent.h>
Expand All @@ -47,27 +37,18 @@ using namespace Gen;

#define INVALID_EXIT 0xFFFFFFFF

bool JitBlock::ContainsAddress(u32 em_address)
{
// WARNING - THIS DOES NOT WORK WITH INLINING ENABLED.
return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize);
}

bool JitBaseBlockCache::IsFull() const
{
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
}

void JitBaseBlockCache::Init()
{
MAX_NUM_BLOCKS = 65536*2;

#if defined USE_OPROFILE && USE_OPROFILE
agent = op_open_agent();
#endif
blocks = new JitBlock[MAX_NUM_BLOCKS];
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
#ifdef JIT_UNLIMITED_ICACHE
if (iCache == 0 && iCacheEx == 0 && iCacheVMEM == 0)
{
iCache = new u8[JIT_ICACHE_SIZE];
Expand All @@ -85,15 +66,13 @@ bool JitBlock::ContainsAddress(u32 em_address)
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
#endif
Clear();
}

void JitBaseBlockCache::Shutdown()
{
delete[] blocks;
delete[] blockCodePointers;
#ifdef JIT_UNLIMITED_ICACHE
if (iCache != 0)
delete[] iCache;
iCache = 0;
Expand All @@ -103,7 +82,6 @@ bool JitBlock::ContainsAddress(u32 em_address)
if (iCacheVMEM != 0)
delete[] iCacheVMEM;
iCacheVMEM = 0;
#endif
blocks = 0;
blockCodePointers = 0;
num_blocks = 0;
Expand Down Expand Up @@ -140,11 +118,9 @@ bool JitBlock::ContainsAddress(u32 em_address)

void JitBaseBlockCache::ClearSafe()
{
#ifdef JIT_UNLIMITED_ICACHE
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
#endif
}

/*void JitBaseBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
Expand Down Expand Up @@ -197,7 +173,6 @@ bool JitBlock::ContainsAddress(u32 em_address)
b.exitPtrs[1] = 0;
b.linkStatus[0] = false;
b.linkStatus[1] = false;
b.blockNum = num_blocks;
num_blocks++; //commit the current block
return num_blocks - 1;
}
Expand All @@ -206,8 +181,8 @@ bool JitBlock::ContainsAddress(u32 em_address)
{
blockCodePointers[block_num] = code_ptr;
JitBlock &b = blocks[block_num];
b.originalFirstOpcode = JitInterface::Read_Opcode_JIT(b.originalAddress);
JitInterface::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num);
u32* icp = GetICachePtr(b.originalAddress);
*icp = block_num;

// Convert the logical address to a physical address for the block map
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
Expand Down Expand Up @@ -256,45 +231,22 @@ bool JitBlock::ContainsAddress(u32 em_address)
return blockCodePointers;
}

#ifdef JIT_UNLIMITED_ICACHE
u8* JitBaseBlockCache::GetICache()
u32* JitBaseBlockCache::GetICachePtr(u32 addr)
{
return iCache;
}

u8* JitBaseBlockCache::GetICacheEx()
{
return iCacheEx;
}

u8* JitBaseBlockCache::GetICacheVMEM()
{
return iCacheVMEM;
if (addr & JIT_ICACHE_VMEM_BIT)
return (u32*)(jit->GetBlockCache()->iCacheVMEM + (addr & JIT_ICACHE_MASK));
else if (addr & JIT_ICACHE_EXRAM_BIT)
return (u32*)(jit->GetBlockCache()->iCacheEx + (addr & JIT_ICACHEEX_MASK));
else
return (u32*)(jit->GetBlockCache()->iCache + (addr & JIT_ICACHE_MASK));
}
#endif

int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr)
{
if (!blocks)
return -1;
#ifdef JIT_UNLIMITED_ICACHE
u32 inst;
if (addr & JIT_ICACHE_VMEM_BIT)
{
inst = *(u32*)(iCacheVMEM + (addr & JIT_ICACHE_MASK));
}
else if (addr & JIT_ICACHE_EXRAM_BIT)
{
inst = *(u32*)(iCacheEx + (addr & JIT_ICACHEEX_MASK));
}
else
{
inst = *(u32*)(iCache + (addr & JIT_ICACHE_MASK));
}
inst = Common::swap32(inst);
#else
u32 inst = Memory::ReadFast32(addr);
#endif
inst = *GetICachePtr(addr);
if (inst & 0xfc000000) // definitely not a JIT block
return -1;
if ((int)inst >= num_blocks)
Expand All @@ -304,23 +256,6 @@ bool JitBlock::ContainsAddress(u32 em_address)
return inst;
}

void JitBaseBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers)
{
for (int i = 0; i < num_blocks; i++)
if (blocks[i].ContainsAddress(em_address))
block_numbers->push_back(i);
}

u32 JitBaseBlockCache::GetOriginalFirstOp(int block_num)
{
if (block_num >= num_blocks)
{
//PanicAlert("JitBaseBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num);
return block_num;
}
return blocks[block_num].originalFirstOpcode;
}

CompiledCode JitBaseBlockCache::GetCompiledCodeFromBlock(int block_num)
{
return (CompiledCode)blockCodePointers[block_num];
Expand Down Expand Up @@ -404,12 +339,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
return;
}
b.invalid = true;
#ifdef JIT_UNLIMITED_ICACHE
JitInterface::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD);
#else
if (Memory::ReadFast32(b.originalAddress) == block_num)
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
#endif
*GetICachePtr(b.originalAddress) = JIT_ICACHE_INVALID_WORD;

UnlinkBlock(block_num);

Expand Down Expand Up @@ -441,24 +371,8 @@ bool JitBlock::ContainsAddress(u32 em_address)
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1;
while (it2 != block_map.end() && it2->first.second < pAddr + length)
{
#ifdef JIT_UNLIMITED_ICACHE
JitBlock &b = blocks[it2->second];
if (b.originalAddress & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else if (b.originalAddress & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
#endif
*GetICachePtr(b.originalAddress) = JIT_ICACHE_INVALID_WORD;
DestroyBlock(it2->second, true);
it2++;
}
Expand All @@ -468,7 +382,6 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}

#ifdef JIT_UNLIMITED_ICACHE
// invalidate iCache.
// icbi can be called with any address, so we should check
if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 &&
Expand All @@ -492,7 +405,6 @@ bool JitBlock::ContainsAddress(u32 em_address)
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
#endif
}
void JitBlockCache::WriteLinkBlock(u8* location, const u8* address)
{
Expand Down
38 changes: 12 additions & 26 deletions Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h
Expand Up @@ -27,8 +27,8 @@
#define JIT_ICACHE_EXRAM_BIT 0x10000000
#define JIT_ICACHE_VMEM_BIT 0x20000000
// this corresponds to opcode 5 which is invalid in PowerPC
#define JIT_ICACHE_INVALID_BYTE 0x14
#define JIT_ICACHE_INVALID_WORD 0x14141414
#define JIT_ICACHE_INVALID_BYTE 0x80
#define JIT_ICACHE_INVALID_WORD 0x80808080

struct JitBlock
{
Expand All @@ -39,16 +39,13 @@ struct JitBlock
u32 exitAddress[2]; // 0xFFFFFFFF == unknown

u32 originalAddress;
u32 originalFirstOpcode; //to be able to restore
u32 codeSize;
u32 originalSize;
int runCount; // for profiling.
int blockNum;
int flags;

bool invalid;
bool linkStatus[2];
bool ContainsAddress(u32 em_address);

#ifdef _WIN32
// we don't really need to save start and stop
Expand All @@ -74,12 +71,10 @@ class JitBaseBlockCache
std::multimap<u32, int> links_to;
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
std::bitset<0x20000000 / 32> valid_block;
#ifdef JIT_UNLIMITED_ICACHE
u8 *iCache;
u8 *iCacheEx;
u8 *iCacheVMEM;
#endif
int MAX_NUM_BLOCKS;
enum
{
MAX_NUM_BLOCKS = 65536*2
};

bool RangeIntersect(int s1, int e1, int s2, int e2) const;
void LinkBlockExits(int i);
Expand All @@ -93,10 +88,7 @@ class JitBaseBlockCache
public:
JitBaseBlockCache() :
blockCodePointers(0), blocks(0), num_blocks(0),
#ifdef JIT_UNLIMITED_ICACHE
iCache(0), iCacheEx(0), iCacheVMEM(0),
#endif
MAX_NUM_BLOCKS(0) { }
iCache(0), iCacheEx(0), iCacheVMEM(0) {}
int AllocateBlock(u32 em_address);
void FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr);

Expand All @@ -112,21 +104,15 @@ class JitBaseBlockCache
JitBlock *GetBlock(int block_num);
int GetNumBlocks() const;
const u8 **GetCodePointers();
#ifdef JIT_UNLIMITED_ICACHE
u8 *GetICache();
u8 *GetICacheEx();
u8 *GetICacheVMEM();
#endif
u8 *iCache;
u8 *iCacheEx;
u8 *iCacheVMEM;

u32* GetICachePtr(u32 addr);

// Fast way to get a block. Only works on the first ppc instruction of a block.
int GetBlockNumberFromStartAddress(u32 em_address);

// slower, but can get numbers from within blocks, not just the first instruction.
// WARNING! WILL NOT WORK WITH INLINING ENABLED (not yet a feature but will be soon)
// Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap.
// This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime.
void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers);

u32 GetOriginalFirstOp(int block_num);
CompiledCode GetCompiledCodeFromBlock(int block_num);

Expand Down
27 changes: 19 additions & 8 deletions Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp
Expand Up @@ -5,13 +5,6 @@
#include "Common.h"

#include "CPUDetect.h"
#include "../PowerPC.h"
#include "../../Core.h"
#include "../../HW/GPFifo.h"
#include "../../HW/Memmap.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
#include "x64ABI.h"
#include "JitBase.h"
#include "Jit_Util.h"

Expand Down Expand Up @@ -126,7 +119,10 @@ u8 *EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, Gen::OpArg opAddress, int ac

void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend)
{
registersInUse &= ~(1 << RAX | 1 << reg_value);
if (!jit->js.memcheck)
{
registersInUse &= ~(1 << RAX | 1 << reg_value);
}
#if defined(_M_X64)
#ifdef ENABLE_MEM_CHECK
if (!Core::g_CoreStartupParameter.bMMU && !Core::g_CoreStartupParameter.bEnableDebugging && Core::g_CoreStartupParameter.bFastmem)
Expand Down Expand Up @@ -171,6 +167,9 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
case 8: ABI_CallFunctionC((void *)&Memory::Read_U8_ZX, address); break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, false);

MEMCHECK_START

if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
Expand All @@ -180,6 +179,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
{
MOVZX(32, accessSize, reg_value, R(EAX));
}

MEMCHECK_END
}
}
else
Expand All @@ -199,6 +200,9 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
case 8: ABI_CallFunctionR((void *)&Memory::Read_U8_ZX, EAX); break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, false);

MEMCHECK_START

if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
Expand All @@ -209,6 +213,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
MOVZX(32, accessSize, reg_value, R(EAX));
}

MEMCHECK_END

FixupBranch exit = J();
SetJumpTarget(fast);
UnsafeLoadToReg(reg_value, R(EAX), accessSize, 0, signExtend);
Expand All @@ -227,6 +233,9 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
case 8: ABI_CallFunctionA((void *)&Memory::Read_U8_ZX, opAddress); break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, false);

MEMCHECK_START

if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
Expand All @@ -237,6 +246,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
MOVZX(32, accessSize, reg_value, R(EAX));
}

MEMCHECK_END

FixupBranch exit = J();
SetJumpTarget(fast);
UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend);
Expand Down
14 changes: 13 additions & 1 deletion Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h
Expand Up @@ -8,8 +8,20 @@
#include "x64Emitter.h"
#include <unordered_map>

#define MEMCHECK_START \
FixupBranch memException; \
if (jit->js.memcheck) \
{ TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); \
memException = J_CC(CC_NZ, true); }

#define MEMCHECK_END \
if (jit->js.memcheck) \
SetJumpTarget(memException);


// Like XCodeBlock but has some utilities for memory access.
class EmuCodeBlock : public Gen::XCodeBlock {
class EmuCodeBlock : public Gen::XCodeBlock
{
public:
void UnsafeLoadRegToReg(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset = 0, bool signExtend = false);
void UnsafeLoadRegToRegNoSwap(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset);
Expand Down
1,345 changes: 1,345 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp

Large diffs are not rendered by default.

594 changes: 594 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/IR.h

Large diffs are not rendered by default.

153 changes: 153 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase.h
@@ -0,0 +1,153 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#ifndef _JITILBASE_H
#define _JITILBASE_H

#include "IR.h"
#include "../PowerPC.h"
#include "../PPCAnalyst.h"
#include "../PPCTables.h"
#include "../JitCommon/JitBase.h"
#include "../../ConfigManager.h"
#include "../../Core.h"
#include "../../CoreTiming.h"
#include "../../HW/GPFifo.h"
#include "../../HW/Memmap.h"

#define INSTRUCTION_START

#define JITDISABLE(setting) \
if (Core::g_CoreStartupParameter.bJITOff || \
Core::g_CoreStartupParameter.setting) \
{Default(inst); return;}

class JitILBase : public JitBase
{
protected:
// The default code buffer. We keep it around to not have to alloc/dealloc a
// large chunk of memory for each recompiled block.
PPCAnalyst::CodeBuffer code_buffer;
public:
JitILBase() : code_buffer(32000) {}
~JitILBase() {}

IREmitter::IRBuilder ibuild;

virtual JitBaseBlockCache *GetBlockCache() = 0;

virtual void Jit(u32 em_address) = 0;

virtual const u8 *BackPatch(u8 *codePtr, u32 em_address, void *ctx) = 0;

virtual const CommonAsmRoutinesBase *GetAsmRoutines() = 0;

virtual bool IsInCodeSpace(u8 *ptr) = 0;

// OPCODES
virtual void unknown_instruction(UGeckoInstruction inst) = 0;
virtual void Default(UGeckoInstruction inst) = 0;
virtual void DoNothing(UGeckoInstruction inst) = 0;
virtual void HLEFunction(UGeckoInstruction inst) = 0;

virtual void DynaRunTable4(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable19(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable31(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable59(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable63(UGeckoInstruction _inst) = 0;

// Branches
void sc(UGeckoInstruction inst);
void rfi(UGeckoInstruction inst);
void bx(UGeckoInstruction inst);
void bcx(UGeckoInstruction inst);
void bcctrx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction inst);

// LoadStore
void lXzx(UGeckoInstruction inst);
void lhax(UGeckoInstruction inst);
void stXx(UGeckoInstruction inst);
void lmw(UGeckoInstruction inst);
void stmw(UGeckoInstruction inst);
void stX(UGeckoInstruction inst); //stw sth stb
void lXz(UGeckoInstruction inst);
void lbzu(UGeckoInstruction inst);
void lha(UGeckoInstruction inst);

// System Registers
void mtspr(UGeckoInstruction inst);
void mfspr(UGeckoInstruction inst);
void mtmsr(UGeckoInstruction inst);
void mfmsr(UGeckoInstruction inst);
void mftb(UGeckoInstruction inst);
void mtcrf(UGeckoInstruction inst);
void mfcr(UGeckoInstruction inst);
void mcrf(UGeckoInstruction inst);
void crXX(UGeckoInstruction inst);

void dcbst(UGeckoInstruction inst);
void dcbz(UGeckoInstruction inst);
void icbi(UGeckoInstruction inst);

void addx(UGeckoInstruction inst);
void boolX(UGeckoInstruction inst);
void mulli(UGeckoInstruction inst);
void mulhwux(UGeckoInstruction inst);
void mullwx(UGeckoInstruction inst);
void divwux(UGeckoInstruction inst);
void srawix(UGeckoInstruction inst);
void srawx(UGeckoInstruction inst);
void addex(UGeckoInstruction inst);
void addzex(UGeckoInstruction inst);

void extsbx(UGeckoInstruction inst);
void extshx(UGeckoInstruction inst);

void reg_imm(UGeckoInstruction inst);

void ps_sel(UGeckoInstruction inst);
void ps_mr(UGeckoInstruction inst);
void ps_sign(UGeckoInstruction inst); //aggregate
void ps_arith(UGeckoInstruction inst); //aggregate
void ps_mergeXX(UGeckoInstruction inst);
void ps_maddXX(UGeckoInstruction inst);
void ps_rsqrte(UGeckoInstruction inst);
void ps_sum(UGeckoInstruction inst);
void ps_muls(UGeckoInstruction inst);

void fp_arith_s(UGeckoInstruction inst);

void fcmpx(UGeckoInstruction inst);
void fmrx(UGeckoInstruction inst);

void cmpXX(UGeckoInstruction inst);

void cntlzwx(UGeckoInstruction inst);

void lfs(UGeckoInstruction inst);
void lfd(UGeckoInstruction inst);
void stfd(UGeckoInstruction inst);
void stfs(UGeckoInstruction inst);
void stfsx(UGeckoInstruction inst);
void psq_l(UGeckoInstruction inst);
void psq_st(UGeckoInstruction inst);

void fmaddXX(UGeckoInstruction inst);
void fsign(UGeckoInstruction inst);
void rlwinmx(UGeckoInstruction inst);
void rlwimix(UGeckoInstruction inst);
void rlwnmx(UGeckoInstruction inst);
void negx(UGeckoInstruction inst);
void slwx(UGeckoInstruction inst);
void srwx(UGeckoInstruction inst);
void lfsx(UGeckoInstruction inst);

void subfic(UGeckoInstruction inst);
void subfcx(UGeckoInstruction inst);
void subfx(UGeckoInstruction inst);
void subfex(UGeckoInstruction inst);

};
#endif
185 changes: 185 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_Branch.cpp
@@ -0,0 +1,185 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"


// The branches are known good, or at least reasonably good.
// No need for a disable-mechanism.

// If defined, clears CR0 at blr and bl-s. If the assumption that
// flags never carry over between functions holds, then the task for
// an optimizer becomes much easier.

// #define ACID_TEST

// Zelda and many more games seem to pass the Acid Test.

//#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return;
#define NORMALBRANCH_START

void JitILBase::sc(UGeckoInstruction inst)
{
ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC));
}

void JitILBase::rfi(UGeckoInstruction inst)
{
ibuild.EmitRFIExit();
}

void JitILBase::bx(UGeckoInstruction inst)
{
NORMALBRANCH_START
INSTRUCTION_START;

// We must always process the following sentence
// even if the blocks are merged by PPCAnalyst::Flatten().
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));

// If this is not the last instruction of a block,
// we will skip the rest process.
// Because PPCAnalyst::Flatten() merged the blocks.
if (!js.isLastInstruction) {
return;
}

u32 destination;
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = js.compilerPC + SignExt26(inst.LI << 2);

if (destination == js.compilerPC) {
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}

ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}

static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) {
IREmitter::InstLoc CRTest = 0, CTRTest = 0;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
CRTest = ibuild.EmitXor(CRCmp, CRTest);
}

if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
if (inst.BO & 2) {
CTRTest = ibuild.EmitICmpEq(c,
ibuild.EmitIntConst(0));
} else {
CTRTest = c;
}
}

IREmitter::InstLoc Test = CRTest;
if (CTRTest) {
if (Test)
Test = ibuild.EmitAnd(Test, CTRTest);
else
Test = CTRTest;
}

if (!Test) {
Test = ibuild.EmitIntConst(1);
}
return Test;
}

void JitILBase::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
ibuild.EmitStoreLink(
ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc Test = TestBranch(ibuild, inst);

u32 destination;
if(inst.AA)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);

if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
)
{
ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination));
}
else
{
ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination));
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}

void JitILBase::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
}
IREmitter::InstLoc test;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
test = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
test = ibuild.EmitXor(test, CRCmp);
} else {
test = ibuild.EmitIntConst(1);
}
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc destination = ibuild.EmitLoadCTR();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}

void JitILBase::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START

if (!js.isLastInstruction &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
return;
}

if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));

IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
123 changes: 123 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_FloatingPoint.cpp
@@ -0,0 +1,123 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

void JitILBase::fp_arith_s(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 &&
inst.SUBOP5 != 21 && inst.SUBOP5 != 26)) {
Default(inst); return;
}
// Only the interpreter has "proper" support for (some) FP flags
if (inst.SUBOP5 == 25 && Core::g_CoreStartupParameter.bEnableFPRF) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
switch (inst.SUBOP5)
{
case 20: //sub
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 21: //add
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 25: //mul
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
break;
case 26: //rsqrte
val = ibuild.EmitLoadFReg(inst.FB);
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitFSRSqrt(val);
val = ibuild.EmitDupSingleToMReg(val);
break;
default:
_assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!");
}

if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}

void JitILBase::fmaddXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
if (inst.Rc) {
Default(inst); return;
}
// Only the interpreter has "proper" support for (some) FP flags
if (inst.SUBOP5 == 29 && Core::g_CoreStartupParameter.bEnableFPRF) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
if (inst.SUBOP5 & 1)
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
else
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
if (inst.SUBOP5 & 2)
val = ibuild.EmitFDNeg(val);
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}

void JitILBase::fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB);
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
ibuild.EmitStoreFReg(val, inst.FD);
}

void JitILBase::fcmpx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
IREmitter::InstLoc lhs, rhs, res;
lhs = ibuild.EmitLoadFReg(inst.FA);
rhs = ibuild.EmitLoadFReg(inst.FB);
int ordered = (inst.SUBOP10 == 32) ? 1 : 0;
res = ibuild.EmitFDCmpCR(lhs, rhs, ordered);
ibuild.EmitStoreFPRF(res);
ibuild.EmitStoreCR(res, inst.CRFD);
}

void JitILBase::fsign(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
Default(inst);
return;

// TODO
switch (inst.SUBOP10) {
case 40: // fnegx
break;
case 264: // fabsx
break;
case 136: // fnabs
break;
default:
PanicAlert("fsign bleh");
break;
}
}
526 changes: 526 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_Integer.cpp

Large diffs are not rendered by default.

208 changes: 208 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_LoadStore.cpp
@@ -0,0 +1,208 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

void JitILBase::lhax(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
}

void JitILBase::lXz(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
IREmitter::InstLoc val;
switch (inst.OPCD & ~0x1)
{
case 32: val = ibuild.EmitLoad32(addr); break; //lwz
case 40: val = ibuild.EmitLoad16(addr); break; //lhz
case 34: val = ibuild.EmitLoad8(addr); break; //lbz
default: PanicAlert("lXz: invalid access size"); val = 0; break;
}
ibuild.EmitStoreGReg(val, inst.RD);
}

void JitILBase::lbzu(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
const IREmitter::InstLoc uAddress = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), ibuild.EmitIntConst((int)inst.SIMM_16));
const IREmitter::InstLoc temp = ibuild.EmitLoad8(uAddress);
ibuild.EmitStoreGReg(temp, inst.RD);
ibuild.EmitStoreGReg(uAddress, inst.RA);
}

void JitILBase::lha(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr =
ibuild.EmitIntConst((s32)(s16)inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
}

void JitILBase::lXzx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);

if (inst.RA)
{
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.SUBOP10 & 32)
ibuild.EmitStoreGReg(addr, inst.RA);
}

IREmitter::InstLoc val;
switch (inst.SUBOP10 & ~32)
{
default: PanicAlert("lXzx: invalid access size");
case 23: val = ibuild.EmitLoad32(addr); break; //lwzx
case 279: val = ibuild.EmitLoad16(addr); break; //lhzx
case 87: val = ibuild.EmitLoad8(addr); break; //lbzx
}
ibuild.EmitStoreGReg(val, inst.RD);
}

void JitILBase::dcbst(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)

// If the dcbst instruction is preceded by dcbt, it is flushing a prefetched
// memory location. Do not invalidate the JIT cache in this case as the memory
// will be the same.
// dcbt = 0x7c00022c
if ((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c)
{
Default(inst); return;
}
}

// Zero cache line.
void JitILBase::dcbz(UGeckoInstruction inst)
{
Default(inst); return;

// TODO!
#if 0
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff)
{Default(inst); return;} // turn off from debugger
INSTRUCTION_START;
MOV(32, R(EAX), gpr.R(inst.RB));
if (inst.RA)
ADD(32, R(EAX), gpr.R(inst.RA));
AND(32, R(EAX), Imm32(~31));
XORPD(XMM0, R(XMM0));
#ifdef _M_X64
MOVAPS(MComplex(EBX, EAX, SCALE_1, 0), XMM0);
MOVAPS(MComplex(EBX, EAX, SCALE_1, 16), XMM0);
#else
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOVAPS(MDisp(EAX, (u32)Memory::base), XMM0);
MOVAPS(MDisp(EAX, (u32)Memory::base + 16), XMM0);
#endif
#endif
}

void JitILBase::stX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
value = ibuild.EmitLoadGReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), addr);
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
switch (inst.OPCD & ~1)
{
case 36: ibuild.EmitStore32(value, addr); break; //stw
case 44: ibuild.EmitStore16(value, addr); break; //sth
case 38: ibuild.EmitStore8(value, addr); break; //stb
default: _assert_msg_(DYNA_REC, 0, "AWETKLJASDLKF"); return;
}
}

void JitILBase::stXx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB),
value = ibuild.EmitLoadGReg(inst.RS);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.SUBOP10 & 32)
ibuild.EmitStoreGReg(addr, inst.RA);
switch (inst.SUBOP10 & ~32)
{
case 151: ibuild.EmitStore32(value, addr); break; //stw
case 407: ibuild.EmitStore16(value, addr); break; //sth
case 215: ibuild.EmitStore8(value, addr); break; //stb
default: _assert_msg_(DYNA_REC, 0, "AWETKLJASDLKF"); return;
}
}

// A few games use these heavily in video codecs. (GFZP01 @ 0x80020E18)
void JitILBase::lmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoad32(addr);
ibuild.EmitStoreGReg(val, i);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}

void JitILBase::stmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoadGReg(i);
ibuild.EmitStore32(val, addr);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}

void JitILBase::icbi(UGeckoInstruction inst)
{
Default(inst);
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
@@ -0,0 +1,100 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

// TODO: Add peephole optimizations for multiple consecutive lfd/lfs/stfd/stfs since they are so common,
// and pshufb could help a lot.
// Also add hacks for things like lfs/stfs the same reg consecutively, that is, simple memory moves.

void JitILBase::lfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitDupSingleToMReg(ibuild.EmitLoadSingle(addr));
ibuild.EmitStoreFReg(val, inst.RD);
return;
}


void JitILBase::lfd(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitLoadFReg(inst.RD);
val = ibuild.EmitInsertDoubleInMReg(ibuild.EmitLoadDouble(addr), val);
ibuild.EmitStoreFReg(val, inst.RD);
return;
}


void JitILBase::stfd(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
ibuild.EmitStoreDouble(val, addr);
return;
}


void JitILBase::stfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitDoubleToSingle(val);
ibuild.EmitStoreSingle(val, addr);
return;
}


void JitILBase::stfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB),
val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitDoubleToSingle(val);
ibuild.EmitStoreSingle(val, addr);
return;
}


void JitILBase::lfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff)
if (js.memcheck) { Default(inst); return; }
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitDupSingleToMReg(ibuild.EmitLoadSingle(addr));
ibuild.EmitStoreFReg(val, inst.RD);
}

@@ -0,0 +1,38 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

void JitILBase::psq_st(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStorePairedOff)
if (js.memcheck) { Default(inst); return; }
if (inst.W) {Default(inst); return;}
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD == 61)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitLoadFReg(inst.RS);
val = ibuild.EmitCompactMRegToPacked(val);
ibuild.EmitStorePaired(val, addr, inst.I);
}

void JitILBase::psq_l(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStorePairedOff)
if (js.memcheck) { Default(inst); return; }
if (inst.W) {Default(inst); return;}
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD == 57)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitLoadPaired(addr, inst.I | (inst.W << 3)); // The lower 3 bits is for GQR index. The next 1 bit is for inst.W
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.RD);
}
199 changes: 199 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_Paired.cpp
@@ -0,0 +1,199 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

void JitILBase::ps_mr(UGeckoInstruction inst)
{
Default(inst); return;
}

void JitILBase::ps_sel(UGeckoInstruction inst)
{
Default(inst); return;
}

void JitILBase::ps_sign(UGeckoInstruction inst)
{
Default(inst); return;
}

void JitILBase::ps_rsqrte(UGeckoInstruction inst)
{
Default(inst); return;
}

void JitILBase::ps_arith(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITPairedOff)
if (inst.Rc || (inst.SUBOP5 != 21 && inst.SUBOP5 != 20 && inst.SUBOP5 != 25)) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), rhs;
if (inst.SUBOP5 == 25)
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
else
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitCompactMRegToPacked(val);

switch (inst.SUBOP5)
{
case 20:
val = ibuild.EmitFPSub(val, rhs);
break;
case 21:
val = ibuild.EmitFPAdd(val, rhs);
break;
case 25:
val = ibuild.EmitFPMul(val, rhs);
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}

void JitILBase::ps_sum(UGeckoInstruction inst)
{
// TODO: This operation strikes me as a bit strange...
// perhaps we can optimize it depending on the users?
// TODO: ps_sum breaks Sonic Colours (black screen)
Default(inst); return;
INSTRUCTION_START
JITDISABLE(bJITPairedOff)
if (inst.Rc || inst.SUBOP5 != 10) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), temp;
val = ibuild.EmitCompactMRegToPacked(val);
val = ibuild.EmitFPDup0(val);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, temp);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMerge11(val, temp);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}


void JitILBase::ps_muls(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITPairedOff)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA),
rhs = ibuild.EmitLoadFReg(inst.FC);

val = ibuild.EmitCompactMRegToPacked(val);
rhs = ibuild.EmitCompactMRegToPacked(rhs);

if (inst.SUBOP5 == 12)
rhs = ibuild.EmitFPDup0(rhs);
else
rhs = ibuild.EmitFPDup1(rhs);

val = ibuild.EmitFPMul(val, rhs);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}


//TODO: find easy cases and optimize them, do a breakout like ps_arith
void JitILBase::ps_mergeXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITPairedOff)
if (inst.Rc) {
Default(inst); return;
}

IREmitter::InstLoc val = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FA)),
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));

switch (inst.SUBOP10)
{
case 528:
val = ibuild.EmitFPMerge00(val, rhs);
break; //00
case 560:
val = ibuild.EmitFPMerge01(val, rhs);
break; //01
case 592:
val = ibuild.EmitFPMerge10(val, rhs);
break; //10
case 624:
val = ibuild.EmitFPMerge11(val, rhs);
break; //11
default:
_assert_msg_(DYNA_REC, 0, "ps_merge - invalid op");
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}


void JitILBase::ps_maddXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITPairedOff)
if (inst.Rc) {
Default(inst); return;
}

IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), op2, op3;
val = ibuild.EmitCompactMRegToPacked(val);
switch (inst.SUBOP5)
{
case 14: {//madds0
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup0(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 15: {//madds1
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup1(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 28: {//msub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
break;
}
case 29: {//madd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 30: {//nmsub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
case 31: {//nmadd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
220 changes: 220 additions & 0 deletions Source/Core/Core/Src/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp
@@ -0,0 +1,220 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "JitILBase.h"

#include "../../HW/SystemTimers.h"


void JitILBase::mtspr(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff)
u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
switch(iIndex) {
case SPR_TL:
case SPR_TU:
Default(inst);
return;
case SPR_LR:
ibuild.EmitStoreLink(ibuild.EmitLoadGReg(inst.RD));
return;
case SPR_CTR:
ibuild.EmitStoreCTR(ibuild.EmitLoadGReg(inst.RD));
return;
case SPR_GQR0:
case SPR_GQR0 + 1:
case SPR_GQR0 + 2:
case SPR_GQR0 + 3:
case SPR_GQR0 + 4:
case SPR_GQR0 + 5:
case SPR_GQR0 + 6:
case SPR_GQR0 + 7:
ibuild.EmitStoreGQR(ibuild.EmitLoadGReg(inst.RD), iIndex - SPR_GQR0);
return;
case SPR_SRR0:
case SPR_SRR1:
ibuild.EmitStoreSRR(ibuild.EmitLoadGReg(inst.RD), iIndex - SPR_SRR0);
return;
default:
Default(inst);
return;
}
}

void JitILBase::mfspr(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff)
u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
switch (iIndex)
{
case SPR_TL:
case SPR_TU:
Default(inst);
return;
case SPR_LR:
ibuild.EmitStoreGReg(ibuild.EmitLoadLink(), inst.RD);
return;
case SPR_CTR:
ibuild.EmitStoreGReg(ibuild.EmitLoadCTR(), inst.RD);
return;
case SPR_GQR0:
case SPR_GQR0 + 1:
case SPR_GQR0 + 2:
case SPR_GQR0 + 3:
case SPR_GQR0 + 4:
case SPR_GQR0 + 5:
case SPR_GQR0 + 6:
case SPR_GQR0 + 7:
ibuild.EmitStoreGReg(ibuild.EmitLoadGQR(iIndex - SPR_GQR0), inst.RD);
return;
default:
Default(inst);
return;
}
}


// =======================================================================================
// Don't interpret this, if we do we get thrown out
// --------------
void JitILBase::mtmsr(UGeckoInstruction inst)
{
ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS), ibuild.EmitIntConst(js.compilerPC));
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
// ==============


void JitILBase::mfmsr(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff)
ibuild.EmitStoreGReg(ibuild.EmitLoadMSR(), inst.RD);
}

void JitILBase::mftb(UGeckoInstruction inst)
{
INSTRUCTION_START;
JITDISABLE(bJITSystemRegistersOff)
mfspr(inst);
}

void JitILBase::mfcr(UGeckoInstruction inst)
{
INSTRUCTION_START;
JITDISABLE(bJITSystemRegistersOff)

IREmitter::InstLoc d = ibuild.EmitIntConst(0);
for (int i = 0; i < 8; ++i)
{
d = ibuild.EmitShl(d, ibuild.EmitIntConst(4));
d = ibuild.EmitOr(d, ibuild.EmitLoadCR(i));
}
ibuild.EmitStoreGReg(d, inst.RD);
}

void JitILBase::mtcrf(UGeckoInstruction inst)
{
INSTRUCTION_START;
JITDISABLE(bJITSystemRegistersOff)

IREmitter::InstLoc s = ibuild.EmitLoadGReg(inst.RS);
for (int i = 0; i < 8; ++i)
{
if (inst.CRM & (0x80 >> i))
{
IREmitter::InstLoc value;
value = ibuild.EmitShrl(s, ibuild.EmitIntConst(28 - i * 4));
value = ibuild.EmitAnd(value, ibuild.EmitIntConst(0xF));
ibuild.EmitStoreCR(value, i);
}
}
}

void JitILBase::mcrf(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff)

if (inst.CRFS != inst.CRFD)
{
ibuild.EmitStoreCR(ibuild.EmitLoadCR(inst.CRFS), inst.CRFD);
}
}

void JitILBase::crXX(UGeckoInstruction inst)
{
// Ported from Jit_SystemRegister.cpp

// Get bit CRBA in EAX aligned with bit CRBD
const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
IREmitter::InstLoc eax = ibuild.EmitLoadCR(inst.CRBA >> 2);
if (shiftA < 0)
eax = ibuild.EmitShl(eax, ibuild.EmitIntConst(-shiftA));
else if (shiftA > 0)
eax = ibuild.EmitShrl(eax, ibuild.EmitIntConst(shiftA));

// Get bit CRBB in ECX aligned with bit CRBD
const int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
IREmitter::InstLoc ecx = ibuild.EmitLoadCR(inst.CRBB >> 2);
if (shiftB < 0)
ecx = ibuild.EmitShl(ecx, ibuild.EmitIntConst(-shiftB));
else if (shiftB > 0)
ecx = ibuild.EmitShrl(ecx, ibuild.EmitIntConst(shiftB));

// Compute combined bit
const unsigned subop = inst.SUBOP10;
switch (subop) {
case 257:
// crand
eax = ibuild.EmitAnd(eax, ecx);
break;
case 129:
// crandc
ecx = ibuild.EmitNot(ecx);
eax = ibuild.EmitAnd(eax, ecx);
break;
case 289:
// creqv
eax = ibuild.EmitXor(eax, ecx);
eax = ibuild.EmitNot(eax);
break;
case 225:
// crnand
eax = ibuild.EmitAnd(eax, ecx);
eax = ibuild.EmitNot(eax);
break;
case 33:
// crnor
eax = ibuild.EmitOr(eax, ecx);
eax = ibuild.EmitNot(eax);
break;
case 449:
// cror
eax = ibuild.EmitOr(eax, ecx);
break;
case 417:
// crorc
ecx = ibuild.EmitNot(ecx);
eax = ibuild.EmitOr(eax, ecx);
break;
case 193:
// crxor
eax = ibuild.EmitXor(eax, ecx);
break;
default:
PanicAlert("crXX: invalid instruction");
break;
}

// Store result bit in CRBD
eax = ibuild.EmitAnd(eax, ibuild.EmitIntConst(0x8 >> (inst.CRBD & 3)));
IREmitter::InstLoc bd = ibuild.EmitLoadCR(inst.CRBD >> 2);
bd = ibuild.EmitAnd(bd, ibuild.EmitIntConst(~(0x8 >> (inst.CRBD & 3))));
bd = ibuild.EmitOr(bd, eax);
ibuild.EmitStoreCR(bd, inst.CRBD >> 2);
}
122 changes: 15 additions & 107 deletions Source/Core/Core/Src/PowerPC/JitInterface.cpp
Expand Up @@ -21,6 +21,8 @@
#ifdef _M_ARM
#include "JitArm32/Jit.h"
#include "JitArm32/JitArm_Tables.h"
#include "JitArmIL/JitIL.h"
#include "JitArmIL/JitIL_Tables.h"
#endif

#include "Profiler.h"
Expand Down Expand Up @@ -64,6 +66,11 @@ namespace JitInterface
ptr = new JitArm();
break;
}
case 4:
{
ptr = new JitArmIL();
break;
}
#endif
default:
{
Expand Down Expand Up @@ -99,6 +106,11 @@ namespace JitInterface
JitArmTables::InitTables();
break;
}
case 4:
{
JitArmILTables::InitTables();
break;
}
#endif
default:
{
Expand Down Expand Up @@ -197,46 +209,6 @@ namespace JitInterface
jit->GetBlockCache()->InvalidateICache(address, size);
}


// Memory functions
u32 Read_Opcode_JIT_Uncached(const u32 _Address)
{
u8* iCache;
u32 addr;
if (_Address & JIT_ICACHE_VMEM_BIT)
{
iCache = jit->GetBlockCache()->GetICacheVMEM();
addr = _Address & JIT_ICACHE_MASK;
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{
iCache = jit->GetBlockCache()->GetICacheEx();
addr = _Address & JIT_ICACHEEX_MASK;
}
else
{
iCache = jit->GetBlockCache()->GetICache();
addr = _Address & JIT_ICACHE_MASK;
}
u32 inst = *(u32*)(iCache + addr);
if (inst == JIT_ICACHE_INVALID_WORD)
{
u32 cache_block_start = addr & ~0x1f;
u32 mem_block_start = _Address & ~0x1f;
u8 *pMem = Memory::GetPointer(mem_block_start);
memcpy(iCache + cache_block_start, pMem, 32);
inst = *(u32*)(iCache + addr);
}
inst = Common::swap32(inst);

if ((inst & 0xfc000000) == 0)
{
inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
}

return inst;
}

u32 Read_Opcode_JIT(u32 _Address)
{
#ifdef FAST_ICACHE
Expand All @@ -248,83 +220,19 @@ namespace JitInterface
return 0;
}
}
u32 inst = 0;

u32 inst;
// Bypass the icache for the external interrupt exception handler
// -- this is stupid, should respect HID0
if ( (_Address & 0x0FFFFF00) == 0x00000500 )
inst = Read_Opcode_JIT_Uncached(_Address);
else
inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
#else
u32 inst = Memory::ReadUnchecked_U32(_Address);
#endif
return inst;
}

// The following function is deprecated in favour of FAST_ICACHE
u32 Read_Opcode_JIT_LC(const u32 _Address)
{
#ifdef JIT_UNLIMITED_ICACHE
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
(_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
(_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
{
PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address);
return 0;
}
u8* iCache;
u32 addr;
if (_Address & JIT_ICACHE_VMEM_BIT)
{
iCache = jit->GetBlockCache()->GetICacheVMEM();
addr = _Address & JIT_ICACHE_MASK;
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{
iCache = jit->GetBlockCache()->GetICacheEx();
addr = _Address & JIT_ICACHEEX_MASK;
}
else
{
iCache = jit->GetBlockCache()->GetICache();
addr = _Address & JIT_ICACHE_MASK;
}
u32 inst = *(u32*)(iCache + addr);
if (inst == JIT_ICACHE_INVALID_WORD)
inst = Memory::ReadUnchecked_U32(_Address);
else
inst = Common::swap32(inst);
inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
#else
u32 inst = Memory::ReadUnchecked_U32(_Address);
#endif
if ((inst & 0xfc000000) == 0)
{
inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
}
return inst;
}

// WARNING! No checks!
// We assume that _Address is cached
void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
{
#ifdef JIT_UNLIMITED_ICACHE
if (_Address & JIT_ICACHE_VMEM_BIT)
{
*(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{
*(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
}
else
*(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
#else
Memory::WriteUnchecked_U32(_Value, _Address);
#endif
}


void Shutdown()
{
Expand Down
3 changes: 0 additions & 3 deletions Source/Core/Core/Src/PowerPC/JitInterface.h
Expand Up @@ -22,9 +22,6 @@ namespace JitInterface

// used by JIT to read instructions
u32 Read_Opcode_JIT(const u32 _Address);
// used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode
u32 Read_Opcode_JIT_LC(const u32 _Address);
void Write_Opcode_JIT(const u32 _Address, const u32 _Value);

// Clearing CodeCache
void ClearCache();
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/Core/Src/PowerPC/PPCAnalyst.h
Expand Up @@ -8,10 +8,10 @@
#include <vector>
#include <map>

#include <cstdlib>
#include <string>

#include "Common.h"
#include "Gekko.h"
#include "PPCTables.h"

class PPCSymbolDB;
Expand Down Expand Up @@ -62,8 +62,8 @@ struct BlockRegStats

int GetTotalNumAccesses(int reg) {return numReads[reg] + numWrites[reg];}
int GetUseRange(int reg) {
return max(lastRead[reg], lastWrite[reg]) -
min(firstRead[reg], firstWrite[reg]);}
return std::max(lastRead[reg], lastWrite[reg]) -
std::min(firstRead[reg], firstWrite[reg]);}

inline void SetInputRegister(int reg, short opindex) {
if (firstRead[reg] == -1)
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/PPCCache.h
Expand Up @@ -5,7 +5,7 @@
#ifndef _PPCCACHE_H
#define _PPCCACHE_H

#include "Common.h"
#include "CommonTypes.h"

#define FAST_ICACHE

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/PPCSymbolDB.h
Expand Up @@ -2,7 +2,7 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "CommonTypes.h"

#include <map>
#include <string>
Expand Down
3 changes: 0 additions & 3 deletions Source/Core/Core/Src/PowerPC/PowerPC.cpp
Expand Up @@ -2,8 +2,6 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include <float.h>

#include "Common.h"
#include "Atomic.h"
#include "MathUtil.h"
Expand Down Expand Up @@ -121,7 +119,6 @@ void Init(int cpu_core)
memset(ppcState.sr, 0, sizeof(ppcState.sr));
ppcState.DebugCount = 0;
ppcState.dtlb_last = 0;
ppcState.dtlb_last = 0;
memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va));
memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa));
ppcState.itlb_last = 0;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/SignatureDB.h
Expand Up @@ -2,7 +2,7 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "CommonTypes.h"

#include <map>
#include <string>
Expand Down
1 change: 0 additions & 1 deletion Source/Core/Core/Src/ec_wii.cpp
Expand Up @@ -10,7 +10,6 @@
#include <stdio.h>
#include <string.h>
#include "Common.h"
#include "Crypto/aes.h"
#include "polarssl/sha1.h"
#include "Crypto/tools.h"
#include "FileUtil.h"
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/x64MemTools.cpp
Expand Up @@ -22,7 +22,7 @@
namespace EMM
{

#if defined __APPLE__ || defined __linux__ || defined __FreeBSD__
#if (defined __APPLE__ || defined __linux__ || defined __FreeBSD__) && !defined(ANDROID)
#include <execinfo.h>
void print_trace(const char * msg)
{
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/DiscIO/CMakeLists.txt
Expand Up @@ -21,5 +21,4 @@ set(SRCS Src/BannerLoader.cpp
Src/VolumeWiiCrypted.cpp
Src/WiiWad.cpp)

add_library(discio STATIC ${SRCS})
target_link_libraries(discio common)
add_dolphin_library(discio "${SRCS}" "")
4 changes: 1 addition & 3 deletions Source/Core/DiscIO/Src/BannerLoaderGC.cpp
Expand Up @@ -2,9 +2,7 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

// HyperIris: need clean code
#include "../../Core/Src/ConfigManager.h"

#include "CommonTypes.h"
#include "ColorUtil.h"
#include "BannerLoaderGC.h"

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/BannerLoaderWii.cpp
Expand Up @@ -5,7 +5,7 @@
#include <stdio.h>
#include <algorithm>

#include "Common.h"
#include "CommonTypes.h"
#include "ColorUtil.h"
#include "BannerLoaderWii.h"
#include "VolumeCreator.h"
Expand Down
9 changes: 4 additions & 5 deletions Source/Core/DiscIO/Src/Blob.cpp
Expand Up @@ -2,14 +2,13 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "FileUtil.h"
#include "CDUtils.h"
#include "Blob.h"
#include "CompressedBlob.h"
#include "FileBlob.h"
#include "CDUtils.h"
#include "CISOBlob.h"
#include "CompressedBlob.h"
#include "DriveBlob.h"
#include "FileBlob.h"
#include "FileUtil.h"
#include "WbfsBlob.h"

namespace DiscIO
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/Blob.h
Expand Up @@ -15,7 +15,7 @@
// detect whether the file is a compressed blob, or just a big hunk of data, or a drive, and
// automatically do the right thing.

#include "Common.h"
#include "CommonTypes.h"

namespace DiscIO
{
Expand Down
1 change: 0 additions & 1 deletion Source/Core/DiscIO/Src/CompressedBlob.cpp
Expand Up @@ -9,7 +9,6 @@
#include <unistd.h>
#endif

#include "Common.h"
#include "CompressedBlob.h"
#include "DiscScrubber.h"
#include "FileUtil.h"
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/DiscScrubber.cpp
Expand Up @@ -13,7 +13,7 @@ namespace DiscIO
namespace DiscScrubber
{

#define CLUSTER_SIZE 0x8000
#define CLUSTER_SIZE 0x8000

u8* m_FreeTable = NULL;
u64 m_FileSize;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/DiscScrubber.h
Expand Up @@ -14,7 +14,7 @@
#ifndef DISC_SCRUBBER_H
#define DISC_SCRUBBER_H

#include "Common.h"
#include "CommonTypes.h"
#include "Blob.h"


Expand Down
6 changes: 3 additions & 3 deletions Source/Core/DiscIO/Src/DriveBlob.cpp
Expand Up @@ -36,8 +36,8 @@ DriveReader::DriveReader(const char *drive)
// removal while reading from it.
pmrLockCDROM.PreventMediaRemoval = TRUE;
DeviceIoControl(hDisc, IOCTL_CDROM_MEDIA_REMOVAL,
&pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
0, &dwNotUsed, NULL);
&pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
0, &dwNotUsed, NULL);
#endif
#else
SectorReader::SetSectorSize(2048);
Expand Down Expand Up @@ -67,7 +67,7 @@ DriveReader::~DriveReader()
}
#else
file_.Close();
#endif
#endif
}

DriveReader *DriveReader::Create(const char *drive)
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/DiscIO/Src/FileHandlerARC.cpp
Expand Up @@ -2,8 +2,6 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"

#include "FileHandlerARC.h"
#include "StringUtil.h"
#include "Blob.h"
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/FileHandlerARC.h
Expand Up @@ -8,7 +8,7 @@
#include <string>
#include <vector>

#include "Common.h"
#include "CommonTypes.h"
#include "Filesystem.h"

namespace DiscIO
Expand Down
8 changes: 3 additions & 5 deletions Source/Core/DiscIO/Src/VolumeDirectory.cpp
Expand Up @@ -2,11 +2,10 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common.h"
#include "MathUtil.h"
#include "CommonPaths.h"
#include "VolumeDirectory.h"
#include "FileBlob.h"
#include "MathUtil.h"
#include "VolumeDirectory.h"

namespace DiscIO
{
Expand Down Expand Up @@ -484,8 +483,7 @@ static u32 ComputeNameSize(const File::FSTEntry& parentEntry)
{
u32 nameSize = 0;
const std::vector<File::FSTEntry>& children = parentEntry.children;
for (std::vector<File::FSTEntry>::const_iterator it = children.begin();
it != children.end(); ++it)
for (auto it = children.cbegin(); it != children.cend(); ++it)
{
const File::FSTEntry& entry = *it;
if (entry.isDirectory)
Expand Down
8 changes: 4 additions & 4 deletions Source/Core/DiscIO/Src/VolumeDirectory.h
Expand Up @@ -5,11 +5,11 @@
#ifndef _VOLUME_DIRECTORY
#define _VOLUME_DIRECTORY

#include "Volume.h"
#include "Common.h"
#include "FileUtil.h"
#include <string>
#include <map>
#include <string>

#include "FileUtil.h"
#include "Volume.h"

//
// --- this volume type is used for reading files directly from the hard drive ---
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/DiscIO/Src/VolumeGC.cpp
Expand Up @@ -2,8 +2,6 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "stdafx.h"

#include "VolumeGC.h"
#include "StringUtil.h"
#include "FileMonitor.h"
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/Src/WiiWad.h
Expand Up @@ -9,7 +9,7 @@
#include <vector>
#include <map>

#include "Common.h"
#include "CommonTypes.h"
#include "Blob.h"
#include "Volume.h"

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/InputCommon/CMakeLists.txt
Expand Up @@ -32,4 +32,4 @@ elseif(ANDROID)
Src/ControllerInterface/Android/Android.cpp)
endif()

add_library(inputcommon ${SRCS})
add_dolphin_library(inputcommon "${SRCS}" "")
2 changes: 0 additions & 2 deletions Source/Core/InputCommon/Src/GCPadStatus.h
Expand Up @@ -5,8 +5,6 @@
#ifndef _GCPAD_H_INCLUDED__
#define _GCPAD_H_INCLUDED__

#include "CommonTypes.h"

#define PAD_ERR_NONE 0
#define PAD_ERR_NO_CONTROLLER -1
#define PAD_ERR_NOT_READY -2
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/InputCommon/Src/InputConfig.h
Expand Up @@ -12,10 +12,8 @@
#include "ControllerInterface/ControllerInterface.h"
#include "ControllerEmu.h"

#include <string>
#include <vector>
#include <map>
#include <sstream>

// InputPlugin isn't a very good name anymore since it's used by GCPad/Wiimote
// which are not even plugins anymore.
Expand Down