blob: 1a722f740ddd16ab3e8ed894b0c650ed6e90fb3b [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);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700418 void Bind(Label* label);
419
Ian Rogers2c8f6532011-09-02 17:16:34 -0700420 //
421 // Overridden common assembler high-level functionality
422 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700423
Ian Rogers2c8f6532011-09-02 17:16:34 -0700424 // Emit code that will create an activation on the stack
425 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersbdb03912011-09-14 00:55:44 -0700426 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogersb033c752011-07-20 12:22:35 -0700427
Ian Rogers2c8f6532011-09-02 17:16:34 -0700428 // Emit code that will remove an activation from the stack
429 virtual void RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -0700430 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700431
432 virtual void IncreaseFrameSize(size_t adjust);
433 virtual void DecreaseFrameSize(size_t adjust);
434
435 // Store routines
436 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
437 virtual void StoreRef(FrameOffset dest, ManagedRegister src);
438 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700439
440 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
441 ManagedRegister scratch);
442
443 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
444 ManagedRegister scratch);
445
446 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
447 FrameOffset fr_offs,
448 ManagedRegister scratch);
449
450 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
451
Ian Rogersbdb03912011-09-14 00:55:44 -0700452 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
453 FrameOffset in_off, ManagedRegister scratch);
454
Ian Rogers2c8f6532011-09-02 17:16:34 -0700455 // Load routines
456 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
457
458 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
459
460 virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
461 MemberOffset offs);
462
463 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
464 Offset offs);
465
466 virtual void LoadRawPtrFromThread(ManagedRegister dest,
467 ThreadOffset offs);
468
469 // Copying routines
470 virtual void Move(ManagedRegister dest, ManagedRegister src);
471
472 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
473 ManagedRegister scratch);
474
475 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
476 ManagedRegister scratch);
477
478 virtual void CopyRef(FrameOffset dest, FrameOffset src,
479 ManagedRegister scratch);
480
481 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
482 unsigned int size);
483
484 // Exploit fast access in managed code to Thread::Current()
485 virtual void GetCurrentThread(ManagedRegister tr);
486 virtual void GetCurrentThread(FrameOffset dest_offset,
487 ManagedRegister scratch);
488
489 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
490 // value is null and null_allowed. in_reg holds a possibly stale reference
491 // that can be used to avoid loading the SIRT entry to see if the value is
492 // NULL.
493 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
494 ManagedRegister in_reg, bool null_allowed);
495
496 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
497 // value is null and null_allowed.
498 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
499 ManagedRegister scratch, bool null_allowed);
500
501 // src holds a SIRT entry (Object**) load this into dst
502 virtual void LoadReferenceFromSirt(ManagedRegister dst,
503 ManagedRegister src);
504
505 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
506 // know that src may not be null.
507 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
508 virtual void VerifyObject(FrameOffset src, bool could_be_null);
509
510 // Call to address held at [base+offset]
511 virtual void Call(ManagedRegister base, Offset offset,
512 ManagedRegister scratch);
513 virtual void Call(FrameOffset base, Offset offset,
514 ManagedRegister scratch);
Ian Rogersbdb03912011-09-14 00:55:44 -0700515 virtual void Call(ThreadOffset offset, ManagedRegister scratch);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700516
517 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
518 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
519 // at the next instruction.
520 virtual void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
521 FrameOffset return_save_location,
522 size_t return_size);
523
524 // Generate code to check if Thread::Current()->exception_ is non-null
525 // and branch to a ExceptionSlowPath if it is.
526 virtual void ExceptionPoll(ManagedRegister scratch);
Ian Rogersb033c752011-07-20 12:22:35 -0700527
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700528 private:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700529 void EmitType01(Condition cond,
530 int type,
531 Opcode opcode,
532 int set_cc,
533 Register rn,
534 Register rd,
535 ShifterOperand so);
536
537 void EmitType5(Condition cond, int offset, bool link);
538
539 void EmitMemOp(Condition cond,
540 bool load,
541 bool byte,
542 Register rd,
543 Address ad);
544
545 void EmitMemOpAddressMode3(Condition cond,
546 int32_t mode,
547 Register rd,
548 Address ad);
549
550 void EmitMultiMemOp(Condition cond,
551 BlockAddressMode am,
552 bool load,
553 Register base,
554 RegList regs);
555
556 void EmitShiftImmediate(Condition cond,
557 Shift opcode,
558 Register rd,
559 Register rm,
560 ShifterOperand so);
561
562 void EmitShiftRegister(Condition cond,
563 Shift opcode,
564 Register rd,
565 Register rm,
566 ShifterOperand so);
567
568 void EmitMulOp(Condition cond,
569 int32_t opcode,
570 Register rd,
571 Register rn,
572 Register rm,
573 Register rs);
574
575 void EmitVFPsss(Condition cond,
576 int32_t opcode,
577 SRegister sd,
578 SRegister sn,
579 SRegister sm);
580
581 void EmitVFPddd(Condition cond,
582 int32_t opcode,
583 DRegister dd,
584 DRegister dn,
585 DRegister dm);
586
587 void EmitVFPsd(Condition cond,
588 int32_t opcode,
589 SRegister sd,
590 DRegister dm);
591
592 void EmitVFPds(Condition cond,
593 int32_t opcode,
594 DRegister dd,
595 SRegister sm);
596
597 void EmitBranch(Condition cond, Label* label, bool link);
598 static int32_t EncodeBranchOffset(int offset, int32_t inst);
599 static int DecodeBranchOffset(int32_t inst);
600 int32_t EncodeTstOffset(int offset, int32_t inst);
601 int DecodeTstOffset(int32_t inst);
602
603 // Returns whether or not the given register is used for passing parameters.
604 static int RegisterCompare(const Register* reg1, const Register* reg2) {
605 return *reg1 - *reg2;
606 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700607};
608
Ian Rogers2c8f6532011-09-02 17:16:34 -0700609// Slowpath entered when Thread::Current()->_exception is non-null
610class ArmExceptionSlowPath : public SlowPath {
611 public:
Ian Rogers67375ac2011-09-14 00:55:44 -0700612 ArmExceptionSlowPath(ArmManagedRegister scratch) : scratch_(scratch) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -0700613 virtual void Emit(Assembler *sp_asm);
Ian Rogers67375ac2011-09-14 00:55:44 -0700614 private:
615 const ArmManagedRegister scratch_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700616};
617
618// Slowpath entered when Thread::Current()->_suspend_count is non-zero
619class ArmSuspendCountSlowPath : public SlowPath {
620 public:
621 ArmSuspendCountSlowPath(ArmManagedRegister return_reg,
622 FrameOffset return_save_location,
623 size_t return_size) :
624 return_register_(return_reg), return_save_location_(return_save_location),
625 return_size_(return_size) {}
626 virtual void Emit(Assembler *sp_asm);
627
628 private:
629 // Remember how to save the return value
630 const ArmManagedRegister return_register_;
631 const FrameOffset return_save_location_;
632 const size_t return_size_;
633};
634
635} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700636} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700637
638#endif // ART_SRC_ASSEMBLER_ARM_H_