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 <type_traits>
21 #include <vector>
22 
23 #include "base/arena_allocator.h"
24 #include "base/arena_containers.h"
25 #include "base/bit_utils.h"
26 #include "base/enums.h"
27 #include "base/logging.h"
28 #include "base/stl_util.h"
29 #include "base/value_object.h"
30 #include "constants_arm.h"
31 #include "utils/arm/assembler_arm_shared.h"
32 #include "utils/arm/managed_register_arm.h"
33 #include "utils/assembler.h"
34 #include "utils/jni_macro_assembler.h"
35 #include "offsets.h"
36 
37 namespace art {
38 namespace arm {
39 
40 class Thumb2Assembler;
41 
42 // Assembler literal is a value embedded in code, retrieved using a PC-relative load.
43 class Literal {
44  public:
45   static constexpr size_t kMaxSize = 8;
46 
Literal(uint32_t size,const uint8_t * data)47   Literal(uint32_t size, const uint8_t* data)
48       : label_(), size_(size) {
49     DCHECK_LE(size, Literal::kMaxSize);
50     memcpy(data_, data, size);
51   }
52 
53   template <typename T>
GetValue()54   T GetValue() const {
55     DCHECK_EQ(size_, sizeof(T));
56     T value;
57     memcpy(&value, data_, sizeof(T));
58     return value;
59   }
60 
GetSize()61   uint32_t GetSize() const {
62     return size_;
63   }
64 
GetData()65   const uint8_t* GetData() const {
66     return data_;
67   }
68 
GetLabel()69   Label* GetLabel() {
70     return &label_;
71   }
72 
GetLabel()73   const Label* GetLabel() const {
74     return &label_;
75   }
76 
77  private:
78   Label label_;
79   const uint32_t size_;
80   uint8_t data_[kMaxSize];
81 
82   DISALLOW_COPY_AND_ASSIGN(Literal);
83 };
84 
85 // Jump table: table of labels emitted after the literals. Similar to literals.
86 class JumpTable {
87  public:
JumpTable(std::vector<Label * > && labels)88   explicit JumpTable(std::vector<Label*>&& labels)
89       : label_(), anchor_label_(), labels_(std::move(labels)) {
90   }
91 
GetSize()92   uint32_t GetSize() const {
93     return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t);
94   }
95 
GetData()96   const std::vector<Label*>& GetData() const {
97     return labels_;
98   }
99 
GetLabel()100   Label* GetLabel() {
101     return &label_;
102   }
103 
GetLabel()104   const Label* GetLabel() const {
105     return &label_;
106   }
107 
GetAnchorLabel()108   Label* GetAnchorLabel() {
109     return &anchor_label_;
110   }
111 
GetAnchorLabel()112   const Label* GetAnchorLabel() const {
113     return &anchor_label_;
114   }
115 
116  private:
117   Label label_;
118   Label anchor_label_;
119   std::vector<Label*> labels_;
120 
121   DISALLOW_COPY_AND_ASSIGN(JumpTable);
122 };
123 
124 class ShifterOperand {
125  public:
ShifterOperand()126   ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
127       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
128   }
129 
130   explicit ShifterOperand(uint32_t immed);
131 
132   // Data-processing operands - Register
ShifterOperand(Register rm)133   explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
134       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
135   }
136 
ShifterOperand(uint32_t rotate,uint32_t immed8)137   ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
138       rs_(kNoRegister),
139       is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
140   }
141 
type_(kRegister)142   ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
143       rs_(kNoRegister),
144       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
145   }
146 
147   // Data-processing operands - Logical shift/rotate by register
ShifterOperand(Register rm,Shift shift,Register rs)148   ShifterOperand(Register rm, Shift shift, Register rs)  : type_(kRegister), rm_(rm),
149       rs_(rs),
150       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
151   }
152 
is_valid()153   bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
154 
type()155   uint32_t type() const {
156     CHECK(is_valid());
157     return type_;
158   }
159 
160   uint32_t encodingArm() const;
161   uint32_t encodingThumb() const;
162 
IsEmpty()163   bool IsEmpty() const {
164     return type_ == kUnknown;
165   }
166 
IsImmediate()167   bool IsImmediate() const {
168     return type_ == kImmediate;
169   }
170 
IsRegister()171   bool IsRegister() const {
172     return type_ == kRegister;
173   }
174 
IsShift()175   bool IsShift() const {
176     return is_shift_;
177   }
178 
GetImmediate()179   uint32_t GetImmediate() const {
180     return immed_;
181   }
182 
GetShift()183   Shift GetShift() const {
184     return shift_;
185   }
186 
GetRegister()187   Register GetRegister() const {
188     return rm_;
189   }
190 
GetSecondRegister()191   Register GetSecondRegister() const {
192     return rs_;
193   }
194 
195   enum Type {
196     kUnknown = -1,
197     kRegister,
198     kImmediate
199   };
200 
201  private:
202   Type type_;
203   Register rm_;
204   Register rs_;
205   bool is_rotate_;
206   bool is_shift_;
207   Shift shift_;
208   uint32_t rotate_;
209   uint32_t immed_;
210 
211   friend class Thumb2Assembler;
212 
213 #ifdef SOURCE_ASSEMBLER_SUPPORT
214   friend class BinaryAssembler;
215 #endif
216 };
217 
218 // Load/store multiple addressing mode.
219 enum BlockAddressMode {
220   // bit encoding P U W
221   DA           = (0|0|0) << 21,  // decrement after
222   IA           = (0|4|0) << 21,  // increment after
223   DB           = (8|0|0) << 21,  // decrement before
224   IB           = (8|4|0) << 21,  // increment before
225   DA_W         = (0|0|1) << 21,  // decrement after with writeback to base
226   IA_W         = (0|4|1) << 21,  // increment after with writeback to base
227   DB_W         = (8|0|1) << 21,  // decrement before with writeback to base
228   IB_W         = (8|4|1) << 21   // increment before with writeback to base
229 };
230 inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
231   os << static_cast<int>(rhs);
232   return os;
233 }
234 
235 class Address : public ValueObject {
236  public:
237   // Memory operand addressing mode (in ARM encoding form.  For others we need
238   // to adjust)
239   enum Mode {
240     // bit encoding P U W
241     Offset       = (8|4|0) << 21,  // offset (w/o writeback to base)
242     PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
243     PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
244     NegOffset    = (8|0|0) << 21,  // negative offset (w/o writeback to base)
245     NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
246     NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
247   };
248 
rn_(rn)249   explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
250       offset_(offset),
251       am_(am), is_immed_offset_(true), shift_(LSL) {
252   }
253 
rn_(rn)254   Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
255       am_(am), is_immed_offset_(false), shift_(LSL) {
256     CHECK_NE(rm, PC);
257   }
258 
259   Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
rn_(rn)260                        rn_(rn), rm_(rm), offset_(count),
261                        am_(am), is_immed_offset_(false), shift_(shift) {
262     CHECK_NE(rm, PC);
263   }
264 
265   static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
266   static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
267 
268   static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
269   static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
270 
271   uint32_t encodingArm() const;
272   uint32_t encodingThumb(bool is_32bit) const;
273 
274   uint32_t encoding3() const;
275   uint32_t vencoding() const;
276 
277   uint32_t encodingThumbLdrdStrd() const;
278 
GetRegister()279   Register GetRegister() const {
280     return rn_;
281   }
282 
GetRegisterOffset()283   Register GetRegisterOffset() const {
284     return rm_;
285   }
286 
GetOffset()287   int32_t GetOffset() const {
288     return offset_;
289   }
290 
GetMode()291   Mode GetMode() const {
292     return am_;
293   }
294 
IsImmediate()295   bool IsImmediate() const {
296     return is_immed_offset_;
297   }
298 
GetShift()299   Shift GetShift() const {
300     return shift_;
301   }
302 
GetShiftCount()303   int32_t GetShiftCount() const {
304     CHECK(!is_immed_offset_);
305     return offset_;
306   }
307 
308  private:
309   const Register rn_;
310   const Register rm_;
311   const int32_t offset_;      // Used as shift amount for register offset.
312   const Mode am_;
313   const bool is_immed_offset_;
314   const Shift shift_;
315 };
316 inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
317   os << static_cast<int>(rhs);
318   return os;
319 }
320 
321 // Instruction encoding bits.
322 enum {
323   H   = 1 << 5,   // halfword (or byte)
324   L   = 1 << 20,  // load (or store)
325   S   = 1 << 20,  // set condition code (or leave unchanged)
326   W   = 1 << 21,  // writeback base register (or leave unchanged)
327   A   = 1 << 21,  // accumulate in multiply instruction (or not)
328   B   = 1 << 22,  // unsigned byte (or word)
329   N   = 1 << 22,  // long (or short)
330   U   = 1 << 23,  // positive (or negative) offset/index
331   P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
332   I   = 1 << 25,  // immediate shifter operand (or not)
333 
334   B0 = 1,
335   B1 = 1 << 1,
336   B2 = 1 << 2,
337   B3 = 1 << 3,
338   B4 = 1 << 4,
339   B5 = 1 << 5,
340   B6 = 1 << 6,
341   B7 = 1 << 7,
342   B8 = 1 << 8,
343   B9 = 1 << 9,
344   B10 = 1 << 10,
345   B11 = 1 << 11,
346   B12 = 1 << 12,
347   B13 = 1 << 13,
348   B14 = 1 << 14,
349   B15 = 1 << 15,
350   B16 = 1 << 16,
351   B17 = 1 << 17,
352   B18 = 1 << 18,
353   B19 = 1 << 19,
354   B20 = 1 << 20,
355   B21 = 1 << 21,
356   B22 = 1 << 22,
357   B23 = 1 << 23,
358   B24 = 1 << 24,
359   B25 = 1 << 25,
360   B26 = 1 << 26,
361   B27 = 1 << 27,
362   B28 = 1 << 28,
363   B29 = 1 << 29,
364   B30 = 1 << 30,
365   B31 = 1 << 31,
366 
367   // Instruction bit masks.
368   RdMask = 15 << 12,  // in str instruction
369   CondMask = 15 << 28,
370   CoprocessorMask = 15 << 8,
371   OpCodeMask = 15 << 21,  // in data-processing instructions
372   Imm24Mask = (1 << 24) - 1,
373   Off12Mask = (1 << 12) - 1,
374 
375   // ldrex/strex register field encodings.
376   kLdExRnShift = 16,
377   kLdExRtShift = 12,
378   kStrExRnShift = 16,
379   kStrExRdShift = 12,
380   kStrExRtShift = 0,
381 };
382 
383 // IfThen state for IT instructions.
384 enum ItState {
385   kItOmitted,
386   kItThen,
387   kItT = kItThen,
388   kItElse,
389   kItE = kItElse
390 };
391 
392 constexpr uint32_t kNoItCondition = 3;
393 constexpr uint32_t kInvalidModifiedImmediate = -1;
394 
395 extern const char* kRegisterNames[];
396 extern const char* kConditionNames[];
397 
398 // This is an abstract ARM assembler.  Subclasses provide assemblers for the individual
399 // instruction sets (ARM32, Thumb2, etc.)
400 //
401 class ArmAssembler : public Assembler {
402  public:
~ArmAssembler()403   virtual ~ArmAssembler() {}
404 
405   // Is this assembler for the thumb instruction set?
406   virtual bool IsThumb() const = 0;
407 
408   // Data-processing instructions.
409   virtual void and_(Register rd, Register rn, const ShifterOperand& so,
410                     Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
411 
412   virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
413     and_(rd, rn, so, cond, kCcSet);
414   }
415 
416   virtual void eor(Register rd, Register rn, const ShifterOperand& so,
417                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
418 
419   virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
420     eor(rd, rn, so, cond, kCcSet);
421   }
422 
423   virtual void sub(Register rd, Register rn, const ShifterOperand& so,
424                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
425 
426   virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
427     sub(rd, rn, so, cond, kCcSet);
428   }
429 
430   virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
431                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
432 
433   virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
434     rsb(rd, rn, so, cond, kCcSet);
435   }
436 
437   virtual void add(Register rd, Register rn, const ShifterOperand& so,
438                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
439 
440   virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
441     add(rd, rn, so, cond, kCcSet);
442   }
443 
444   virtual void adc(Register rd, Register rn, const ShifterOperand& so,
445                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
446 
447   virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
448     adc(rd, rn, so, cond, kCcSet);
449   }
450 
451   virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
452                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
453 
454   virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
455     sbc(rd, rn, so, cond, kCcSet);
456   }
457 
458   virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
459                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
460 
461   virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
462     rsc(rd, rn, so, cond, kCcSet);
463   }
464 
465   virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
466 
467   virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
468 
469   virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
470 
471   // Note: CMN updates flags based on addition of its operands. Do not confuse
472   // the "N" suffix with bitwise inversion performed by MVN.
473   virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
474 
475   virtual void orr(Register rd, Register rn, const ShifterOperand& so,
476                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
477 
478   virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
479     orr(rd, rn, so, cond, kCcSet);
480   }
481 
482   virtual void orn(Register rd, Register rn, const ShifterOperand& so,
483                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
484 
485   virtual void orns(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
486     orn(rd, rn, so, cond, kCcSet);
487   }
488 
489   virtual void mov(Register rd, const ShifterOperand& so,
490                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
491 
492   virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) {
493     mov(rd, so, cond, kCcSet);
494   }
495 
496   virtual void bic(Register rd, Register rn, const ShifterOperand& so,
497                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
498 
499   virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
500     bic(rd, rn, so, cond, kCcSet);
501   }
502 
503   virtual void mvn(Register rd, const ShifterOperand& so,
504                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
505 
506   virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) {
507     mvn(rd, so, cond, kCcSet);
508   }
509 
510   // Miscellaneous data-processing instructions.
511   virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
512   virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
513   virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
514   virtual void rbit(Register rd, Register rm, Condition cond = AL) = 0;
515   virtual void rev(Register rd, Register rm, Condition cond = AL) = 0;
516   virtual void rev16(Register rd, Register rm, Condition cond = AL) = 0;
517   virtual void revsh(Register rd, Register rm, Condition cond = AL) = 0;
518 
519   // Multiply instructions.
520   virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
521   virtual void mla(Register rd, Register rn, Register rm, Register ra,
522                    Condition cond = AL) = 0;
523   virtual void mls(Register rd, Register rn, Register rm, Register ra,
524                    Condition cond = AL) = 0;
525   virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
526                      Condition cond = AL) = 0;
527   virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
528                      Condition cond = AL) = 0;
529 
530   virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
531   virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
532 
533   // Bit field extract instructions.
534   virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
535                     Condition cond = AL) = 0;
536   virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
537                     Condition cond = AL) = 0;
538 
539   // Load/store instructions.
540   virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
541   virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
542 
543   virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
544   virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
545 
546   virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
547   virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
548 
549   virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
550   virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
551 
552   virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
553   virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
554 
555   virtual void ldm(BlockAddressMode am, Register base,
556                    RegList regs, Condition cond = AL) = 0;
557   virtual void stm(BlockAddressMode am, Register base,
558                    RegList regs, Condition cond = AL) = 0;
559 
560   virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
561   virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
562   virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
563   virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
564 
565   // Miscellaneous instructions.
566   virtual void clrex(Condition cond = AL) = 0;
567   virtual void nop(Condition cond = AL) = 0;
568 
569   // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
570   virtual void bkpt(uint16_t imm16) = 0;
571   virtual void svc(uint32_t imm24) = 0;
572 
573   virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
574                   ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
575                   ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
576                   ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
577     // Ignored if not supported.
578   }
579 
580   virtual void cbz(Register rn, Label* target) = 0;
581   virtual void cbnz(Register rn, Label* target) = 0;
582 
583   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
584   virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
585   virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
586   virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
587   virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
588   virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
589   virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
590   virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
591   virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
592 
593   // Returns false if the immediate cannot be encoded.
594   virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
595   virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
596 
597   virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
598   virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
599   virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
600   virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
601 
602   virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
603   virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
604   virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
605   virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
606   virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
607   virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
608   virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
609   virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
610   virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
611   virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
612   virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
613   virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
614 
615   virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
616   virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
617   virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
618   virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
619   virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
620   virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
621 
622   virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
623   virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
624   virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
625   virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
626   virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
627   virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
628   virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
629   virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
630   virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
631   virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
632 
633   virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
634   virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
635   virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
636   virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
637   virtual void vmstat(Condition cond = AL) = 0;  // VMRS APSR_nzcv, FPSCR
638 
639   virtual void vcntd(DRegister dd, DRegister dm) = 0;
640   virtual void vpaddld(DRegister dd, DRegister dm, int32_t size, bool is_unsigned) = 0;
641 
642   virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
643   virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
644   virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
645   virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
646   virtual void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0;
647   virtual void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0;
648 
649   // Branch instructions.
650   virtual void b(Label* label, Condition cond = AL) = 0;
651   virtual void bl(Label* label, Condition cond = AL) = 0;
652   virtual void blx(Register rm, Condition cond = AL) = 0;
653   virtual void bx(Register rm, Condition cond = AL) = 0;
654 
655   // Memory barriers.
656   virtual void dmb(DmbOptions flavor) = 0;
657 
658   void Pad(uint32_t bytes);
659 
660   // Adjust label position.
AdjustLabelPosition(Label * label)661   void AdjustLabelPosition(Label* label) {
662     DCHECK(label->IsBound());
663     uint32_t old_position = static_cast<uint32_t>(label->Position());
664     uint32_t new_position = GetAdjustedPosition(old_position);
665     label->Reinitialize();
666     DCHECK_GE(static_cast<int>(new_position), 0);
667     label->BindTo(static_cast<int>(new_position));
668   }
669 
670   // Get the final position of a label after local fixup based on the old position
671   // recorded before FinalizeCode().
672   virtual uint32_t GetAdjustedPosition(uint32_t old_position) = 0;
673 
674   // Macros.
675   // Most of these are pure virtual as they need to be implemented per instruction set.
676 
677   // Create a new literal with a given value.
678   // NOTE: Force the template parameter to be explicitly specified.
679   template <typename T>
NewLiteral(typename Identity<T>::type value)680   Literal* NewLiteral(typename Identity<T>::type value) {
681     static_assert(std::is_integral<T>::value, "T must be an integral type.");
682     return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
683   }
684 
685   // Create a new literal with the given data.
686   virtual Literal* NewLiteral(size_t size, const uint8_t* data) = 0;
687 
688   // Load literal.
689   virtual void LoadLiteral(Register rt, Literal* literal) = 0;
690   virtual void LoadLiteral(Register rt, Register rt2, Literal* literal) = 0;
691   virtual void LoadLiteral(SRegister sd, Literal* literal) = 0;
692   virtual void LoadLiteral(DRegister dd, Literal* literal) = 0;
693 
694   // Add signed constant value to rd. May clobber IP.
695   virtual void AddConstant(Register rd, Register rn, int32_t value,
696                            Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
697   void AddConstantSetFlags(Register rd, Register rn, int32_t value, Condition cond = AL) {
698     AddConstant(rd, rn, value, cond, kCcSet);
699   }
700   void AddConstant(Register rd, int32_t value, Condition cond = AL, SetCc set_cc = kCcDontCare) {
701     AddConstant(rd, rd, value, cond, set_cc);
702   }
703 
704   virtual void CmpConstant(Register rn, int32_t value, Condition cond = AL) = 0;
705 
706   // Load and Store. May clobber IP.
707   virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
708   void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
709     if (!vmovs(sd, value, cond)) {
710       int32_t int_value = bit_cast<int32_t, float>(value);
711       if (int_value == bit_cast<int32_t, float>(0.0f)) {
712         // 0.0 is quite common, so we special case it by loading
713         // 2.0 in `sd` and then substracting it.
714         bool success = vmovs(sd, 2.0, cond);
715         CHECK(success);
716         vsubs(sd, sd, sd, cond);
717       } else {
718         LoadImmediate(IP, int_value, cond);
719         vmovsr(sd, IP, cond);
720       }
721     }
722   }
723 
724   virtual void LoadDImmediate(DRegister dd, double value, Condition cond = AL) = 0;
725 
726   virtual void MarkExceptionHandler(Label* label) = 0;
727   virtual void LoadFromOffset(LoadOperandType type,
728                               Register reg,
729                               Register base,
730                               int32_t offset,
731                               Condition cond = AL) = 0;
732   virtual void StoreToOffset(StoreOperandType type,
733                              Register reg,
734                              Register base,
735                              int32_t offset,
736                              Condition cond = AL) = 0;
737   virtual void LoadSFromOffset(SRegister reg,
738                                Register base,
739                                int32_t offset,
740                                Condition cond = AL) = 0;
741   virtual void StoreSToOffset(SRegister reg,
742                               Register base,
743                               int32_t offset,
744                               Condition cond = AL) = 0;
745   virtual void LoadDFromOffset(DRegister reg,
746                                Register base,
747                                int32_t offset,
748                                Condition cond = AL) = 0;
749   virtual void StoreDToOffset(DRegister reg,
750                               Register base,
751                               int32_t offset,
752                               Condition cond = AL) = 0;
753 
754   virtual void Push(Register rd, Condition cond = AL) = 0;
755   virtual void Pop(Register rd, Condition cond = AL) = 0;
756 
757   virtual void PushList(RegList regs, Condition cond = AL) = 0;
758   virtual void PopList(RegList regs, Condition cond = AL) = 0;
759 
760   virtual void StoreList(RegList regs, size_t stack_offset) = 0;
761   virtual void LoadList(RegList regs, size_t stack_offset) = 0;
762 
763   virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
764 
765   // Convenience shift instructions. Use mov instruction with shifter operand
766   // for variants setting the status flags or using a register shift count.
767   virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
768                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
769 
770   void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
771     Lsl(rd, rm, shift_imm, cond, kCcSet);
772   }
773 
774   virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
775                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
776 
777   void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
778     Lsr(rd, rm, shift_imm, cond, kCcSet);
779   }
780 
781   virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
782                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
783 
784   void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
785     Asr(rd, rm, shift_imm, cond, kCcSet);
786   }
787 
788   virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
789                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
790 
791   void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
792     Ror(rd, rm, shift_imm, cond, kCcSet);
793   }
794 
795   virtual void Rrx(Register rd, Register rm,
796                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
797 
798   void Rrxs(Register rd, Register rm, Condition cond = AL) {
799     Rrx(rd, rm, cond, kCcSet);
800   }
801 
802   virtual void Lsl(Register rd, Register rm, Register rn,
803                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
804 
805   void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) {
806     Lsl(rd, rm, rn, cond, kCcSet);
807   }
808 
809   virtual void Lsr(Register rd, Register rm, Register rn,
810                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
811 
812   void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) {
813     Lsr(rd, rm, rn, cond, kCcSet);
814   }
815 
816   virtual void Asr(Register rd, Register rm, Register rn,
817                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
818 
819   void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) {
820     Asr(rd, rm, rn, cond, kCcSet);
821   }
822 
823   virtual void Ror(Register rd, Register rm, Register rn,
824                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
825 
826   void Rors(Register rd, Register rm, Register rn, Condition cond = AL) {
827     Ror(rd, rm, rn, cond, kCcSet);
828   }
829 
830   // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
831   // `shifter_op` contains the operand.
832   virtual bool ShifterOperandCanHold(Register rd,
833                                      Register rn,
834                                      Opcode opcode,
835                                      uint32_t immediate,
836                                      SetCc set_cc,
837                                      ShifterOperand* shifter_op) = 0;
ShifterOperandCanHold(Register rd,Register rn,Opcode opcode,uint32_t immediate,ShifterOperand * shifter_op)838   bool ShifterOperandCanHold(Register rd,
839                              Register rn,
840                              Opcode opcode,
841                              uint32_t immediate,
842                              ShifterOperand* shifter_op) {
843     return ShifterOperandCanHold(rd, rn, opcode, immediate, kCcDontCare, shifter_op);
844   }
845 
846   virtual bool ShifterOperandCanAlwaysHold(uint32_t immediate) = 0;
847 
848   static bool IsInstructionForExceptionHandling(uintptr_t pc);
849 
850   virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
851   virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
852 
853   static uint32_t ModifiedImmediate(uint32_t value);
854 
IsLowRegister(Register r)855   static bool IsLowRegister(Register r) {
856     return r < R8;
857   }
858 
IsHighRegister(Register r)859   static bool IsHighRegister(Register r) {
860      return r >= R8;
861   }
862 
863   //
864   // Heap poisoning.
865   //
866 
867   // Poison a heap reference contained in `reg`.
PoisonHeapReference(Register reg)868   void PoisonHeapReference(Register reg) {
869     // reg = -reg.
870     rsb(reg, reg, ShifterOperand(0));
871   }
872   // Unpoison a heap reference contained in `reg`.
UnpoisonHeapReference(Register reg)873   void UnpoisonHeapReference(Register reg) {
874     // reg = -reg.
875     rsb(reg, reg, ShifterOperand(0));
876   }
877   // Poison a heap reference contained in `reg` if heap poisoning is enabled.
MaybePoisonHeapReference(Register reg)878   void MaybePoisonHeapReference(Register reg) {
879     if (kPoisonHeapReferences) {
880       PoisonHeapReference(reg);
881     }
882   }
883   // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
MaybeUnpoisonHeapReference(Register reg)884   void MaybeUnpoisonHeapReference(Register reg) {
885     if (kPoisonHeapReferences) {
886       UnpoisonHeapReference(reg);
887     }
888   }
889 
Jump(Label * label)890   void Jump(Label* label) OVERRIDE {
891     b(label);
892   }
893 
894   // Jump table support. This is split into three functions:
895   //
896   // * CreateJumpTable creates the internal metadata to track the jump targets, and emits code to
897   // load the base address of the jump table.
898   //
899   // * EmitJumpTableDispatch emits the code to actually jump, assuming that the right table value
900   // has been loaded into a register already.
901   //
902   // * FinalizeTables emits the jump table into the literal pool. This can only be called after the
903   // labels for the jump targets have been finalized.
904 
905   // Create a jump table for the given labels that will be emitted when finalizing. Create a load
906   // sequence (or placeholder) that stores the base address into the given register. When the table
907   // is emitted, offsets will be relative to the location EmitJumpTableDispatch was called on (the
908   // anchor).
909   virtual JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) = 0;
910 
911   // Emit the jump-table jump, assuming that the right value was loaded into displacement_reg.
912   virtual void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) = 0;
913 
914   // Bind a Label that needs to be updated by the assembler in FinalizeCode() if its position
915   // changes due to branch/literal fixup.
BindTrackedLabel(Label * label)916   void BindTrackedLabel(Label* label) {
917     Bind(label);
918     tracked_labels_.push_back(label);
919   }
920 
921  protected:
ArmAssembler(ArenaAllocator * arena)922   explicit ArmAssembler(ArenaAllocator* arena)
923       : Assembler(arena), tracked_labels_(arena->Adapter(kArenaAllocAssembler)) {}
924 
925   // Returns whether or not the given register is used for passing parameters.
RegisterCompare(const Register * reg1,const Register * reg2)926   static int RegisterCompare(const Register* reg1, const Register* reg2) {
927     return *reg1 - *reg2;
928   }
929 
930   void FinalizeTrackedLabels();
931 
932   // Tracked labels. Use a vector, as we need to sort before adjusting.
933   ArenaVector<Label*> tracked_labels_;
934 };
935 
936 }  // namespace arm
937 }  // namespace art
938 
939 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
940