Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index c4d5ad680c99e3cd19eb5d1e991a6f9423a2b2db..0132d709a20e992cf05c4d3d69d975105ba7c44f 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -175,22 +175,6 @@ RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
return decodeGPRRegister((Value >> Shift) & 0xF); |
} |
-// Defines alternate layouts of instruction operands, should the (common) |
-// default pattern not be used. |
-enum OpEncoding { |
- // No alternate layout specified. |
- DefaultOpEncoding, |
- // Alternate encoding for ImmRegOffset, where the offset is divided by 4 |
- // before encoding. |
- ImmRegOffsetDiv4, |
- // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and |
- // ldrh. |
- OpEncoding3, |
- // Alternate encoding for memory operands for ldrex and strex, which only |
- // actually expect a register. |
- OpEncodingMemEx |
-}; |
- |
IValueT getEncodedGPRegNum(const Variable *Var) { |
assert(Var->hasReg()); |
int32_t Reg = Var->getRegNum(); |
@@ -215,6 +199,23 @@ IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } |
IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } |
+// Defines layouts of an operand representing a (register) memory address, |
+// possibly modified by an immediate value. |
+enum EncodedImmAddress { |
+ // Address modified by a rotated immediate 8-bit value. |
+ RotatedImm8Address, |
+ // Alternate encoding for RotatedImm8Address, where the offset is divided by 4 |
Jim Stichnoth
2016/01/25 20:37:50
Optional: Consider adding a blank line after each
Karl
2016/01/25 23:59:16
Added blank lines. Did same for following enum Enc
|
+ // before encoding. |
+ RotatedImm8Div4Address, |
+ // Address modified by an immediate 12-bit value. |
+ Imm12Address, |
+ // Alternate encoding 3, for an address modified by a rotated immediate 8-bit |
+ // value. |
+ RotatedImm8Enc3Address, |
+ // Encoding where no immediate offset is used. |
+ NoImmOffsetAddress |
+}; |
+ |
// The way an operand is encoded into a sequence of bits in functions |
// encodeOperand and encodeAddress below. |
enum EncodedOperand { |
@@ -226,24 +227,29 @@ enum EncodedOperand { |
// value. |
EncodedAsRotatedImm8, |
// EncodedAsImmRegOffset is a memory operand that can take three forms, based |
- // on OpEncoding: |
+ // on type EncodedImmAddress: |
// |
- // ***** DefaultOpEncoding ***** |
+ // ***** RotatedImm8Address ***** |
// |
// Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
// p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
// Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
// |
- // ***** OpEncoding3 ***** |
+ // ***** RotatedImm8Div4Address ***** |
// |
// Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
// if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
// Rn. |
// |
- // ***** OpEncodingMemEx ***** |
+ // ***** Imm12Address ***** |
// |
- // Value=00000000U000nnnn00000000xxxxxxxx where nnnn=Rn, xxxxxxxx=abs(Offset), |
- // and U=1 Offset>=0. |
+ // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
+ // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
+ // Rn should be used, and iiiiiiiiiiii defines the immediate 12-bit value. |
+ // |
+ // ***** NoImmOffsetAddress ***** |
+ // |
+ // Value=000000001000nnnn0000000000000000 where nnnn=Rn. |
EncodedAsImmRegOffset, |
// Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
// mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
@@ -356,14 +362,16 @@ EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value, |
return CantEncode; |
} |
-IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
- OperandARM32Mem::AddrMode Mode, |
- IValueT OffsetShift = 0) { |
+inline IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
Jim Stichnoth
2016/01/25 20:37:50
Why inline here? This seems inconsistent with the
Karl
2016/01/25 23:59:16
Removed.
|
+ OperandARM32Mem::AddrMode Mode, |
+ IOffsetT MaxOffset, IValueT OffsetShift) { |
IValueT Value = Mode | (Reg << kRnShift); |
if (Offset < 0) { |
Offset = -Offset; |
Value ^= U; // Flip U to adjust sign. |
} |
+ assert(Offset <= MaxOffset); |
+ (void)MaxOffset; |
return Value | (Offset >> OffsetShift); |
} |
@@ -380,23 +388,33 @@ IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, |
return Value; |
} |
-IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
+IValueT encodeImmRegOffset(EncodedImmAddress ImmEncoding, IValueT Reg, |
IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
- switch (AddressEncoding) { |
- case DefaultOpEncoding: |
- return encodeImmRegOffset(Reg, Offset, Mode); |
- case ImmRegOffsetDiv4: { |
+ switch (ImmEncoding) { |
+ case RotatedImm8Address: { |
+ constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
+ constexpr IValueT NoRightShift = 0; |
+ return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); |
+ } |
+ case RotatedImm8Div4Address: { |
assert((Offset & 0x3) == 0); |
+ constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
constexpr IValueT RightShift2 = 2; |
- return encodeImmRegOffset(Reg, Offset, Mode, RightShift2); |
+ return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, RightShift2); |
+ } |
+ case Imm12Address: { |
+ constexpr IOffsetT MaxOffset = (1 << 12) - 1; |
+ constexpr IValueT NoRightShift = 0; |
+ return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); |
} |
- case OpEncoding3: |
+ case RotatedImm8Enc3Address: |
return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
- case OpEncodingMemEx: |
+ case NoImmOffsetAddress: { |
assert(Offset == 0); |
assert(Mode == OperandARM32Mem::Offset); |
return Reg << kRnShift; |
} |
+ } |
llvm_unreachable("(silence g++ warning)"); |
} |
@@ -404,7 +422,7 @@ IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
// on how ARM represents the address. Returns how the value was encoded. |
EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
const AssemblerARM32::TargetInfo &TInfo, |
- OpEncoding AddressEncoding = DefaultOpEncoding) { |
+ EncodedImmAddress ImmEncoding) { |
Value = 0; // Make sure initialized. |
if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
// Should be a stack variable, with an offset. |
@@ -416,7 +434,7 @@ EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
int32_t BaseRegNum = Var->getBaseRegNum(); |
if (BaseRegNum == Variable::NoRegister) |
BaseRegNum = TInfo.FrameOrStackReg; |
- Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, |
+ Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset, |
OperandARM32Mem::Offset); |
return EncodedAsImmRegOffset; |
} |
@@ -436,7 +454,7 @@ EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
} |
// Encoded as immediate register offset. |
ConstantInteger32 *Offset = Mem->getOffset(); |
- Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), |
+ Value = encodeImmRegOffset(ImmEncoding, Rn, Offset->getValue(), |
Mem->getAddrMode()); |
return EncodedAsImmRegOffset; |
} |
@@ -802,7 +820,7 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, |
IValueT Rt, const Operand *OpAddress, |
const TargetInfo &TInfo, const char *InstName) { |
IValueT Address; |
- switch (encodeAddress(OpAddress, Address, TInfo)) { |
+ switch (encodeAddress(OpAddress, Address, TInfo, Imm12Address)) { |
default: |
llvm::report_fatal_error(std::string(InstName) + |
": Memory address not understood"); |
@@ -860,7 +878,7 @@ void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
const TargetInfo &TInfo, |
const char *InstName) { |
IValueT Address; |
- switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
+ switch (encodeAddress(OpAddress, Address, TInfo, RotatedImm8Enc3Address)) { |
default: |
llvm::report_fatal_error(std::string(InstName) + |
": Memory address not understood"); |
@@ -1356,7 +1374,7 @@ void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad, |
MemExOpcode |= B1; |
} |
IValueT AddressRn; |
- if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) != |
+ if (encodeAddress(OpAddress, AddressRn, TInfo, NoImmOffsetAddress) != |
EncodedAsImmRegOffset) |
llvm::report_fatal_error(std::string(InstName) + |
": Can't extract Rn from address"); |
@@ -1730,8 +1748,11 @@ void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) { |
// Same as load instruction. |
constexpr bool IsLoad = true; |
constexpr bool IsByte = false; |
- IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
- OperandARM32Mem::PostIndex); |
+ constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
+ constexpr IValueT NoShiftRight = 0; |
+ IValueT Address = |
+ encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
+ OperandARM32Mem::PostIndex, MaxOffset, NoShiftRight); |
emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
} |
@@ -1756,8 +1777,11 @@ void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
// Same as store instruction. |
constexpr bool isLoad = false; |
constexpr bool isByte = false; |
- IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
- OperandARM32Mem::PreIndex); |
+ constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
+ constexpr IValueT NoShiftRight = 0; |
+ IValueT Address = |
+ encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
+ OperandARM32Mem::PreIndex, MaxOffset, NoShiftRight); |
emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); |
} |
@@ -2322,7 +2346,7 @@ void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, |
assert(CondARM32::isDefined(Cond)); |
IValueT Address; |
EncodedOperand AddressEncoding = |
- encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
+ encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
(void)AddressEncoding; |
assert(AddressEncoding == EncodedAsImmRegOffset); |
IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | |
@@ -2344,7 +2368,7 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, |
assert(CondARM32::isDefined(Cond)); |
IValueT Address; |
EncodedOperand AddressEncoding = |
- encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
+ encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
(void)AddressEncoding; |
assert(AddressEncoding == EncodedAsImmRegOffset); |
IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | |
@@ -2429,7 +2453,7 @@ void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress, |
assert(CondARM32::isDefined(Cond)); |
IValueT Address; |
IValueT AddressEncoding = |
- encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
+ encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
(void)AddressEncoding; |
assert(AddressEncoding == EncodedAsImmRegOffset); |
IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | |
@@ -2451,7 +2475,7 @@ void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, |
assert(CondARM32::isDefined(Cond)); |
IValueT Address; |
IValueT AddressEncoding = |
- encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
+ encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
(void)AddressEncoding; |
assert(AddressEncoding == EncodedAsImmRegOffset); |
IValueT Encoding = |