Added mov immediate
This commit is contained in:
		| @@ -166,3 +166,12 @@ ARMFuncs::ResultCarry ARMFuncs::RRX_C(InstructionBlock* instruction, llvm::Value | |||||||
|     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); | ||||||
|  | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
|  * 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); | ||||||
| }; | }; | ||||||
| @@ -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,9 +38,13 @@ 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 (form) | ||||||
|  | 	{ | ||||||
|  | 	case Form::Register: | ||||||
|  | 		result = { instruction_block->Read(rm), carry_in }; | ||||||
| 		switch (op2) | 		switch (op2) | ||||||
| 		{ | 		{ | ||||||
| 		case Op2Type::MoveAndLSL: | 		case Op2Type::MoveAndLSL: | ||||||
| @@ -57,6 +75,14 @@ void MovShift::GenerateInstructionCode(InstructionBlock* instruction_block) | |||||||
| 			} | 			} | ||||||
| 			break; | 			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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| }; | }; | ||||||
		Reference in New Issue
	
	Block a user
	 Dani Messerman
					Dani Messerman