blob: 13f3becb6d184d179fc94e3150c81941c447d008 [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
Vladimir Marko93205e32016-04-13 11:59:46 +010024#include "base/arena_containers.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070025#include "base/logging.h"
26#include "constants_arm.h"
27#include "utils/arm/managed_register_arm.h"
28#include "utils/arm/assembler_arm.h"
Vladimir Marko6b756b52015-07-14 11:58:38 +010029#include "utils/array_ref.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070030#include "offsets.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070031
32namespace art {
33namespace arm {
34
Dave Allison65fcc2c2014-04-28 13:45:27 -070035class Thumb2Assembler FINAL : public ArmAssembler {
36 public:
Vladimir Marko93205e32016-04-13 11:59:46 +010037 explicit Thumb2Assembler(ArenaAllocator* arena, bool can_relocate_branches = true)
38 : ArmAssembler(arena),
39 can_relocate_branches_(can_relocate_branches),
Nicolas Geoffray8d486732014-07-16 16:23:40 +010040 force_32bit_(false),
41 it_cond_index_(kNoItCondition),
Vladimir Markocf93a5c2015-06-16 11:33:24 +000042 next_condition_(AL),
Vladimir Marko93205e32016-04-13 11:59:46 +010043 fixups_(arena->Adapter(kArenaAllocAssembler)),
44 fixup_dependents_(arena->Adapter(kArenaAllocAssembler)),
45 literals_(arena->Adapter(kArenaAllocAssembler)),
Vladimir Markoebdbf4b2016-07-07 15:37:02 +010046 literal64_dedupe_map_(std::less<uint64_t>(), arena->Adapter(kArenaAllocAssembler)),
Vladimir Marko93205e32016-04-13 11:59:46 +010047 jump_tables_(arena->Adapter(kArenaAllocAssembler)),
Vladimir Markocf93a5c2015-06-16 11:33:24 +000048 last_position_adjustment_(0u),
49 last_old_position_(0u),
50 last_fixup_id_(0u) {
Vladimir Marko10ef6942015-10-22 15:25:54 +010051 cfi().DelayEmittingAdvancePCs();
Dave Allison65fcc2c2014-04-28 13:45:27 -070052 }
53
54 virtual ~Thumb2Assembler() {
Dave Allison65fcc2c2014-04-28 13:45:27 -070055 }
56
57 bool IsThumb() const OVERRIDE {
58 return true;
59 }
60
61 bool IsForced32Bit() const {
62 return force_32bit_;
63 }
64
Nicolas Geoffrayd126ba12015-05-20 11:25:27 +010065 bool CanRelocateBranches() const {
66 return can_relocate_branches_;
Nicolas Geoffray8d486732014-07-16 16:23:40 +010067 }
68
Vladimir Markocf93a5c2015-06-16 11:33:24 +000069 void FinalizeCode() OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070070
71 // Data-processing instructions.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010072 virtual void and_(Register rd, Register rn, const ShifterOperand& so,
73 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070074
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010075 virtual void eor(Register rd, Register rn, const ShifterOperand& so,
76 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070077
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010078 virtual void sub(Register rd, Register rn, const ShifterOperand& so,
79 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070080
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010081 virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
82 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070083
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010084 virtual void add(Register rd, Register rn, const ShifterOperand& so,
85 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070086
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010087 virtual void adc(Register rd, Register rn, const ShifterOperand& so,
88 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070089
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010090 virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
91 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070092
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010093 virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
94 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -070095
96 void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
97
98 void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
99
100 void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
101
102 void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
103
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100104 virtual void orr(Register rd, Register rn, const ShifterOperand& so,
105 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700106
Vladimir Markod2b4ca22015-09-14 15:13:26 +0100107 virtual void orn(Register rd, Register rn, const ShifterOperand& so,
108 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
109
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100110 virtual void mov(Register rd, const ShifterOperand& so,
111 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700112
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100113 virtual void bic(Register rd, Register rn, const ShifterOperand& so,
114 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700115
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100116 virtual void mvn(Register rd, const ShifterOperand& so,
117 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700118
119 // Miscellaneous data-processing instructions.
120 void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
121 void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
122 void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100123 void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
Artem Serovc257da72016-02-02 13:49:43 +0000124 void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
125 void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
126 void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700127
128 // Multiply instructions.
129 void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
130 void mla(Register rd, Register rn, Register rm, Register ra,
131 Condition cond = AL) OVERRIDE;
132 void mls(Register rd, Register rn, Register rm, Register ra,
133 Condition cond = AL) OVERRIDE;
Zheng Xuc6667102015-05-15 16:08:45 +0800134 void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
135 Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700136 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
137 Condition cond = AL) OVERRIDE;
138
139 void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
140 void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
141
Roland Levillain981e4542014-11-14 11:47:14 +0000142 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000143 void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
Roland Levillain981e4542014-11-14 11:47:14 +0000144 void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000145
Dave Allison65fcc2c2014-04-28 13:45:27 -0700146 // Load/store instructions.
147 void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
148 void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
149
150 void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
151 void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
152
153 void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
154 void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
155
156 void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
157 void ldrsh(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 `rd` + 1.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700160 void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
161 void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
162
Roland Levillain4af147e2015-04-07 13:54:49 +0100163 // Load/store register dual instructions using registers `rd` and `rd2`.
164 // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding
165 // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1.
166 void ldrd(Register rd, Register rd2, const Address& ad, Condition cond);
167 void strd(Register rd, Register rd2, const Address& ad, Condition cond);
168
169
Dave Allison65fcc2c2014-04-28 13:45:27 -0700170 void ldm(BlockAddressMode am, Register base,
171 RegList regs, Condition cond = AL) OVERRIDE;
172 void stm(BlockAddressMode am, Register base,
173 RegList regs, Condition cond = AL) OVERRIDE;
174
175 void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE;
176 void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE;
177
178 void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL);
179 void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL);
180
Calin Juravle52c48962014-12-16 17:02:57 +0000181 void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
182 void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700183
184 // Miscellaneous instructions.
185 void clrex(Condition cond = AL) OVERRIDE;
186 void nop(Condition cond = AL) OVERRIDE;
187
188 void bkpt(uint16_t imm16) OVERRIDE;
189 void svc(uint32_t imm24) OVERRIDE;
190
191 // If-then
192 void it(Condition firstcond, ItState i1 = kItOmitted,
193 ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE;
194
195 void cbz(Register rn, Label* target) OVERRIDE;
196 void cbnz(Register rn, Label* target) OVERRIDE;
197
198 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
199 void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE;
200 void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE;
201 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
202 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE;
203 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
204 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE;
205 void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
206 void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
207
208 // Returns false if the immediate cannot be encoded.
209 bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE;
210 bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE;
211
212 void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
213 void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
214 void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
215 void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
216
217 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
218 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
219 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
220 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
221 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
222 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
223 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
224 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
225 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
226 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
227 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
228 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
229
230 void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
231 void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
232 void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
233 void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
234 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
235 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
236
237 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
238 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
239 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
240 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
241 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
242 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
243 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
244 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
245 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
246 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
247
248 void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
249 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
250 void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE;
251 void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE;
252 void vmstat(Condition cond = AL) OVERRIDE; // VMRS APSR_nzcv, FPSCR
253
xueliang.zhonge652c122016-06-13 14:42:27 +0100254 void vcntd(DRegister dd, DRegister dm) OVERRIDE;
255 void vpaddld(DRegister dd, DRegister dm, int32_t size, bool is_unsigned) OVERRIDE;
256
Dave Allison65fcc2c2014-04-28 13:45:27 -0700257 void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
258 void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
259 void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
260 void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
Artem Serovcb3cf4a2016-07-15 15:01:13 +0100261 void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
262 void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700263
264 // Branch instructions.
265 void b(Label* label, Condition cond = AL);
266 void bl(Label* label, Condition cond = AL);
267 void blx(Label* label);
268 void blx(Register rm, Condition cond = AL) OVERRIDE;
269 void bx(Register rm, Condition cond = AL) OVERRIDE;
270
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100271 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
272 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
273 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
274 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
275 virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
276 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
277 virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
278 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
279 virtual void Rrx(Register rd, Register rm,
280 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison45fdb932014-06-25 12:37:10 -0700281
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100282 virtual void Lsl(Register rd, Register rm, Register rn,
283 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
284 virtual void Lsr(Register rd, Register rm, Register rn,
285 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
286 virtual void Asr(Register rd, Register rm, Register rn,
287 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
288 virtual void Ror(Register rd, Register rm, Register rn,
289 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700290
291 void Push(Register rd, Condition cond = AL) OVERRIDE;
292 void Pop(Register rd, Condition cond = AL) OVERRIDE;
293
294 void PushList(RegList regs, Condition cond = AL) OVERRIDE;
295 void PopList(RegList regs, Condition cond = AL) OVERRIDE;
296
297 void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
298
299 void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE;
300 void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE;
301
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100302 // Memory barriers.
303 void dmb(DmbOptions flavor) OVERRIDE;
304
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000305 // Get the final position of a label after local fixup based on the old position
306 // recorded before FinalizeCode().
307 uint32_t GetAdjustedPosition(uint32_t old_position) OVERRIDE;
308
309 using ArmAssembler::NewLiteral; // Make the helper template visible.
310
311 Literal* NewLiteral(size_t size, const uint8_t* data) OVERRIDE;
312 void LoadLiteral(Register rt, Literal* literal) OVERRIDE;
313 void LoadLiteral(Register rt, Register rt2, Literal* literal) OVERRIDE;
314 void LoadLiteral(SRegister sd, Literal* literal) OVERRIDE;
315 void LoadLiteral(DRegister dd, Literal* literal) OVERRIDE;
316
Dave Allison65fcc2c2014-04-28 13:45:27 -0700317 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700318 void AddConstant(Register rd, Register rn, int32_t value,
Vladimir Marko449b1092015-09-08 12:16:45 +0100319 Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700320
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700321 void CmpConstant(Register rn, int32_t value, Condition cond = AL) OVERRIDE;
322
Dave Allison65fcc2c2014-04-28 13:45:27 -0700323 // Load and Store. May clobber IP.
324 void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100325 void LoadDImmediate(DRegister dd, double value, Condition cond = AL) OVERRIDE;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700326 void MarkExceptionHandler(Label* label) OVERRIDE;
327 void LoadFromOffset(LoadOperandType type,
328 Register reg,
329 Register base,
330 int32_t offset,
331 Condition cond = AL) OVERRIDE;
332 void StoreToOffset(StoreOperandType type,
333 Register reg,
334 Register base,
335 int32_t offset,
336 Condition cond = AL) OVERRIDE;
337 void LoadSFromOffset(SRegister reg,
338 Register base,
339 int32_t offset,
340 Condition cond = AL) OVERRIDE;
341 void StoreSToOffset(SRegister reg,
342 Register base,
343 int32_t offset,
344 Condition cond = AL) OVERRIDE;
345 void LoadDFromOffset(DRegister reg,
346 Register base,
347 int32_t offset,
348 Condition cond = AL) OVERRIDE;
349 void StoreDToOffset(DRegister reg,
350 Register base,
351 int32_t offset,
352 Condition cond = AL) OVERRIDE;
353
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000354 bool ShifterOperandCanHold(Register rd,
355 Register rn,
356 Opcode opcode,
357 uint32_t immediate,
Vladimir Markof5c09c32015-12-17 12:08:08 +0000358 SetCc set_cc,
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000359 ShifterOperand* shifter_op) OVERRIDE;
Vladimir Markof5c09c32015-12-17 12:08:08 +0000360 using ArmAssembler::ShifterOperandCanHold; // Don't hide the non-virtual override.
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000361
Nicolas Geoffray5bd05a52015-10-13 09:48:30 +0100362 bool ShifterOperandCanAlwaysHold(uint32_t immediate) OVERRIDE;
363
Dave Allison65fcc2c2014-04-28 13:45:27 -0700364
Ian Rogers13735952014-10-08 12:43:28 -0700365 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700366
367 // Emit data (e.g. encoded instruction or immediate) to the.
368 // instruction stream.
369 void Emit32(int32_t value); // Emit a 32 bit instruction in thumb format.
370 void Emit16(int16_t value); // Emit a 16 bit instruction in little endian format.
371 void Bind(Label* label) OVERRIDE;
372
Dave Allison65fcc2c2014-04-28 13:45:27 -0700373 // Force the assembler to generate 32 bit instructions.
374 void Force32Bit() {
375 force_32bit_ = true;
376 }
377
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700378 // Emit an ADR (or a sequence of instructions) to load the jump table address into base_reg. This
379 // will generate a fixup.
380 JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) OVERRIDE;
381 // Emit an ADD PC, X to dispatch a jump-table jump. This will generate a fixup.
382 void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) OVERRIDE;
383
Dave Allison65fcc2c2014-04-28 13:45:27 -0700384 private:
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000385 typedef uint16_t FixupId;
386
387 // Fixup: branches and literal pool references.
388 //
389 // The thumb2 architecture allows branches to be either 16 or 32 bit instructions. This
390 // depends on both the type of branch and the offset to which it is branching. The 16-bit
391 // cbz and cbnz instructions may also need to be replaced with a separate 16-bit compare
392 // instruction and a 16- or 32-bit branch instruction. Load from a literal pool can also be
393 // 16-bit or 32-bit instruction and, if the method is large, we may need to use a sequence
394 // of instructions to make up for the limited range of load literal instructions (up to
395 // 4KiB for the 32-bit variant). When generating code for these insns we don't know the
396 // size before hand, so we assume it is the smallest available size and determine the final
397 // code offsets and sizes and emit code in FinalizeCode().
398 //
399 // To handle this, we keep a record of every branch and literal pool load in the program.
400 // The actual instruction encoding for these is delayed until we know the final size of
401 // every instruction. When we bind a label to a branch we don't know the final location yet
402 // as some preceding instructions may need to be expanded, so we record a non-final offset.
403 // In FinalizeCode(), we expand the sizes of branches and literal loads that are out of
404 // range. With each expansion, we need to update dependent Fixups, i.e. insntructios with
405 // target on the other side of the expanded insn, as their offsets change and this may
406 // trigger further expansion.
407 //
408 // All Fixups have a 'fixup id' which is a 16 bit unsigned number used to identify the
409 // Fixup. For each unresolved label we keep a singly-linked list of all Fixups pointing
410 // to it, using the fixup ids as links. The first link is stored in the label's position
411 // (the label is linked but not bound), the following links are stored in the code buffer,
412 // in the placeholder where we will eventually emit the actual code.
413
414 class Fixup {
415 public:
416 // Branch type.
417 enum Type : uint8_t {
418 kConditional, // B<cond>.
419 kUnconditional, // B.
420 kUnconditionalLink, // BL.
421 kUnconditionalLinkX, // BLX.
422 kCompareAndBranchXZero, // cbz/cbnz.
423 kLoadLiteralNarrow, // Load narrrow integer literal.
424 kLoadLiteralWide, // Load wide integer literal.
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700425 kLoadLiteralAddr, // Load address of literal (used for jump table).
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000426 kLoadFPLiteralSingle, // Load FP literal single.
427 kLoadFPLiteralDouble, // Load FP literal double.
428 };
429
430 // Calculated size of branch instruction based on type and offset.
431 enum Size : uint8_t {
432 // Branch variants.
433 kBranch16Bit,
434 kBranch32Bit,
435 // NOTE: We don't support branches which would require multiple instructions, i.e.
436 // conditinoal branches beyond +-1MiB and unconditional branches beyond +-16MiB.
437
438 // CBZ/CBNZ variants.
439 kCbxz16Bit, // CBZ/CBNZ rX, label; X < 8; 7-bit positive offset.
440 kCbxz32Bit, // CMP rX, #0 + Bcc label; X < 8; 16-bit Bcc; +-8-bit offset.
441 kCbxz48Bit, // CMP rX, #0 + Bcc label; X < 8; 32-bit Bcc; up to +-1MiB offset.
442
443 // Load integer literal variants.
444 // LDR rX, label; X < 8; 16-bit variant up to 1KiB offset; 2 bytes.
445 kLiteral1KiB,
446 // LDR rX, label; 32-bit variant up to 4KiB offset; 4 bytes.
447 kLiteral4KiB,
448 // MOV rX, imm16 + ADD rX, pc + LDR rX, [rX]; X < 8; up to 64KiB offset; 8 bytes.
449 kLiteral64KiB,
450 // MOV rX, modimm + ADD rX, pc + LDR rX, [rX, #imm12]; up to 1MiB offset; 10 bytes.
451 kLiteral1MiB,
452 // NOTE: We don't provide the 12-byte version of kLiteralFar below where the LDR is 16-bit.
453 // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc + LDR rX, [rX]; any offset; 14 bytes.
454 kLiteralFar,
455
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700456 // Load literal base addr.
457 // ADR rX, label; X < 8; 8 bit immediate, shifted to 10 bit. 2 bytes.
458 kLiteralAddr1KiB,
459 // ADR rX, label; 4KiB offset. 4 bytes.
460 kLiteralAddr4KiB,
461 // MOV rX, imm16 + ADD rX, pc; 64KiB offset. 6 bytes.
462 kLiteralAddr64KiB,
463 // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc; any offset; 10 bytes.
464 kLiteralAddrFar,
465
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000466 // Load long or FP literal variants.
467 // VLDR s/dX, label; 32-bit insn, up to 1KiB offset; 4 bytes.
468 kLongOrFPLiteral1KiB,
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100469 // MOV ip, imm16 + ADD ip, pc + VLDR s/dX, [IP, #0]; up to 64KiB offset; 10 bytes.
470 kLongOrFPLiteral64KiB,
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000471 // MOV ip, imm16 + MOVT ip, imm16 + ADD ip, pc + VLDR s/dX, [IP]; any offset; 14 bytes.
472 kLongOrFPLiteralFar,
473 };
474
475 // Unresolved branch possibly with a condition.
476 static Fixup Branch(uint32_t location, Type type, Size size = kBranch16Bit,
477 Condition cond = AL) {
478 DCHECK(type == kConditional || type == kUnconditional ||
479 type == kUnconditionalLink || type == kUnconditionalLinkX);
480 DCHECK(size == kBranch16Bit || size == kBranch32Bit);
481 DCHECK(size == kBranch32Bit || (type == kConditional || type == kUnconditional));
482 return Fixup(kNoRegister, kNoRegister, kNoSRegister, kNoDRegister,
483 cond, type, size, location);
484 }
485
486 // Unresolved compare-and-branch instruction with a register and condition (EQ or NE).
487 static Fixup CompareAndBranch(uint32_t location, Register rn, Condition cond) {
488 DCHECK(cond == EQ || cond == NE);
489 return Fixup(rn, kNoRegister, kNoSRegister, kNoDRegister,
490 cond, kCompareAndBranchXZero, kCbxz16Bit, location);
491 }
492
493 // Load narrow literal.
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700494 static Fixup LoadNarrowLiteral(uint32_t location, Register rt, Size size) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000495 DCHECK(size == kLiteral1KiB || size == kLiteral4KiB || size == kLiteral64KiB ||
496 size == kLiteral1MiB || size == kLiteralFar);
497 DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
498 return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
499 AL, kLoadLiteralNarrow, size, location);
500 }
501
502 // Load wide literal.
503 static Fixup LoadWideLiteral(uint32_t location, Register rt, Register rt2,
504 Size size = kLongOrFPLiteral1KiB) {
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100505 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral64KiB ||
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000506 size == kLongOrFPLiteralFar);
507 DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
508 return Fixup(rt, rt2, kNoSRegister, kNoDRegister,
509 AL, kLoadLiteralWide, size, location);
510 }
511
512 // Load FP single literal.
513 static Fixup LoadSingleLiteral(uint32_t location, SRegister sd,
514 Size size = kLongOrFPLiteral1KiB) {
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100515 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral64KiB ||
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000516 size == kLongOrFPLiteralFar);
517 return Fixup(kNoRegister, kNoRegister, sd, kNoDRegister,
518 AL, kLoadFPLiteralSingle, size, location);
519 }
520
521 // Load FP double literal.
522 static Fixup LoadDoubleLiteral(uint32_t location, DRegister dd,
523 Size size = kLongOrFPLiteral1KiB) {
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100524 DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral64KiB ||
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000525 size == kLongOrFPLiteralFar);
526 return Fixup(kNoRegister, kNoRegister, kNoSRegister, dd,
527 AL, kLoadFPLiteralDouble, size, location);
528 }
529
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700530 static Fixup LoadLiteralAddress(uint32_t location, Register rt, Size size) {
531 DCHECK(size == kLiteralAddr1KiB || size == kLiteralAddr4KiB || size == kLiteralAddr64KiB ||
532 size == kLiteralAddrFar);
533 DCHECK(!IsHighRegister(rt) || size != kLiteralAddr1KiB);
534 return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
535 AL, kLoadLiteralAddr, size, location);
536 }
537
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000538 Type GetType() const {
539 return type_;
540 }
541
Vladimir Marko663c9342015-07-22 11:28:14 +0100542 bool IsLoadLiteral() const {
543 return GetType() >= kLoadLiteralNarrow;
544 }
545
Vladimir Markoa64f2492016-04-25 12:43:50 +0000546 // Returns whether the Fixup can expand from the original size.
547 bool CanExpand() const {
548 switch (GetOriginalSize()) {
549 case kBranch32Bit:
550 case kCbxz48Bit:
551 case kLiteralFar:
552 case kLiteralAddrFar:
553 case kLongOrFPLiteralFar:
554 return false;
555 default:
556 return true;
557 }
558 }
559
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000560 Size GetOriginalSize() const {
561 return original_size_;
562 }
563
564 Size GetSize() const {
565 return size_;
566 }
567
568 uint32_t GetOriginalSizeInBytes() const;
569
570 uint32_t GetSizeInBytes() const;
571
572 uint32_t GetLocation() const {
573 return location_;
574 }
575
576 uint32_t GetAdjustment() const {
577 return adjustment_;
578 }
579
Vladimir Marko6b756b52015-07-14 11:58:38 +0100580 // Prepare the assembler->fixup_dependents_ and each Fixup's dependents_start_/count_.
581 static void PrepareDependents(Thumb2Assembler* assembler);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000582
Vladimir Marko93205e32016-04-13 11:59:46 +0100583 ArrayRef<const FixupId> Dependents(const Thumb2Assembler& assembler) const {
584 return ArrayRef<const FixupId>(assembler.fixup_dependents_).SubArray(dependents_start_,
585 dependents_count_);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000586 }
587
588 // Resolve a branch when the target is known.
589 void Resolve(uint32_t target) {
590 DCHECK_EQ(target_, kUnresolved);
591 DCHECK_NE(target, kUnresolved);
592 target_ = target;
593 }
594
595 // Check if the current size is OK for current location_, target_ and adjustment_.
596 // If not, increase the size. Return the size increase, 0 if unchanged.
597 // If the target if after this Fixup, also add the difference to adjustment_,
598 // so that we don't need to consider forward Fixups as their own dependencies.
599 uint32_t AdjustSizeIfNeeded(uint32_t current_code_size);
600
601 // Increase adjustments. This is called for dependents of a Fixup when its size changes.
602 void IncreaseAdjustment(uint32_t increase) {
603 adjustment_ += increase;
604 }
605
606 // Finalize the branch with an adjustment to the location. Both location and target are updated.
607 void Finalize(uint32_t location_adjustment) {
608 DCHECK_NE(target_, kUnresolved);
609 location_ += location_adjustment;
610 target_ += location_adjustment;
611 }
612
613 // Emit the branch instruction into the assembler buffer. This does the
614 // encoding into the thumb instruction.
615 void Emit(AssemblerBuffer* buffer, uint32_t code_size) const;
616
617 private:
618 Fixup(Register rn, Register rt2, SRegister sd, DRegister dd,
619 Condition cond, Type type, Size size, uint32_t location)
620 : rn_(rn),
621 rt2_(rt2),
622 sd_(sd),
623 dd_(dd),
624 cond_(cond),
625 type_(type),
626 original_size_(size), size_(size),
627 location_(location),
628 target_(kUnresolved),
629 adjustment_(0u),
Vladimir Marko6b756b52015-07-14 11:58:38 +0100630 dependents_count_(0u),
631 dependents_start_(0u) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000632 }
Vladimir Markoa64f2492016-04-25 12:43:50 +0000633
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000634 static size_t SizeInBytes(Size size);
635
636 // The size of padding added before the literal pool.
637 static size_t LiteralPoolPaddingSize(uint32_t current_code_size);
638
639 // Returns the offset from the PC-using insn to the target.
640 int32_t GetOffset(uint32_t current_code_size) const;
641
642 size_t IncreaseSize(Size new_size);
643
644 int32_t LoadWideOrFpEncoding(Register rbase, int32_t offset) const;
645
Vladimir Markoa64f2492016-04-25 12:43:50 +0000646 template <typename Function>
647 static void ForExpandableDependencies(Thumb2Assembler* assembler, Function fn);
648
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000649 static constexpr uint32_t kUnresolved = 0xffffffff; // Value for target_ for unresolved.
650
651 const Register rn_; // Rn for cbnz/cbz, Rt for literal loads.
652 Register rt2_; // For kLoadLiteralWide.
653 SRegister sd_; // For kLoadFPLiteralSingle.
654 DRegister dd_; // For kLoadFPLiteralDouble.
655 const Condition cond_;
656 const Type type_;
657 Size original_size_;
658 Size size_;
659 uint32_t location_; // Offset into assembler buffer in bytes.
660 uint32_t target_; // Offset into assembler buffer in bytes.
661 uint32_t adjustment_; // The number of extra bytes inserted between location_ and target_.
Vladimir Marko6b756b52015-07-14 11:58:38 +0100662 // Fixups that require adjustment when current size changes are stored in a single
663 // array in the assembler and we store only the start index and count here.
664 uint32_t dependents_count_;
665 uint32_t dependents_start_;
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000666 };
667
Dave Allison65fcc2c2014-04-28 13:45:27 -0700668 // Emit a single 32 or 16 bit data processing instruction.
669 void EmitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700670 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100671 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700672 Register rn,
673 Register rd,
674 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700675
Artem Serovc257da72016-02-02 13:49:43 +0000676 // Emit a single 32 bit miscellaneous instruction.
677 void Emit32Miscellaneous(uint8_t op1,
678 uint8_t op2,
679 uint32_t rest_encoding);
680
681 // Emit reverse byte instructions: rev, rev16, revsh.
682 void EmitReverseBytes(Register rd, Register rm, uint32_t op);
683
684 // Emit a single 16 bit miscellaneous instruction.
685 void Emit16Miscellaneous(uint32_t rest_encoding);
686
Dave Allison65fcc2c2014-04-28 13:45:27 -0700687 // Must the instruction be 32 bits or can it possibly be encoded
688 // in 16 bits?
689 bool Is32BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700690 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100691 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700692 Register rn,
693 Register rd,
694 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700695
696 // Emit a 32 bit data processing instruction.
697 void Emit32BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700698 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100699 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700700 Register rn,
701 Register rd,
702 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700703
704 // Emit a 16 bit data processing instruction.
705 void Emit16BitDataProcessing(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700706 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100707 SetCc set_cc,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700708 Register rn,
709 Register rd,
710 const ShifterOperand& so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700711
712 void Emit16BitAddSub(Condition cond,
713 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100714 SetCc set_cc,
Dave Allison65fcc2c2014-04-28 13:45:27 -0700715 Register rn,
716 Register rd,
717 const ShifterOperand& so);
718
719 uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n);
720
721 void EmitLoadStore(Condition cond,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700722 bool load,
723 bool byte,
724 bool half,
725 bool is_signed,
726 Register rd,
727 const Address& ad);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700728
729 void EmitMemOpAddressMode3(Condition cond,
730 int32_t mode,
731 Register rd,
732 const Address& ad);
733
734 void EmitMultiMemOp(Condition cond,
735 BlockAddressMode am,
736 bool load,
737 Register base,
738 RegList regs);
739
740 void EmitMulOp(Condition cond,
741 int32_t opcode,
742 Register rd,
743 Register rn,
744 Register rm,
745 Register rs);
746
747 void EmitVFPsss(Condition cond,
748 int32_t opcode,
749 SRegister sd,
750 SRegister sn,
751 SRegister sm);
752
Artem Serovcb3cf4a2016-07-15 15:01:13 +0100753 void EmitVLdmOrStm(int32_t rest,
754 uint32_t reg,
755 int nregs,
756 Register rn,
757 bool is_load,
758 bool dbl,
759 Condition cond);
760
Dave Allison65fcc2c2014-04-28 13:45:27 -0700761 void EmitVFPddd(Condition cond,
762 int32_t opcode,
763 DRegister dd,
764 DRegister dn,
765 DRegister dm);
766
767 void EmitVFPsd(Condition cond,
768 int32_t opcode,
769 SRegister sd,
770 DRegister dm);
771
772 void EmitVFPds(Condition cond,
773 int32_t opcode,
774 DRegister dd,
775 SRegister sm);
776
777 void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
778
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000779 void EmitBranch(Condition cond, Label* label, bool link, bool x);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700780 static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
781 static int DecodeBranchOffset(int32_t inst);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100782 void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount,
783 Condition cond = AL, SetCc set_cc = kCcDontCare);
784 void EmitShift(Register rd, Register rn, Shift shift, Register rm,
785 Condition cond = AL, SetCc set_cc = kCcDontCare);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700786
Vladimir Marko6fd0ffe2015-11-19 21:13:52 +0000787 static int32_t GetAllowedLoadOffsetBits(LoadOperandType type);
788 static int32_t GetAllowedStoreOffsetBits(StoreOperandType type);
789 bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
790 int32_t offset,
791 /*out*/ int32_t* add_to_base,
792 /*out*/ int32_t* offset_for_load_store);
793 int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits,
794 Register temp,
795 Register base,
796 int32_t offset,
797 Condition cond);
798
Nicolas Geoffrayd126ba12015-05-20 11:25:27 +0100799 // Whether the assembler can relocate branches. If false, unresolved branches will be
800 // emitted on 32bits.
801 bool can_relocate_branches_;
802
803 // Force the assembler to use 32 bit thumb2 instructions.
804 bool force_32bit_;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700805
806 // IfThen conditions. Used to check that conditional instructions match the preceding IT.
807 Condition it_conditions_[4];
808 uint8_t it_cond_index_;
809 Condition next_condition_;
810
811 void SetItCondition(ItState s, Condition cond, uint8_t index);
812
813 void CheckCondition(Condition cond) {
814 CHECK_EQ(cond, next_condition_);
815
816 // Move to the next condition if there is one.
817 if (it_cond_index_ < 3) {
818 ++it_cond_index_;
819 next_condition_ = it_conditions_[it_cond_index_];
820 } else {
821 next_condition_ = AL;
822 }
823 }
824
825 void CheckConditionLastIt(Condition cond) {
826 if (it_cond_index_ < 3) {
827 // Check that the next condition is AL. This means that the
828 // current condition is the last in the IT block.
829 CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL);
830 }
831 CheckCondition(cond);
832 }
833
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000834 FixupId AddFixup(Fixup fixup) {
835 FixupId fixup_id = static_cast<FixupId>(fixups_.size());
836 fixups_.push_back(fixup);
837 // For iterating using FixupId, we need the next id to be representable.
838 DCHECK_EQ(static_cast<size_t>(static_cast<FixupId>(fixups_.size())), fixups_.size());
839 return fixup_id;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700840 }
841
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000842 Fixup* GetFixup(FixupId fixup_id) {
843 DCHECK_LT(fixup_id, fixups_.size());
844 return &fixups_[fixup_id];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700845 }
846
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000847 void BindLabel(Label* label, uint32_t bound_pc);
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700848 uint32_t BindLiterals();
849 void BindJumpTables(uint32_t code_size);
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000850 void AdjustFixupIfNeeded(Fixup* fixup, uint32_t* current_code_size,
851 std::deque<FixupId>* fixups_to_recalculate);
852 uint32_t AdjustFixups();
853 void EmitFixups(uint32_t adjusted_code_size);
854 void EmitLiterals();
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700855 void EmitJumpTables();
Vladimir Marko10ef6942015-10-22 15:25:54 +0100856 void PatchCFI();
Dave Allison65fcc2c2014-04-28 13:45:27 -0700857
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000858 static int16_t BEncoding16(int32_t offset, Condition cond);
859 static int32_t BEncoding32(int32_t offset, Condition cond);
860 static int16_t CbxzEncoding16(Register rn, int32_t offset, Condition cond);
861 static int16_t CmpRnImm8Encoding16(Register rn, int32_t value);
862 static int16_t AddRdnRmEncoding16(Register rdn, Register rm);
863 static int32_t MovwEncoding32(Register rd, int32_t value);
864 static int32_t MovtEncoding32(Register rd, int32_t value);
865 static int32_t MovModImmEncoding32(Register rd, int32_t value);
866 static int16_t LdrLitEncoding16(Register rt, int32_t offset);
867 static int32_t LdrLitEncoding32(Register rt, int32_t offset);
868 static int32_t LdrdEncoding32(Register rt, Register rt2, Register rn, int32_t offset);
869 static int32_t VldrsEncoding32(SRegister sd, Register rn, int32_t offset);
870 static int32_t VldrdEncoding32(DRegister dd, Register rn, int32_t offset);
871 static int16_t LdrRtRnImm5Encoding16(Register rt, Register rn, int32_t offset);
872 static int32_t LdrRtRnImm12Encoding(Register rt, Register rn, int32_t offset);
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700873 static int16_t AdrEncoding16(Register rd, int32_t offset);
874 static int32_t AdrEncoding32(Register rd, int32_t offset);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700875
Vladimir Marko93205e32016-04-13 11:59:46 +0100876 ArenaVector<Fixup> fixups_;
877 ArenaVector<FixupId> fixup_dependents_;
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000878
879 // Use std::deque<> for literal labels to allow insertions at the end
880 // without invalidating pointers and references to existing elements.
Vladimir Marko93205e32016-04-13 11:59:46 +0100881 ArenaDeque<Literal> literals_;
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000882
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100883 // Deduplication map for 64-bit literals, used for LoadDImmediate().
884 ArenaSafeMap<uint64_t, Literal*> literal64_dedupe_map_;
885
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700886 // Jump table list.
Vladimir Marko93205e32016-04-13 11:59:46 +0100887 ArenaDeque<JumpTable> jump_tables_;
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700888
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000889 // Data for AdjustedPosition(), see the description there.
890 uint32_t last_position_adjustment_;
891 uint32_t last_old_position_;
892 FixupId last_fixup_id_;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700893};
894
895} // namespace arm
896} // namespace art
897
898#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_