Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Rebase ArmEmitter on PPSSPP's base. The loadstores are making my hear…
…t cry at this point.
  • Loading branch information
Sonicadvance1 committed Mar 11, 2013
1 parent e160218 commit b94b4a9
Show file tree
Hide file tree
Showing 9 changed files with 401 additions and 183 deletions.
439 changes: 301 additions & 138 deletions Source/Core/Common/Src/ArmEmitter.cpp

Large diffs are not rendered by default.

87 changes: 71 additions & 16 deletions Source/Core/Common/Src/ArmEmitter.h
Expand Up @@ -25,13 +25,20 @@
#if defined(__SYMBIAN32__) || defined(PANDORA)
#include <signal.h>
#endif
#include <vector>

#undef _IP
#undef R0
#undef _SP
#undef _LR
#undef _PC

// VCVT flags
#define TO_FLOAT 0
#define TO_INT 1 << 0
#define IS_SIGNED 1 << 1
#define ROUND_TO_ZERO 1 << 2

namespace ArmGen
{
enum ARMReg
Expand Down Expand Up @@ -171,7 +178,7 @@ class Operand2
Value = base;
}

Operand2(u8 shift, ShiftType type, ARMReg base)// For IMM shifted register
Operand2(ARMReg base, ShiftType type, u8 shift)// For IMM shifted register
{
if(shift == 32) shift = 0;
switch (type)
Expand Down Expand Up @@ -327,6 +334,13 @@ struct FixupBranch
int type; //0 = B 1 = BL
};

struct LiteralPool
{
s32 loc;
u8* ldr_address;
u32 val;
};

typedef const u8* JumpTarget;

class ARMXEmitter
Expand All @@ -336,8 +350,9 @@ class ARMXEmitter
u8 *code, *startcode;
u8 *lastCacheFlushEnd;
u32 condition;
std::vector<LiteralPool> currentLitPool;

void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, s16 op2);
void WriteStoreOp(u32 op, ARMReg src, ARMReg dest, s16 op2);
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
Expand Down Expand Up @@ -373,6 +388,10 @@ class ARMXEmitter
void FlushIcacheSection(u8 *start, u8 *end);
u8 *GetWritableCodePtr();

void FlushLitPool();
void AddNewLit(u32 val);

CCFlags GetCC() { return CCFlags(condition >> 28); }
void SetCC(CCFlags cond = CC_AL);

// Special purpose instructions
Expand Down Expand Up @@ -425,8 +444,10 @@ class ARMXEmitter
void LSL (ARMReg dest, ARMReg src, ARMReg op2);
void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
void LSLS(ARMReg dest, ARMReg src, ARMReg op2);
void LSR (ARMReg dest, ARMReg src, Operand2 op2);
void SBC (ARMReg dest, ARMReg src, Operand2 op2);
void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
void RBIT(ARMReg dest, ARMReg src);
void REV (ARMReg dest, ARMReg src);
void REV16 (ARMReg dest, ARMReg src);
void RSC (ARMReg dest, ARMReg src, Operand2 op2);
Expand Down Expand Up @@ -457,33 +478,53 @@ class ARMXEmitter
void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);

void UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);

void SXTB(ARMReg dest, ARMReg op2);
void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0);
void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0);
void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width);
void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width);
void CLZ(ARMReg rd, ARMReg rm);

// Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...)
// Just need to put an underscore here, bit annoying.
void _MSR (bool nzcvq, bool g, Operand2 op2);
void _MSR (bool nzcvq, bool g, ARMReg src );
void _MSR (bool nzcvq, bool g, ARMReg src);
void MRS (ARMReg dest);

// Memory load/store operations
void LDR (ARMReg dest, ARMReg src, s16 op2 = 0);
void LDR (ARMReg dest, ARMReg src, s16 op2 = 0);
void LDRH (ARMReg dest, ARMReg src, Operand2 op2 = 0);
void LDRSH(ARMReg dest, ARMReg src, s16 op2 = 0);
void LDRB (ARMReg dest, ARMReg src, s16 op2 = 0);
void LDRSB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
// Offset adds to the base register in LDR
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0);
void LDRB(ARMReg dest, ARMReg src, s16 op2 = 0);
void STR (ARMReg dest, ARMReg src, s16 op2 = 0);
void LDR (ARMReg dest, ARMReg base, Operand2 op2, bool Index, bool Add);
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRH (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRSH(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRB (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRSB(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void LDRLIT(ARMReg dest, u32 offset, bool Add);

void STR (ARMReg result, ARMReg base, s16 op2 = 0);
void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0);
void STRB (ARMReg result, ARMReg base, s16 op2 = 0);
// Offset adds on to the destination register in STR
void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
void STR (ARMReg result, ARMReg base, Operand2 op2, bool Index, bool Add);
void STR (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add);
void STRH (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add);
void STRB (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add);

void STRB(ARMReg dest, ARMReg src, s16 op2 = 0);
void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);

// Exclusive Access operations
void LDREX(ARMReg dest, ARMReg base);
// dest contains the result if the instruction managed to store the value
void STREX(ARMReg dest, ARMReg base, ARMReg op);
// result contains the result if the instruction managed to store the value
void STREX(ARMReg result, ARMReg base, ARMReg op);
void DMB ();
void SVC(Operand2 op);

Expand All @@ -501,9 +542,9 @@ class ARMXEmitter
// VFP Only
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
void VSTR(ARMReg Src, ARMReg Base, s16 offset);
void VCMP(ARMReg Vd, ARMReg Vm);
void VCMP(ARMReg Vd, ARMReg Vm, bool E);
// Compares against zero
void VCMP(ARMReg Vd);
void VCMP(ARMReg Vd, bool E);
void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VSQRT(ARMReg Vd, ARMReg Vm);

Expand All @@ -513,13 +554,25 @@ class ARMXEmitter
void VABS(ARMReg Vd, ARMReg Vm);
void VNEG(ARMReg Vd, ARMReg Vm);
void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMOV(ARMReg Dest, ARMReg Src, bool high);
void VMOV(ARMReg Dest, ARMReg Src);
void VCVT(ARMReg Dest, ARMReg Src, int flags);

void VMRS_APSR();
void VMRS(ARMReg Rt);
void VMSR(ARMReg Rt);

void QuickCallFunction(ARMReg scratchreg, void *func);
// Utility functions

// Wrapper around MOVT/MOVW with fallbacks.
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
void ARMABI_MOVI2M(Operand2 op, Operand2 val);
void MOVI2F(ARMReg dest, float val, ARMReg tempReg);

void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);


}; // class ARMXEmitter


Expand Down Expand Up @@ -556,7 +609,9 @@ class ARMXCodeBlock : public ARMXEmitter
// Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
void FreeCodeSpace()
{
#ifndef __SYMBIAN32__
FreeMemoryPages(region, region_size);
#endif
region = NULL;
region_size = 0;
}
Expand Down
16 changes: 8 additions & 8 deletions Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp
Expand Up @@ -148,20 +148,20 @@ void JitArm::DoDownCount()
if(js.downcountAmount < 255) // We can enlarge this if we used rotations
{
SUBS(rB, rB, js.downcountAmount);
STR(rA, rB);
STR(rB, rA);
}
else
{
ARMReg rC = gpr.GetReg(false);
MOVI2R(rC, js.downcountAmount);
SUBS(rB, rB, rC);
STR(rA, rB);
STR(rB, rA);
}
gpr.Unlock(rA, rB);
}
void JitArm::WriteExitDestInR(ARMReg Reg)
{
STR(R9, Reg, PPCSTATE_OFF(pc));
STR(Reg, R9, PPCSTATE_OFF(pc));
Cleanup();
DoDownCount();
MOVI2R(Reg, (u32)asm_routines.dispatcher);
Expand All @@ -170,7 +170,7 @@ void JitArm::WriteExitDestInR(ARMReg Reg)
}
void JitArm::WriteRfiExitDestInR(ARMReg Reg)
{
STR(R9, Reg, PPCSTATE_OFF(pc));
STR(Reg, R9, PPCSTATE_OFF(pc));
Cleanup();
DoDownCount();

Expand Down Expand Up @@ -209,7 +209,7 @@ void JitArm::WriteExit(u32 destination, int exit_num)
{
ARMReg A = gpr.GetReg(false);
MOVI2R(A, destination);
STR(R9, A, PPCSTATE_OFF(pc));
STR(A, R9, PPCSTATE_OFF(pc));
MOVI2R(A, (u32)asm_routines.dispatcher);
B(A);
}
Expand Down Expand Up @@ -384,7 +384,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
LDR(A, R9, PPCSTATE_OFF(msr));
TST(A, Shift);
FixupBranch b1 = B_CC(CC_NEQ);
STR(R9, C, PPCSTATE_OFF(pc));
STR(C, R9, PPCSTATE_OFF(pc));
MOVI2R(A, (u32)asm_routines.fpException);
B(A);
SetJumpTarget(b1);
Expand All @@ -397,7 +397,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
MOVI2R(rA, (u32)&b->runCount); // Load in to register
LDR(rB, rA); // Load the actual value in to R11.
ADD(rB, rB, 1); // Add one to the value
STR(rA, rB); // Now store it back in the memory location
STR(rB, rA); // Now store it back in the memory location
// get start tic
PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStart);
gpr.Unlock(rA, rB);
Expand Down Expand Up @@ -461,7 +461,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
MOVI2R(RA, (u32)&opinfo->runCount);
LDR(RB, RA);
ADD(RB, RB, 1);
STR(RA, RB);
STR(RB, RA);
gpr.Unlock(RA, RB);
}
if (!ops[i].skip)
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp
Expand Up @@ -38,7 +38,7 @@ using namespace ArmGen;
ARMXEmitter emit((u8 *)location);
emit.MOVI2R(R11, address);
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
emit.STR(R9, R11, PPCSTATE_OFF(pc));
emit.STR(R11, R9, PPCSTATE_OFF(pc));
emit.B(R12);
}

Expand Down
22 changes: 11 additions & 11 deletions Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp
Expand Up @@ -52,7 +52,7 @@ void JitArm::sc(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg();
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
ORR(rA, rA, EXCEPTION_SYSCALL);
STR(R9, rA, PPCSTATE_OFF(Exceptions));
STR(rA, R9, PPCSTATE_OFF(Exceptions));
gpr.Unlock(rA);

WriteExceptionExit();
Expand Down Expand Up @@ -84,14 +84,14 @@ void JitArm::rfi(UGeckoInstruction inst)
LDR(rD, R9, PPCSTATE_OFF(msr));

AND(rD, rD, rB); // rD = Masked MSR
STR(R9, rD, PPCSTATE_OFF(msr));
STR(rD, R9, PPCSTATE_OFF(msr));

LDR(rB, R9, PPCSTATE_OFF(spr[SPR_SRR1])); // rB contains SRR1 here

AND(rB, rB, rC); // rB contains masked SRR1 here
ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1

STR(R9, rB, PPCSTATE_OFF(msr)); // STR rB in to rA
STR(rB, R9, PPCSTATE_OFF(msr)); // STR rB in to rA

LDR(rA, R9, PPCSTATE_OFF(spr[SPR_SRR0]));

Expand All @@ -117,7 +117,7 @@ void JitArm::bx(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg(false);
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
// If this is not the last instruction of a block,
Expand Down Expand Up @@ -168,7 +168,7 @@ void JitArm::bcx(UGeckoInstruction inst)
{
LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
SUBS(rB, rB, 1);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_CTR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));

//SUB(32, M(&CTR), Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
Expand All @@ -193,7 +193,7 @@ void JitArm::bcx(UGeckoInstruction inst)
{
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12
}
gpr.Unlock(rA, rB);
Expand Down Expand Up @@ -235,7 +235,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
{
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
MVN(rB, 0x3); // 0xFFFFFFFC
Expand Down Expand Up @@ -269,7 +269,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
if (inst.LK_3){
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
Expand All @@ -290,7 +290,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg(false);
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
return;
Expand All @@ -305,7 +305,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
{
LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
SUBS(rB, rB, 1);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_CTR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));

//SUB(32, M(&CTR), Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
Expand Down Expand Up @@ -341,7 +341,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
if (inst.LK){
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp
Expand Up @@ -141,7 +141,7 @@ void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset)
switch (accessSize)
{
case 32:
STR(dest, value); // 8
STR(value, dest); // 8
break;
case 16:
// Not implemented
Expand Down
Expand Up @@ -70,7 +70,7 @@ void JitArm::mtspr(UGeckoInstruction inst)
}

// OK, this is easy.
STR(R9, RD, PPCSTATE_OFF(spr) + iIndex * 4);
STR(RD, R9, PPCSTATE_OFF(spr) + iIndex * 4);
}

void JitArm::mfspr(UGeckoInstruction inst)
Expand Down Expand Up @@ -99,6 +99,6 @@ void JitArm::mtmsr(UGeckoInstruction inst)
// Don't interpret this, if we do we get thrown out
//JITDISABLE(SystemRegisters)

STR(R9, gpr.R(inst.RS), PPCSTATE_OFF(msr));
STR(gpr.R(inst.RS), R9, PPCSTATE_OFF(msr));
WriteExit(js.compilerPC + 4, 0);
}

0 comments on commit b94b4a9

Please sign in to comment.