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) |
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 | |
104 // halfword (or byte) | |
105 static constexpr uint32_t H = 1 << 5; | |
106 // load (or store) | |
107 static constexpr uint32_t L = 1 << 20; | |
108 // set condition code (or leave unchanged) | |
109 static constexpr uint32_t S = 1 << 20; | |
110 // writeback base register (or leave unchanged) | |
111 static constexpr uint32_t W = 1 << 21; | |
112 // accumulate in multiply instruction (or not) | |
113 static constexpr uint32_t A = 1 << 21; | |
114 // unsigned byte (or word) | |
115 static constexpr uint32_t B = 1 << 22; | |
116 // high/lo bit of start of s/d register range | |
117 static constexpr uint32_t D = 1 << 22; | |
118 // long (or short) | |
119 static constexpr uint32_t N = 1 << 22; | |
120 // positive (or negative) offset/index | |
121 static constexpr uint32_t U = 1 << 23; | |
122 // offset/pre-indexed addressing (or post-indexed addressing) | |
123 static constexpr uint32_t P = 1 << 24; | |
124 // immediate shifter operand (or not) | |
125 static constexpr uint32_t I = 1 << 25; | |
126 | |
127 // The following define individual bits. | |
128 static constexpr uint32_t B0 = 1; | |
129 static constexpr uint32_t B1 = 1 << 1; | |
130 static constexpr uint32_t B2 = 1 << 2; | |
131 static constexpr uint32_t B3 = 1 << 3; | |
132 static constexpr uint32_t B4 = 1 << 4; | |
133 static constexpr uint32_t B5 = 1 << 5; | |
134 static constexpr uint32_t B6 = 1 << 6; | |
135 static constexpr uint32_t B7 = 1 << 7; | |
136 static constexpr uint32_t B8 = 1 << 8; | |
137 static constexpr uint32_t B9 = 1 << 9; | |
138 static constexpr uint32_t B10 = 1 << 10; | |
139 static constexpr uint32_t B11 = 1 << 11; | |
140 static constexpr uint32_t B12 = 1 << 12; | |
141 static constexpr uint32_t B16 = 1 << 16; | |
142 static constexpr uint32_t B17 = 1 << 17; | |
143 static constexpr uint32_t B18 = 1 << 18; | |
144 static constexpr uint32_t B19 = 1 << 19; | |
145 static constexpr uint32_t B20 = 1 << 20; | |
146 static constexpr uint32_t B21 = 1 << 21; | |
147 static constexpr uint32_t B22 = 1 << 22; | |
148 static constexpr uint32_t B23 = 1 << 23; | |
149 static constexpr uint32_t B24 = 1 << 24; | |
150 static constexpr uint32_t B25 = 1 << 25; | |
151 static constexpr uint32_t B26 = 1 << 26; | |
152 static constexpr uint32_t B27 = 1 << 27; | |
153 | |
154 // Constants used for the decoding or encoding of the individual fields of | |
155 // instructions. Based on section A5.1 from the "ARM Architecture Reference | |
156 // Manual, ARMv7-A and ARMv7-R edition" | |
Jim Stichnoth
2015/10/09 20:05:45
End sentence with a period.
Also, it would be rea
Karl
2015/10/09 20:29:32
Done.
| |
157 | |
158 static constexpr uint32_t kConditionShift = 28; | |
159 static constexpr uint32_t kConditionBits = 4; | |
160 static constexpr uint32_t kTypeShift = 25; | |
161 static constexpr uint32_t kTypeBits = 3; | |
162 static constexpr uint32_t kLinkShift = 24; | |
163 static constexpr uint32_t kLinkBits = 1; | |
164 static constexpr uint32_t kUShift = 23; | |
165 static constexpr uint32_t kUBits = 1; | |
166 static constexpr uint32_t kOpcodeShift = 21; | |
167 static constexpr uint32_t kOpcodeBits = 4; | |
168 static constexpr uint32_t kSShift = 20; | |
169 static constexpr uint32_t kSBits = 1; | |
170 static constexpr uint32_t kRnShift = 16; | |
171 static constexpr uint32_t kRnBits = 4; | |
172 static constexpr uint32_t kRdShift = 12; | |
173 static constexpr uint32_t kRdBits = 4; | |
174 static constexpr uint32_t kRsShift = 8; | |
175 static constexpr uint32_t kRsBits = 4; | |
176 static constexpr uint32_t kRmShift = 0; | |
177 static constexpr uint32_t kRmBits = 4; | |
178 | |
179 // Immediate instruction fields encoding. | |
180 static constexpr uint32_t kRotateShift = 8; | |
181 static constexpr uint32_t kRotateBits = 4; | |
182 static constexpr uint32_t kImmed8Shift = 0; | |
183 static constexpr uint32_t kImmed8Bits = 8; | |
184 | |
185 // Shift instruction register fields encodings. | |
186 static constexpr uint32_t kShiftImmShift = 7; | |
187 static constexpr uint32_t kShiftRegisterShift = 8; | |
188 static constexpr uint32_t kShiftImmBits = 5; | |
189 static constexpr uint32_t kShiftShift = 5; | |
190 static constexpr uint32_t kShiftBits = 2; | |
191 | |
192 // Load/store instruction offset field encoding. | |
193 static constexpr uint32_t kOffset12Shift = 0; | |
194 static constexpr uint32_t kOffset12Bits = 12; | |
195 static constexpr uint32_t kOffset12Mask = 0x00000fff; | |
196 | |
197 // Mul instruction register field encodings. | |
198 static constexpr uint32_t kMulRdShift = 16; | |
199 static constexpr uint32_t kMulRdBits = 4; | |
200 static constexpr uint32_t kMulRnShift = 12; | |
201 static constexpr uint32_t kMulRnBits = 4; | |
202 | |
203 // Div instruction register field encodings. | |
204 static constexpr uint32_t kDivRdShift = 16; | |
205 static constexpr uint32_t kDivRdBits = 4; | |
206 static constexpr uint32_t kDivRmShift = 8; | |
207 static constexpr uint32_t kDivRmBints = 4; | |
208 static constexpr uint32_t kDivRnShift = 0; | |
209 static constexpr uint32_t kDivRnBits = 4; | |
210 | |
211 // ldrex/strex register field encodings. | |
212 static constexpr uint32_t kLdExRnShift = 16; | |
213 static constexpr uint32_t kLdExRtShift = 12; | |
214 static constexpr uint32_t kStrExRnShift = 16; | |
215 static constexpr uint32_t kStrExRdShift = 12; | |
216 static constexpr uint32_t kStrExRtShift = 0; | |
217 | |
218 // MRC instruction offset field encoding. | |
219 static constexpr uint32_t kCRmShift = 0; | |
220 static constexpr uint32_t kCRmBits = 4; | |
221 static constexpr uint32_t kOpc2Shift = 5; | |
222 static constexpr uint32_t kOpc2Bits = 3; | |
223 static constexpr uint32_t kCoprocShift = 8; | |
224 static constexpr uint32_t kCoprocBits = 4; | |
225 static constexpr uint32_t kCRnShift = 16; | |
226 static constexpr uint32_t kCRnBits = 4; | |
227 static constexpr uint32_t kOpc1Shift = 21; | |
228 static constexpr uint32_t kOpc1Bits = 3; | |
229 | |
230 static constexpr uint32_t kBranchOffsetMask = 0x00ffffff; | |
231 | |
232 // A vector of pool-allocated x86 labels for CFG nodes. | |
233 using LabelVector = std::vector<Label *>; | |
234 LabelVector CfgNodeLabels; | |
235 | |
236 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); | |
237 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { | |
238 return getOrCreateLabel(NodeNumber, CfgNodeLabels); | |
239 } | |
240 | |
241 void emitInt32(int32_t Value) { Buffer.emit<int32_t>(Value); } | |
242 | |
243 static int32_t BkptEncoding(uint16_t imm16) { | |
244 // bkpt requires that the cond field is AL. | |
245 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and i in imm16 | |
246 return (CondARM32::AL << kConditionShift) | B24 | B21 | | |
247 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | |
248 } | |
82 }; | 249 }; |
83 | 250 |
84 } // end of namespace ARM32 | 251 } // end of namespace ARM32 |
85 } // end of namespace Ice | 252 } // end of namespace Ice |
86 | 253 |
87 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H | 254 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H |
OLD | NEW |