blob: bb9207cadb28db240572e962caddd7705743d15f [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;
38 }
39
40 // Data-processing operands - Immediate
41 explicit ShifterOperand(uint32_t immediate) {
42 CHECK(immediate < (1 << kImmed8Bits));
43 type_ = 1;
44 encoding_ = immediate;
45 }
46
47 // Data-processing operands - Rotated immediate
48 ShifterOperand(uint32_t rotate, uint32_t immed8) {
49 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
50 type_ = 1;
51 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
52 }
53
54 // Data-processing operands - Register
55 explicit ShifterOperand(Register rm) {
56 type_ = 0;
57 encoding_ = static_cast<uint32_t>(rm);
58 }
59
60 // Data-processing operands - Logical shift/rotate by immediate
61 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
62 CHECK(shift_imm < (1 << kShiftImmBits));
63 type_ = 0;
64 encoding_ = shift_imm << kShiftImmShift |
65 static_cast<uint32_t>(shift) << kShiftShift |
66 static_cast<uint32_t>(rm);
67 }
68
69 // Data-processing operands - Logical shift/rotate by register
70 ShifterOperand(Register rm, Shift shift, Register rs) {
71 type_ = 0;
72 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
73 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
74 static_cast<uint32_t>(rm);
75 }
76
77 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
78 // Avoid the more expensive test for frequent small immediate values.
79 if (immediate < (1 << kImmed8Bits)) {
80 shifter_op->type_ = 1;
81 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
82 return true;
83 }
84 // Note that immediate must be unsigned for the test to work correctly.
85 for (int rot = 0; rot < 16; rot++) {
86 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
87 if (imm8 < (1 << kImmed8Bits)) {
88 shifter_op->type_ = 1;
89 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
90 return true;
91 }
92 }
93 return false;
94 }
95
96 private:
97 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
98
99 uint32_t type() const {
100 CHECK(is_valid());
101 return type_;
102 }
103
104 uint32_t encoding() const {
105 CHECK(is_valid());
106 return encoding_;
107 }
108
109 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
110 uint32_t encoding_;
111
Ian Rogers2c8f6532011-09-02 17:16:34 -0700112 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700113#ifdef SOURCE_ASSEMBLER_SUPPORT
114 friend class BinaryAssembler;
115#endif
116};
117
118
119enum LoadOperandType {
120 kLoadSignedByte,
121 kLoadUnsignedByte,
122 kLoadSignedHalfword,
123 kLoadUnsignedHalfword,
124 kLoadWord,
125 kLoadWordPair,
126 kLoadSWord,
127 kLoadDWord
128};
129
130
131enum StoreOperandType {
132 kStoreByte,
133 kStoreHalfword,
134 kStoreWord,
135 kStoreWordPair,
136 kStoreSWord,
137 kStoreDWord
138};
139
140
141// Load/store multiple addressing mode.
142enum BlockAddressMode {
143 // bit encoding P U W
144 DA = (0|0|0) << 21, // decrement after
145 IA = (0|4|0) << 21, // increment after
146 DB = (8|0|0) << 21, // decrement before
147 IB = (8|4|0) << 21, // increment before
148 DA_W = (0|0|1) << 21, // decrement after with writeback to base
149 IA_W = (0|4|1) << 21, // increment after with writeback to base
150 DB_W = (8|0|1) << 21, // decrement before with writeback to base
151 IB_W = (8|4|1) << 21 // increment before with writeback to base
152};
153
154
155class Address {
156 public:
157 // Memory operand addressing mode
158 enum Mode {
159 // bit encoding P U W
160 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
161 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
162 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
163 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
164 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
165 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
166 };
167
168 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
169 CHECK(IsAbsoluteUint(12, offset));
170 if (offset < 0) {
171 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
172 } else {
173 encoding_ = am | offset;
174 }
175 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
176 }
177
178 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
179 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
180
181 private:
182 uint32_t encoding() const { return encoding_; }
183
184 // Encoding for addressing mode 3.
185 uint32_t encoding3() const {
186 const uint32_t offset_mask = (1 << 12) - 1;
187 uint32_t offset = encoding_ & offset_mask;
Ian Rogersb033c752011-07-20 12:22:35 -0700188 CHECK_LT(offset, 256u);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700189 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
190 }
191
192 // Encoding for vfp load/store addressing.
193 uint32_t vencoding() const {
194 const uint32_t offset_mask = (1 << 12) - 1;
195 uint32_t offset = encoding_ & offset_mask;
196 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
Elliott Hughes06b37d92011-10-16 11:51:29 -0700197 CHECK_ALIGNED(offset, 2); // Multiple of 4.
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700198 int mode = encoding_ & ((8|4|1) << 21);
199 CHECK((mode == Offset) || (mode == NegOffset));
200 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
201 if (mode == Offset) {
202 vencoding |= 1 << 23;
203 }
204 return vencoding;
205 }
206
207 uint32_t encoding_;
208
Ian Rogers2c8f6532011-09-02 17:16:34 -0700209 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700210};
211
212
Ian Rogers2c8f6532011-09-02 17:16:34 -0700213class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700214 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700215 ArmAssembler() {}
216 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700217
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700218 // Data-processing instructions.
219 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
220
221 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
222
223 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
224 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
225
226 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
227 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
228
229 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
230
231 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
232
233 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
234
235 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
236
237 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
238
239 void tst(Register rn, ShifterOperand so, Condition cond = AL);
240
241 void teq(Register rn, ShifterOperand so, Condition cond = AL);
242
243 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
244
245 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
246
247 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
248 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
249
250 void mov(Register rd, ShifterOperand so, Condition cond = AL);
251 void movs(Register rd, ShifterOperand so, Condition cond = AL);
252
253 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
254
255 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
256 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
257
258 // Miscellaneous data-processing instructions.
259 void clz(Register rd, Register rm, Condition cond = AL);
260 void movw(Register rd, uint16_t imm16, Condition cond = AL);
261 void movt(Register rd, uint16_t imm16, Condition cond = AL);
262
263 // Multiply instructions.
264 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
265 void mla(Register rd, Register rn, Register rm, Register ra,
266 Condition cond = AL);
267 void mls(Register rd, Register rn, Register rm, Register ra,
268 Condition cond = AL);
269 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
270 Condition cond = AL);
271
272 // Load/store instructions.
273 void ldr(Register rd, Address ad, Condition cond = AL);
274 void str(Register rd, Address ad, Condition cond = AL);
275
276 void ldrb(Register rd, Address ad, Condition cond = AL);
277 void strb(Register rd, Address ad, Condition cond = AL);
278
279 void ldrh(Register rd, Address ad, Condition cond = AL);
280 void strh(Register rd, Address ad, Condition cond = AL);
281
282 void ldrsb(Register rd, Address ad, Condition cond = AL);
283 void ldrsh(Register rd, Address ad, Condition cond = AL);
284
285 void ldrd(Register rd, Address ad, Condition cond = AL);
286 void strd(Register rd, Address ad, Condition cond = AL);
287
288 void ldm(BlockAddressMode am, Register base,
289 RegList regs, Condition cond = AL);
290 void stm(BlockAddressMode am, Register base,
291 RegList regs, Condition cond = AL);
292
293 void ldrex(Register rd, Register rn, Condition cond = AL);
294 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
295
296 // Miscellaneous instructions.
297 void clrex();
298 void nop(Condition cond = AL);
299
300 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
301 void bkpt(uint16_t imm16);
302 void svc(uint32_t imm24);
303
304 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
305 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
306 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
307 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
308 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
309 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
310 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
311 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
312 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
313
314 // Returns false if the immediate cannot be encoded.
315 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
316 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
317
318 void vldrs(SRegister sd, Address ad, Condition cond = AL);
319 void vstrs(SRegister sd, Address ad, Condition cond = AL);
320 void vldrd(DRegister dd, Address ad, Condition cond = AL);
321 void vstrd(DRegister dd, Address ad, Condition cond = AL);
322
323 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
324 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
325 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
326 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
327 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
328 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
329 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
330 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
331 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
332 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
333 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
334 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
335
336 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
337 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
338 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
339 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
340 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
341 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
342
343 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
344 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
345 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
346 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
347 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
348 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
349 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
350 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
351 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
352 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
353
354 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
355 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
356 void vcmpsz(SRegister sd, Condition cond = AL);
357 void vcmpdz(DRegister dd, Condition cond = AL);
358 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
359
360 // Branch instructions.
361 void b(Label* label, Condition cond = AL);
362 void bl(Label* label, Condition cond = AL);
363 void blx(Register rm, Condition cond = AL);
Ian Rogersae675992011-10-09 17:10:22 -0700364 void bx(Register rm, Condition cond = AL);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700365
366 // Macros.
367 // Add signed constant value to rd. May clobber IP.
368 void AddConstant(Register rd, int32_t value, Condition cond = AL);
369 void AddConstant(Register rd, Register rn, int32_t value,
370 Condition cond = AL);
371 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
372 Condition cond = AL);
373 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
374 Condition cond = AL);
375
376 // Load and Store. May clobber IP.
377 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
378 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
379 void LoadDImmediate(DRegister dd, double value,
380 Register scratch, Condition cond = AL);
381 void MarkExceptionHandler(Label* label);
382 void LoadFromOffset(LoadOperandType type,
383 Register reg,
384 Register base,
385 int32_t offset,
386 Condition cond = AL);
387 void StoreToOffset(StoreOperandType type,
388 Register reg,
389 Register base,
390 int32_t offset,
391 Condition cond = AL);
392 void LoadSFromOffset(SRegister reg,
393 Register base,
394 int32_t offset,
395 Condition cond = AL);
396 void StoreSToOffset(SRegister reg,
397 Register base,
398 int32_t offset,
399 Condition cond = AL);
400 void LoadDFromOffset(DRegister reg,
401 Register base,
402 int32_t offset,
403 Condition cond = AL);
404 void StoreDToOffset(DRegister reg,
405 Register base,
406 int32_t offset,
407 Condition cond = AL);
408
409 void Push(Register rd, Condition cond = AL);
410 void Pop(Register rd, Condition cond = AL);
411
412 void PushList(RegList regs, Condition cond = AL);
413 void PopList(RegList regs, Condition cond = AL);
414
415 void Mov(Register rd, Register rm, Condition cond = AL);
416
417 // Convenience shift instructions. Use mov instruction with shifter operand
418 // for variants setting the status flags or using a register shift count.
419 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
420 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
421 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
422 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
423 void Rrx(Register rd, Register rm, Condition cond = AL);
424
425 // Encode a signed constant in tst instructions, only affecting the flags.
426 void EncodeUint32InTstInstructions(uint32_t data);
427 // ... and decode from a pc pointing to the start of encoding instructions.
428 static uint32_t DecodeUint32FromTstInstructions(uword pc);
429 static bool IsInstructionForExceptionHandling(uword pc);
430
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700431 // Emit data (e.g. encoded instruction or immediate) to the
432 // instruction stream.
433 void Emit(int32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700434 void Bind(Label* label);
435
Ian Rogers2c8f6532011-09-02 17:16:34 -0700436 //
437 // Overridden common assembler high-level functionality
438 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700439
Ian Rogers2c8f6532011-09-02 17:16:34 -0700440 // Emit code that will create an activation on the stack
441 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800442 const std::vector<ManagedRegister>& callee_save_regs,
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700443 const ManagedRegisterEntrySpills& entry_spills);
Ian Rogersb033c752011-07-20 12:22:35 -0700444
Ian Rogers2c8f6532011-09-02 17:16:34 -0700445 // Emit code that will remove an activation from the stack
446 virtual void RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -0700447 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700448
449 virtual void IncreaseFrameSize(size_t adjust);
450 virtual void DecreaseFrameSize(size_t adjust);
451
452 // Store routines
453 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
454 virtual void StoreRef(FrameOffset dest, ManagedRegister src);
455 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700456
457 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
458 ManagedRegister scratch);
459
460 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
461 ManagedRegister scratch);
462
463 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
464 FrameOffset fr_offs,
465 ManagedRegister scratch);
466
467 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
468
Ian Rogersbdb03912011-09-14 00:55:44 -0700469 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
470 FrameOffset in_off, ManagedRegister scratch);
471
Ian Rogers2c8f6532011-09-02 17:16:34 -0700472 // Load routines
473 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
474
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700475 virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size);
476
Ian Rogers2c8f6532011-09-02 17:16:34 -0700477 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
478
479 virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
480 MemberOffset offs);
481
482 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
483 Offset offs);
484
485 virtual void LoadRawPtrFromThread(ManagedRegister dest,
486 ThreadOffset offs);
487
488 // Copying routines
Ian Rogersb5d09b22012-03-06 22:14:17 -0800489 virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700490
491 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
492 ManagedRegister scratch);
493
494 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
495 ManagedRegister scratch);
496
497 virtual void CopyRef(FrameOffset dest, FrameOffset src,
498 ManagedRegister scratch);
499
Elliott Hughesa09aea22012-01-06 18:58:27 -0800500 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700501
Ian Rogersdc51b792011-09-22 20:41:37 -0700502 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
503 ManagedRegister scratch, size_t size);
504
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700505 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
506 ManagedRegister scratch, size_t size);
507
Ian Rogersdc51b792011-09-22 20:41:37 -0700508 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
509 ManagedRegister scratch, size_t size);
510
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700511 virtual void Copy(ManagedRegister dest, Offset dest_offset,
512 ManagedRegister src, Offset src_offset,
513 ManagedRegister scratch, size_t size);
514
515 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
516 ManagedRegister scratch, size_t size);
Ian Rogersdc51b792011-09-22 20:41:37 -0700517
Ian Rogerse5de95b2011-09-18 20:31:38 -0700518 virtual void MemoryBarrier(ManagedRegister scratch);
519
jeffhao58136ca2012-05-24 13:40:11 -0700520 // Sign extension
521 virtual void SignExtend(ManagedRegister mreg, size_t size);
522
jeffhaocee4d0c2012-06-15 14:42:01 -0700523 // Zero extension
524 virtual void ZeroExtend(ManagedRegister mreg, size_t size);
525
Ian Rogers2c8f6532011-09-02 17:16:34 -0700526 // Exploit fast access in managed code to Thread::Current()
527 virtual void GetCurrentThread(ManagedRegister tr);
528 virtual void GetCurrentThread(FrameOffset dest_offset,
529 ManagedRegister scratch);
530
531 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
532 // value is null and null_allowed. in_reg holds a possibly stale reference
533 // that can be used to avoid loading the SIRT entry to see if the value is
534 // NULL.
535 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
536 ManagedRegister in_reg, bool null_allowed);
537
538 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
539 // value is null and null_allowed.
540 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
541 ManagedRegister scratch, bool null_allowed);
542
543 // src holds a SIRT entry (Object**) load this into dst
544 virtual void LoadReferenceFromSirt(ManagedRegister dst,
545 ManagedRegister src);
546
547 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
548 // know that src may not be null.
549 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
550 virtual void VerifyObject(FrameOffset src, bool could_be_null);
551
552 // Call to address held at [base+offset]
553 virtual void Call(ManagedRegister base, Offset offset,
554 ManagedRegister scratch);
555 virtual void Call(FrameOffset base, Offset offset,
556 ManagedRegister scratch);
Ian Rogersbdb03912011-09-14 00:55:44 -0700557 virtual void Call(ThreadOffset offset, ManagedRegister scratch);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700558
Ian Rogers2c8f6532011-09-02 17:16:34 -0700559 // Generate code to check if Thread::Current()->exception_ is non-null
560 // and branch to a ExceptionSlowPath if it is.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700561 virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust);
Ian Rogersb033c752011-07-20 12:22:35 -0700562
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700563 private:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700564 void EmitType01(Condition cond,
565 int type,
566 Opcode opcode,
567 int set_cc,
568 Register rn,
569 Register rd,
570 ShifterOperand so);
571
572 void EmitType5(Condition cond, int offset, bool link);
573
574 void EmitMemOp(Condition cond,
575 bool load,
576 bool byte,
577 Register rd,
578 Address ad);
579
580 void EmitMemOpAddressMode3(Condition cond,
581 int32_t mode,
582 Register rd,
583 Address ad);
584
585 void EmitMultiMemOp(Condition cond,
586 BlockAddressMode am,
587 bool load,
588 Register base,
589 RegList regs);
590
591 void EmitShiftImmediate(Condition cond,
592 Shift opcode,
593 Register rd,
594 Register rm,
595 ShifterOperand so);
596
597 void EmitShiftRegister(Condition cond,
598 Shift opcode,
599 Register rd,
600 Register rm,
601 ShifterOperand so);
602
603 void EmitMulOp(Condition cond,
604 int32_t opcode,
605 Register rd,
606 Register rn,
607 Register rm,
608 Register rs);
609
610 void EmitVFPsss(Condition cond,
611 int32_t opcode,
612 SRegister sd,
613 SRegister sn,
614 SRegister sm);
615
616 void EmitVFPddd(Condition cond,
617 int32_t opcode,
618 DRegister dd,
619 DRegister dn,
620 DRegister dm);
621
622 void EmitVFPsd(Condition cond,
623 int32_t opcode,
624 SRegister sd,
625 DRegister dm);
626
627 void EmitVFPds(Condition cond,
628 int32_t opcode,
629 DRegister dd,
630 SRegister sm);
631
632 void EmitBranch(Condition cond, Label* label, bool link);
633 static int32_t EncodeBranchOffset(int offset, int32_t inst);
634 static int DecodeBranchOffset(int32_t inst);
635 int32_t EncodeTstOffset(int offset, int32_t inst);
636 int DecodeTstOffset(int32_t inst);
637
638 // Returns whether or not the given register is used for passing parameters.
639 static int RegisterCompare(const Register* reg1, const Register* reg2) {
640 return *reg1 - *reg2;
641 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700642};
643
Ian Rogers2c8f6532011-09-02 17:16:34 -0700644// Slowpath entered when Thread::Current()->_exception is non-null
645class ArmExceptionSlowPath : public SlowPath {
646 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700647 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
648 : scratch_(scratch), stack_adjust_(stack_adjust) {
649 }
Ian Rogers2c8f6532011-09-02 17:16:34 -0700650 virtual void Emit(Assembler *sp_asm);
Ian Rogers67375ac2011-09-14 00:55:44 -0700651 private:
652 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700653 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654};
655
Ian Rogers2c8f6532011-09-02 17:16:34 -0700656} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700657} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700658
Ian Rogers166db042013-07-26 12:05:57 -0700659#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_