Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index d60b3b48283a633a96a93448ebac30c768462f42..51a45ccebf2c79d269fa0d000ec2679b5956f16c 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -90,6 +90,9 @@ static constexpr IValueT kShiftShift = 5; |
static constexpr IValueT kImmed12Bits = 12; |
static constexpr IValueT kImm12Shift = 0; |
+// Rotation instructions (uxtb etc.). |
+static constexpr IValueT kRotationShift = 10; |
+ |
// Div instruction register field encodings. |
static constexpr IValueT kDivRdShift = 16; |
static constexpr IValueT kDivRmShift = 8; |
@@ -110,6 +113,10 @@ static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff; |
inline IValueT encodeBool(bool B) { return B ? 1 : 0; } |
+inline IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) { |
+ return static_cast<IValueT>(Value); |
+} |
+ |
inline IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) { |
return static_cast<IValueT>(Rn); |
} |
@@ -545,6 +552,18 @@ void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
emitInst(Encoding); |
} |
+void AssemblerARM32::emitUxt(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
+ IValueT Rn, IValueT Rm, RotationValue Rotation) { |
+ IValueT Rot = encodeRotation(Rotation); |
+ if (!isConditionDefined(Cond) || !Utils::IsUint(2, Rot)) |
+ return setNeedsTextFixup(); |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | |
+ (Rn << kRnShift) | (Rd << kRdShift) | |
+ (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); |
+ emitInst(Encoding); |
+} |
+ |
void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond, |
BlockAddressMode AddressMode, bool IsLoad, |
IValueT BaseReg, IValueT Registers) { |
@@ -1131,5 +1150,42 @@ void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi, |
emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags); |
} |
+void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
+ CondARM32::Cond Cond) { |
+ IValueT Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ // Note: For the moment, we assume no rotation is specified. |
+ RotationValue Rotation = kRotateNone; |
+ constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; |
+ IValueT Rm; |
+ if (decodeOperand(OpSrc0, Rm) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ switch (typeWidthInBytes(OpSrc0->getType())) { |
+ default: |
+ return setNeedsTextFixup(); |
+ case 1: { |
+ // UXTB - ARM section A8.8.274, encoding A1: |
+ // uxtb<c> <Rd>, <Rm>{, <rotate>} |
+ // |
+ // cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
+ // rr defined (RotationValue) rotate. |
+ constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21; |
+ emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
+ return; |
+ } |
+ case 2: { |
+ // UXTH - ARM section A8.8.276, encoding A1: |
+ // uxth<c> <Rd>< <Rm>{, <rotate>} |
+ // |
+ // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
+ // rr defined (RotationValue) rotate. |
+ constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
+ emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
+ return; |
+ } |
+ } |
+} |
+ |
} // end of namespace ARM32 |
} // end of namespace Ice |