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