Chromium Code Reviews| 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 |