blob: 0eafb5fed5946d816211aa9ab22c318217cc6ec9 [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"
Ian Rogers0d666d82011-08-14 16:03:46 -070011#include <vector>
Carl Shapiroa2e18e12011-06-21 18:57:55 -070012
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070013namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070014
Carl Shapiroa2e18e12011-06-21 18:57:55 -070015// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
16class ShifterOperand {
17 public:
18 // Data-processing operands - Uninitialized
19 ShifterOperand() {
20 type_ = -1;
21 }
22
23 // Data-processing operands - Immediate
24 explicit ShifterOperand(uint32_t immediate) {
25 CHECK(immediate < (1 << kImmed8Bits));
26 type_ = 1;
27 encoding_ = immediate;
28 }
29
30 // Data-processing operands - Rotated immediate
31 ShifterOperand(uint32_t rotate, uint32_t immed8) {
32 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
33 type_ = 1;
34 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
35 }
36
37 // Data-processing operands - Register
38 explicit ShifterOperand(Register rm) {
39 type_ = 0;
40 encoding_ = static_cast<uint32_t>(rm);
41 }
42
43 // Data-processing operands - Logical shift/rotate by immediate
44 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
45 CHECK(shift_imm < (1 << kShiftImmBits));
46 type_ = 0;
47 encoding_ = shift_imm << kShiftImmShift |
48 static_cast<uint32_t>(shift) << kShiftShift |
49 static_cast<uint32_t>(rm);
50 }
51
52 // Data-processing operands - Logical shift/rotate by register
53 ShifterOperand(Register rm, Shift shift, Register rs) {
54 type_ = 0;
55 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
56 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
57 static_cast<uint32_t>(rm);
58 }
59
60 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
61 // Avoid the more expensive test for frequent small immediate values.
62 if (immediate < (1 << kImmed8Bits)) {
63 shifter_op->type_ = 1;
64 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
65 return true;
66 }
67 // Note that immediate must be unsigned for the test to work correctly.
68 for (int rot = 0; rot < 16; rot++) {
69 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
70 if (imm8 < (1 << kImmed8Bits)) {
71 shifter_op->type_ = 1;
72 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
73 return true;
74 }
75 }
76 return false;
77 }
78
79 private:
80 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
81
82 uint32_t type() const {
83 CHECK(is_valid());
84 return type_;
85 }
86
87 uint32_t encoding() const {
88 CHECK(is_valid());
89 return encoding_;
90 }
91
92 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
93 uint32_t encoding_;
94
95 friend class Assembler;
96#ifdef SOURCE_ASSEMBLER_SUPPORT
97 friend class BinaryAssembler;
98#endif
99};
100
101
102enum LoadOperandType {
103 kLoadSignedByte,
104 kLoadUnsignedByte,
105 kLoadSignedHalfword,
106 kLoadUnsignedHalfword,
107 kLoadWord,
108 kLoadWordPair,
109 kLoadSWord,
110 kLoadDWord
111};
112
113
114enum StoreOperandType {
115 kStoreByte,
116 kStoreHalfword,
117 kStoreWord,
118 kStoreWordPair,
119 kStoreSWord,
120 kStoreDWord
121};
122
123
124// Load/store multiple addressing mode.
125enum BlockAddressMode {
126 // bit encoding P U W
127 DA = (0|0|0) << 21, // decrement after
128 IA = (0|4|0) << 21, // increment after
129 DB = (8|0|0) << 21, // decrement before
130 IB = (8|4|0) << 21, // increment before
131 DA_W = (0|0|1) << 21, // decrement after with writeback to base
132 IA_W = (0|4|1) << 21, // increment after with writeback to base
133 DB_W = (8|0|1) << 21, // decrement before with writeback to base
134 IB_W = (8|4|1) << 21 // increment before with writeback to base
135};
136
137
138class Address {
139 public:
140 // Memory operand addressing mode
141 enum Mode {
142 // bit encoding P U W
143 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
144 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
145 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
146 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
147 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
148 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
149 };
150
151 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
152 CHECK(IsAbsoluteUint(12, offset));
153 if (offset < 0) {
154 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
155 } else {
156 encoding_ = am | offset;
157 }
158 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
159 }
160
161 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
162 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
163
164 private:
165 uint32_t encoding() const { return encoding_; }
166
167 // Encoding for addressing mode 3.
168 uint32_t encoding3() const {
169 const uint32_t offset_mask = (1 << 12) - 1;
170 uint32_t offset = encoding_ & offset_mask;
Ian Rogersb033c752011-07-20 12:22:35 -0700171 CHECK_LT(offset, 256u);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700172 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
173 }
174
175 // Encoding for vfp load/store addressing.
176 uint32_t vencoding() const {
177 const uint32_t offset_mask = (1 << 12) - 1;
178 uint32_t offset = encoding_ & offset_mask;
179 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
180 CHECK(IsAligned(offset, 2)); // Multiple of 4.
181 int mode = encoding_ & ((8|4|1) << 21);
182 CHECK((mode == Offset) || (mode == NegOffset));
183 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
184 if (mode == Offset) {
185 vencoding |= 1 << 23;
186 }
187 return vencoding;
188 }
189
190 uint32_t encoding_;
191
192 friend class Assembler;
193};
194
195
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700196class Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700197 public:
198 Assembler() : buffer_() {}
199
buzbeec143c552011-08-20 17:38:58 -0700200 InstructionSet GetInstructionSet() const {
201 return kArm;
202 }
203
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700204 // Data-processing instructions.
205 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
206
207 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
208
209 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
210 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
211
212 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
213 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
214
215 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
216
217 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
218
219 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
220
221 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
222
223 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
224
225 void tst(Register rn, ShifterOperand so, Condition cond = AL);
226
227 void teq(Register rn, ShifterOperand so, Condition cond = AL);
228
229 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
230
231 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
232
233 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
234 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
235
236 void mov(Register rd, ShifterOperand so, Condition cond = AL);
237 void movs(Register rd, ShifterOperand so, Condition cond = AL);
238
239 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
240
241 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
242 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
243
244 // Miscellaneous data-processing instructions.
245 void clz(Register rd, Register rm, Condition cond = AL);
246 void movw(Register rd, uint16_t imm16, Condition cond = AL);
247 void movt(Register rd, uint16_t imm16, Condition cond = AL);
248
249 // Multiply instructions.
250 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
251 void mla(Register rd, Register rn, Register rm, Register ra,
252 Condition cond = AL);
253 void mls(Register rd, Register rn, Register rm, Register ra,
254 Condition cond = AL);
255 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
256 Condition cond = AL);
257
258 // Load/store instructions.
259 void ldr(Register rd, Address ad, Condition cond = AL);
260 void str(Register rd, Address ad, Condition cond = AL);
261
262 void ldrb(Register rd, Address ad, Condition cond = AL);
263 void strb(Register rd, Address ad, Condition cond = AL);
264
265 void ldrh(Register rd, Address ad, Condition cond = AL);
266 void strh(Register rd, Address ad, Condition cond = AL);
267
268 void ldrsb(Register rd, Address ad, Condition cond = AL);
269 void ldrsh(Register rd, Address ad, Condition cond = AL);
270
271 void ldrd(Register rd, Address ad, Condition cond = AL);
272 void strd(Register rd, Address ad, Condition cond = AL);
273
274 void ldm(BlockAddressMode am, Register base,
275 RegList regs, Condition cond = AL);
276 void stm(BlockAddressMode am, Register base,
277 RegList regs, Condition cond = AL);
278
279 void ldrex(Register rd, Register rn, Condition cond = AL);
280 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
281
282 // Miscellaneous instructions.
283 void clrex();
284 void nop(Condition cond = AL);
285
286 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
287 void bkpt(uint16_t imm16);
288 void svc(uint32_t imm24);
289
290 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
291 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
292 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
293 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
294 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
295 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
296 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
297 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
298 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
299
300 // Returns false if the immediate cannot be encoded.
301 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
302 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
303
304 void vldrs(SRegister sd, Address ad, Condition cond = AL);
305 void vstrs(SRegister sd, Address ad, Condition cond = AL);
306 void vldrd(DRegister dd, Address ad, Condition cond = AL);
307 void vstrd(DRegister dd, Address ad, Condition cond = AL);
308
309 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
310 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
311 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
312 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
313 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
314 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
315 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
316 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
317 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
318 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
319 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
320 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
321
322 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
323 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
324 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
325 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
326 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
327 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
328
329 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
330 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
331 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
332 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
333 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
334 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
335 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
336 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
337 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
338 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
339
340 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
341 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
342 void vcmpsz(SRegister sd, Condition cond = AL);
343 void vcmpdz(DRegister dd, Condition cond = AL);
344 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
345
346 // Branch instructions.
347 void b(Label* label, Condition cond = AL);
348 void bl(Label* label, Condition cond = AL);
349 void blx(Register rm, Condition cond = AL);
350
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
Ian Rogersb033c752011-07-20 12:22:35 -0700416 // Emit code that will create an activation on the stack
Ian Rogers0d666d82011-08-14 16:03:46 -0700417 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
418 const std::vector<ManagedRegister>& spill_regs);
Ian Rogersb033c752011-07-20 12:22:35 -0700419
420 // Emit code that will remove an activation from the stack
Ian Rogers0d666d82011-08-14 16:03:46 -0700421 void RemoveFrame(size_t frame_size,
422 const std::vector<ManagedRegister>& spill_regs);
423
424 // Fill registers from spill area, excluding R0 (Method*) and LR
425 void FillFromSpillArea(const std::vector<ManagedRegister>& spill_regs,
426 size_t displacement);
Ian Rogersb033c752011-07-20 12:22:35 -0700427
428 void IncreaseFrameSize(size_t adjust);
429 void DecreaseFrameSize(size_t adjust);
430
431 // Store bytes from the given register onto the stack
432 void Store(FrameOffset dest, ManagedRegister src, size_t size);
Ian Rogersb033c752011-07-20 12:22:35 -0700433 void StoreRef(FrameOffset dest, ManagedRegister src);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700434 void StoreRawPtr(FrameOffset dest, ManagedRegister src);
Ian Rogers7a99c112011-09-07 12:48:27 -0700435 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
436 ManagedRegister scratch);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700437
Ian Rogersb033c752011-07-20 12:22:35 -0700438 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch);
439 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs);
Ian Rogersa04d3972011-08-17 11:33:44 -0700440 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs);
Ian Rogersb033c752011-07-20 12:22:35 -0700441
442 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
443 ManagedRegister scratch);
444 void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
445 ManagedRegister scratch);
446
447 void Load(ManagedRegister dest, FrameOffset src, size_t size);
448
449 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset offs);
450 void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
451 ManagedRegister scratch);
452 void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
453 ManagedRegister scratch);
454
455 void StoreStackOffsetToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
456 ManagedRegister scratch);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700457 void StoreStackPointerToThread(ThreadOffset thr_offs);
Ian Rogersb033c752011-07-20 12:22:35 -0700458
459 void Move(ManagedRegister dest, ManagedRegister src);
460 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
461 size_t size);
Ian Rogers408f79a2011-08-23 18:22:33 -0700462 void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
463 ManagedRegister in_reg, bool null_allowed);
Ian Rogersb033c752011-07-20 12:22:35 -0700464
Ian Rogers408f79a2011-08-23 18:22:33 -0700465 void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
466 ManagedRegister scratch, bool null_allowed);
Ian Rogersb033c752011-07-20 12:22:35 -0700467
Ian Rogers408f79a2011-08-23 18:22:33 -0700468 void LoadReferenceFromSirt(ManagedRegister dst, ManagedRegister src);
Ian Rogersb033c752011-07-20 12:22:35 -0700469
Ian Rogers408f79a2011-08-23 18:22:33 -0700470 void VerifyObject(ManagedRegister src, bool could_be_null);
Ian Rogersb033c752011-07-20 12:22:35 -0700471
Ian Rogers408f79a2011-08-23 18:22:33 -0700472 void VerifyObject(FrameOffset src, bool could_be_null);
Ian Rogersb033c752011-07-20 12:22:35 -0700473
Ian Rogersdf20fe02011-07-20 20:34:16 -0700474 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch);
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700475 void Call(FrameOffset base, Offset offset, ManagedRegister scratch);
Shih-wei Liao668512a2011-09-01 14:18:34 -0700476 void Call(uintptr_t addr, ManagedRegister scratch);
477
478 void GetCurrentThread(ManagedRegister tr);
479 void GetCurrentThread(FrameOffset offset, ManagedRegister scratch);
Ian Rogersb033c752011-07-20 12:22:35 -0700480
Ian Rogers45a76cb2011-07-21 22:00:15 -0700481 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
482 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
483 // at the next instruction.
484 void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
485 FrameOffset return_save_location, size_t return_size);
486
487 // Generate code to check if Thread::Current()->exception_ is non-null
488 // and branch to a ExceptionSlowPath if it is.
489 void ExceptionPoll(ManagedRegister scratch);
490
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700491 // Emit data (e.g. encoded instruction or immediate) to the
492 // instruction stream.
493 void Emit(int32_t value);
494
495 void Bind(Label* label);
496
Ian Rogers45a76cb2011-07-21 22:00:15 -0700497 void EmitSlowPaths() { buffer_.EmitSlowPaths(this); }
498
Ian Rogersb033c752011-07-20 12:22:35 -0700499 size_t CodeSize() const { return buffer_.Size(); }
500
501 void FinalizeInstructions(const MemoryRegion& region) {
502 buffer_.FinalizeInstructions(region);
503 }
504
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700505 private:
506 AssemblerBuffer buffer_;
507
508 void EmitType01(Condition cond,
509 int type,
510 Opcode opcode,
511 int set_cc,
512 Register rn,
513 Register rd,
514 ShifterOperand so);
515
516 void EmitType5(Condition cond, int offset, bool link);
517
518 void EmitMemOp(Condition cond,
519 bool load,
520 bool byte,
521 Register rd,
522 Address ad);
523
524 void EmitMemOpAddressMode3(Condition cond,
525 int32_t mode,
526 Register rd,
527 Address ad);
528
529 void EmitMultiMemOp(Condition cond,
530 BlockAddressMode am,
531 bool load,
532 Register base,
533 RegList regs);
534
535 void EmitShiftImmediate(Condition cond,
536 Shift opcode,
537 Register rd,
538 Register rm,
539 ShifterOperand so);
540
541 void EmitShiftRegister(Condition cond,
542 Shift opcode,
543 Register rd,
544 Register rm,
545 ShifterOperand so);
546
547 void EmitMulOp(Condition cond,
548 int32_t opcode,
549 Register rd,
550 Register rn,
551 Register rm,
552 Register rs);
553
554 void EmitVFPsss(Condition cond,
555 int32_t opcode,
556 SRegister sd,
557 SRegister sn,
558 SRegister sm);
559
560 void EmitVFPddd(Condition cond,
561 int32_t opcode,
562 DRegister dd,
563 DRegister dn,
564 DRegister dm);
565
566 void EmitVFPsd(Condition cond,
567 int32_t opcode,
568 SRegister sd,
569 DRegister dm);
570
571 void EmitVFPds(Condition cond,
572 int32_t opcode,
573 DRegister dd,
574 SRegister sm);
575
576 void EmitBranch(Condition cond, Label* label, bool link);
577 static int32_t EncodeBranchOffset(int offset, int32_t inst);
578 static int DecodeBranchOffset(int32_t inst);
579 int32_t EncodeTstOffset(int offset, int32_t inst);
580 int DecodeTstOffset(int32_t inst);
581
582 // Returns whether or not the given register is used for passing parameters.
583 static int RegisterCompare(const Register* reg1, const Register* reg2) {
584 return *reg1 - *reg2;
585 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700586};
587
Ian Rogersb033c752011-07-20 12:22:35 -0700588} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700589
590#endif // ART_SRC_ASSEMBLER_ARM_H_