1 /*
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  */
16 
17 #ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
19 
20 #include <vector>
21 
22 #include "base/logging.h"
23 #include "constants_arm.h"
24 #include "utils/arm/managed_register_arm.h"
25 #include "utils/assembler.h"
26 #include "offsets.h"
27 #include "utils.h"
28 
29 namespace art {
30 namespace arm {
31 
32 class ShifterOperand {
33  public:
ShifterOperand()34   ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
35       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
36   }
37 
38   explicit ShifterOperand(uint32_t immed);
39 
40   // Data-processing operands - Register
ShifterOperand(Register rm)41   explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
42       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
43   }
44 
ShifterOperand(uint32_t rotate,uint32_t immed8)45   ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
46       rs_(kNoRegister),
47       is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
48   }
49 
type_(kRegister)50   ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
51       rs_(kNoRegister),
52       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
53   }
54 
55   // Data-processing operands - Logical shift/rotate by register
ShifterOperand(Register rm,Shift shift,Register rs)56   ShifterOperand(Register rm, Shift shift, Register rs)  : type_(kRegister), rm_(rm),
57       rs_(rs),
58       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
59   }
60 
is_valid()61   bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
62 
type()63   uint32_t type() const {
64     CHECK(is_valid());
65     return type_;
66   }
67 
68   uint32_t encodingArm() const;
69   uint32_t encodingThumb() const;
70 
IsEmpty()71   bool IsEmpty() const {
72     return type_ == kUnknown;
73   }
74 
IsImmediate()75   bool IsImmediate() const {
76     return type_ == kImmediate;
77   }
78 
IsRegister()79   bool IsRegister() const {
80     return type_ == kRegister;
81   }
82 
IsShift()83   bool IsShift() const {
84     return is_shift_;
85   }
86 
GetImmediate()87   uint32_t GetImmediate() const {
88     return immed_;
89   }
90 
GetShift()91   Shift GetShift() const {
92     return shift_;
93   }
94 
GetRegister()95   Register GetRegister() const {
96     return rm_;
97   }
98 
99   enum Type {
100     kUnknown = -1,
101     kRegister,
102     kImmediate
103   };
104 
CanHoldArm(uint32_t immediate,ShifterOperand * shifter_op)105   static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) {
106     // Avoid the more expensive test for frequent small immediate values.
107     if (immediate < (1 << kImmed8Bits)) {
108       shifter_op->type_ = kImmediate;
109       shifter_op->is_rotate_ = true;
110       shifter_op->rotate_ = 0;
111       shifter_op->immed_ = immediate;
112       return true;
113     }
114     // Note that immediate must be unsigned for the test to work correctly.
115     for (int rot = 0; rot < 16; rot++) {
116       uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
117       if (imm8 < (1 << kImmed8Bits)) {
118         shifter_op->type_ = kImmediate;
119         shifter_op->is_rotate_ = true;
120         shifter_op->rotate_ = rot;
121         shifter_op->immed_ = imm8;
122         return true;
123       }
124     }
125     return false;
126   }
127 
128   static bool CanHoldThumb(Register rd, Register rn, Opcode opcode,
129                            uint32_t immediate, ShifterOperand* shifter_op);
130 
131 
132  private:
133   Type type_;
134   Register rm_;
135   Register rs_;
136   bool is_rotate_;
137   bool is_shift_;
138   Shift shift_;
139   uint32_t rotate_;
140   uint32_t immed_;
141 
142 #ifdef SOURCE_ASSEMBLER_SUPPORT
143   friend class BinaryAssembler;
144 #endif
145 };
146 
147 
148 enum LoadOperandType {
149   kLoadSignedByte,
150   kLoadUnsignedByte,
151   kLoadSignedHalfword,
152   kLoadUnsignedHalfword,
153   kLoadWord,
154   kLoadWordPair,
155   kLoadSWord,
156   kLoadDWord
157 };
158 
159 
160 enum StoreOperandType {
161   kStoreByte,
162   kStoreHalfword,
163   kStoreWord,
164   kStoreWordPair,
165   kStoreSWord,
166   kStoreDWord
167 };
168 
169 
170 // Load/store multiple addressing mode.
171 enum BlockAddressMode {
172   // bit encoding P U W
173   DA           = (0|0|0) << 21,  // decrement after
174   IA           = (0|4|0) << 21,  // increment after
175   DB           = (8|0|0) << 21,  // decrement before
176   IB           = (8|4|0) << 21,  // increment before
177   DA_W         = (0|0|1) << 21,  // decrement after with writeback to base
178   IA_W         = (0|4|1) << 21,  // increment after with writeback to base
179   DB_W         = (8|0|1) << 21,  // decrement before with writeback to base
180   IB_W         = (8|4|1) << 21   // increment before with writeback to base
181 };
182 
183 class Address {
184  public:
185   // Memory operand addressing mode (in ARM encoding form.  For others we need
186   // to adjust)
187   enum Mode {
188     // bit encoding P U W
189     Offset       = (8|4|0) << 21,  // offset (w/o writeback to base)
190     PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
191     PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
192     NegOffset    = (8|0|0) << 21,  // negative offset (w/o writeback to base)
193     NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
194     NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
195   };
196 
rn_(rn)197   Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
198       offset_(offset),
199       am_(am), is_immed_offset_(true), shift_(LSL) {
200   }
201 
rn_(rn)202   Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
203       am_(am), is_immed_offset_(false), shift_(LSL) {
204     CHECK_NE(rm, PC);
205   }
206 
207   Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
rn_(rn)208                        rn_(rn), rm_(rm), offset_(count),
209                        am_(am), is_immed_offset_(false), shift_(shift) {
210     CHECK_NE(rm, PC);
211   }
212 
213   // LDR(literal) - pc relative load.
Address(int32_t offset)214   explicit Address(int32_t offset) :
215                rn_(PC), rm_(R0), offset_(offset),
216                am_(Offset), is_immed_offset_(false), shift_(LSL) {
217   }
218 
219   static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
220   static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
221 
222   static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
223   static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
224 
225   uint32_t encodingArm() const;
226   uint32_t encodingThumb(bool is_32bit) const;
227 
228   uint32_t encoding3() const;
229   uint32_t vencoding() const;
230 
231   uint32_t encodingThumbLdrdStrd() const;
232 
GetRegister()233   Register GetRegister() const {
234     return rn_;
235   }
236 
GetRegisterOffset()237   Register GetRegisterOffset() const {
238     return rm_;
239   }
240 
GetOffset()241   int32_t GetOffset() const {
242     return offset_;
243   }
244 
GetMode()245   Mode GetMode() const {
246     return am_;
247   }
248 
IsImmediate()249   bool IsImmediate() const {
250     return is_immed_offset_;
251   }
252 
GetShift()253   Shift GetShift() const {
254     return shift_;
255   }
256 
GetShiftCount()257   int32_t GetShiftCount() const {
258     CHECK(!is_immed_offset_);
259     return offset_;
260   }
261 
262  private:
263   Register rn_;
264   Register rm_;
265   int32_t offset_;      // Used as shift amount for register offset.
266   Mode am_;
267   bool is_immed_offset_;
268   Shift shift_;
269 };
270 
271 // Instruction encoding bits.
272 enum {
273   H   = 1 << 5,   // halfword (or byte)
274   L   = 1 << 20,  // load (or store)
275   S   = 1 << 20,  // set condition code (or leave unchanged)
276   W   = 1 << 21,  // writeback base register (or leave unchanged)
277   A   = 1 << 21,  // accumulate in multiply instruction (or not)
278   B   = 1 << 22,  // unsigned byte (or word)
279   N   = 1 << 22,  // long (or short)
280   U   = 1 << 23,  // positive (or negative) offset/index
281   P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
282   I   = 1 << 25,  // immediate shifter operand (or not)
283 
284   B0 = 1,
285   B1 = 1 << 1,
286   B2 = 1 << 2,
287   B3 = 1 << 3,
288   B4 = 1 << 4,
289   B5 = 1 << 5,
290   B6 = 1 << 6,
291   B7 = 1 << 7,
292   B8 = 1 << 8,
293   B9 = 1 << 9,
294   B10 = 1 << 10,
295   B11 = 1 << 11,
296   B12 = 1 << 12,
297   B13 = 1 << 13,
298   B14 = 1 << 14,
299   B15 = 1 << 15,
300   B16 = 1 << 16,
301   B17 = 1 << 17,
302   B18 = 1 << 18,
303   B19 = 1 << 19,
304   B20 = 1 << 20,
305   B21 = 1 << 21,
306   B22 = 1 << 22,
307   B23 = 1 << 23,
308   B24 = 1 << 24,
309   B25 = 1 << 25,
310   B26 = 1 << 26,
311   B27 = 1 << 27,
312   B28 = 1 << 28,
313   B29 = 1 << 29,
314   B30 = 1 << 30,
315   B31 = 1 << 31,
316 
317   // Instruction bit masks.
318   RdMask = 15 << 12,  // in str instruction
319   CondMask = 15 << 28,
320   CoprocessorMask = 15 << 8,
321   OpCodeMask = 15 << 21,  // in data-processing instructions
322   Imm24Mask = (1 << 24) - 1,
323   Off12Mask = (1 << 12) - 1,
324 
325   // ldrex/strex register field encodings.
326   kLdExRnShift = 16,
327   kLdExRtShift = 12,
328   kStrExRnShift = 16,
329   kStrExRdShift = 12,
330   kStrExRtShift = 0,
331 };
332 
333 // IfThen state for IT instructions.
334 enum ItState {
335   kItOmitted,
336   kItThen,
337   kItT = kItThen,
338   kItElse,
339   kItE = kItElse
340 };
341 
342 constexpr uint32_t kNoItCondition = 3;
343 constexpr uint32_t kInvalidModifiedImmediate = -1;
344 
345 extern const char* kRegisterNames[];
346 extern const char* kConditionNames[];
347 extern std::ostream& operator<<(std::ostream& os, const Register& rhs);
348 extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs);
349 extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
350 extern std::ostream& operator<<(std::ostream& os, const Condition& rhs);
351 
352 // This is an abstract ARM assembler.  Subclasses provide assemblers for the individual
353 // instruction sets (ARM32, Thumb2, etc.)
354 //
355 class ArmAssembler : public Assembler {
356  public:
~ArmAssembler()357   virtual ~ArmAssembler() {}
358 
359   // Is this assembler for the thumb instruction set?
360   virtual bool IsThumb() const = 0;
361 
362   // Data-processing instructions.
363   virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
364 
365   virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
366 
367   virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
368   virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
369 
370   virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
371   virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
372 
373   virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
374 
375   virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
376 
377   virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
378 
379   virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
380 
381   virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
382 
383   virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
384 
385   virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
386 
387   virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
388 
389   virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
390 
391   virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
392   virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
393 
394   virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
395   virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
396 
397   virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
398 
399   virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
400   virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
401 
402   // Miscellaneous data-processing instructions.
403   virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
404   virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
405   virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
406 
407   // Multiply instructions.
408   virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
409   virtual void mla(Register rd, Register rn, Register rm, Register ra,
410                    Condition cond = AL) = 0;
411   virtual void mls(Register rd, Register rn, Register rm, Register ra,
412                    Condition cond = AL) = 0;
413   virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
414                      Condition cond = AL) = 0;
415 
416   virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
417   virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
418 
419   // Load/store instructions.
420   virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
421   virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
422 
423   virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
424   virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
425 
426   virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
427   virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
428 
429   virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
430   virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
431 
432   virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
433   virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
434 
435   virtual void ldm(BlockAddressMode am, Register base,
436                    RegList regs, Condition cond = AL) = 0;
437   virtual void stm(BlockAddressMode am, Register base,
438                    RegList regs, Condition cond = AL) = 0;
439 
440   virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
441   virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
442 
443   // Miscellaneous instructions.
444   virtual void clrex(Condition cond = AL) = 0;
445   virtual void nop(Condition cond = AL) = 0;
446 
447   // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
448   virtual void bkpt(uint16_t imm16) = 0;
449   virtual void svc(uint32_t imm24) = 0;
450 
451   virtual void it(Condition firstcond, ItState i1 = kItOmitted,
452                   ItState i2 = kItOmitted, ItState i3 = kItOmitted) {
453     // Ignored if not supported.
454   }
455 
456   virtual void cbz(Register rn, Label* target) = 0;
457   virtual void cbnz(Register rn, Label* target) = 0;
458 
459   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
460   virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
461   virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
462   virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
463   virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
464   virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
465   virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
466   virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
467   virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
468 
469   // Returns false if the immediate cannot be encoded.
470   virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
471   virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
472 
473   virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
474   virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
475   virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
476   virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
477 
478   virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
479   virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
480   virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
481   virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
482   virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
483   virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
484   virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
485   virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
486   virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
487   virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
488   virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
489   virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
490 
491   virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
492   virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
493   virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
494   virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
495   virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
496   virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
497 
498   virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
499   virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
500   virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
501   virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
502   virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
503   virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
504   virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
505   virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
506   virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
507   virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
508 
509   virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
510   virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
511   virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
512   virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
513   virtual void vmstat(Condition cond = AL) = 0;  // VMRS APSR_nzcv, FPSCR
514 
515   virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
516   virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
517   virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
518   virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
519 
520   // Branch instructions.
521   virtual void b(Label* label, Condition cond = AL) = 0;
522   virtual void bl(Label* label, Condition cond = AL) = 0;
523   virtual void blx(Register rm, Condition cond = AL) = 0;
524   virtual void bx(Register rm, Condition cond = AL) = 0;
525 
526   void Pad(uint32_t bytes);
527 
528   // Macros.
529   // Most of these are pure virtual as they need to be implemented per instruction set.
530 
531   // Add signed constant value to rd. May clobber IP.
532   virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
533   virtual void AddConstant(Register rd, Register rn, int32_t value,
534                            Condition cond = AL) = 0;
535   virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
536                                    Condition cond = AL) = 0;
537   virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value,
538                                     Condition cond = AL) = 0;
539 
540   // Load and Store. May clobber IP.
541   virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
542   virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0;
543   virtual void LoadDImmediate(DRegister dd, double value,
544                               Register scratch, Condition cond = AL) = 0;
545   virtual void MarkExceptionHandler(Label* label) = 0;
546   virtual void LoadFromOffset(LoadOperandType type,
547                               Register reg,
548                               Register base,
549                               int32_t offset,
550                               Condition cond = AL) = 0;
551   virtual void StoreToOffset(StoreOperandType type,
552                              Register reg,
553                              Register base,
554                              int32_t offset,
555                              Condition cond = AL) = 0;
556   virtual void LoadSFromOffset(SRegister reg,
557                                Register base,
558                                int32_t offset,
559                                Condition cond = AL) = 0;
560   virtual void StoreSToOffset(SRegister reg,
561                               Register base,
562                               int32_t offset,
563                               Condition cond = AL) = 0;
564   virtual void LoadDFromOffset(DRegister reg,
565                                Register base,
566                                int32_t offset,
567                                Condition cond = AL) = 0;
568   virtual void StoreDToOffset(DRegister reg,
569                               Register base,
570                               int32_t offset,
571                               Condition cond = AL) = 0;
572 
573   virtual void Push(Register rd, Condition cond = AL) = 0;
574   virtual void Pop(Register rd, Condition cond = AL) = 0;
575 
576   virtual void PushList(RegList regs, Condition cond = AL) = 0;
577   virtual void PopList(RegList regs, Condition cond = AL) = 0;
578 
579   virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
580 
581   // Convenience shift instructions. Use mov instruction with shifter operand
582   // for variants setting the status flags or using a register shift count.
583   virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
584                    Condition cond = AL) = 0;
585   virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
586                    Condition cond = AL) = 0;
587   virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
588                    Condition cond = AL) = 0;
589   virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
590                    Condition cond = AL) = 0;
591   virtual void Rrx(Register rd, Register rm, bool setcc = false,
592                    Condition cond = AL) = 0;
593 
594   virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
595                    Condition cond = AL) = 0;
596   virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
597                    Condition cond = AL) = 0;
598   virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
599                    Condition cond = AL) = 0;
600   virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
601                    Condition cond = AL) = 0;
602 
603   static bool IsInstructionForExceptionHandling(uword pc);
604 
605   virtual void Bind(Label* label) = 0;
606 
607   virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
608   virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
609 
610   //
611   // Overridden common assembler high-level functionality
612   //
613 
614   // Emit code that will create an activation on the stack
615   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
616                   const std::vector<ManagedRegister>& callee_save_regs,
617                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
618 
619   // Emit code that will remove an activation from the stack
620   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
621     OVERRIDE;
622 
623   void IncreaseFrameSize(size_t adjust) OVERRIDE;
624   void DecreaseFrameSize(size_t adjust) OVERRIDE;
625 
626   // Store routines
627   void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
628   void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
629   void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
630 
631   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
632 
633   void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
634       OVERRIDE;
635 
636   void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
637                                   ManagedRegister scratch) OVERRIDE;
638 
639   void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
640 
641   void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
642                      ManagedRegister scratch) OVERRIDE;
643 
644   // Load routines
645   void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
646 
647   void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
648 
649   void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
650 
651   void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
652 
653   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
654 
655   void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
656 
657   // Copying routines
658   void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
659 
660   void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
661                               ManagedRegister scratch) OVERRIDE;
662 
663   void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
664       OVERRIDE;
665 
666   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
667 
668   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
669 
670   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
671             size_t size) OVERRIDE;
672 
673   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
674             size_t size) OVERRIDE;
675 
676   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
677             size_t size) OVERRIDE;
678 
679   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
680             ManagedRegister scratch, size_t size) OVERRIDE;
681 
682   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
683             ManagedRegister scratch, size_t size) OVERRIDE;
684 
685   // Sign extension
686   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
687 
688   // Zero extension
689   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
690 
691   // Exploit fast access in managed code to Thread::Current()
692   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
693   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
694 
695   // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the
696   // value is null and null_allowed. in_reg holds a possibly stale reference
697   // that can be used to avoid loading the handle scope entry to see if the value is
698   // NULL.
699   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
700                        bool null_allowed) OVERRIDE;
701 
702   // Set up out_off to hold a Object** into the handle scope, or to be NULL if the
703   // value is null and null_allowed.
704   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
705                        bool null_allowed) OVERRIDE;
706 
707   // src holds a handle scope entry (Object**) load this into dst
708   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
709 
710   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
711   // know that src may not be null.
712   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
713   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
714 
715   // Call to address held at [base+offset]
716   void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
717   void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
718   void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
719 
720   // Generate code to check if Thread::Current()->exception_ is non-null
721   // and branch to a ExceptionSlowPath if it is.
722   void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
723 
724   static uint32_t ModifiedImmediate(uint32_t value);
725 
IsLowRegister(Register r)726   static bool IsLowRegister(Register r) {
727     return r < R8;
728   }
729 
IsHighRegister(Register r)730   static bool IsHighRegister(Register r) {
731      return r >= R8;
732   }
733 
734  protected:
735   // Returns whether or not the given register is used for passing parameters.
RegisterCompare(const Register * reg1,const Register * reg2)736   static int RegisterCompare(const Register* reg1, const Register* reg2) {
737     return *reg1 - *reg2;
738   }
739 };
740 
741 // Slowpath entered when Thread::Current()->_exception is non-null
742 class ArmExceptionSlowPath FINAL : public SlowPath {
743  public:
ArmExceptionSlowPath(ArmManagedRegister scratch,size_t stack_adjust)744   explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
745       : scratch_(scratch), stack_adjust_(stack_adjust) {
746   }
747   void Emit(Assembler *sp_asm) OVERRIDE;
748  private:
749   const ArmManagedRegister scratch_;
750   const size_t stack_adjust_;
751 };
752 
753 }  // namespace arm
754 }  // namespace art
755 
756 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
757