blob: cf031c7e58b13410320ed32db50db05435585a88 [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.
182 CHECK(IsAligned(offset, 2)); // Multiple of 4.
183 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);
349
350 // Macros.
351 // Add signed constant value to rd. May clobber IP.
352 void AddConstant(Register rd, int32_t value, Condition cond = AL);
353 void AddConstant(Register rd, Register rn, int32_t value,
354 Condition cond = AL);
355 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
356 Condition cond = AL);
357 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
358 Condition cond = AL);
359
360 // Load and Store. May clobber IP.
361 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
362 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
363 void LoadDImmediate(DRegister dd, double value,
364 Register scratch, Condition cond = AL);
365 void MarkExceptionHandler(Label* label);
366 void LoadFromOffset(LoadOperandType type,
367 Register reg,
368 Register base,
369 int32_t offset,
370 Condition cond = AL);
371 void StoreToOffset(StoreOperandType type,
372 Register reg,
373 Register base,
374 int32_t offset,
375 Condition cond = AL);
376 void LoadSFromOffset(SRegister reg,
377 Register base,
378 int32_t offset,
379 Condition cond = AL);
380 void StoreSToOffset(SRegister reg,
381 Register base,
382 int32_t offset,
383 Condition cond = AL);
384 void LoadDFromOffset(DRegister reg,
385 Register base,
386 int32_t offset,
387 Condition cond = AL);
388 void StoreDToOffset(DRegister reg,
389 Register base,
390 int32_t offset,
391 Condition cond = AL);
392
393 void Push(Register rd, Condition cond = AL);
394 void Pop(Register rd, Condition cond = AL);
395
396 void PushList(RegList regs, Condition cond = AL);
397 void PopList(RegList regs, Condition cond = AL);
398
399 void Mov(Register rd, Register rm, Condition cond = AL);
400
401 // Convenience shift instructions. Use mov instruction with shifter operand
402 // for variants setting the status flags or using a register shift count.
403 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
404 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
405 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
406 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
407 void Rrx(Register rd, Register rm, Condition cond = AL);
408
409 // Encode a signed constant in tst instructions, only affecting the flags.
410 void EncodeUint32InTstInstructions(uint32_t data);
411 // ... and decode from a pc pointing to the start of encoding instructions.
412 static uint32_t DecodeUint32FromTstInstructions(uword pc);
413 static bool IsInstructionForExceptionHandling(uword pc);
414
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700415 // Emit data (e.g. encoded instruction or immediate) to the
416 // instruction stream.
417 void Emit(int32_t value);
418
419 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,
427 const std::vector<ManagedRegister>& spill_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,
431 const std::vector<ManagedRegister>& spill_regs);
432
433 // Fill list of registers from spill area
434 virtual void FillFromSpillArea(const std::vector<ManagedRegister>& spill_regs,
435 size_t displacement);
436
437 virtual void IncreaseFrameSize(size_t adjust);
438 virtual void DecreaseFrameSize(size_t adjust);
439
440 // Store routines
441 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
442 virtual void StoreRef(FrameOffset dest, ManagedRegister src);
443 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
444 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
445 FrameOffset in_off, ManagedRegister scratch);
446
447 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
448 ManagedRegister scratch);
449
450 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
451 ManagedRegister scratch);
452
453 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
454 FrameOffset fr_offs,
455 ManagedRegister scratch);
456
457 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
458
459 // Load routines
460 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
461
462 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
463
464 virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
465 MemberOffset offs);
466
467 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
468 Offset offs);
469
470 virtual void LoadRawPtrFromThread(ManagedRegister dest,
471 ThreadOffset offs);
472
473 // Copying routines
474 virtual void Move(ManagedRegister dest, ManagedRegister src);
475
476 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
477 ManagedRegister scratch);
478
479 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
480 ManagedRegister scratch);
481
482 virtual void CopyRef(FrameOffset dest, FrameOffset src,
483 ManagedRegister scratch);
484
485 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
486 unsigned int size);
487
488 // Exploit fast access in managed code to Thread::Current()
489 virtual void GetCurrentThread(ManagedRegister tr);
490 virtual void GetCurrentThread(FrameOffset dest_offset,
491 ManagedRegister scratch);
492
493 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
494 // value is null and null_allowed. in_reg holds a possibly stale reference
495 // that can be used to avoid loading the SIRT entry to see if the value is
496 // NULL.
497 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
498 ManagedRegister in_reg, bool null_allowed);
499
500 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
501 // value is null and null_allowed.
502 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
503 ManagedRegister scratch, bool null_allowed);
504
505 // src holds a SIRT entry (Object**) load this into dst
506 virtual void LoadReferenceFromSirt(ManagedRegister dst,
507 ManagedRegister src);
508
509 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
510 // know that src may not be null.
511 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
512 virtual void VerifyObject(FrameOffset src, bool could_be_null);
513
514 // Call to address held at [base+offset]
515 virtual void Call(ManagedRegister base, Offset offset,
516 ManagedRegister scratch);
517 virtual void Call(FrameOffset base, Offset offset,
518 ManagedRegister scratch);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700519
520 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
521 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
522 // at the next instruction.
523 virtual void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
524 FrameOffset return_save_location,
525 size_t return_size);
526
527 // Generate code to check if Thread::Current()->exception_ is non-null
528 // and branch to a ExceptionSlowPath if it is.
529 virtual void ExceptionPoll(ManagedRegister scratch);
Ian Rogersb033c752011-07-20 12:22:35 -0700530
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700531 private:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700532 void EmitType01(Condition cond,
533 int type,
534 Opcode opcode,
535 int set_cc,
536 Register rn,
537 Register rd,
538 ShifterOperand so);
539
540 void EmitType5(Condition cond, int offset, bool link);
541
542 void EmitMemOp(Condition cond,
543 bool load,
544 bool byte,
545 Register rd,
546 Address ad);
547
548 void EmitMemOpAddressMode3(Condition cond,
549 int32_t mode,
550 Register rd,
551 Address ad);
552
553 void EmitMultiMemOp(Condition cond,
554 BlockAddressMode am,
555 bool load,
556 Register base,
557 RegList regs);
558
559 void EmitShiftImmediate(Condition cond,
560 Shift opcode,
561 Register rd,
562 Register rm,
563 ShifterOperand so);
564
565 void EmitShiftRegister(Condition cond,
566 Shift opcode,
567 Register rd,
568 Register rm,
569 ShifterOperand so);
570
571 void EmitMulOp(Condition cond,
572 int32_t opcode,
573 Register rd,
574 Register rn,
575 Register rm,
576 Register rs);
577
578 void EmitVFPsss(Condition cond,
579 int32_t opcode,
580 SRegister sd,
581 SRegister sn,
582 SRegister sm);
583
584 void EmitVFPddd(Condition cond,
585 int32_t opcode,
586 DRegister dd,
587 DRegister dn,
588 DRegister dm);
589
590 void EmitVFPsd(Condition cond,
591 int32_t opcode,
592 SRegister sd,
593 DRegister dm);
594
595 void EmitVFPds(Condition cond,
596 int32_t opcode,
597 DRegister dd,
598 SRegister sm);
599
600 void EmitBranch(Condition cond, Label* label, bool link);
601 static int32_t EncodeBranchOffset(int offset, int32_t inst);
602 static int DecodeBranchOffset(int32_t inst);
603 int32_t EncodeTstOffset(int offset, int32_t inst);
604 int DecodeTstOffset(int32_t inst);
605
606 // Returns whether or not the given register is used for passing parameters.
607 static int RegisterCompare(const Register* reg1, const Register* reg2) {
608 return *reg1 - *reg2;
609 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700610};
611
Ian Rogers2c8f6532011-09-02 17:16:34 -0700612// Slowpath entered when Thread::Current()->_exception is non-null
613class ArmExceptionSlowPath : public SlowPath {
614 public:
615 ArmExceptionSlowPath() {}
616 virtual void Emit(Assembler *sp_asm);
617};
618
619// Slowpath entered when Thread::Current()->_suspend_count is non-zero
620class ArmSuspendCountSlowPath : public SlowPath {
621 public:
622 ArmSuspendCountSlowPath(ArmManagedRegister return_reg,
623 FrameOffset return_save_location,
624 size_t return_size) :
625 return_register_(return_reg), return_save_location_(return_save_location),
626 return_size_(return_size) {}
627 virtual void Emit(Assembler *sp_asm);
628
629 private:
630 // Remember how to save the return value
631 const ArmManagedRegister return_register_;
632 const FrameOffset return_save_location_;
633 const size_t return_size_;
634};
635
636} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700637} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700638
639#endif // ART_SRC_ASSEMBLER_ARM_H_