OLD | NEW |
---|---|
1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
11 // The Subzero Code Generator | 11 // The Subzero Code Generator |
12 // | 12 // |
13 // This file is distributed under the University of Illinois Open Source | 13 // This file is distributed under the University of Illinois Open Source |
14 // License. See LICENSE.TXT for details. | 14 // License. See LICENSE.TXT for details. |
15 // | 15 // |
16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
17 /// | 17 /// |
18 /// \file | 18 /// \file |
19 /// This file implements the Assembler class for ARM32. | 19 /// This file implements the Assembler class for ARM32. |
20 /// | 20 /// |
21 //===----------------------------------------------------------------------===// | 21 //===----------------------------------------------------------------------===// |
22 | 22 |
23 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H | 23 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H |
24 #define SUBZERO_SRC_ICEASSEMBLERARM32_H | 24 #define SUBZERO_SRC_ICEASSEMBLERARM32_H |
25 | 25 |
26 #include "IceAssembler.h" | 26 #include "IceAssembler.h" |
27 #include "IceConditionCodesARM32.h" | |
27 #include "IceDefs.h" | 28 #include "IceDefs.h" |
28 #include "IceFixups.h" | 29 #include "IceFixups.h" |
30 #include "IceRegistersARM32.h" | |
31 #include "IceTargetLowering.h" | |
29 | 32 |
30 namespace Ice { | 33 namespace Ice { |
31 namespace ARM32 { | 34 namespace ARM32 { |
32 | 35 |
33 class AssemblerARM32 : public Assembler { | 36 class AssemblerARM32 : public Assembler { |
34 AssemblerARM32(const AssemblerARM32 &) = delete; | 37 AssemblerARM32(const AssemblerARM32 &) = delete; |
35 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; | 38 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; |
36 | 39 |
37 public: | 40 public: |
38 explicit AssemblerARM32(bool use_far_branches = false) | 41 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
| |
39 : Assembler(Asm_ARM32) { | 42 : Assembler(Asm_ARM32, Ctx) { |
40 // This mode is only needed and implemented for MIPS and ARM. | 43 // TODO(kschimpf): Add mode if needed when branches are handled. |
41 assert(!use_far_branches); | |
42 (void)use_far_branches; | 44 (void)use_far_branches; |
43 } | 45 } |
44 ~AssemblerARM32() override = default; | 46 ~AssemblerARM32() override = default; |
45 | 47 |
46 void alignFunction() override { llvm_unreachable("Not yet implemented."); } | 48 void alignFunction() override { |
49 const SizeT Align = 1 << getBundleAlignLog2Bytes(); | |
50 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); | |
51 constexpr SizeT InstSize = sizeof(int32_t); | |
52 assert(BytesNeeded % InstSize == 0); | |
53 while (BytesNeeded > 0) { | |
54 // TODO(kschimpf) Should this be NOP or some other instruction? | |
55 bkpt(0); | |
56 BytesNeeded -= InstSize; | |
57 } | |
58 } | |
47 | 59 |
48 SizeT getBundleAlignLog2Bytes() const override { return 4; } | 60 SizeT getBundleAlignLog2Bytes() const override { return 4; } |
49 | 61 |
50 const char *getAlignDirective() const override { return ".p2alignl"; } | 62 const char *getAlignDirective() const override { return ".p2alignl"; } |
51 | 63 |
52 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { | 64 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { |
53 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0 | 65 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0 |
54 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943 | 66 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943 |
55 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0}; | 67 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0}; |
56 return llvm::ArrayRef<uint8_t>(Padding, 4); | 68 return llvm::ArrayRef<uint8_t>(Padding, 4); |
57 } | 69 } |
58 | 70 |
59 void padWithNop(intptr_t Padding) override { | 71 void padWithNop(intptr_t Padding) override { |
60 (void)Padding; | 72 (void)Padding; |
61 llvm_unreachable("Not yet implemented."); | 73 llvm_unreachable("Not yet implemented."); |
62 } | 74 } |
63 | 75 |
64 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { | 76 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { |
65 (void)NodeNumber; | 77 (void)NodeNumber; |
66 llvm_unreachable("Not yet implemented."); | 78 llvm_unreachable("Not yet implemented."); |
67 } | 79 } |
68 | 80 |
69 void bindCfgNodeLabel(SizeT NodeNumber) override { | 81 void bindCfgNodeLabel(SizeT NodeNumber) override { |
70 (void)NodeNumber; | 82 assert(!getPreliminary()); |
71 llvm_unreachable("Not yet implemented."); | 83 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
84 this->bind(L); | |
72 } | 85 } |
73 | 86 |
74 bool fixupIsPCRel(FixupKind Kind) const override { | 87 bool fixupIsPCRel(FixupKind Kind) const override { |
75 (void)Kind; | 88 (void)Kind; |
76 llvm_unreachable("Not yet implemented."); | 89 llvm_unreachable("Not yet implemented."); |
77 } | 90 } |
91 void bind(Label *label); | |
92 | |
93 void bkpt(uint16_t imm16); | |
94 | |
95 void bx(RegARM32::GPRRegister rm, CondARM32::Cond cond = CondARM32::AL); | |
78 | 96 |
79 static bool classof(const Assembler *Asm) { | 97 static bool classof(const Assembler *Asm) { |
80 return Asm->getKind() == Asm_ARM32; | 98 return Asm->getKind() == Asm_ARM32; |
81 } | 99 } |
100 | |
101 private: | |
102 // Instruction encoding bits. | |
103 enum { | |
John
2015/10/09 12:12:24
this trick for introducing class-level constants i
Karl
2015/10/09 19:08:18
Done.
| |
104 H = 1 << 5, // halfword (or byte) | |
105 L = 1 << 20, // load (or store) | |
106 S = 1 << 20, // set condition code (or leave unchanged) | |
107 W = 1 << 21, // writeback base register (or leave unchanged) | |
108 A = 1 << 21, // accumulate in multiply instruction (or not) | |
109 B = 1 << 22, // unsigned byte (or word) | |
110 D = 1 << 22, // high/lo bit of start of s/d register range | |
111 N = 1 << 22, // long (or short) | |
112 U = 1 << 23, // positive (or negative) offset/index | |
113 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) | |
114 I = 1 << 25, // immediate shifter operand (or not) | |
115 | |
116 B0 = 1, | |
117 B1 = 1 << 1, | |
118 B2 = 1 << 2, | |
119 B3 = 1 << 3, | |
120 B4 = 1 << 4, | |
121 B5 = 1 << 5, | |
122 B6 = 1 << 6, | |
123 B7 = 1 << 7, | |
124 B8 = 1 << 8, | |
125 B9 = 1 << 9, | |
126 B10 = 1 << 10, | |
127 B11 = 1 << 11, | |
128 B12 = 1 << 12, | |
129 B16 = 1 << 16, | |
130 B17 = 1 << 17, | |
131 B18 = 1 << 18, | |
132 B19 = 1 << 19, | |
133 B20 = 1 << 20, | |
134 B21 = 1 << 21, | |
135 B22 = 1 << 22, | |
136 B23 = 1 << 23, | |
137 B24 = 1 << 24, | |
138 B25 = 1 << 25, | |
139 B26 = 1 << 26, | |
140 B27 = 1 << 27, | |
141 }; | |
142 | |
143 // Constants used for the decoding or encoding of the individual fields of | |
144 // 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
| |
145 enum InstructionFields { | |
146 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.
| |
147 kConditionBits = 4, | |
148 kTypeShift = 25, | |
149 kTypeBits = 3, | |
150 kLinkShift = 24, | |
151 kLinkBits = 1, | |
152 kUShift = 23, | |
153 kUBits = 1, | |
154 kOpcodeShift = 21, | |
155 kOpcodeBits = 4, | |
156 kSShift = 20, | |
157 kSBits = 1, | |
158 kRnShift = 16, | |
159 kRnBits = 4, | |
160 kRdShift = 12, | |
161 kRdBits = 4, | |
162 kRsShift = 8, | |
163 kRsBits = 4, | |
164 kRmShift = 0, | |
165 kRmBits = 4, | |
166 | |
167 // Immediate instruction fields encoding. | |
168 kRotateShift = 8, | |
169 kRotateBits = 4, | |
170 kImmed8Shift = 0, | |
171 kImmed8Bits = 8, | |
172 | |
173 // Shift instruction register fields encodings. | |
174 kShiftImmShift = 7, | |
175 kShiftRegisterShift = 8, | |
176 kShiftImmBits = 5, | |
177 kShiftShift = 5, | |
178 kShiftBits = 2, | |
179 | |
180 // Load/store instruction offset field encoding. | |
181 kOffset12Shift = 0, | |
182 kOffset12Bits = 12, | |
183 kOffset12Mask = 0x00000fff, | |
184 | |
185 // Mul instruction register field encodings. | |
186 kMulRdShift = 16, | |
187 kMulRdBits = 4, | |
188 kMulRnShift = 12, | |
189 kMulRnBits = 4, | |
190 | |
191 // Div instruction register field encodings. | |
192 kDivRdShift = 16, | |
193 kDivRdBits = 4, | |
194 kDivRmShift = 8, | |
195 kDivRmBints = 4, | |
196 kDivRnShift = 0, | |
197 kDivRnBits = 4, | |
198 | |
199 // ldrex/strex register field encodings. | |
200 kLdExRnShift = 16, | |
201 kLdExRtShift = 12, | |
202 kStrExRnShift = 16, | |
203 kStrExRdShift = 12, | |
204 kStrExRtShift = 0, | |
205 | |
206 // MRC instruction offset field encoding. | |
207 kCRmShift = 0, | |
208 kCRmBits = 4, | |
209 kOpc2Shift = 5, | |
210 kOpc2Bits = 3, | |
211 kCoprocShift = 8, | |
212 kCoprocBits = 4, | |
213 kCRnShift = 16, | |
214 kCRnBits = 4, | |
215 kOpc1Shift = 21, | |
216 kOpc1Bits = 3, | |
217 | |
218 kBranchOffsetMask = 0x00ffffff | |
219 }; | |
220 | |
221 // A vector of pool-allocated x86 labels for CFG nodes. | |
222 using LabelVector = std::vector<Label *>; | |
223 LabelVector CfgNodeLabels; | |
224 | |
225 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); | |
226 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { | |
227 return getOrCreateLabel(NodeNumber, CfgNodeLabels); | |
228 } | |
229 | |
230 void emitInt32(int32_t Value) { Buffer.emit<int32_t>(Value); } | |
231 | |
232 static int32_t BkptEncoding(uint16_t imm16) { | |
233 // bkpt requires that the cond field is AL. | |
234 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and i in imm16 | |
235 return (CondARM32::AL << kConditionShift) | B24 | B21 | | |
236 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | |
237 } | |
82 }; | 238 }; |
83 | 239 |
84 } // end of namespace ARM32 | 240 } // end of namespace ARM32 |
85 } // end of namespace Ice | 241 } // end of namespace Ice |
86 | 242 |
87 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H | 243 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H |
OLD | NEW |