blob: 31c3ab02b02051897748cf2dd0398017b55be965 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070016
Ian Rogers57b86d42012-03-27 16:05:41 -070017#ifndef ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_
18#define ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070019
Elliott Hughes0f3c5532012-03-30 14:51:51 -070020#include "constants_arm.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070021#include "logging.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070022#include "oat/utils/arm/managed_register_arm.h"
23#include "oat/utils/assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070024#include "offsets.h"
25#include "utils.h"
Ian Rogers0d666d82011-08-14 16:03:46 -070026#include <vector>
Carl Shapiroa2e18e12011-06-21 18:57:55 -070027
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070028namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070029namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070030
Carl Shapiroa2e18e12011-06-21 18:57:55 -070031// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
32class ShifterOperand {
33 public:
34 // Data-processing operands - Uninitialized
35 ShifterOperand() {
36 type_ = -1;
37 }
38
39 // Data-processing operands - Immediate
40 explicit ShifterOperand(uint32_t immediate) {
41 CHECK(immediate < (1 << kImmed8Bits));
42 type_ = 1;
43 encoding_ = immediate;
44 }
45
46 // Data-processing operands - Rotated immediate
47 ShifterOperand(uint32_t rotate, uint32_t immed8) {
48 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
49 type_ = 1;
50 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
51 }
52
53 // Data-processing operands - Register
54 explicit ShifterOperand(Register rm) {
55 type_ = 0;
56 encoding_ = static_cast<uint32_t>(rm);
57 }
58
59 // Data-processing operands - Logical shift/rotate by immediate
60 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
61 CHECK(shift_imm < (1 << kShiftImmBits));
62 type_ = 0;
63 encoding_ = shift_imm << kShiftImmShift |
64 static_cast<uint32_t>(shift) << kShiftShift |
65 static_cast<uint32_t>(rm);
66 }
67
68 // Data-processing operands - Logical shift/rotate by register
69 ShifterOperand(Register rm, Shift shift, Register rs) {
70 type_ = 0;
71 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
72 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
73 static_cast<uint32_t>(rm);
74 }
75
76 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
77 // Avoid the more expensive test for frequent small immediate values.
78 if (immediate < (1 << kImmed8Bits)) {
79 shifter_op->type_ = 1;
80 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
81 return true;
82 }
83 // Note that immediate must be unsigned for the test to work correctly.
84 for (int rot = 0; rot < 16; rot++) {
85 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
86 if (imm8 < (1 << kImmed8Bits)) {
87 shifter_op->type_ = 1;
88 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
89 return true;
90 }
91 }
92 return false;
93 }
94
95 private:
96 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
97
98 uint32_t type() const {
99 CHECK(is_valid());
100 return type_;
101 }
102
103 uint32_t encoding() const {
104 CHECK(is_valid());
105 return encoding_;
106 }
107
108 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
109 uint32_t encoding_;
110
Ian Rogers2c8f6532011-09-02 17:16:34 -0700111 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700112#ifdef SOURCE_ASSEMBLER_SUPPORT
113 friend class BinaryAssembler;
114#endif
115};
116
117
118enum LoadOperandType {
119 kLoadSignedByte,
120 kLoadUnsignedByte,
121 kLoadSignedHalfword,
122 kLoadUnsignedHalfword,
123 kLoadWord,
124 kLoadWordPair,
125 kLoadSWord,
126 kLoadDWord
127};
128
129
130enum StoreOperandType {
131 kStoreByte,
132 kStoreHalfword,
133 kStoreWord,
134 kStoreWordPair,
135 kStoreSWord,
136 kStoreDWord
137};
138
139
140// Load/store multiple addressing mode.
141enum BlockAddressMode {
142 // bit encoding P U W
143 DA = (0|0|0) << 21, // decrement after
144 IA = (0|4|0) << 21, // increment after
145 DB = (8|0|0) << 21, // decrement before
146 IB = (8|4|0) << 21, // increment before
147 DA_W = (0|0|1) << 21, // decrement after with writeback to base
148 IA_W = (0|4|1) << 21, // increment after with writeback to base
149 DB_W = (8|0|1) << 21, // decrement before with writeback to base
150 IB_W = (8|4|1) << 21 // increment before with writeback to base
151};
152
153
154class Address {
155 public:
156 // Memory operand addressing mode
157 enum Mode {
158 // bit encoding P U W
159 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
160 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
161 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
162 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
163 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
164 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
165 };
166
167 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
168 CHECK(IsAbsoluteUint(12, offset));
169 if (offset < 0) {
170 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
171 } else {
172 encoding_ = am | offset;
173 }
174 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
175 }
176
177 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
178 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
179
180 private:
181 uint32_t encoding() const { return encoding_; }
182
183 // Encoding for addressing mode 3.
184 uint32_t encoding3() const {
185 const uint32_t offset_mask = (1 << 12) - 1;
186 uint32_t offset = encoding_ & offset_mask;
Ian Rogersb033c752011-07-20 12:22:35 -0700187 CHECK_LT(offset, 256u);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700188 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
189 }
190
191 // Encoding for vfp load/store addressing.
192 uint32_t vencoding() const {
193 const uint32_t offset_mask = (1 << 12) - 1;
194 uint32_t offset = encoding_ & offset_mask;
195 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
Elliott Hughes06b37d92011-10-16 11:51:29 -0700196 CHECK_ALIGNED(offset, 2); // Multiple of 4.
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700197 int mode = encoding_ & ((8|4|1) << 21);
198 CHECK((mode == Offset) || (mode == NegOffset));
199 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
200 if (mode == Offset) {
201 vencoding |= 1 << 23;
202 }
203 return vencoding;
204 }
205
206 uint32_t encoding_;
207
Ian Rogers2c8f6532011-09-02 17:16:34 -0700208 friend class ArmAssembler;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700209};
210
211
Ian Rogers2c8f6532011-09-02 17:16:34 -0700212class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700213 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700214 ArmAssembler() {}
215 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700216
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700217 // Data-processing instructions.
218 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
219
220 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
221
222 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
223 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
224
225 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
226 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
227
228 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
229
230 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
231
232 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
233
234 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
235
236 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
237
238 void tst(Register rn, ShifterOperand so, Condition cond = AL);
239
240 void teq(Register rn, ShifterOperand so, Condition cond = AL);
241
242 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
243
244 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
245
246 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
247 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
248
249 void mov(Register rd, ShifterOperand so, Condition cond = AL);
250 void movs(Register rd, ShifterOperand so, Condition cond = AL);
251
252 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
253
254 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
255 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
256
257 // Miscellaneous data-processing instructions.
258 void clz(Register rd, Register rm, Condition cond = AL);
259 void movw(Register rd, uint16_t imm16, Condition cond = AL);
260 void movt(Register rd, uint16_t imm16, Condition cond = AL);
261
262 // Multiply instructions.
263 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
264 void mla(Register rd, Register rn, Register rm, Register ra,
265 Condition cond = AL);
266 void mls(Register rd, Register rn, Register rm, Register ra,
267 Condition cond = AL);
268 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
269 Condition cond = AL);
270
271 // Load/store instructions.
272 void ldr(Register rd, Address ad, Condition cond = AL);
273 void str(Register rd, Address ad, Condition cond = AL);
274
275 void ldrb(Register rd, Address ad, Condition cond = AL);
276 void strb(Register rd, Address ad, Condition cond = AL);
277
278 void ldrh(Register rd, Address ad, Condition cond = AL);
279 void strh(Register rd, Address ad, Condition cond = AL);
280
281 void ldrsb(Register rd, Address ad, Condition cond = AL);
282 void ldrsh(Register rd, Address ad, Condition cond = AL);
283
284 void ldrd(Register rd, Address ad, Condition cond = AL);
285 void strd(Register rd, Address ad, Condition cond = AL);
286
287 void ldm(BlockAddressMode am, Register base,
288 RegList regs, Condition cond = AL);
289 void stm(BlockAddressMode am, Register base,
290 RegList regs, Condition cond = AL);
291
292 void ldrex(Register rd, Register rn, Condition cond = AL);
293 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
294
295 // Miscellaneous instructions.
296 void clrex();
297 void nop(Condition cond = AL);
298
299 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
300 void bkpt(uint16_t imm16);
301 void svc(uint32_t imm24);
302
303 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
304 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
305 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
306 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
307 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
308 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
309 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
310 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
311 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
312
313 // Returns false if the immediate cannot be encoded.
314 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
315 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
316
317 void vldrs(SRegister sd, Address ad, Condition cond = AL);
318 void vstrs(SRegister sd, Address ad, Condition cond = AL);
319 void vldrd(DRegister dd, Address ad, Condition cond = AL);
320 void vstrd(DRegister dd, Address ad, Condition cond = AL);
321
322 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
323 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
324 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
325 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
326 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
327 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
328 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
329 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
330 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
331 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
332 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
333 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
334
335 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
336 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
337 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
338 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
339 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
340 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
341
342 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
343 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
344 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
345 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
346 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
347 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
348 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
349 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
350 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
351 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
352
353 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
354 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
355 void vcmpsz(SRegister sd, Condition cond = AL);
356 void vcmpdz(DRegister dd, Condition cond = AL);
357 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
358
359 // Branch instructions.
360 void b(Label* label, Condition cond = AL);
361 void bl(Label* label, Condition cond = AL);
362 void blx(Register rm, Condition cond = AL);
Ian Rogersae675992011-10-09 17:10:22 -0700363 void bx(Register rm, Condition cond = AL);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700364
365 // Macros.
366 // Add signed constant value to rd. May clobber IP.
367 void AddConstant(Register rd, int32_t value, Condition cond = AL);
368 void AddConstant(Register rd, Register rn, int32_t value,
369 Condition cond = AL);
370 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
371 Condition cond = AL);
372 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
373 Condition cond = AL);
374
375 // Load and Store. May clobber IP.
376 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
377 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
378 void LoadDImmediate(DRegister dd, double value,
379 Register scratch, Condition cond = AL);
380 void MarkExceptionHandler(Label* label);
381 void LoadFromOffset(LoadOperandType type,
382 Register reg,
383 Register base,
384 int32_t offset,
385 Condition cond = AL);
386 void StoreToOffset(StoreOperandType type,
387 Register reg,
388 Register base,
389 int32_t offset,
390 Condition cond = AL);
391 void LoadSFromOffset(SRegister reg,
392 Register base,
393 int32_t offset,
394 Condition cond = AL);
395 void StoreSToOffset(SRegister reg,
396 Register base,
397 int32_t offset,
398 Condition cond = AL);
399 void LoadDFromOffset(DRegister reg,
400 Register base,
401 int32_t offset,
402 Condition cond = AL);
403 void StoreDToOffset(DRegister reg,
404 Register base,
405 int32_t offset,
406 Condition cond = AL);
407
408 void Push(Register rd, Condition cond = AL);
409 void Pop(Register rd, Condition cond = AL);
410
411 void PushList(RegList regs, Condition cond = AL);
412 void PopList(RegList regs, Condition cond = AL);
413
414 void Mov(Register rd, Register rm, Condition cond = AL);
415
416 // Convenience shift instructions. Use mov instruction with shifter operand
417 // for variants setting the status flags or using a register shift count.
418 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
419 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
420 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
421 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
422 void Rrx(Register rd, Register rm, Condition cond = AL);
423
424 // Encode a signed constant in tst instructions, only affecting the flags.
425 void EncodeUint32InTstInstructions(uint32_t data);
426 // ... and decode from a pc pointing to the start of encoding instructions.
427 static uint32_t DecodeUint32FromTstInstructions(uword pc);
428 static bool IsInstructionForExceptionHandling(uword pc);
429
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700430 // Emit data (e.g. encoded instruction or immediate) to the
431 // instruction stream.
432 void Emit(int32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700433 void Bind(Label* label);
434
Ian Rogers2c8f6532011-09-02 17:16:34 -0700435 //
436 // Overridden common assembler high-level functionality
437 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700438
Ian Rogers2c8f6532011-09-02 17:16:34 -0700439 // Emit code that will create an activation on the stack
440 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800441 const std::vector<ManagedRegister>& callee_save_regs,
442 const std::vector<ManagedRegister>& entry_spills);
Ian Rogersb033c752011-07-20 12:22:35 -0700443
Ian Rogers2c8f6532011-09-02 17:16:34 -0700444 // Emit code that will remove an activation from the stack
445 virtual void RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -0700446 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700447
448 virtual void IncreaseFrameSize(size_t adjust);
449 virtual void DecreaseFrameSize(size_t adjust);
450
451 // Store routines
452 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
453 virtual void StoreRef(FrameOffset dest, ManagedRegister src);
454 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700455
456 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
457 ManagedRegister scratch);
458
459 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
460 ManagedRegister scratch);
461
462 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
463 FrameOffset fr_offs,
464 ManagedRegister scratch);
465
466 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
467
Ian Rogersbdb03912011-09-14 00:55:44 -0700468 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
469 FrameOffset in_off, ManagedRegister scratch);
470
Ian Rogers2c8f6532011-09-02 17:16:34 -0700471 // Load routines
472 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
473
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700474 virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size);
475
Ian Rogers2c8f6532011-09-02 17:16:34 -0700476 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
477
478 virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
479 MemberOffset offs);
480
481 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
482 Offset offs);
483
484 virtual void LoadRawPtrFromThread(ManagedRegister dest,
485 ThreadOffset offs);
486
487 // Copying routines
Ian Rogersb5d09b22012-03-06 22:14:17 -0800488 virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700489
490 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
491 ManagedRegister scratch);
492
493 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
494 ManagedRegister scratch);
495
496 virtual void CopyRef(FrameOffset dest, FrameOffset src,
497 ManagedRegister scratch);
498
Elliott Hughesa09aea22012-01-06 18:58:27 -0800499 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700500
Ian Rogersdc51b792011-09-22 20:41:37 -0700501 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
502 ManagedRegister scratch, size_t size);
503
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700504 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
505 ManagedRegister scratch, size_t size);
506
Ian Rogersdc51b792011-09-22 20:41:37 -0700507 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
508 ManagedRegister scratch, size_t size);
509
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700510 virtual void Copy(ManagedRegister dest, Offset dest_offset,
511 ManagedRegister src, Offset src_offset,
512 ManagedRegister scratch, size_t size);
513
514 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
515 ManagedRegister scratch, size_t size);
Ian Rogersdc51b792011-09-22 20:41:37 -0700516
Ian Rogerse5de95b2011-09-18 20:31:38 -0700517 virtual void MemoryBarrier(ManagedRegister scratch);
518
jeffhao58136ca2012-05-24 13:40:11 -0700519 // Sign extension
520 virtual void SignExtend(ManagedRegister mreg, size_t size);
521
jeffhaocee4d0c2012-06-15 14:42:01 -0700522 // Zero extension
523 virtual void ZeroExtend(ManagedRegister mreg, size_t size);
524
Ian Rogers2c8f6532011-09-02 17:16:34 -0700525 // Exploit fast access in managed code to Thread::Current()
526 virtual void GetCurrentThread(ManagedRegister tr);
527 virtual void GetCurrentThread(FrameOffset dest_offset,
528 ManagedRegister scratch);
529
530 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
531 // value is null and null_allowed. in_reg holds a possibly stale reference
532 // that can be used to avoid loading the SIRT entry to see if the value is
533 // NULL.
534 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
535 ManagedRegister in_reg, bool null_allowed);
536
537 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
538 // value is null and null_allowed.
539 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
540 ManagedRegister scratch, bool null_allowed);
541
542 // src holds a SIRT entry (Object**) load this into dst
543 virtual void LoadReferenceFromSirt(ManagedRegister dst,
544 ManagedRegister src);
545
546 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
547 // know that src may not be null.
548 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
549 virtual void VerifyObject(FrameOffset src, bool could_be_null);
550
551 // Call to address held at [base+offset]
552 virtual void Call(ManagedRegister base, Offset offset,
553 ManagedRegister scratch);
554 virtual void Call(FrameOffset base, Offset offset,
555 ManagedRegister scratch);
Ian Rogersbdb03912011-09-14 00:55:44 -0700556 virtual void Call(ThreadOffset offset, ManagedRegister scratch);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700557
558 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
559 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
560 // at the next instruction.
561 virtual void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
562 FrameOffset return_save_location,
563 size_t return_size);
564
565 // Generate code to check if Thread::Current()->exception_ is non-null
566 // and branch to a ExceptionSlowPath if it is.
567 virtual void ExceptionPoll(ManagedRegister scratch);
Ian Rogersb033c752011-07-20 12:22:35 -0700568
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700569 private:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700570 void EmitType01(Condition cond,
571 int type,
572 Opcode opcode,
573 int set_cc,
574 Register rn,
575 Register rd,
576 ShifterOperand so);
577
578 void EmitType5(Condition cond, int offset, bool link);
579
580 void EmitMemOp(Condition cond,
581 bool load,
582 bool byte,
583 Register rd,
584 Address ad);
585
586 void EmitMemOpAddressMode3(Condition cond,
587 int32_t mode,
588 Register rd,
589 Address ad);
590
591 void EmitMultiMemOp(Condition cond,
592 BlockAddressMode am,
593 bool load,
594 Register base,
595 RegList regs);
596
597 void EmitShiftImmediate(Condition cond,
598 Shift opcode,
599 Register rd,
600 Register rm,
601 ShifterOperand so);
602
603 void EmitShiftRegister(Condition cond,
604 Shift opcode,
605 Register rd,
606 Register rm,
607 ShifterOperand so);
608
609 void EmitMulOp(Condition cond,
610 int32_t opcode,
611 Register rd,
612 Register rn,
613 Register rm,
614 Register rs);
615
616 void EmitVFPsss(Condition cond,
617 int32_t opcode,
618 SRegister sd,
619 SRegister sn,
620 SRegister sm);
621
622 void EmitVFPddd(Condition cond,
623 int32_t opcode,
624 DRegister dd,
625 DRegister dn,
626 DRegister dm);
627
628 void EmitVFPsd(Condition cond,
629 int32_t opcode,
630 SRegister sd,
631 DRegister dm);
632
633 void EmitVFPds(Condition cond,
634 int32_t opcode,
635 DRegister dd,
636 SRegister sm);
637
638 void EmitBranch(Condition cond, Label* label, bool link);
639 static int32_t EncodeBranchOffset(int offset, int32_t inst);
640 static int DecodeBranchOffset(int32_t inst);
641 int32_t EncodeTstOffset(int offset, int32_t inst);
642 int DecodeTstOffset(int32_t inst);
643
644 // Returns whether or not the given register is used for passing parameters.
645 static int RegisterCompare(const Register* reg1, const Register* reg2) {
646 return *reg1 - *reg2;
647 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700648};
649
Ian Rogers2c8f6532011-09-02 17:16:34 -0700650// Slowpath entered when Thread::Current()->_exception is non-null
651class ArmExceptionSlowPath : public SlowPath {
652 public:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700653 explicit ArmExceptionSlowPath(ArmManagedRegister scratch) : scratch_(scratch) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654 virtual void Emit(Assembler *sp_asm);
Ian Rogers67375ac2011-09-14 00:55:44 -0700655 private:
656 const ArmManagedRegister scratch_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700657};
658
659// Slowpath entered when Thread::Current()->_suspend_count is non-zero
660class ArmSuspendCountSlowPath : public SlowPath {
661 public:
662 ArmSuspendCountSlowPath(ArmManagedRegister return_reg,
663 FrameOffset return_save_location,
664 size_t return_size) :
665 return_register_(return_reg), return_save_location_(return_save_location),
666 return_size_(return_size) {}
667 virtual void Emit(Assembler *sp_asm);
668
669 private:
670 // Remember how to save the return value
671 const ArmManagedRegister return_register_;
672 const FrameOffset return_save_location_;
673 const size_t return_size_;
674};
675
676} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700677} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700678
Ian Rogers57b86d42012-03-27 16:05:41 -0700679#endif // ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_