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