Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index ab22450f04ba482c6e3ffa71b8c4a647c93dbb43..16f1e4a1223a7ecf88244942989bb7c3772e46ea 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -24,6 +24,65 @@ |
namespace Ice { |
+// The following define individual bits. |
+static constexpr uint32_t B0 = 1; |
+static constexpr uint32_t B2 = 1 << 2; |
+static constexpr uint32_t B3 = 1 << 3; |
+static constexpr uint32_t B4 = 1 << 4; |
+static constexpr uint32_t B5 = 1 << 5; |
+static constexpr uint32_t B6 = 1 << 6; |
+static constexpr uint32_t B21 = 1 << 21; |
+static constexpr uint32_t B24 = 1 << 24; |
+ |
+// Constants used for the decoding or encoding of the individual fields of |
+// instructions. Based on ARM section A5.1. |
+static constexpr uint32_t kConditionShift = 28; |
+static constexpr uint32_t kOpcodeShift = 21; |
+static constexpr uint32_t kRdShift = 12; |
+static constexpr uint32_t kRmShift = 0; |
+static constexpr uint32_t kRnShift = 16; |
+static constexpr uint32_t kSShift = 20; |
+static constexpr uint32_t kTypeShift = 25; |
+ |
+// Immediate instruction fields encoding. |
+static constexpr uint32_t kImmed8Bits = 8; |
+static constexpr uint32_t kImmed8Shift = 0; |
+static constexpr uint32_t kRotateBits = 4; |
+static constexpr uint32_t kRotateShift = 8; |
+ |
+// Types of instructions. |
+static constexpr uint32_t kInstTypeImmediate = 1; |
+ |
+inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
+ |
+inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
+ return static_cast<uint32_t>(Rn); |
+} |
+ |
+inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
+ return R != RegARM32::Encoded_Not_GPR; |
+} |
+ |
+inline bool isGPRRegisterDefined(uint32_t R) { |
+ return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |
+} |
+ |
+inline bool isConditionDefined(CondARM32::Cond Cond) { |
+ return Cond != CondARM32::kNone; |
+} |
+ |
+inline uint32_t encodeCondition(CondARM32::Cond Cond) { |
+ return static_cast<uint32_t>(Cond); |
+} |
+ |
+// Converts rotated immediate into imm12. |
+inline uint32_t encodeImm12FromFlexImm(const OperandARM32FlexImm &FlexImm) { |
+ uint32_t Immed8 = FlexImm.getImm(); |
+ uint32_t Rotate = FlexImm.getRotateAmt(); |
+ assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); |
+ return (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
+} |
+ |
Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, |
LabelVector &Labels) { |
Label *L = nullptr; |
@@ -56,20 +115,47 @@ void ARM32::AssemblerARM32::bind(Label *label) { |
label->bindTo(bound); |
} |
+void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
+ uint32_t Opcode, bool SetCc, uint32_t Rn, |
+ uint32_t Rd, uint32_t Imm12) { |
+ assert(isGPRRegisterDefined(Rd)); |
+ assert(Cond != CondARM32::kNone); |
+ uint32_t Encoding = encodeCondition(Cond) << kConditionShift | |
+ (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
+ (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
+ (Rd << kRdShift) | Imm12; |
+ emitInst(Encoding); |
+} |
+ |
void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { |
AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
- emitInt32(BkptEncoding(imm16)); |
+ uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
+ ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); |
+ emitInst(Encoding); |
} |
-void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister rm, CondARM32::Cond cond) { |
+void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
// cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
- assert(rm != RegARM32::Encoded_Not_GPR); |
- assert(cond != CondARM32::kNone); |
+ // (ARM section A8.8.27, encoding A1). |
+ assert(isGPRRegisterDefined(Rm)); |
+ assert(isConditionDefined(Cond)); |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | |
+ (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift); |
+ emitInst(Encoding); |
+} |
+ |
+void ARM32::AssemblerARM32::mov(RegARM32::GPRRegister Rd, |
+ const OperandARM32FlexImm &FlexImm, |
+ CondARM32::Cond Cond) { |
+ // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) |
+ assert(isConditionDefined(Cond)); |
AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
- int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | B24 | |
- B21 | (0xfff << 8) | B4 | |
- (static_cast<int32_t>(rm) << kRmShift); |
- emitInt32(encoding); |
+ bool SetCc = false; // Note: We don't use movs in this assembler. |
+ uint32_t Rn = 0; |
+ uint32_t Mov = B3 | B2 | B0; // 1101. |
+ emitType01(Cond, kInstTypeImmediate, Mov, SetCc, Rn, encodeGPRRegister(Rd), |
+ encodeImm12FromFlexImm(FlexImm)); |
} |
} // end of namespace Ice |