blob: f5be04acb7992df1a0596a56a694a25f147c99d3 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070016
Ian Rogers166db042013-07-26 12:05:57 -070017#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
18#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070019
Elliott Hughes07ed66b2012-12-12 18:34:25 -080020#include <vector>
21
22#include "base/logging.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070023#include "constants_arm.h"
Ian Rogers166db042013-07-26 12:05:57 -070024#include "utils/arm/managed_register_arm.h"
25#include "utils/assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070026#include "offsets.h"
27#include "utils.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070028
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070029namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070030namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070031
Carl Shapiroa2e18e12011-06-21 18:57:55 -070032// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
33class ShifterOperand {
34 public:
35 // Data-processing operands - Uninitialized
36 ShifterOperand() {
37 type_ = -1;
Ian Rogersdd7624d2014-03-14 17:43:00 -070038 encoding_ = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070039 }
40
41 // Data-processing operands - Immediate
42 explicit ShifterOperand(uint32_t immediate) {
43 CHECK(immediate < (1 << kImmed8Bits));
44 type_ = 1;
45 encoding_ = immediate;
46 }
47
48 // Data-processing operands - Rotated immediate
49 ShifterOperand(uint32_t rotate, uint32_t immed8) {
50 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
51 type_ = 1;
52 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
53 }
54
55 // Data-processing operands - Register
56 explicit ShifterOperand(Register rm) {
57 type_ = 0;
58 encoding_ = static_cast<uint32_t>(rm);
59 }
60
61 // Data-processing operands - Logical shift/rotate by immediate
62 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
63 CHECK(shift_imm < (1 << kShiftImmBits));
64 type_ = 0;
65 encoding_ = shift_imm << kShiftImmShift |
66 static_cast<uint32_t>(shift) << kShiftShift |
67 static_cast<uint32_t>(rm);
68 }
69
70 // Data-processing operands - Logical shift/rotate by register
71 ShifterOperand(Register rm, Shift shift, Register rs) {
72 type_ = 0;
73 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
74 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
75 static_cast<uint32_t>(rm);
76 }
77
78 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
79 // Avoid the more expensive test for frequent small immediate values.
80 if (immediate < (1 << kImmed8Bits)) {
81 shifter_op->type_ = 1;
82 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
83 return true;
84 }
85 // Note that immediate must be unsigned for the test to work correctly.
86 for (int rot = 0; rot < 16; rot++) {
87 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
88 if (imm8 < (1 << kImmed8Bits)) {
89 shifter_op->type_ = 1;
90 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
91 return true;
92 }
93 }
94 return false;
95 }
96
97 private:
98 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
99
100 uint32_t type() const {
101 CHECK(is_valid());
102 return type_;
103 }
104
105 uint32_t encoding() const {
106 CHECK(is_valid());
107 return encoding_;
108 }
109
110 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
111 uint32_t encoding_;
112
Ian Rogers2c8f6532011-09-02 17:16:34 -0700113 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700114#ifdef SOURCE_ASSEMBLER_SUPPORT
115 friend class BinaryAssembler;
116#endif
117};
118
119
120enum LoadOperandType {
121 kLoadSignedByte,
122 kLoadUnsignedByte,
123 kLoadSignedHalfword,
124 kLoadUnsignedHalfword,
125 kLoadWord,
126 kLoadWordPair,
127 kLoadSWord,
128 kLoadDWord
129};
130
131
132enum StoreOperandType {
133 kStoreByte,
134 kStoreHalfword,
135 kStoreWord,
136 kStoreWordPair,
137 kStoreSWord,
138 kStoreDWord
139};
140
141
142// Load/store multiple addressing mode.
143enum BlockAddressMode {
144 // bit encoding P U W
145 DA = (0|0|0) << 21, // decrement after
146 IA = (0|4|0) << 21, // increment after
147 DB = (8|0|0) << 21, // decrement before
148 IB = (8|4|0) << 21, // increment before
149 DA_W = (0|0|1) << 21, // decrement after with writeback to base
150 IA_W = (0|4|1) << 21, // increment after with writeback to base
151 DB_W = (8|0|1) << 21, // decrement before with writeback to base
152 IB_W = (8|4|1) << 21 // increment before with writeback to base
153};
154
155
156class Address {
157 public:
158 // Memory operand addressing mode
159 enum Mode {
160 // bit encoding P U W
161 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
162 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
163 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
164 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
165 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
166 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
167 };
168
169 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
170 CHECK(IsAbsoluteUint(12, offset));
171 if (offset < 0) {
172 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
173 } else {
174 encoding_ = am | offset;
175 }
176 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
177 }
178
179 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
180 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
181
182 private:
183 uint32_t encoding() const { return encoding_; }
184
185 // Encoding for addressing mode 3.
186 uint32_t encoding3() const {
187 const uint32_t offset_mask = (1 << 12) - 1;
188 uint32_t offset = encoding_ & offset_mask;
Ian Rogersb033c752011-07-20 12:22:35 -0700189 CHECK_LT(offset, 256u);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700190 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
191 }
192
193 // Encoding for vfp load/store addressing.
194 uint32_t vencoding() const {
195 const uint32_t offset_mask = (1 << 12) - 1;
196 uint32_t offset = encoding_ & offset_mask;
197 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
Elliott Hughes06b37d92011-10-16 11:51:29 -0700198 CHECK_ALIGNED(offset, 2); // Multiple of 4.
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700199 int mode = encoding_ & ((8|4|1) << 21);
200 CHECK((mode == Offset) || (mode == NegOffset));
201 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
202 if (mode == Offset) {
203 vencoding |= 1 << 23;
204 }
205 return vencoding;
206 }
207
208 uint32_t encoding_;
209
Ian Rogers2c8f6532011-09-02 17:16:34 -0700210 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700211};
212
213
Ian Rogersdd7624d2014-03-14 17:43:00 -0700214class ArmAssembler FINAL : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700215 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700216 ArmAssembler() {}
217 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700218
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700219 // Data-processing instructions.
220 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
221
222 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
223
224 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
225 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
226
227 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
228 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
229
230 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
231
232 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
233
234 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
235
236 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
237
238 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
239
240 void tst(Register rn, ShifterOperand so, Condition cond = AL);
241
242 void teq(Register rn, ShifterOperand so, Condition cond = AL);
243
244 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
245
246 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
247
248 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
249 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
250
251 void mov(Register rd, ShifterOperand so, Condition cond = AL);
252 void movs(Register rd, ShifterOperand so, Condition cond = AL);
253
254 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
255
256 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
257 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
258
259 // Miscellaneous data-processing instructions.
260 void clz(Register rd, Register rm, Condition cond = AL);
261 void movw(Register rd, uint16_t imm16, Condition cond = AL);
262 void movt(Register rd, uint16_t imm16, Condition cond = AL);
263
264 // Multiply instructions.
265 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
266 void mla(Register rd, Register rn, Register rm, Register ra,
267 Condition cond = AL);
268 void mls(Register rd, Register rn, Register rm, Register ra,
269 Condition cond = AL);
270 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
271 Condition cond = AL);
272
273 // Load/store instructions.
274 void ldr(Register rd, Address ad, Condition cond = AL);
275 void str(Register rd, Address ad, Condition cond = AL);
276
277 void ldrb(Register rd, Address ad, Condition cond = AL);
278 void strb(Register rd, Address ad, Condition cond = AL);
279
280 void ldrh(Register rd, Address ad, Condition cond = AL);
281 void strh(Register rd, Address ad, Condition cond = AL);
282
283 void ldrsb(Register rd, Address ad, Condition cond = AL);
284 void ldrsh(Register rd, Address ad, Condition cond = AL);
285
286 void ldrd(Register rd, Address ad, Condition cond = AL);
287 void strd(Register rd, Address ad, Condition cond = AL);
288
289 void ldm(BlockAddressMode am, Register base,
290 RegList regs, Condition cond = AL);
291 void stm(BlockAddressMode am, Register base,
292 RegList regs, Condition cond = AL);
293
294 void ldrex(Register rd, Register rn, Condition cond = AL);
295 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
296
297 // Miscellaneous instructions.
298 void clrex();
299 void nop(Condition cond = AL);
300
301 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
302 void bkpt(uint16_t imm16);
303 void svc(uint32_t imm24);
304
305 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
306 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
307 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
308 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
309 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
310 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
311 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
312 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
313 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
314
315 // Returns false if the immediate cannot be encoded.
316 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
317 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
318
319 void vldrs(SRegister sd, Address ad, Condition cond = AL);
320 void vstrs(SRegister sd, Address ad, Condition cond = AL);
321 void vldrd(DRegister dd, Address ad, Condition cond = AL);
322 void vstrd(DRegister dd, Address ad, Condition cond = AL);
323
324 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
325 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
326 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
327 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
328 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
329 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
330 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
331 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
332 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
333 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
334 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
335 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
336
337 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
338 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
339 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
340 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
341 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
342 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
343
344 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
345 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
346 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
347 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
348 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
349 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
350 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
351 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
352 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
353 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
354
355 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
356 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
357 void vcmpsz(SRegister sd, Condition cond = AL);
358 void vcmpdz(DRegister dd, Condition cond = AL);
359 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
360
361 // Branch instructions.
362 void b(Label* label, Condition cond = AL);
363 void bl(Label* label, Condition cond = AL);
364 void blx(Register rm, Condition cond = AL);
Ian Rogersae675992011-10-09 17:10:22 -0700365 void bx(Register rm, Condition cond = AL);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700366
367 // Macros.
368 // Add signed constant value to rd. May clobber IP.
369 void AddConstant(Register rd, int32_t value, Condition cond = AL);
370 void AddConstant(Register rd, Register rn, int32_t value,
371 Condition cond = AL);
372 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
373 Condition cond = AL);
374 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
375 Condition cond = AL);
376
377 // Load and Store. May clobber IP.
378 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
379 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
380 void LoadDImmediate(DRegister dd, double value,
381 Register scratch, Condition cond = AL);
382 void MarkExceptionHandler(Label* label);
383 void LoadFromOffset(LoadOperandType type,
384 Register reg,
385 Register base,
386 int32_t offset,
387 Condition cond = AL);
388 void StoreToOffset(StoreOperandType type,
389 Register reg,
390 Register base,
391 int32_t offset,
392 Condition cond = AL);
393 void LoadSFromOffset(SRegister reg,
394 Register base,
395 int32_t offset,
396 Condition cond = AL);
397 void StoreSToOffset(SRegister reg,
398 Register base,
399 int32_t offset,
400 Condition cond = AL);
401 void LoadDFromOffset(DRegister reg,
402 Register base,
403 int32_t offset,
404 Condition cond = AL);
405 void StoreDToOffset(DRegister reg,
406 Register base,
407 int32_t offset,
408 Condition cond = AL);
409
410 void Push(Register rd, Condition cond = AL);
411 void Pop(Register rd, Condition cond = AL);
412
413 void PushList(RegList regs, Condition cond = AL);
414 void PopList(RegList regs, Condition cond = AL);
415
416 void Mov(Register rd, Register rm, Condition cond = AL);
417
418 // Convenience shift instructions. Use mov instruction with shifter operand
419 // for variants setting the status flags or using a register shift count.
420 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
421 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
422 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
423 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
424 void Rrx(Register rd, Register rm, Condition cond = AL);
425
426 // Encode a signed constant in tst instructions, only affecting the flags.
427 void EncodeUint32InTstInstructions(uint32_t data);
428 // ... and decode from a pc pointing to the start of encoding instructions.
429 static uint32_t DecodeUint32FromTstInstructions(uword pc);
430 static bool IsInstructionForExceptionHandling(uword pc);
431
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700432 // Emit data (e.g. encoded instruction or immediate) to the
433 // instruction stream.
434 void Emit(int32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700435 void Bind(Label* label);
436
Ian Rogers2c8f6532011-09-02 17:16:34 -0700437 //
438 // Overridden common assembler high-level functionality
439 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700440
Ian Rogers2c8f6532011-09-02 17:16:34 -0700441 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700442 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
443 const std::vector<ManagedRegister>& callee_save_regs,
444 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700445
Ian Rogers2c8f6532011-09-02 17:16:34 -0700446 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700447 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
448 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700449
Ian Rogersdd7624d2014-03-14 17:43:00 -0700450 void IncreaseFrameSize(size_t adjust) OVERRIDE;
451 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700452
453 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700454 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
455 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
456 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700457
Ian Rogersdd7624d2014-03-14 17:43:00 -0700458 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700459
Ian Rogersdd7624d2014-03-14 17:43:00 -0700460 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
461 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700462
Ian Rogersdd7624d2014-03-14 17:43:00 -0700463 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
464 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700465
Ian Rogersdd7624d2014-03-14 17:43:00 -0700466 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700467
Ian Rogersdd7624d2014-03-14 17:43:00 -0700468 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
469 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700470
Ian Rogers2c8f6532011-09-02 17:16:34 -0700471 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700472 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700473
Ian Rogersdd7624d2014-03-14 17:43:00 -0700474 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700475
Ian Rogersdd7624d2014-03-14 17:43:00 -0700476 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700477
Ian Rogersdd7624d2014-03-14 17:43:00 -0700478 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700479
Ian Rogersdd7624d2014-03-14 17:43:00 -0700480 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700481
Ian Rogersdd7624d2014-03-14 17:43:00 -0700482 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700483
484 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700485 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700486
Ian Rogersdd7624d2014-03-14 17:43:00 -0700487 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
488 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700489
Ian Rogersdd7624d2014-03-14 17:43:00 -0700490 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
491 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700492
Ian Rogersdd7624d2014-03-14 17:43:00 -0700493 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700494
Ian Rogersdd7624d2014-03-14 17:43:00 -0700495 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700496
Ian Rogersdd7624d2014-03-14 17:43:00 -0700497 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
498 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700499
Ian Rogersdd7624d2014-03-14 17:43:00 -0700500 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
501 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700502
Ian Rogersdd7624d2014-03-14 17:43:00 -0700503 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
504 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700505
Ian Rogersdd7624d2014-03-14 17:43:00 -0700506 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
507 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700508
Ian Rogersdd7624d2014-03-14 17:43:00 -0700509 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
510 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700511
Ian Rogersdd7624d2014-03-14 17:43:00 -0700512 void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
Ian Rogerse5de95b2011-09-18 20:31:38 -0700513
jeffhao58136ca2012-05-24 13:40:11 -0700514 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700515 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700516
jeffhaocee4d0c2012-06-15 14:42:01 -0700517 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700518 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700519
Ian Rogers2c8f6532011-09-02 17:16:34 -0700520 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700521 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
522 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700523
524 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
525 // value is null and null_allowed. in_reg holds a possibly stale reference
526 // that can be used to avoid loading the SIRT entry to see if the value is
527 // NULL.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700528 void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset, ManagedRegister in_reg,
529 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700530
531 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
532 // value is null and null_allowed.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700533 void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset, ManagedRegister scratch,
534 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700535
536 // src holds a SIRT entry (Object**) load this into dst
Ian Rogersdd7624d2014-03-14 17:43:00 -0700537 void LoadReferenceFromSirt(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700538
539 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
540 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700541 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
542 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700543
544 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700545 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
546 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
547 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700548
Ian Rogers2c8f6532011-09-02 17:16:34 -0700549 // Generate code to check if Thread::Current()->exception_ is non-null
550 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700551 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700552
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700553 private:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700554 void EmitType01(Condition cond,
555 int type,
556 Opcode opcode,
557 int set_cc,
558 Register rn,
559 Register rd,
560 ShifterOperand so);
561
562 void EmitType5(Condition cond, int offset, bool link);
563
564 void EmitMemOp(Condition cond,
565 bool load,
566 bool byte,
567 Register rd,
568 Address ad);
569
570 void EmitMemOpAddressMode3(Condition cond,
571 int32_t mode,
572 Register rd,
573 Address ad);
574
575 void EmitMultiMemOp(Condition cond,
576 BlockAddressMode am,
577 bool load,
578 Register base,
579 RegList regs);
580
581 void EmitShiftImmediate(Condition cond,
582 Shift opcode,
583 Register rd,
584 Register rm,
585 ShifterOperand so);
586
587 void EmitShiftRegister(Condition cond,
588 Shift opcode,
589 Register rd,
590 Register rm,
591 ShifterOperand so);
592
593 void EmitMulOp(Condition cond,
594 int32_t opcode,
595 Register rd,
596 Register rn,
597 Register rm,
598 Register rs);
599
600 void EmitVFPsss(Condition cond,
601 int32_t opcode,
602 SRegister sd,
603 SRegister sn,
604 SRegister sm);
605
606 void EmitVFPddd(Condition cond,
607 int32_t opcode,
608 DRegister dd,
609 DRegister dn,
610 DRegister dm);
611
612 void EmitVFPsd(Condition cond,
613 int32_t opcode,
614 SRegister sd,
615 DRegister dm);
616
617 void EmitVFPds(Condition cond,
618 int32_t opcode,
619 DRegister dd,
620 SRegister sm);
621
622 void EmitBranch(Condition cond, Label* label, bool link);
623 static int32_t EncodeBranchOffset(int offset, int32_t inst);
624 static int DecodeBranchOffset(int32_t inst);
625 int32_t EncodeTstOffset(int offset, int32_t inst);
626 int DecodeTstOffset(int32_t inst);
627
628 // Returns whether or not the given register is used for passing parameters.
629 static int RegisterCompare(const Register* reg1, const Register* reg2) {
630 return *reg1 - *reg2;
631 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700632};
633
Ian Rogers2c8f6532011-09-02 17:16:34 -0700634// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700635class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700636 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700637 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
638 : scratch_(scratch), stack_adjust_(stack_adjust) {
639 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700640 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700641 private:
642 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700643 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700644};
645
Ian Rogers2c8f6532011-09-02 17:16:34 -0700646} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700647} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700648
Ian Rogers166db042013-07-26 12:05:57 -0700649#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_