From 2f63b56c19e748f78fc5dcd9b25a8655183d4482 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 28 Mar 2013 21:26:13 +1000 Subject: [PATCH] If MOVI2R can be done in 2 ops for ARMv6, prefer that over litpool. Litpool can take 1-3 cycles depending on when the value is used. So, usually 3 cycles :\. --- Common/ArmEmitter.cpp | 29 ++++++++++++++++++++++++++++- Common/ArmEmitter.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 96665a444c..1e7ab45925 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -90,6 +90,33 @@ Operand2 AssumeMakeOperand2(u32 imm) { return op2; } +bool ARMXEmitter::TrySetValue_TwoOp(ARMReg reg, u32 val) +{ + int ops = 0; + for (int i = 0; i < 16; i++) + { + if ((val >> (i*2)) & 0x3) + { + ops++; + i+=3; + } + } + if (ops > 2) + return false; + + bool first = true; + for (int i = 0; i < 16; i++, val >>=2) { + if (val & 0x3) { + first ? MOV(reg, Operand2((u8)val, (u8)((16-i) & 0xF))) + : ORR(reg, reg, Operand2((u8)val, (u8)((16-i) & 0xF))); + first = false; + i+=3; + val >>= 6; + } + } + return true; +} + void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg) { union {float f; u32 u;} conv; @@ -210,7 +237,7 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize) MOVW(reg, val & 0xFFFF); if(val & 0xFFFF0000) MOVT(reg, val, true); - } else { + } else if (!TrySetValue_TwoOp(reg,val) { // Use literal pool for ARMv6. AddNewLit(val); LDR(reg, _PC); // To be backpatched later diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index 144e3d76fc..c4ca4a245a 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -393,6 +393,7 @@ public: void FlushLitPool(); void AddNewLit(u32 val); + bool TrySetValue_TwoOp(ARMReg reg, u32 val); CCFlags GetCC() { return CCFlags(condition >> 28); } void SetCC(CCFlags cond = CC_AL);