blob: 6b61acafacf97452cb277b07f56e26c5ccac7827 [file] [log] [blame]
Dave Allison65fcc2c2014-04-28 13:45:27 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
18#define ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
19
Vladimir Markocf93a5c2015-06-16 11:33:24 +000020#include <deque>
Andreas Gampe7cffc3b2015-10-19 21:31:53 -070021#include <utility>
Dave Allison65fcc2c2014-04-28 13:45:27 -070022#include <vector>
23
24#include "base/logging.h"
25#include "constants_arm.h"
26#include "utils/arm/managed_register_arm.h"
27#include "utils/arm/assembler_arm.h"
Vladimir Marko6b756b52015-07-14 11:58:38 +010028#include "utils/array_ref.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070029#include "offsets.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070030
31namespace art {
32namespace arm {
33
Dave Allison65fcc2c2014-04-28 13:45:27 -070034class Thumb2Assembler FINAL : public ArmAssembler {
35 public:
Nicolas Geoffrayd126ba12015-05-20 11:25:27 +010036 explicit Thumb2Assembler(bool can_relocate_branches = true)
37 : can_relocate_branches_(can_relocate_branches),
Nicolas Geoffray8d486732014-07-16 16:23:40 +010038 force_32bit_(false),
39 it_cond_index_(kNoItCondition),
Vladimir Markocf93a5c2015-06-16 11:33:24 +000040 next_condition_(AL),
41 fixups_(),
Vladimir Marko6b756b52015-07-14 11:58:38 +010042 fixup_dependents_(),
Vladimir Markocf93a5c2015-06-16 11:33:24 +000043 literals_(),
44 last_position_adjustment_(0u),
45 last_old_position_(0u),
46 last_fixup_id_(0u) {
Vladimir Marko10ef6942015-10-22 15:25:54 +010047 cfi().DelayEmittingAdvancePCs();
Dave Allison65fcc2c2014-04-28 13:45:27 -070048 }
49
50 virtual ~Thumb2Assembler() {
Dave Allison65fcc2c2014-04-28 13:45:27 -070051 }
52
53 bool IsThumb() const OVERRIDE {
54 return true;
55 }
56
57 bool IsForced32Bit() const {
58 return force_32bit_;
59 }
60
Nicolas Geoffrayd126ba12015-05-20 11:25:27 +010061 bool CanRelocateBranches() const {
62 return can_relocate_branches_;
Nicolas Geoffray8d486732014-07-16 16:23:40 +010063 }
64
Vladimir Markocf93a5c2015-06-16 11:33:24 +000065 void FinalizeCode() OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070066
67 // Data-processing instructions.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010068 virtual void and_(Register rd, Register rn, const ShifterOperand& so,
69 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070070
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010071 virtual void eor(Register rd, Register rn, const ShifterOperand& so,
72 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070073
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010074 virtual void sub(Register rd, Register rn, const ShifterOperand& so,
75 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070076
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010077 virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
78 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070079
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010080 virtual void add(Register rd, Register rn, const ShifterOperand& so,
81 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070082
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010083 virtual void adc(Register rd, Register rn, const ShifterOperand& so,
84 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070085
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010086 virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
87 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070088
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010089 virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
90 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070091
92 void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
93
94 void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
95
96 void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
97
98 void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
99
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100100 virtual void orr(Register rd, Register rn, const ShifterOperand& so,
101 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700102
Vladimir Markod2b4ca22015-09-14 15:13:26 +0100103 virtual void orn(Register rd, Register rn, const ShifterOperand& so,
104 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
105
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100106 virtual void mov(Register rd, const ShifterOperand& so,
107 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700108
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100109 virtual void bic(Register rd, Register rn, const ShifterOperand& so,
110 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700111
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100112 virtual void mvn(Register rd, const ShifterOperand& so,
113 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700114
115 // Miscellaneous data-processing instructions.
116 void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
117 void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
118 void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100119 void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
Artem Serovc257da72016-02-02 13:49:43 +0000120 void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
121 void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
122 void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700123
124 // Multiply instructions.
125 void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
126 void mla(Register rd, Register rn, Register rm, Register ra,
127 Condition cond = AL) OVERRIDE;
128 void mls(Register rd, Register rn, Register rm, Register ra,
129 Condition cond = AL) OVERRIDE;
Zheng Xuc6667102015-05-15 16:08:45 +0800130 void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
131 Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700132 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
133 Condition cond = AL) OVERRIDE;
134
135 void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
136 void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
137
Roland Levillain981e4542014-11-14 11:47:14 +0000138 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000139 void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
Roland Levillain981e4542014-11-14 11:47:14 +0000140 void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000141
Dave Allison65fcc2c2014-04-28 13:45:27 -0700142 // Load/store instructions.
143 void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
144 void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
145
146 void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
147 void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
148
149 void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
150 void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
151
152 void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
153 void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
154
Roland Levillain4af147e2015-04-07 13:54:49 +0100155 // Load/store register dual instructions using registers `rd` and `rd` + 1.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700156 void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
157 void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
158
Roland Levillain4af147e2015-04-07 13:54:49 +0100159 // Load/store register dual instructions using registers `rd` and `rd2`.
160 // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding
161 // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1.
162 void ldrd(Register rd, Register rd2, const Address& ad, Condition cond);
163 void strd(Register rd, Register rd2, const Address& ad, Condition cond);
164
165
Dave Allison65fcc2c2014-04-28 13:45:27 -0700166 void ldm(BlockAddressMode am, Register base,
167 RegList regs, Condition cond = AL) OVERRIDE;
168 void stm(BlockAddressMode am, Register base,
169 RegList regs, Condition cond = AL) OVERRIDE;
170
171 void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE;
172 void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE;
173
174 void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL);
175 void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL);
176
Calin Juravle52c48962014-12-16 17:02:57 +0000177 void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
178 void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700179
180 // Miscellaneous instructions.
181 void clrex(Condition cond = AL) OVERRIDE;
182 void nop(Condition cond = AL) OVERRIDE;
183
184 void bkpt(uint16_t imm16) OVERRIDE;
185 void svc(uint32_t imm24) OVERRIDE;
186
187 // If-then
188 void it(Condition firstcond, ItState i1 = kItOmitted,
189 ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE;
190
191 void cbz(Register rn, Label* target) OVERRIDE;
192 void cbnz(Register rn, Label* target) OVERRIDE;
193
194 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
195 void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE;
196 void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE;
197 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
198 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE;
199 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
200 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE;
201 void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
202 void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
203
204 // Returns false if the immediate cannot be encoded.
205 bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE;
206 bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE;
207
208 void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
209 void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
210 void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
211 void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
212
213 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
214 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
215 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
216 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
217 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
218 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
219 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
220 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
221 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
222 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
223 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
224 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
225
226 void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
227 void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
228 void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
229 void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
230 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
231 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
232
233 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
234 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
235 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
236 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
237 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
238 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
239 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
240 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
241 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
242 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
243
244 void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
245 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
246 void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE;
247 void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE;
248 void vmstat(Condition cond = AL) OVERRIDE; // VMRS APSR_nzcv, FPSCR
249
250 void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
251 void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
252 void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
253 void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
254
255 // Branch instructions.
256 void b(Label* label, Condition cond = AL);
257 void bl(Label* label, Condition cond = AL);
258 void blx(Label* label);
259 void blx(Register rm, Condition cond = AL) OVERRIDE;
260 void bx(Register rm, Condition cond = AL) OVERRIDE;
261
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100262 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
263 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
264 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
265 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
266 virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
267 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
268 virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
269 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
270 virtual void Rrx(Register rd, Register rm,
271 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison45fdb932014-06-25 12:37:10 -0700272
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100273 virtual void Lsl(Register rd, Register rm, Register rn,
274 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
275 virtual void Lsr(Register rd, Register rm, Register rn,
276 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
277 virtual void Asr(Register rd, Register rm, Register rn,
278 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
279 virtual void Ror(Register rd, Register rm, Register rn,
280 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700281
282 void Push(Register rd, Condition cond = AL) OVERRIDE;
283 void Pop(Register rd, Condition cond = AL) OVERRIDE;
284
285 void PushList(RegList regs, Condition cond = AL) OVERRIDE;
286 void PopList(RegList regs, Condition cond = AL) OVERRIDE;
287
288 void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
289
290 void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE;
291 void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE;
292
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100293 // Memory barriers.
294 void dmb(DmbOptions flavor) OVERRIDE;
295
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000296 // Get the final position of a label after local fixup based on the old position
297 // recorded before FinalizeCode().
298 uint32_t GetAdjustedPosition(uint32_t old_position) OVERRIDE;
299
300 using ArmAssembler::NewLiteral; // Make the helper template visible.
301
302 Literal* NewLiteral(size_t size, const uint8_t* data) OVERRIDE;
303 void LoadLiteral(Register rt, Literal* literal) OVERRIDE;
304 void LoadLiteral(Register rt, Register rt2, Literal* literal) OVERRIDE;
305 void LoadLiteral(SRegister sd, Literal* literal) OVERRIDE;
306 void LoadLiteral(DRegister dd, Literal* literal) OVERRIDE;
307
Dave Allison65fcc2c2014-04-28 13:45:27 -0700308 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700309 void AddConstant(Register rd, Register rn, int32_t value,
Vladimir Marko449b1092015-09-08 12:16:45 +0100310 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700311
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700312 void CmpConstant(Register rn, int32_t value, Condition cond = AL) OVERRIDE;
313
Dave Allison65fcc2c2014-04-28 13:45:27 -0700314 // Load and Store. May clobber IP.
315 void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700316 void MarkExceptionHandler(Label* label) OVERRIDE;
317 void LoadFromOffset(LoadOperandType type,
318 Register reg,
319 Register base,
320 int32_t offset,
321 Condition cond = AL) OVERRIDE;
322 void StoreToOffset(StoreOperandType type,
323 Register reg,
324 Register base,
325 int32_t offset,
326 Condition cond = AL) OVERRIDE;
327 void LoadSFromOffset(SRegister reg,
328 Register base,
329 int32_t offset,
330 Condition cond = AL) OVERRIDE;
331 void StoreSToOffset(SRegister reg,
332 Register base,
333 int32_t offset,
334 Condition cond = AL) OVERRIDE;
335 void LoadDFromOffset(DRegister reg,
336 Register base,
337 int32_t offset,
338 Condition cond = AL) OVERRIDE;
339 void StoreDToOffset(DRegister reg,
340 Register base,
341 int32_t offset,
342 Condition cond = AL) OVERRIDE;
343
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000344 bool ShifterOperandCanHold(Register rd,
345 Register rn,
346 Opcode opcode,
347 uint32_t immediate,
Vladimir Markof5c09c32015-12-17 12:08:08 +0000348 SetCc set_cc,
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000349 ShifterOperand* shifter_op) OVERRIDE;
Vladimir Markof5c09c32015-12-17 12:08:08 +0000350 using ArmAssembler::ShifterOperandCanHold; // Don't hide the non-virtual override.
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000351
Nicolas Geoffray5bd05a52015-10-13 09:48:30 +0100352 bool ShifterOperandCanAlwaysHold(uint32_t immediate) OVERRIDE;
353
Dave Allison65fcc2c2014-04-28 13:45:27 -0700354
Ian Rogers13735952014-10-08 12:43:28 -0700355 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700356
357 // Emit data (e.g. encoded instruction or immediate) to the.
358 // instruction stream.
359 void Emit32(int32_t value); // Emit a 32 bit instruction in thumb format.
360 void Emit16(int16_t value); // Emit a 16 bit instruction in little endian format.
361 void Bind(Label* label) OVERRIDE;
362
363 void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
364
365 // Force the assembler to generate 32 bit instructions.
366 void Force32Bit() {
367 force_32bit_ = true;
368 }
369
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700370 // Emit an ADR (or a sequence of instructions) to load the jump table address into base_reg. This
371 // will generate a fixup.
372 JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) OVERRIDE;
373 // Emit an ADD PC, X to dispatch a jump-table jump. This will generate a fixup.
374 void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) OVERRIDE;
375
Dave Allison65fcc2c2014-04-28 13:45:27 -0700376 private:
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000377 typedef uint16_t FixupId;
378
379 // Fixup: branches and literal pool references.
380 //
381 // The thumb2 architecture allows branches to be either 16 or 32 bit instructions. This
382 // depends on both the type of branch and the offset to which it is branching. The 16-bit
383 // cbz and cbnz instructions may also need to be replaced with a separate 16-bit compare
384 // instruction and a 16- or 32-bit branch instruction. Load from a literal pool can also be
385 // 16-bit or 32-bit instruction and, if the method is large, we may need to use a sequence
386 // of instructions to make up for the limited range of load literal instructions (up to
387 // 4KiB for the 32-bit variant). When generating code for these insns we don't know the
388 // size before hand, so we assume it is the smallest available size and determine the final
389 // code offsets and sizes and emit code in FinalizeCode().
390 //
391 // To handle this, we keep a record of every branch and literal pool load in the program.
392 // The actual instruction encoding for these is delayed until we know the final size of
393 // every instruction. When we bind a label to a branch we don't know the final location yet
394 // as some preceding instructions may need to be expanded, so we record a non-final offset.
395 // In FinalizeCode(), we expand the sizes of branches and literal loads that are out of
396 // range. With each expansion, we need to update dependent Fixups, i.e. insntructios with
397 // target on the other side of the expanded insn, as their offsets change and this may
398 // trigger further expansion.
399 //
400 // All Fixups have a 'fixup id' which is a 16 bit unsigned number used to identify the
401 // Fixup. For each unresolved label we keep a singly-linked list of all Fixups pointing
402 // to it, using the fixup ids as links. The first link is stored in the label's position
403 // (the label is linked but not bound), the following links are stored in the code buffer,
404 // in the placeholder where we will eventually emit the actual code.
405
406 class Fixup {
407 public:
408 // Branch type.
409 enum Type : uint8_t {
410 kConditional, // B<cond>.
411 kUnconditional, // B.
412 kUnconditionalLink, // BL.
413 kUnconditionalLinkX, // BLX.
414 kCompareAndBranchXZero, // cbz/cbnz.
415 kLoadLiteralNarrow, // Load narrrow integer literal.
416 kLoadLiteralWide, // Load wide integer literal.
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700417 kLoadLiteralAddr, // Load address of literal (used for jump table).
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000418 kLoadFPLiteralSingle, // Load FP literal single.
419 kLoadFPLiteralDouble, // Load FP literal double.
420 };
421
422 // Calculated size of branch instruction based on type and offset.
423 enum Size : uint8_t {
424 // Branch variants.
425 kBranch16Bit,
426 kBranch32Bit,
427 // NOTE: We don't support branches which would require multiple instructions, i.e.
428 // conditinoal branches beyond +-1MiB and unconditional branches beyond +-16MiB.
429
430 // CBZ/CBNZ variants.
431 kCbxz16Bit, // CBZ/CBNZ rX, label; X < 8; 7-bit positive offset.
432 kCbxz32Bit, // CMP rX, #0 + Bcc label; X < 8; 16-bit Bcc; +-8-bit offset.
433 kCbxz48Bit, // CMP rX, #0 + Bcc label; X < 8; 32-bit Bcc; up to +-1MiB offset.
434
435 // Load integer literal variants.
436 // LDR rX, label; X < 8; 16-bit variant up to 1KiB offset; 2 bytes.
437 kLiteral1KiB,
438 // LDR rX, label; 32-bit variant up to 4KiB offset; 4 bytes.
439 kLiteral4KiB,
440 // MOV rX, imm16 + ADD rX, pc + LDR rX, [rX]; X < 8; up to 64KiB offset; 8 bytes.
441 kLiteral64KiB,
442 // MOV rX, modimm + ADD rX, pc + LDR rX, [rX, #imm12]; up to 1MiB offset; 10 bytes.
443 kLiteral1MiB,
444 // NOTE: We don't provide the 12-byte version of kLiteralFar below where the LDR is 16-bit.
445 // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc + LDR rX, [rX]; any offset; 14 bytes.
446 kLiteralFar,
447
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700448 // Load literal base addr.
449 // ADR rX, label; X < 8; 8 bit immediate, shifted to 10 bit. 2 bytes.
450 kLiteralAddr1KiB,
451 // ADR rX, label; 4KiB offset. 4 bytes.
452 kLiteralAddr4KiB,
453 // MOV rX, imm16 + ADD rX, pc; 64KiB offset. 6 bytes.
454 kLiteralAddr64KiB,
455 // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc; any offset; 10 bytes.
456 kLiteralAddrFar,
457
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000458 // Load long or FP literal variants.
459 // VLDR s/dX, label; 32-bit insn, up to 1KiB offset; 4 bytes.
460 kLongOrFPLiteral1KiB,
461 // MOV ip, modimm + ADD ip, pc + VLDR s/dX, [IP, #imm8*4]; up to 256KiB offset; 10 bytes.
462 kLongOrFPLiteral256KiB,
463 // MOV ip, imm16 + MOVT ip, imm16 + ADD ip, pc + VLDR s/dX, [IP]; any offset; 14 bytes.
464 kLongOrFPLiteralFar,
465 };
466
467 // Unresolved branch possibly with a condition.
468 static Fixup Branch(uint32_t location, Type type, Size size = kBranch16Bit,
469 Condition cond = AL) {
470 DCHECK(type == kConditional || type == kUnconditional ||
471 type == kUnconditionalLink || type == kUnconditionalLinkX);
472 DCHECK(size == kBranch16Bit || size == kBranch32Bit);
473 DCHECK(size == kBranch32Bit || (type == kConditional || type == kUnconditional));
474 return Fixup(kNoRegister, kNoRegister, kNoSRegister, kNoDRegister,
475 cond, type, size, location);
476 }
477
478 // Unresolved compare-and-branch instruction with a register and condition (EQ or NE).
479 static Fixup CompareAndBranch(uint32_t location, Register rn, Condition cond) {
480 DCHECK(cond == EQ || cond == NE);
481 return Fixup(rn, kNoRegister, kNoSRegister, kNoDRegister,
482 cond, kCompareAndBranchXZero, kCbxz16Bit, location);
483 }
484
485 // Load narrow literal.
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700486 static Fixup LoadNarrowLiteral(uint32_t location, Register rt, Size size) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000487 DCHECK(size == kLiteral1KiB || size == kLiteral4KiB || size == kLiteral64KiB ||
488 size == kLiteral1MiB || size == kLiteralFar);
489 DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
490 return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
491 AL, kLoadLiteralNarrow, size, location);
492 }
493
494 // Load wide literal.
495 static Fixup LoadWideLiteral(uint32_t location, Register rt, Register rt2,
496 Size size = kLongOrFPLiteral1KiB) {
497 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
498 size == kLongOrFPLiteralFar);
499 DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
500 return Fixup(rt, rt2, kNoSRegister, kNoDRegister,
501 AL, kLoadLiteralWide, size, location);
502 }
503
504 // Load FP single literal.
505 static Fixup LoadSingleLiteral(uint32_t location, SRegister sd,
506 Size size = kLongOrFPLiteral1KiB) {
507 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
508 size == kLongOrFPLiteralFar);
509 return Fixup(kNoRegister, kNoRegister, sd, kNoDRegister,
510 AL, kLoadFPLiteralSingle, size, location);
511 }
512
513 // Load FP double literal.
514 static Fixup LoadDoubleLiteral(uint32_t location, DRegister dd,
515 Size size = kLongOrFPLiteral1KiB) {
516 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
517 size == kLongOrFPLiteralFar);
518 return Fixup(kNoRegister, kNoRegister, kNoSRegister, dd,
519 AL, kLoadFPLiteralDouble, size, location);
520 }
521
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700522 static Fixup LoadLiteralAddress(uint32_t location, Register rt, Size size) {
523 DCHECK(size == kLiteralAddr1KiB || size == kLiteralAddr4KiB || size == kLiteralAddr64KiB ||
524 size == kLiteralAddrFar);
525 DCHECK(!IsHighRegister(rt) || size != kLiteralAddr1KiB);
526 return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
527 AL, kLoadLiteralAddr, size, location);
528 }
529
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000530 Type GetType() const {
531 return type_;
532 }
533
Vladimir Marko663c9342015-07-22 11:28:14 +0100534 bool IsLoadLiteral() const {
535 return GetType() >= kLoadLiteralNarrow;
536 }
537
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000538 Size GetOriginalSize() const {
539 return original_size_;
540 }
541
542 Size GetSize() const {
543 return size_;
544 }
545
546 uint32_t GetOriginalSizeInBytes() const;
547
548 uint32_t GetSizeInBytes() const;
549
550 uint32_t GetLocation() const {
551 return location_;
552 }
553
554 uint32_t GetAdjustment() const {
555 return adjustment_;
556 }
557
Vladimir Marko6b756b52015-07-14 11:58:38 +0100558 // Prepare the assembler->fixup_dependents_ and each Fixup's dependents_start_/count_.
559 static void PrepareDependents(Thumb2Assembler* assembler);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000560
Vladimir Marko6b756b52015-07-14 11:58:38 +0100561 ArrayRef<FixupId> Dependents(const Thumb2Assembler& assembler) const {
562 return ArrayRef<FixupId>(assembler.fixup_dependents_.get() + dependents_start_,
563 dependents_count_);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000564 }
565
566 // Resolve a branch when the target is known.
567 void Resolve(uint32_t target) {
568 DCHECK_EQ(target_, kUnresolved);
569 DCHECK_NE(target, kUnresolved);
570 target_ = target;
571 }
572
573 // Check if the current size is OK for current location_, target_ and adjustment_.
574 // If not, increase the size. Return the size increase, 0 if unchanged.
575 // If the target if after this Fixup, also add the difference to adjustment_,
576 // so that we don't need to consider forward Fixups as their own dependencies.
577 uint32_t AdjustSizeIfNeeded(uint32_t current_code_size);
578
579 // Increase adjustments. This is called for dependents of a Fixup when its size changes.
580 void IncreaseAdjustment(uint32_t increase) {
581 adjustment_ += increase;
582 }
583
584 // Finalize the branch with an adjustment to the location. Both location and target are updated.
585 void Finalize(uint32_t location_adjustment) {
586 DCHECK_NE(target_, kUnresolved);
587 location_ += location_adjustment;
588 target_ += location_adjustment;
589 }
590
591 // Emit the branch instruction into the assembler buffer. This does the
592 // encoding into the thumb instruction.
593 void Emit(AssemblerBuffer* buffer, uint32_t code_size) const;
594
595 private:
596 Fixup(Register rn, Register rt2, SRegister sd, DRegister dd,
597 Condition cond, Type type, Size size, uint32_t location)
598 : rn_(rn),
599 rt2_(rt2),
600 sd_(sd),
601 dd_(dd),
602 cond_(cond),
603 type_(type),
604 original_size_(size), size_(size),
605 location_(location),
606 target_(kUnresolved),
607 adjustment_(0u),
Vladimir Marko6b756b52015-07-14 11:58:38 +0100608 dependents_count_(0u),
609 dependents_start_(0u) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000610 }
611 static size_t SizeInBytes(Size size);
612
613 // The size of padding added before the literal pool.
614 static size_t LiteralPoolPaddingSize(uint32_t current_code_size);
615
616 // Returns the offset from the PC-using insn to the target.
617 int32_t GetOffset(uint32_t current_code_size) const;
618
619 size_t IncreaseSize(Size new_size);
620
621 int32_t LoadWideOrFpEncoding(Register rbase, int32_t offset) const;
622
623 static constexpr uint32_t kUnresolved = 0xffffffff; // Value for target_ for unresolved.
624
625 const Register rn_; // Rn for cbnz/cbz, Rt for literal loads.
626 Register rt2_; // For kLoadLiteralWide.
627 SRegister sd_; // For kLoadFPLiteralSingle.
628 DRegister dd_; // For kLoadFPLiteralDouble.
629 const Condition cond_;
630 const Type type_;
631 Size original_size_;
632 Size size_;
633 uint32_t location_; // Offset into assembler buffer in bytes.
634 uint32_t target_; // Offset into assembler buffer in bytes.
635 uint32_t adjustment_; // The number of extra bytes inserted between location_ and target_.
Vladimir Marko6b756b52015-07-14 11:58:38 +0100636 // Fixups that require adjustment when current size changes are stored in a single
637 // array in the assembler and we store only the start index and count here.
638 uint32_t dependents_count_;
639 uint32_t dependents_start_;
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000640 };
641
Dave Allison65fcc2c2014-04-28 13:45:27 -0700642 // Emit a single 32 or 16 bit data processing instruction.
643 void EmitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700644 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100645 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700646 Register rn,
647 Register rd,
648 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700649
Artem Serovc257da72016-02-02 13:49:43 +0000650 // Emit a single 32 bit miscellaneous instruction.
651 void Emit32Miscellaneous(uint8_t op1,
652 uint8_t op2,
653 uint32_t rest_encoding);
654
655 // Emit reverse byte instructions: rev, rev16, revsh.
656 void EmitReverseBytes(Register rd, Register rm, uint32_t op);
657
658 // Emit a single 16 bit miscellaneous instruction.
659 void Emit16Miscellaneous(uint32_t rest_encoding);
660
Dave Allison65fcc2c2014-04-28 13:45:27 -0700661 // Must the instruction be 32 bits or can it possibly be encoded
662 // in 16 bits?
663 bool Is32BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700664 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100665 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700666 Register rn,
667 Register rd,
668 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700669
670 // Emit a 32 bit data processing instruction.
671 void Emit32BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700672 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100673 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700674 Register rn,
675 Register rd,
676 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700677
678 // Emit a 16 bit data processing instruction.
679 void Emit16BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700680 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100681 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700682 Register rn,
683 Register rd,
684 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700685
686 void Emit16BitAddSub(Condition cond,
687 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100688 SetCc set_cc,
Dave Allison65fcc2c2014-04-28 13:45:27 -0700689 Register rn,
690 Register rd,
691 const ShifterOperand& so);
692
693 uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n);
694
695 void EmitLoadStore(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700696 bool load,
697 bool byte,
698 bool half,
699 bool is_signed,
700 Register rd,
701 const Address& ad);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700702
703 void EmitMemOpAddressMode3(Condition cond,
704 int32_t mode,
705 Register rd,
706 const Address& ad);
707
708 void EmitMultiMemOp(Condition cond,
709 BlockAddressMode am,
710 bool load,
711 Register base,
712 RegList regs);
713
714 void EmitMulOp(Condition cond,
715 int32_t opcode,
716 Register rd,
717 Register rn,
718 Register rm,
719 Register rs);
720
721 void EmitVFPsss(Condition cond,
722 int32_t opcode,
723 SRegister sd,
724 SRegister sn,
725 SRegister sm);
726
727 void EmitVFPddd(Condition cond,
728 int32_t opcode,
729 DRegister dd,
730 DRegister dn,
731 DRegister dm);
732
733 void EmitVFPsd(Condition cond,
734 int32_t opcode,
735 SRegister sd,
736 DRegister dm);
737
738 void EmitVFPds(Condition cond,
739 int32_t opcode,
740 DRegister dd,
741 SRegister sm);
742
743 void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
744
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000745 void EmitBranch(Condition cond, Label* label, bool link, bool x);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700746 static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
747 static int DecodeBranchOffset(int32_t inst);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100748 void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount,
749 Condition cond = AL, SetCc set_cc = kCcDontCare);
750 void EmitShift(Register rd, Register rn, Shift shift, Register rm,
751 Condition cond = AL, SetCc set_cc = kCcDontCare);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700752
Vladimir Marko6fd0ffe2015-11-19 21:13:52 +0000753 static int32_t GetAllowedLoadOffsetBits(LoadOperandType type);
754 static int32_t GetAllowedStoreOffsetBits(StoreOperandType type);
755 bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
756 int32_t offset,
757 /*out*/ int32_t* add_to_base,
758 /*out*/ int32_t* offset_for_load_store);
759 int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits,
760 Register temp,
761 Register base,
762 int32_t offset,
763 Condition cond);
764
Nicolas Geoffrayd126ba12015-05-20 11:25:27 +0100765 // Whether the assembler can relocate branches. If false, unresolved branches will be
766 // emitted on 32bits.
767 bool can_relocate_branches_;
768
769 // Force the assembler to use 32 bit thumb2 instructions.
770 bool force_32bit_;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700771
772 // IfThen conditions. Used to check that conditional instructions match the preceding IT.
773 Condition it_conditions_[4];
774 uint8_t it_cond_index_;
775 Condition next_condition_;
776
777 void SetItCondition(ItState s, Condition cond, uint8_t index);
778
779 void CheckCondition(Condition cond) {
780 CHECK_EQ(cond, next_condition_);
781
782 // Move to the next condition if there is one.
783 if (it_cond_index_ < 3) {
784 ++it_cond_index_;
785 next_condition_ = it_conditions_[it_cond_index_];
786 } else {
787 next_condition_ = AL;
788 }
789 }
790
791 void CheckConditionLastIt(Condition cond) {
792 if (it_cond_index_ < 3) {
793 // Check that the next condition is AL. This means that the
794 // current condition is the last in the IT block.
795 CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL);
796 }
797 CheckCondition(cond);
798 }
799
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000800 FixupId AddFixup(Fixup fixup) {
801 FixupId fixup_id = static_cast<FixupId>(fixups_.size());
802 fixups_.push_back(fixup);
803 // For iterating using FixupId, we need the next id to be representable.
804 DCHECK_EQ(static_cast<size_t>(static_cast<FixupId>(fixups_.size())), fixups_.size());
805 return fixup_id;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700806 }
807
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000808 Fixup* GetFixup(FixupId fixup_id) {
809 DCHECK_LT(fixup_id, fixups_.size());
810 return &fixups_[fixup_id];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700811 }
812
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000813 void BindLabel(Label* label, uint32_t bound_pc);
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700814 uint32_t BindLiterals();
815 void BindJumpTables(uint32_t code_size);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000816 void AdjustFixupIfNeeded(Fixup* fixup, uint32_t* current_code_size,
817 std::deque<FixupId>* fixups_to_recalculate);
818 uint32_t AdjustFixups();
819 void EmitFixups(uint32_t adjusted_code_size);
820 void EmitLiterals();
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700821 void EmitJumpTables();
Vladimir Marko10ef6942015-10-22 15:25:54 +0100822 void PatchCFI();
Dave Allison65fcc2c2014-04-28 13:45:27 -0700823
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000824 static int16_t BEncoding16(int32_t offset, Condition cond);
825 static int32_t BEncoding32(int32_t offset, Condition cond);
826 static int16_t CbxzEncoding16(Register rn, int32_t offset, Condition cond);
827 static int16_t CmpRnImm8Encoding16(Register rn, int32_t value);
828 static int16_t AddRdnRmEncoding16(Register rdn, Register rm);
829 static int32_t MovwEncoding32(Register rd, int32_t value);
830 static int32_t MovtEncoding32(Register rd, int32_t value);
831 static int32_t MovModImmEncoding32(Register rd, int32_t value);
832 static int16_t LdrLitEncoding16(Register rt, int32_t offset);
833 static int32_t LdrLitEncoding32(Register rt, int32_t offset);
834 static int32_t LdrdEncoding32(Register rt, Register rt2, Register rn, int32_t offset);
835 static int32_t VldrsEncoding32(SRegister sd, Register rn, int32_t offset);
836 static int32_t VldrdEncoding32(DRegister dd, Register rn, int32_t offset);
837 static int16_t LdrRtRnImm5Encoding16(Register rt, Register rn, int32_t offset);
838 static int32_t LdrRtRnImm12Encoding(Register rt, Register rn, int32_t offset);
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700839 static int16_t AdrEncoding16(Register rd, int32_t offset);
840 static int32_t AdrEncoding32(Register rd, int32_t offset);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700841
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000842 std::vector<Fixup> fixups_;
Vladimir Marko6b756b52015-07-14 11:58:38 +0100843 std::unique_ptr<FixupId[]> fixup_dependents_;
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000844
845 // Use std::deque<> for literal labels to allow insertions at the end
846 // without invalidating pointers and references to existing elements.
847 std::deque<Literal> literals_;
848
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700849 // Jump table list.
850 std::deque<JumpTable> jump_tables_;
851
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000852 // Data for AdjustedPosition(), see the description there.
853 uint32_t last_position_adjustment_;
854 uint32_t last_old_position_;
855 FixupId last_fixup_id_;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700856};
857
858} // namespace arm
859} // namespace art
860
861#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_