Added mov immediate

This commit is contained in:
Dani Messerman 2015-05-01 23:53:42 +03:00
parent 3151d6a99b
commit 0aec1529d3
4 changed files with 75 additions and 36 deletions

View File

@ -165,4 +165,13 @@ ARMFuncs::ResultCarry ARMFuncs::RRX_C(InstructionBlock* instruction, llvm::Value
result = ir_builder->CreateOr(result, ir_builder->CreateShl(ir_builder->CreateZExt(carry_in, ir_builder->getInt32Ty()), 31)); result = ir_builder->CreateOr(result, ir_builder->CreateShl(ir_builder->CreateZExt(carry_in, ir_builder->getInt32Ty()), 31));
auto carry = ir_builder->CreateTrunc(x, ir_builder->getInt1Ty()); auto carry = ir_builder->CreateTrunc(x, ir_builder->getInt1Ty());
return{ result, carry }; return{ result, carry };
}
ARMFuncs::ResultCarry ARMFuncs::ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value* carry)
{
auto ir_builder = instruction->IrBuilder();
auto value = ir_builder->getInt32(imm12 & 0xFF);
auto shift = ir_builder->getInt32(2 * (imm12 >> 8));
return Shift_C(instruction, value, SRType::ROR, shift, carry);
} }

View File

@ -3,7 +3,8 @@
/* /*
* Functions from the manual, * Functions from the manual,
* A8.4.3 Pseudocode details of instruction-specified shifts and rotates * A8.4.3 Pseudocode details of instruction-specified shifts and rotates
* A2.2.1 Integer arithmetic * A2.2.1 Integer arithmetic
* A5.2.4 Modified immediate constants in ARM instructions
*/ */
class InstructionBlock; class InstructionBlock;
@ -39,4 +40,6 @@ public:
static ResultCarry ASR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift); static ResultCarry ASR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
static ResultCarry ROR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift); static ResultCarry ROR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
static ResultCarry RRX_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *carry_in); static ResultCarry RRX_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *carry_in);
static ResultCarry ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value *carry);
}; };

View File

@ -3,12 +3,12 @@
#include "InstructionBlock.h" #include "InstructionBlock.h"
#include "ModuleGen.h" #include "ModuleGen.h"
#include "ARMFuncs.h" #include "ARMFuncs.h"
#include <binary_translation/BinarySearch.h>
static RegisterInstruction<MovShift> register_instruction; static RegisterInstruction<MovShift> register_instruction;
bool MovShift::Decode() bool MovShift::Decode()
{ {
// Mov and shifts must have zeroes at some operands of different data processing instructions
if (ReadFields({ CondDef(), FieldDef<3>(0), FieldDef<4>(13), FieldDef<1>(&s), FieldDef<4>(0), if (ReadFields({ CondDef(), FieldDef<3>(0), FieldDef<4>(13), FieldDef<1>(&s), FieldDef<4>(0),
FieldDef<4>(&rd), FieldDef<5>(&imm5), FieldDef<2>(&op2), FieldDef<1>(0), FieldDef<4>(&rm) })) FieldDef<4>(&rd), FieldDef<5>(&imm5), FieldDef<2>(&op2), FieldDef<1>(0), FieldDef<4>(&rm) }))
{ {
@ -17,6 +17,20 @@ bool MovShift::Decode()
if (rd == Register::PC && s) return false; // SEE SUBS PC, LR and related instructions; if (rd == Register::PC && s) return false; // SEE SUBS PC, LR and related instructions;
return true; return true;
} }
if (ReadFields({ CondDef(), FieldDef<7>(0x1d), FieldDef<1>(&s), FieldDef<4>(0),
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
{
form = Form::ImmediateA1;
return true;
}
if (ReadFields({ CondDef(), FieldDef<8>(0x30), FieldDef<4>(&imm4),
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
{
s = false;
form = Form::ImmediateA2;
if (rd == Register::PC) return false; // UNPREDICTIBLE
return true;
}
return false; return false;
} }
@ -24,39 +38,51 @@ void MovShift::GenerateInstructionCode(InstructionBlock* instruction_block)
{ {
auto ir_builder = instruction_block->IrBuilder(); auto ir_builder = instruction_block->IrBuilder();
auto original_carry = instruction_block->Read(Register::C); auto carry_in = instruction_block->Read(Register::C);
ARMFuncs::ResultCarry result = { instruction_block->Read(rm), original_carry }; ARMFuncs::ResultCarry result = {};
switch (op2) switch (form)
{ {
case Op2Type::MoveAndLSL: case Form::Register:
if (imm5 != 0) result = { instruction_block->Read(rm), carry_in };
{ switch (op2)
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSL, {
ARMFuncs::DecodeImmShift(instruction_block, 0, imm5).amount, result.carry); case Op2Type::MoveAndLSL:
} if (imm5 != 0)
break; {
case Op2Type::LSR: result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSL,
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSR, ARMFuncs::DecodeImmShift(instruction_block, 0, imm5).amount, result.carry);
ARMFuncs::DecodeImmShift(instruction_block, 1, imm5).amount, result.carry); }
break; break;
case Op2Type::ASR: case Op2Type::LSR:
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ASR, result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSR,
ARMFuncs::DecodeImmShift(instruction_block, 2, imm5).amount, result.carry); ARMFuncs::DecodeImmShift(instruction_block, 1, imm5).amount, result.carry);
break; break;
case Op2Type::RRXAndROR: case Op2Type::ASR:
if (imm5 == 0) result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ASR,
{ ARMFuncs::DecodeImmShift(instruction_block, 2, imm5).amount, result.carry);
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::RRX, break;
ir_builder->getInt32(1), result.carry); case Op2Type::RRXAndROR:
} if (imm5 == 0)
else {
{ result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::RRX,
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ROR, ir_builder->getInt32(1), result.carry);
ARMFuncs::DecodeImmShift(instruction_block, 3, imm5).amount, result.carry); }
} else
break; {
} result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ROR,
ARMFuncs::DecodeImmShift(instruction_block, 3, imm5).amount, result.carry);
}
break;
}
break;
case Form::ImmediateA1:
result = ARMFuncs::ARMExpandImm_C(instruction_block, imm12, carry_in);
break;
case Form::ImmediateA2:
result.result = ir_builder->getInt32((imm4 << 12) | imm12);
break;
}
instruction_block->Write(rd, result.result); instruction_block->Write(rd, result.result);
@ -64,7 +90,7 @@ void MovShift::GenerateInstructionCode(InstructionBlock* instruction_block)
{ {
instruction_block->Write(Register::N, ir_builder->CreateTrunc(ir_builder->CreateLShr(result.result, 31), ir_builder->getInt1Ty())); instruction_block->Write(Register::N, ir_builder->CreateTrunc(ir_builder->CreateLShr(result.result, 31), ir_builder->getInt1Ty()));
instruction_block->Write(Register::Z, ir_builder->CreateICmpEQ(result.result, ir_builder->getInt32(0))); instruction_block->Write(Register::Z, ir_builder->CreateICmpEQ(result.result, ir_builder->getInt32(0)));
if (result.carry != original_carry) if (result.carry != carry_in)
instruction_block->Write(Register::C, result.carry); instruction_block->Write(Register::C, result.carry);
} }

View File

@ -15,7 +15,7 @@ public:
}; };
enum class Form enum class Form
{ {
Register, RegisterShiftedRegister, Immediate Register, ImmediateA1, ImmediateA2
}; };
public: public:
@ -29,5 +29,6 @@ private:
Register rm; Register rm;
u32 imm12; u32 imm12;
u32 imm5; u32 imm5;
u32 imm4;
Op2Type op2; Op2Type op2;
}; };