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