From b51b5facfd67620c71a7557a6bbf4f00192cf9a5 Mon Sep 17 00:00:00 2001 From: jpd002 Date: Wed, 13 May 2009 00:03:11 +0000 Subject: [PATCH] Added immediate constant stuff in ARM CodeGen. git-svn-id: http://svn.purei.org/purei/trunk@522 b36208d7-6611-0410-8bec-b1987f11c4a2 --- Source/ArmAssembler.cpp | 5 +++ Source/ArmAssembler.h | 1 + Source/CodeGenARM.cpp | 72 ++++++++++++++++++++++++++++++----------- Source/CodeGenARM.h | 3 ++ 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/Source/ArmAssembler.cpp b/Source/ArmAssembler.cpp index fc7977913..b14004cf4 100644 --- a/Source/ArmAssembler.cpp +++ b/Source/ArmAssembler.cpp @@ -218,6 +218,11 @@ void CArmAssembler::Mov(REGISTER rd, const RegisterAluOperand& operand) WriteWord(opcode); } +void CArmAssembler::Mov(REGISTER rd, const ImmediateAluOperand& operand) +{ + MovCc(CONDITION_AL, rd, operand); +} + void CArmAssembler::MovCc(CONDITION condition, REGISTER rd, const ImmediateAluOperand& operand) { InstructionAlu instruction; diff --git a/Source/ArmAssembler.h b/Source/ArmAssembler.h index 2558e7daf..0d881cf36 100644 --- a/Source/ArmAssembler.h +++ b/Source/ArmAssembler.h @@ -177,6 +177,7 @@ public: void Ldr(REGISTER, REGISTER, const LdrAddress&); void Mov(REGISTER, REGISTER); void Mov(REGISTER, const RegisterAluOperand&); + void Mov(REGISTER, const ImmediateAluOperand&); void MovCc(CONDITION, REGISTER, const ImmediateAluOperand&); void Mvn(REGISTER, REGISTER); void Or(REGISTER, REGISTER, REGISTER); diff --git a/Source/CodeGenARM.cpp b/Source/CodeGenARM.cpp index 8671f15c5..46ce8ea44 100644 --- a/Source/CodeGenARM.cpp +++ b/Source/CodeGenARM.cpp @@ -964,33 +964,69 @@ void CCodeGen::LoadRelativeInRegister(CArmAssembler::REGISTER registerId, uint32 m_assembler.Ldr(registerId, g_baseRegister, CArmAssembler::MakeImmediateLdrAddress(relative)); } +uint32 CCodeGen::RotateRight(uint32 value) +{ + uint32 carry = value & 1; + value >>= 1; + value |= carry << 31; + return value; +} + +uint32 CCodeGen::RotateLeft(uint32 value) +{ + uint32 carry = value >> 31; + value <<= 1; + value |= carry; + return value; +} + void CCodeGen::LoadConstantInRegister(CArmAssembler::REGISTER registerId, uint32 constant) { - //Search for an existing literal - unsigned int literalPtr = -1; - for(unsigned int i = 0; i < m_lastLiteralPtr; i++) + uint32 shadowConstant = constant; + int shiftAmount = -1; + for(unsigned int i = 0; i < 16; i++) { - if(m_literalPool[i] == constant) + if((shadowConstant & 0xFF) == shadowConstant) { - literalPtr = i; + shiftAmount = i; break; } + shadowConstant = RotateLeft(shadowConstant); + shadowConstant = RotateLeft(shadowConstant); } - if(literalPtr == -1) + + if(shiftAmount != -1) { - assert(m_lastLiteralPtr != LITERAL_POOL_SIZE); - literalPtr = m_lastLiteralPtr++; - m_literalPool[literalPtr] = constant; + m_assembler.Mov(registerId, CArmAssembler::MakeImmediateAluOperand(shadowConstant, shiftAmount)); + } + else + { + //Search for an existing literal + unsigned int literalPtr = -1; + for(unsigned int i = 0; i < m_lastLiteralPtr; i++) + { + if(m_literalPool[i] == constant) + { + literalPtr = i; + break; + } + } + if(literalPtr == -1) + { + assert(m_lastLiteralPtr != LITERAL_POOL_SIZE); + literalPtr = m_lastLiteralPtr++; + m_literalPool[literalPtr] = constant; + } + + LITERAL_POOL_REF reference; + reference.poolPtr = literalPtr; + reference.dstRegister = registerId; + reference.offset = m_stream->Tell(); + m_literalPoolRefs.push_back(reference); + + //Write a blank instruction + m_stream->Write32(0); } - - LITERAL_POOL_REF reference; - reference.poolPtr = literalPtr; - reference.dstRegister = registerId; - reference.offset = m_stream->Tell(); - m_literalPoolRefs.push_back(reference); - - //Write a blank instruction - m_stream->Write32(0); } void CCodeGen::DumpLiteralPool() diff --git a/Source/CodeGenARM.h b/Source/CodeGenARM.h index cc1f410b1..81727c967 100644 --- a/Source/CodeGenARM.h +++ b/Source/CodeGenARM.h @@ -161,6 +161,9 @@ private: void PushReg(CArmAssembler::REGISTER); + uint32 RotateRight(uint32); + uint32 RotateLeft(uint32); + void LoadRelativeInRegister(CArmAssembler::REGISTER, uint32); void LoadConstantInRegister(CArmAssembler::REGISTER, uint32);