blob: 04671db26091d1df6ea0ed31084fdf4255b8a604 [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
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006#include "constants.h"
7#include "managed_register.h"
8#include "logging.h"
9#include "offsets.h"
10#include "utils.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070011
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070012namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070013
Carl Shapiroa2e18e12011-06-21 18:57:55 -070014// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
15class ShifterOperand {
16 public:
17 // Data-processing operands - Uninitialized
18 ShifterOperand() {
19 type_ = -1;
20 }
21
22 // Data-processing operands - Immediate
23 explicit ShifterOperand(uint32_t immediate) {
24 CHECK(immediate < (1 << kImmed8Bits));
25 type_ = 1;
26 encoding_ = immediate;
27 }
28
29 // Data-processing operands - Rotated immediate
30 ShifterOperand(uint32_t rotate, uint32_t immed8) {
31 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
32 type_ = 1;
33 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
34 }
35
36 // Data-processing operands - Register
37 explicit ShifterOperand(Register rm) {
38 type_ = 0;
39 encoding_ = static_cast<uint32_t>(rm);
40 }
41
42 // Data-processing operands - Logical shift/rotate by immediate
43 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
44 CHECK(shift_imm < (1 << kShiftImmBits));
45 type_ = 0;
46 encoding_ = shift_imm << kShiftImmShift |
47 static_cast<uint32_t>(shift) << kShiftShift |
48 static_cast<uint32_t>(rm);
49 }
50
51 // Data-processing operands - Logical shift/rotate by register
52 ShifterOperand(Register rm, Shift shift, Register rs) {
53 type_ = 0;
54 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
55 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
56 static_cast<uint32_t>(rm);
57 }
58
59 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
60 // Avoid the more expensive test for frequent small immediate values.
61 if (immediate < (1 << kImmed8Bits)) {
62 shifter_op->type_ = 1;
63 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
64 return true;
65 }
66 // Note that immediate must be unsigned for the test to work correctly.
67 for (int rot = 0; rot < 16; rot++) {
68 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
69 if (imm8 < (1 << kImmed8Bits)) {
70 shifter_op->type_ = 1;
71 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
72 return true;
73 }
74 }
75 return false;
76 }
77
78 private:
79 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
80
81 uint32_t type() const {
82 CHECK(is_valid());
83 return type_;
84 }
85
86 uint32_t encoding() const {
87 CHECK(is_valid());
88 return encoding_;
89 }
90
91 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
92 uint32_t encoding_;
93
94 friend class Assembler;
95#ifdef SOURCE_ASSEMBLER_SUPPORT
96 friend class BinaryAssembler;
97#endif
98};
99
100
101enum LoadOperandType {
102 kLoadSignedByte,
103 kLoadUnsignedByte,
104 kLoadSignedHalfword,
105 kLoadUnsignedHalfword,
106 kLoadWord,
107 kLoadWordPair,
108 kLoadSWord,
109 kLoadDWord
110};
111
112
113enum StoreOperandType {
114 kStoreByte,
115 kStoreHalfword,
116 kStoreWord,
117 kStoreWordPair,
118 kStoreSWord,
119 kStoreDWord
120};
121
122
123// Load/store multiple addressing mode.
124enum BlockAddressMode {
125 // bit encoding P U W
126 DA = (0|0|0) << 21, // decrement after
127 IA = (0|4|0) << 21, // increment after
128 DB = (8|0|0) << 21, // decrement before
129 IB = (8|4|0) << 21, // increment before
130 DA_W = (0|0|1) << 21, // decrement after with writeback to base
131 IA_W = (0|4|1) << 21, // increment after with writeback to base
132 DB_W = (8|0|1) << 21, // decrement before with writeback to base
133 IB_W = (8|4|1) << 21 // increment before with writeback to base
134};
135
136
137class Address {
138 public:
139 // Memory operand addressing mode
140 enum Mode {
141 // bit encoding P U W
142 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
143 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
144 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
145 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
146 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
147 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
148 };
149
150 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
151 CHECK(IsAbsoluteUint(12, offset));
152 if (offset < 0) {
153 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
154 } else {
155 encoding_ = am | offset;
156 }
157 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
158 }
159
160 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
161 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
162
163 private:
164 uint32_t encoding() const { return encoding_; }
165
166 // Encoding for addressing mode 3.
167 uint32_t encoding3() const {
168 const uint32_t offset_mask = (1 << 12) - 1;
169 uint32_t offset = encoding_ & offset_mask;
Ian Rogersb033c752011-07-20 12:22:35 -0700170 CHECK_LT(offset, 256u);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700171 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
172 }
173
174 // Encoding for vfp load/store addressing.
175 uint32_t vencoding() const {
176 const uint32_t offset_mask = (1 << 12) - 1;
177 uint32_t offset = encoding_ & offset_mask;
178 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
179 CHECK(IsAligned(offset, 2)); // Multiple of 4.
180 int mode = encoding_ & ((8|4|1) << 21);
181 CHECK((mode == Offset) || (mode == NegOffset));
182 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
183 if (mode == Offset) {
184 vencoding |= 1 << 23;
185 }
186 return vencoding;
187 }
188
189 uint32_t encoding_;
190
191 friend class Assembler;
192};
193
194
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700195class Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700196 public:
197 Assembler() : buffer_() {}
198
199 // Data-processing instructions.
200 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
201
202 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
203
204 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
205 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
206
207 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
208 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
209
210 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
211
212 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
213
214 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
215
216 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
217
218 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
219
220 void tst(Register rn, ShifterOperand so, Condition cond = AL);
221
222 void teq(Register rn, ShifterOperand so, Condition cond = AL);
223
224 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
225
226 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
227
228 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
229 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
230
231 void mov(Register rd, ShifterOperand so, Condition cond = AL);
232 void movs(Register rd, ShifterOperand so, Condition cond = AL);
233
234 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
235
236 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
237 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
238
239 // Miscellaneous data-processing instructions.
240 void clz(Register rd, Register rm, Condition cond = AL);
241 void movw(Register rd, uint16_t imm16, Condition cond = AL);
242 void movt(Register rd, uint16_t imm16, Condition cond = AL);
243
244 // Multiply instructions.
245 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
246 void mla(Register rd, Register rn, Register rm, Register ra,
247 Condition cond = AL);
248 void mls(Register rd, Register rn, Register rm, Register ra,
249 Condition cond = AL);
250 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
251 Condition cond = AL);
252
253 // Load/store instructions.
254 void ldr(Register rd, Address ad, Condition cond = AL);
255 void str(Register rd, Address ad, Condition cond = AL);
256
257 void ldrb(Register rd, Address ad, Condition cond = AL);
258 void strb(Register rd, Address ad, Condition cond = AL);
259
260 void ldrh(Register rd, Address ad, Condition cond = AL);
261 void strh(Register rd, Address ad, Condition cond = AL);
262
263 void ldrsb(Register rd, Address ad, Condition cond = AL);
264 void ldrsh(Register rd, Address ad, Condition cond = AL);
265
266 void ldrd(Register rd, Address ad, Condition cond = AL);
267 void strd(Register rd, Address ad, Condition cond = AL);
268
269 void ldm(BlockAddressMode am, Register base,
270 RegList regs, Condition cond = AL);
271 void stm(BlockAddressMode am, Register base,
272 RegList regs, Condition cond = AL);
273
274 void ldrex(Register rd, Register rn, Condition cond = AL);
275 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
276
277 // Miscellaneous instructions.
278 void clrex();
279 void nop(Condition cond = AL);
280
281 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
282 void bkpt(uint16_t imm16);
283 void svc(uint32_t imm24);
284
285 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
286 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
287 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
288 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
289 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
290 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
291 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
292 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
293 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
294
295 // Returns false if the immediate cannot be encoded.
296 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
297 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
298
299 void vldrs(SRegister sd, Address ad, Condition cond = AL);
300 void vstrs(SRegister sd, Address ad, Condition cond = AL);
301 void vldrd(DRegister dd, Address ad, Condition cond = AL);
302 void vstrd(DRegister dd, Address ad, Condition cond = AL);
303
304 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
305 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
306 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
307 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
308 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
309 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
310 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
311 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
312 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
313 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
314 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
315 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
316
317 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
318 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
319 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
320 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
321 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
322 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
323
324 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
325 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
326 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
327 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
328 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
329 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
330 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
331 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
332 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
333 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
334
335 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
336 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
337 void vcmpsz(SRegister sd, Condition cond = AL);
338 void vcmpdz(DRegister dd, Condition cond = AL);
339 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
340
341 // Branch instructions.
342 void b(Label* label, Condition cond = AL);
343 void bl(Label* label, Condition cond = AL);
344 void blx(Register rm, Condition cond = AL);
345
346 // Macros.
347 // Add signed constant value to rd. May clobber IP.
348 void AddConstant(Register rd, int32_t value, Condition cond = AL);
349 void AddConstant(Register rd, Register rn, int32_t value,
350 Condition cond = AL);
351 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
352 Condition cond = AL);
353 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
354 Condition cond = AL);
355
356 // Load and Store. May clobber IP.
357 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
358 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
359 void LoadDImmediate(DRegister dd, double value,
360 Register scratch, Condition cond = AL);
361 void MarkExceptionHandler(Label* label);
362 void LoadFromOffset(LoadOperandType type,
363 Register reg,
364 Register base,
365 int32_t offset,
366 Condition cond = AL);
367 void StoreToOffset(StoreOperandType type,
368 Register reg,
369 Register base,
370 int32_t offset,
371 Condition cond = AL);
372 void LoadSFromOffset(SRegister reg,
373 Register base,
374 int32_t offset,
375 Condition cond = AL);
376 void StoreSToOffset(SRegister reg,
377 Register base,
378 int32_t offset,
379 Condition cond = AL);
380 void LoadDFromOffset(DRegister reg,
381 Register base,
382 int32_t offset,
383 Condition cond = AL);
384 void StoreDToOffset(DRegister reg,
385 Register base,
386 int32_t offset,
387 Condition cond = AL);
388
389 void Push(Register rd, Condition cond = AL);
390 void Pop(Register rd, Condition cond = AL);
391
392 void PushList(RegList regs, Condition cond = AL);
393 void PopList(RegList regs, Condition cond = AL);
394
395 void Mov(Register rd, Register rm, Condition cond = AL);
396
397 // Convenience shift instructions. Use mov instruction with shifter operand
398 // for variants setting the status flags or using a register shift count.
399 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
400 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
401 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
402 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
403 void Rrx(Register rd, Register rm, Condition cond = AL);
404
405 // Encode a signed constant in tst instructions, only affecting the flags.
406 void EncodeUint32InTstInstructions(uint32_t data);
407 // ... and decode from a pc pointing to the start of encoding instructions.
408 static uint32_t DecodeUint32FromTstInstructions(uword pc);
409 static bool IsInstructionForExceptionHandling(uword pc);
410
411 // Debugging and bringup support.
412 void Stop(const char* message);
413 void Unimplemented(const char* message);
414 void Untested(const char* message);
415 void Unreachable(const char* message);
416
Ian Rogersb033c752011-07-20 12:22:35 -0700417 // Emit code that will create an activation on the stack
418 void BuildFrame(size_t frame_size, ManagedRegister method_reg);
419
420 // Emit code that will remove an activation from the stack
421 void RemoveFrame(size_t frame_size);
422
423 void IncreaseFrameSize(size_t adjust);
424 void DecreaseFrameSize(size_t adjust);
425
426 // Store bytes from the given register onto the stack
427 void Store(FrameOffset dest, ManagedRegister src, size_t size);
Ian Rogersb033c752011-07-20 12:22:35 -0700428 void StoreRef(FrameOffset dest, ManagedRegister src);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700429 void StoreRawPtr(FrameOffset dest, ManagedRegister src);
430
Ian Rogersb033c752011-07-20 12:22:35 -0700431 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch);
432 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs);
433
434 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
435 ManagedRegister scratch);
436 void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
437 ManagedRegister scratch);
438
439 void Load(ManagedRegister dest, FrameOffset src, size_t size);
440
441 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset offs);
442 void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
443 ManagedRegister scratch);
444 void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
445 ManagedRegister scratch);
446
447 void StoreStackOffsetToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
448 ManagedRegister scratch);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700449 void StoreStackPointerToThread(ThreadOffset thr_offs);
Ian Rogersb033c752011-07-20 12:22:35 -0700450
451 void Move(ManagedRegister dest, ManagedRegister src);
452 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
453 size_t size);
454 void CreateStackHandle(ManagedRegister out_reg, FrameOffset handle_offset,
455 ManagedRegister in_reg, bool null_allowed);
456
457 void CreateStackHandle(FrameOffset out_off, FrameOffset handle_offset,
458 ManagedRegister scratch, bool null_allowed);
459
Ian Rogersdf20fe02011-07-20 20:34:16 -0700460 void LoadReferenceFromStackHandle(ManagedRegister dst, ManagedRegister src);
Ian Rogersb033c752011-07-20 12:22:35 -0700461
462 void ValidateRef(ManagedRegister src, bool could_be_null);
463
464 void ValidateRef(FrameOffset src, bool could_be_null);
465
Ian Rogersdf20fe02011-07-20 20:34:16 -0700466 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch);
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700467 void Call(FrameOffset base, Offset offset, ManagedRegister scratch);
Ian Rogersb033c752011-07-20 12:22:35 -0700468
Ian Rogers45a76cb2011-07-21 22:00:15 -0700469 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
470 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
471 // at the next instruction.
472 void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
473 FrameOffset return_save_location, size_t return_size);
474
475 // Generate code to check if Thread::Current()->exception_ is non-null
476 // and branch to a ExceptionSlowPath if it is.
477 void ExceptionPoll(ManagedRegister scratch);
478
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700479 // Emit data (e.g. encoded instruction or immediate) to the
480 // instruction stream.
481 void Emit(int32_t value);
482
483 void Bind(Label* label);
484
Ian Rogers45a76cb2011-07-21 22:00:15 -0700485 void EmitSlowPaths() { buffer_.EmitSlowPaths(this); }
486
Ian Rogersb033c752011-07-20 12:22:35 -0700487 size_t CodeSize() const { return buffer_.Size(); }
488
489 void FinalizeInstructions(const MemoryRegion& region) {
490 buffer_.FinalizeInstructions(region);
491 }
492
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700493 private:
494 AssemblerBuffer buffer_;
495
496 void EmitType01(Condition cond,
497 int type,
498 Opcode opcode,
499 int set_cc,
500 Register rn,
501 Register rd,
502 ShifterOperand so);
503
504 void EmitType5(Condition cond, int offset, bool link);
505
506 void EmitMemOp(Condition cond,
507 bool load,
508 bool byte,
509 Register rd,
510 Address ad);
511
512 void EmitMemOpAddressMode3(Condition cond,
513 int32_t mode,
514 Register rd,
515 Address ad);
516
517 void EmitMultiMemOp(Condition cond,
518 BlockAddressMode am,
519 bool load,
520 Register base,
521 RegList regs);
522
523 void EmitShiftImmediate(Condition cond,
524 Shift opcode,
525 Register rd,
526 Register rm,
527 ShifterOperand so);
528
529 void EmitShiftRegister(Condition cond,
530 Shift opcode,
531 Register rd,
532 Register rm,
533 ShifterOperand so);
534
535 void EmitMulOp(Condition cond,
536 int32_t opcode,
537 Register rd,
538 Register rn,
539 Register rm,
540 Register rs);
541
542 void EmitVFPsss(Condition cond,
543 int32_t opcode,
544 SRegister sd,
545 SRegister sn,
546 SRegister sm);
547
548 void EmitVFPddd(Condition cond,
549 int32_t opcode,
550 DRegister dd,
551 DRegister dn,
552 DRegister dm);
553
554 void EmitVFPsd(Condition cond,
555 int32_t opcode,
556 SRegister sd,
557 DRegister dm);
558
559 void EmitVFPds(Condition cond,
560 int32_t opcode,
561 DRegister dd,
562 SRegister sm);
563
564 void EmitBranch(Condition cond, Label* label, bool link);
565 static int32_t EncodeBranchOffset(int offset, int32_t inst);
566 static int DecodeBranchOffset(int32_t inst);
567 int32_t EncodeTstOffset(int offset, int32_t inst);
568 int DecodeTstOffset(int32_t inst);
569
570 // Returns whether or not the given register is used for passing parameters.
571 static int RegisterCompare(const Register* reg1, const Register* reg2) {
572 return *reg1 - *reg2;
573 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700574};
575
Ian Rogersb033c752011-07-20 12:22:35 -0700576} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700577
578#endif // ART_SRC_ASSEMBLER_ARM_H_