Index: src/IceAssemblerARM32.h |
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h |
index 2a42826df60df8a77d83bd45db72a1202445e95e..6e2ea3d3b9f97af28b788dbc10ded90db1f04166 100644 |
--- a/src/IceAssemblerARM32.h |
+++ b/src/IceAssemblerARM32.h |
@@ -24,8 +24,11 @@ |
#define SUBZERO_SRC_ICEASSEMBLERARM32_H |
#include "IceAssembler.h" |
+#include "IceConditionCodesARM32.h" |
#include "IceDefs.h" |
#include "IceFixups.h" |
+#include "IceRegistersARM32.h" |
+#include "IceTargetLowering.h" |
namespace Ice { |
namespace ARM32 { |
@@ -35,15 +38,24 @@ class AssemblerARM32 : public Assembler { |
AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; |
public: |
- explicit AssemblerARM32(bool use_far_branches = false) |
- : Assembler(Asm_ARM32) { |
- // This mode is only needed and implemented for MIPS and ARM. |
- assert(!use_far_branches); |
+ explicit AssemblerARM32(GlobalContext *Ctx, bool use_far_branches = false) |
John
2015/10/09 12:12:24
two argument ctor -- explicit is no longer needed.
Karl
2015/10/09 19:08:18
Leaving as is, since C++ 11 will otherwise try imp
|
+ : Assembler(Asm_ARM32, Ctx) { |
+ // TODO(kschimpf): Add mode if needed when branches are handled. |
(void)use_far_branches; |
} |
~AssemblerARM32() override = default; |
- void alignFunction() override { llvm_unreachable("Not yet implemented."); } |
+ void alignFunction() override { |
+ const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
+ SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); |
+ constexpr SizeT InstSize = sizeof(int32_t); |
+ assert(BytesNeeded % InstSize == 0); |
+ while (BytesNeeded > 0) { |
+ // TODO(kschimpf) Should this be NOP or some other instruction? |
+ bkpt(0); |
+ BytesNeeded -= InstSize; |
+ } |
+ } |
SizeT getBundleAlignLog2Bytes() const override { return 4; } |
@@ -67,18 +79,162 @@ public: |
} |
void bindCfgNodeLabel(SizeT NodeNumber) override { |
- (void)NodeNumber; |
- llvm_unreachable("Not yet implemented."); |
+ assert(!getPreliminary()); |
+ Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
+ this->bind(L); |
} |
bool fixupIsPCRel(FixupKind Kind) const override { |
(void)Kind; |
llvm_unreachable("Not yet implemented."); |
} |
+ void bind(Label *label); |
+ |
+ void bkpt(uint16_t imm16); |
+ |
+ void bx(RegARM32::GPRRegister rm, CondARM32::Cond cond = CondARM32::AL); |
static bool classof(const Assembler *Asm) { |
return Asm->getKind() == Asm_ARM32; |
} |
+ |
+private: |
+ // Instruction encoding bits. |
+ enum { |
John
2015/10/09 12:12:24
this trick for introducing class-level constants i
Karl
2015/10/09 19:08:18
Done.
|
+ H = 1 << 5, // halfword (or byte) |
+ L = 1 << 20, // load (or store) |
+ S = 1 << 20, // set condition code (or leave unchanged) |
+ W = 1 << 21, // writeback base register (or leave unchanged) |
+ A = 1 << 21, // accumulate in multiply instruction (or not) |
+ B = 1 << 22, // unsigned byte (or word) |
+ D = 1 << 22, // high/lo bit of start of s/d register range |
+ N = 1 << 22, // long (or short) |
+ U = 1 << 23, // positive (or negative) offset/index |
+ P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) |
+ I = 1 << 25, // immediate shifter operand (or not) |
+ |
+ B0 = 1, |
+ B1 = 1 << 1, |
+ B2 = 1 << 2, |
+ B3 = 1 << 3, |
+ B4 = 1 << 4, |
+ B5 = 1 << 5, |
+ B6 = 1 << 6, |
+ B7 = 1 << 7, |
+ B8 = 1 << 8, |
+ B9 = 1 << 9, |
+ B10 = 1 << 10, |
+ B11 = 1 << 11, |
+ B12 = 1 << 12, |
+ B16 = 1 << 16, |
+ B17 = 1 << 17, |
+ B18 = 1 << 18, |
+ B19 = 1 << 19, |
+ B20 = 1 << 20, |
+ B21 = 1 << 21, |
+ B22 = 1 << 22, |
+ B23 = 1 << 23, |
+ B24 = 1 << 24, |
+ B25 = 1 << 25, |
+ B26 = 1 << 26, |
+ B27 = 1 << 27, |
+ }; |
+ |
+ // Constants used for the decoding or encoding of the individual fields of |
+ // instructions. Based on the "Figure 3-1 ARM instruction set summary". |
Jim Stichnoth
2015/10/08 23:50:41
Figure 3-1 of what document?
Karl
2015/10/09 19:08:18
I agree that this comment is useless (I copied it
|
+ enum InstructionFields { |
+ kConditionShift = 28, |
John
2015/10/09 12:12:24
This is also just introducing class-level constant
Karl
2015/10/09 19:08:18
Done.
|
+ kConditionBits = 4, |
+ kTypeShift = 25, |
+ kTypeBits = 3, |
+ kLinkShift = 24, |
+ kLinkBits = 1, |
+ kUShift = 23, |
+ kUBits = 1, |
+ kOpcodeShift = 21, |
+ kOpcodeBits = 4, |
+ kSShift = 20, |
+ kSBits = 1, |
+ kRnShift = 16, |
+ kRnBits = 4, |
+ kRdShift = 12, |
+ kRdBits = 4, |
+ kRsShift = 8, |
+ kRsBits = 4, |
+ kRmShift = 0, |
+ kRmBits = 4, |
+ |
+ // Immediate instruction fields encoding. |
+ kRotateShift = 8, |
+ kRotateBits = 4, |
+ kImmed8Shift = 0, |
+ kImmed8Bits = 8, |
+ |
+ // Shift instruction register fields encodings. |
+ kShiftImmShift = 7, |
+ kShiftRegisterShift = 8, |
+ kShiftImmBits = 5, |
+ kShiftShift = 5, |
+ kShiftBits = 2, |
+ |
+ // Load/store instruction offset field encoding. |
+ kOffset12Shift = 0, |
+ kOffset12Bits = 12, |
+ kOffset12Mask = 0x00000fff, |
+ |
+ // Mul instruction register field encodings. |
+ kMulRdShift = 16, |
+ kMulRdBits = 4, |
+ kMulRnShift = 12, |
+ kMulRnBits = 4, |
+ |
+ // Div instruction register field encodings. |
+ kDivRdShift = 16, |
+ kDivRdBits = 4, |
+ kDivRmShift = 8, |
+ kDivRmBints = 4, |
+ kDivRnShift = 0, |
+ kDivRnBits = 4, |
+ |
+ // ldrex/strex register field encodings. |
+ kLdExRnShift = 16, |
+ kLdExRtShift = 12, |
+ kStrExRnShift = 16, |
+ kStrExRdShift = 12, |
+ kStrExRtShift = 0, |
+ |
+ // MRC instruction offset field encoding. |
+ kCRmShift = 0, |
+ kCRmBits = 4, |
+ kOpc2Shift = 5, |
+ kOpc2Bits = 3, |
+ kCoprocShift = 8, |
+ kCoprocBits = 4, |
+ kCRnShift = 16, |
+ kCRnBits = 4, |
+ kOpc1Shift = 21, |
+ kOpc1Bits = 3, |
+ |
+ kBranchOffsetMask = 0x00ffffff |
+ }; |
+ |
+ // A vector of pool-allocated x86 labels for CFG nodes. |
+ using LabelVector = std::vector<Label *>; |
+ LabelVector CfgNodeLabels; |
+ |
+ Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); |
+ Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { |
+ return getOrCreateLabel(NodeNumber, CfgNodeLabels); |
+ } |
+ |
+ void emitInt32(int32_t Value) { Buffer.emit<int32_t>(Value); } |
+ |
+ static int32_t BkptEncoding(uint16_t imm16) { |
+ // bkpt requires that the cond field is AL. |
+ // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and i in imm16 |
+ return (CondARM32::AL << kConditionShift) | B24 | B21 | |
+ ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); |
+ } |
}; |
} // end of namespace ARM32 |