blob: bb88e6fdf44e3992e1097961049f85f496ed99cd [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070016
Ian Rogers166db042013-07-26 12:05:57 -070017#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
18#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070019
Vladimir Markocf93a5c2015-06-16 11:33:24 +000020#include <type_traits>
Elliott Hughes07ed66b2012-12-12 18:34:25 -080021#include <vector>
22
Vladimir Marko93205e32016-04-13 11:59:46 +010023#include "base/arena_allocator.h"
24#include "base/arena_containers.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010025#include "base/bit_utils.h"
Andreas Gampe3b165bc2016-08-01 22:07:04 -070026#include "base/enums.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080027#include "base/logging.h"
Vladimir Marko88b2b802015-12-04 14:19:04 +000028#include "base/stl_util.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070029#include "base/value_object.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070030#include "constants_arm.h"
Ian Rogers166db042013-07-26 12:05:57 -070031#include "utils/arm/managed_register_arm.h"
32#include "utils/assembler.h"
Andreas Gampe3b165bc2016-08-01 22:07:04 -070033#include "utils/jni_macro_assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070034#include "offsets.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070035
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070036namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070037namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070038
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +000039class Arm32Assembler;
40class Thumb2Assembler;
41
Vladimir Markocf93a5c2015-06-16 11:33:24 +000042// Assembler literal is a value embedded in code, retrieved using a PC-relative load.
43class Literal {
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +000044 public:
Vladimir Markocf93a5c2015-06-16 11:33:24 +000045 static constexpr size_t kMaxSize = 8;
46
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>
54 T GetValue() const {
55 DCHECK_EQ(size_, sizeof(T));
56 T value;
57 memcpy(&value, data_, sizeof(T));
58 return value;
59 }
60
61 uint32_t GetSize() const {
62 return size_;
63 }
64
65 const uint8_t* GetData() const {
66 return data_;
67 }
68
69 Label* GetLabel() {
70 return &label_;
71 }
72
73 const Label* GetLabel() const {
74 return &label_;
75 }
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +000076
77 private:
Vladimir Markocf93a5c2015-06-16 11:33:24 +000078 Label label_;
79 const uint32_t size_;
80 uint8_t data_[kMaxSize];
81
82 DISALLOW_COPY_AND_ASSIGN(Literal);
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +000083};
84
Andreas Gampe7cffc3b2015-10-19 21:31:53 -070085// Jump table: table of labels emitted after the literals. Similar to literals.
86class JumpTable {
87 public:
88 explicit JumpTable(std::vector<Label*>&& labels)
89 : label_(), anchor_label_(), labels_(std::move(labels)) {
90 }
91
92 uint32_t GetSize() const {
93 return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t);
94 }
95
96 const std::vector<Label*>& GetData() const {
97 return labels_;
98 }
99
100 Label* GetLabel() {
101 return &label_;
102 }
103
104 const Label* GetLabel() const {
105 return &label_;
106 }
107
108 Label* GetAnchorLabel() {
109 return &anchor_label_;
110 }
111
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
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700124class ShifterOperand {
125 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700126 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
127 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700128 }
129
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100130 explicit ShifterOperand(uint32_t immed);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700131
132 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -0700133 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
134 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700135 }
136
Dave Allison65fcc2c2014-04-28 13:45:27 -0700137 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
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) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700145 }
146
147 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -0700148 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) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700151 }
152
Dave Allison65fcc2c2014-04-28 13:45:27 -0700153 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700154
155 uint32_t type() const {
156 CHECK(is_valid());
157 return type_;
158 }
159
Dave Allison65fcc2c2014-04-28 13:45:27 -0700160 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700161 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700162
163 bool IsEmpty() const {
164 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700165 }
166
Dave Allison65fcc2c2014-04-28 13:45:27 -0700167 bool IsImmediate() const {
168 return type_ == kImmediate;
169 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700170
Dave Allison65fcc2c2014-04-28 13:45:27 -0700171 bool IsRegister() const {
172 return type_ == kRegister;
173 }
174
175 bool IsShift() const {
176 return is_shift_;
177 }
178
179 uint32_t GetImmediate() const {
180 return immed_;
181 }
182
183 Shift GetShift() const {
184 return shift_;
185 }
186
187 Register GetRegister() const {
188 return rm_;
189 }
190
Guillaume "Vermeille" Sanchezab4a2f52015-03-11 14:00:30 +0000191 Register GetSecondRegister() const {
192 return rs_;
193 }
194
Dave Allison65fcc2c2014-04-28 13:45:27 -0700195 enum Type {
196 kUnknown = -1,
197 kRegister,
198 kImmediate
199 };
200
Dave Allison65fcc2c2014-04-28 13:45:27 -0700201 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
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000211 friend class Arm32Assembler;
212 friend class Thumb2Assembler;
213
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700214#ifdef SOURCE_ASSEMBLER_SUPPORT
215 friend class BinaryAssembler;
216#endif
217};
218
219
220enum LoadOperandType {
221 kLoadSignedByte,
222 kLoadUnsignedByte,
223 kLoadSignedHalfword,
224 kLoadUnsignedHalfword,
225 kLoadWord,
226 kLoadWordPair,
227 kLoadSWord,
228 kLoadDWord
229};
230
231
232enum StoreOperandType {
233 kStoreByte,
234 kStoreHalfword,
235 kStoreWord,
236 kStoreWordPair,
237 kStoreSWord,
238 kStoreDWord
239};
240
241
242// Load/store multiple addressing mode.
243enum BlockAddressMode {
244 // bit encoding P U W
245 DA = (0|0|0) << 21, // decrement after
246 IA = (0|4|0) << 21, // increment after
247 DB = (8|0|0) << 21, // decrement before
248 IB = (8|4|0) << 21, // increment before
249 DA_W = (0|0|1) << 21, // decrement after with writeback to base
250 IA_W = (0|4|1) << 21, // increment after with writeback to base
251 DB_W = (8|0|1) << 21, // decrement before with writeback to base
252 IB_W = (8|4|1) << 21 // increment before with writeback to base
253};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700254inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
255 os << static_cast<int>(rhs);
256 return os;
257}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700258
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700259class Address : public ValueObject {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700260 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700261 // Memory operand addressing mode (in ARM encoding form. For others we need
262 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700263 enum Mode {
264 // bit encoding P U W
265 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
266 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
267 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
268 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
269 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
270 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
271 };
272
Dave Allison45fdb932014-06-25 12:37:10 -0700273 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
274 offset_(offset),
275 am_(am), is_immed_offset_(true), shift_(LSL) {
276 }
277
278 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
279 am_(am), is_immed_offset_(false), shift_(LSL) {
280 CHECK_NE(rm, PC);
281 }
282
283 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
284 rn_(rn), rm_(rm), offset_(count),
285 am_(am), is_immed_offset_(false), shift_(shift) {
286 CHECK_NE(rm, PC);
287 }
288
289 // LDR(literal) - pc relative load.
290 explicit Address(int32_t offset) :
291 rn_(PC), rm_(R0), offset_(offset),
292 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700293 }
294
Dave Allison65fcc2c2014-04-28 13:45:27 -0700295 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
296 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
297
298 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
299 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
300
301 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700302 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700303
304 uint32_t encoding3() const;
305 uint32_t vencoding() const;
306
307 uint32_t encodingThumbLdrdStrd() const;
308
309 Register GetRegister() const {
310 return rn_;
311 }
312
Dave Allison45fdb932014-06-25 12:37:10 -0700313 Register GetRegisterOffset() const {
314 return rm_;
315 }
316
Dave Allison65fcc2c2014-04-28 13:45:27 -0700317 int32_t GetOffset() const {
318 return offset_;
319 }
320
321 Mode GetMode() const {
322 return am_;
323 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700324
Dave Allison45fdb932014-06-25 12:37:10 -0700325 bool IsImmediate() const {
326 return is_immed_offset_;
327 }
328
329 Shift GetShift() const {
330 return shift_;
331 }
332
333 int32_t GetShiftCount() const {
334 CHECK(!is_immed_offset_);
335 return offset_;
336 }
337
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700338 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700339 const Register rn_;
340 const Register rm_;
341 const int32_t offset_; // Used as shift amount for register offset.
342 const Mode am_;
343 const bool is_immed_offset_;
344 const Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700345};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700346inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
347 os << static_cast<int>(rhs);
348 return os;
349}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700350
Dave Allison65fcc2c2014-04-28 13:45:27 -0700351// Instruction encoding bits.
352enum {
353 H = 1 << 5, // halfword (or byte)
354 L = 1 << 20, // load (or store)
355 S = 1 << 20, // set condition code (or leave unchanged)
356 W = 1 << 21, // writeback base register (or leave unchanged)
357 A = 1 << 21, // accumulate in multiply instruction (or not)
358 B = 1 << 22, // unsigned byte (or word)
359 N = 1 << 22, // long (or short)
360 U = 1 << 23, // positive (or negative) offset/index
361 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
362 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700363
Dave Allison65fcc2c2014-04-28 13:45:27 -0700364 B0 = 1,
365 B1 = 1 << 1,
366 B2 = 1 << 2,
367 B3 = 1 << 3,
368 B4 = 1 << 4,
369 B5 = 1 << 5,
370 B6 = 1 << 6,
371 B7 = 1 << 7,
372 B8 = 1 << 8,
373 B9 = 1 << 9,
374 B10 = 1 << 10,
375 B11 = 1 << 11,
376 B12 = 1 << 12,
377 B13 = 1 << 13,
378 B14 = 1 << 14,
379 B15 = 1 << 15,
380 B16 = 1 << 16,
381 B17 = 1 << 17,
382 B18 = 1 << 18,
383 B19 = 1 << 19,
384 B20 = 1 << 20,
385 B21 = 1 << 21,
386 B22 = 1 << 22,
387 B23 = 1 << 23,
388 B24 = 1 << 24,
389 B25 = 1 << 25,
390 B26 = 1 << 26,
391 B27 = 1 << 27,
392 B28 = 1 << 28,
393 B29 = 1 << 29,
394 B30 = 1 << 30,
395 B31 = 1 << 31,
396
397 // Instruction bit masks.
398 RdMask = 15 << 12, // in str instruction
399 CondMask = 15 << 28,
400 CoprocessorMask = 15 << 8,
401 OpCodeMask = 15 << 21, // in data-processing instructions
402 Imm24Mask = (1 << 24) - 1,
403 Off12Mask = (1 << 12) - 1,
404
405 // ldrex/strex register field encodings.
406 kLdExRnShift = 16,
407 kLdExRtShift = 12,
408 kStrExRnShift = 16,
409 kStrExRdShift = 12,
410 kStrExRtShift = 0,
411};
412
413// IfThen state for IT instructions.
414enum ItState {
415 kItOmitted,
416 kItThen,
417 kItT = kItThen,
418 kItElse,
419 kItE = kItElse
420};
421
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100422// Set condition codes request.
423enum SetCc {
424 kCcDontCare, // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not.
425 kCcSet,
426 kCcKeep,
427};
428
Dave Allison65fcc2c2014-04-28 13:45:27 -0700429constexpr uint32_t kNoItCondition = 3;
430constexpr uint32_t kInvalidModifiedImmediate = -1;
431
432extern const char* kRegisterNames[];
433extern const char* kConditionNames[];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700434
435// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
436// instruction sets (ARM32, Thumb2, etc.)
437//
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700438class ArmAssembler : public Assembler, public JNIMacroAssembler<PointerSize::k32> {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700439 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700440 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700441
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700442 size_t CodeSize() const OVERRIDE { return Assembler::CodeSize(); }
443 DebugFrameOpCodeWriterForAssembler& cfi() { return Assembler::cfi(); }
444 void FinalizeCode() OVERRIDE {
445 Assembler::FinalizeCode();
446 }
447 void FinalizeInstructions(const MemoryRegion& region) {
448 Assembler::FinalizeInstructions(region);
449 }
450
Dave Allison65fcc2c2014-04-28 13:45:27 -0700451 // Is this assembler for the thumb instruction set?
452 virtual bool IsThumb() const = 0;
453
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700454 // Data-processing instructions.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100455 virtual void and_(Register rd, Register rn, const ShifterOperand& so,
456 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700457
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100458 virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
459 and_(rd, rn, so, cond, kCcSet);
460 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700461
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100462 virtual void eor(Register rd, Register rn, const ShifterOperand& so,
463 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700464
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100465 virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
466 eor(rd, rn, so, cond, kCcSet);
467 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700468
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100469 virtual void sub(Register rd, Register rn, const ShifterOperand& so,
470 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700471
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100472 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
473 sub(rd, rn, so, cond, kCcSet);
474 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700475
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100476 virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
477 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700478
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100479 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
480 rsb(rd, rn, so, cond, kCcSet);
481 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700482
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100483 virtual void add(Register rd, Register rn, const ShifterOperand& so,
484 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
485
486 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
487 add(rd, rn, so, cond, kCcSet);
488 }
489
490 virtual void adc(Register rd, Register rn, const ShifterOperand& so,
491 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
492
493 virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
494 adc(rd, rn, so, cond, kCcSet);
495 }
496
497 virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
498 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
499
500 virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
501 sbc(rd, rn, so, cond, kCcSet);
502 }
503
504 virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
505 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
506
507 virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
508 rsc(rd, rn, so, cond, kCcSet);
509 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700510
Dave Allison65fcc2c2014-04-28 13:45:27 -0700511 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700512
Dave Allison65fcc2c2014-04-28 13:45:27 -0700513 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700514
Dave Allison65fcc2c2014-04-28 13:45:27 -0700515 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700516
Vladimir Markoac6ac102015-12-17 12:14:00 +0000517 // Note: CMN updates flags based on addition of its operands. Do not confuse
518 // the "N" suffix with bitwise inversion performed by MVN.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700519 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700520
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100521 virtual void orr(Register rd, Register rn, const ShifterOperand& so,
522 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700523
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100524 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
525 orr(rd, rn, so, cond, kCcSet);
526 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700527
Vladimir Markod2b4ca22015-09-14 15:13:26 +0100528 virtual void orn(Register rd, Register rn, const ShifterOperand& so,
529 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
530
531 virtual void orns(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
532 orn(rd, rn, so, cond, kCcSet);
533 }
534
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100535 virtual void mov(Register rd, const ShifterOperand& so,
536 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700537
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100538 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) {
539 mov(rd, so, cond, kCcSet);
540 }
541
542 virtual void bic(Register rd, Register rn, const ShifterOperand& so,
543 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
544
545 virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
546 bic(rd, rn, so, cond, kCcSet);
547 }
548
549 virtual void mvn(Register rd, const ShifterOperand& so,
550 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
551
552 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) {
553 mvn(rd, so, cond, kCcSet);
554 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700555
556 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700557 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
558 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
559 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100560 virtual void rbit(Register rd, Register rm, Condition cond = AL) = 0;
Artem Serovc257da72016-02-02 13:49:43 +0000561 virtual void rev(Register rd, Register rm, Condition cond = AL) = 0;
562 virtual void rev16(Register rd, Register rm, Condition cond = AL) = 0;
563 virtual void revsh(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700564
565 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700566 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
567 virtual void mla(Register rd, Register rn, Register rm, Register ra,
568 Condition cond = AL) = 0;
569 virtual void mls(Register rd, Register rn, Register rm, Register ra,
570 Condition cond = AL) = 0;
Zheng Xuc6667102015-05-15 16:08:45 +0800571 virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
572 Condition cond = AL) = 0;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700573 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
574 Condition cond = AL) = 0;
575
576 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
577 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700578
Roland Levillain981e4542014-11-14 11:47:14 +0000579 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000580 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
581 Condition cond = AL) = 0;
Roland Levillain981e4542014-11-14 11:47:14 +0000582 virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
583 Condition cond = AL) = 0;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000584
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700585 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700586 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
587 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700588
Dave Allison65fcc2c2014-04-28 13:45:27 -0700589 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
590 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700591
Dave Allison65fcc2c2014-04-28 13:45:27 -0700592 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
593 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700594
Dave Allison65fcc2c2014-04-28 13:45:27 -0700595 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
596 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700597
Dave Allison65fcc2c2014-04-28 13:45:27 -0700598 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
599 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700600
Dave Allison65fcc2c2014-04-28 13:45:27 -0700601 virtual void ldm(BlockAddressMode am, Register base,
602 RegList regs, Condition cond = AL) = 0;
603 virtual void stm(BlockAddressMode am, Register base,
604 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700605
Dave Allison65fcc2c2014-04-28 13:45:27 -0700606 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
607 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Calin Juravle52c48962014-12-16 17:02:57 +0000608 virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
609 virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700610
611 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700612 virtual void clrex(Condition cond = AL) = 0;
613 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700614
615 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700616 virtual void bkpt(uint16_t imm16) = 0;
617 virtual void svc(uint32_t imm24) = 0;
618
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700619 virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
620 ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
621 ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
622 ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700623 // Ignored if not supported.
624 }
625
626 virtual void cbz(Register rn, Label* target) = 0;
627 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700628
629 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700630 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
631 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
632 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
633 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
634 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
635 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
636 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
637 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700638
639 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700640 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
641 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700642
Dave Allison65fcc2c2014-04-28 13:45:27 -0700643 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
644 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
645 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
646 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700647
Dave Allison65fcc2c2014-04-28 13:45:27 -0700648 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
649 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
650 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
651 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
652 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
653 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
654 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
655 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
656 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
657 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
658 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
659 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700660
Dave Allison65fcc2c2014-04-28 13:45:27 -0700661 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
662 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
663 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
664 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
665 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
666 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700667
Dave Allison65fcc2c2014-04-28 13:45:27 -0700668 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
669 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
670 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
671 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
672 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
673 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
674 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
675 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
676 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
677 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700678
Dave Allison65fcc2c2014-04-28 13:45:27 -0700679 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
680 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
681 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
682 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
683 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
684
xueliang.zhonge652c122016-06-13 14:42:27 +0100685 virtual void vcntd(DRegister dd, DRegister dm) = 0;
686 virtual void vpaddld(DRegister dd, DRegister dm, int32_t size, bool is_unsigned) = 0;
687
Dave Allison65fcc2c2014-04-28 13:45:27 -0700688 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
689 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
690 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
691 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700692
693 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700694 virtual void b(Label* label, Condition cond = AL) = 0;
695 virtual void bl(Label* label, Condition cond = AL) = 0;
696 virtual void blx(Register rm, Condition cond = AL) = 0;
697 virtual void bx(Register rm, Condition cond = AL) = 0;
698
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100699 // Memory barriers.
700 virtual void dmb(DmbOptions flavor) = 0;
701
Dave Allison65fcc2c2014-04-28 13:45:27 -0700702 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700703
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000704 // Adjust label position.
705 void AdjustLabelPosition(Label* label) {
706 DCHECK(label->IsBound());
707 uint32_t old_position = static_cast<uint32_t>(label->Position());
708 uint32_t new_position = GetAdjustedPosition(old_position);
709 label->Reinitialize();
710 DCHECK_GE(static_cast<int>(new_position), 0);
711 label->BindTo(static_cast<int>(new_position));
712 }
713
714 // Get the final position of a label after local fixup based on the old position
715 // recorded before FinalizeCode().
716 virtual uint32_t GetAdjustedPosition(uint32_t old_position) = 0;
717
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700718 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700719 // Most of these are pure virtual as they need to be implemented per instruction set.
720
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000721 // Create a new literal with a given value.
Vladimir Marko88b2b802015-12-04 14:19:04 +0000722 // NOTE: Force the template parameter to be explicitly specified.
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000723 template <typename T>
Vladimir Marko88b2b802015-12-04 14:19:04 +0000724 Literal* NewLiteral(typename Identity<T>::type value) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000725 static_assert(std::is_integral<T>::value, "T must be an integral type.");
726 return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
727 }
728
729 // Create a new literal with the given data.
730 virtual Literal* NewLiteral(size_t size, const uint8_t* data) = 0;
731
732 // Load literal.
733 virtual void LoadLiteral(Register rt, Literal* literal) = 0;
734 virtual void LoadLiteral(Register rt, Register rt2, Literal* literal) = 0;
735 virtual void LoadLiteral(SRegister sd, Literal* literal) = 0;
736 virtual void LoadLiteral(DRegister dd, Literal* literal) = 0;
737
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700738 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700739 virtual void AddConstant(Register rd, Register rn, int32_t value,
Vladimir Marko449b1092015-09-08 12:16:45 +0100740 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
741 void AddConstantSetFlags(Register rd, Register rn, int32_t value, Condition cond = AL) {
742 AddConstant(rd, rn, value, cond, kCcSet);
743 }
744 void AddConstant(Register rd, int32_t value, Condition cond = AL, SetCc set_cc = kCcDontCare) {
745 AddConstant(rd, rd, value, cond, set_cc);
746 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700747
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700748 virtual void CmpConstant(Register rn, int32_t value, Condition cond = AL) = 0;
749
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700750 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700751 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000752 void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
753 if (!vmovs(sd, value, cond)) {
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000754 int32_t int_value = bit_cast<int32_t, float>(value);
755 if (int_value == bit_cast<int32_t, float>(0.0f)) {
756 // 0.0 is quite common, so we special case it by loading
757 // 2.0 in `sd` and then substracting it.
758 bool success = vmovs(sd, 2.0, cond);
759 CHECK(success);
760 vsubs(sd, sd, sd, cond);
761 } else {
762 LoadImmediate(IP, int_value, cond);
763 vmovsr(sd, IP, cond);
764 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000765 }
766 }
767
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100768 virtual void LoadDImmediate(DRegister dd, double value, Condition cond = AL) = 0;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000769
Dave Allison65fcc2c2014-04-28 13:45:27 -0700770 virtual void MarkExceptionHandler(Label* label) = 0;
771 virtual void LoadFromOffset(LoadOperandType type,
772 Register reg,
773 Register base,
774 int32_t offset,
775 Condition cond = AL) = 0;
776 virtual void StoreToOffset(StoreOperandType type,
777 Register reg,
778 Register base,
779 int32_t offset,
780 Condition cond = AL) = 0;
781 virtual void LoadSFromOffset(SRegister reg,
782 Register base,
783 int32_t offset,
784 Condition cond = AL) = 0;
785 virtual void StoreSToOffset(SRegister reg,
786 Register base,
787 int32_t offset,
788 Condition cond = AL) = 0;
789 virtual void LoadDFromOffset(DRegister reg,
790 Register base,
791 int32_t offset,
792 Condition cond = AL) = 0;
793 virtual void StoreDToOffset(DRegister reg,
794 Register base,
795 int32_t offset,
796 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700797
Dave Allison65fcc2c2014-04-28 13:45:27 -0700798 virtual void Push(Register rd, Condition cond = AL) = 0;
799 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700800
Dave Allison65fcc2c2014-04-28 13:45:27 -0700801 virtual void PushList(RegList regs, Condition cond = AL) = 0;
802 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700803
Dave Allison65fcc2c2014-04-28 13:45:27 -0700804 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700805
806 // Convenience shift instructions. Use mov instruction with shifter operand
807 // for variants setting the status flags or using a register shift count.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100808 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
809 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Dave Allison45fdb932014-06-25 12:37:10 -0700810
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100811 void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
812 Lsl(rd, rm, shift_imm, cond, kCcSet);
813 }
814
815 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
816 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
817
818 void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
819 Lsr(rd, rm, shift_imm, cond, kCcSet);
820 }
821
822 virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
823 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
824
825 void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
826 Asr(rd, rm, shift_imm, cond, kCcSet);
827 }
828
829 virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
830 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
831
832 void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
833 Ror(rd, rm, shift_imm, cond, kCcSet);
834 }
835
836 virtual void Rrx(Register rd, Register rm,
837 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
838
839 void Rrxs(Register rd, Register rm, Condition cond = AL) {
840 Rrx(rd, rm, cond, kCcSet);
841 }
842
843 virtual void Lsl(Register rd, Register rm, Register rn,
844 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
845
846 void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) {
847 Lsl(rd, rm, rn, cond, kCcSet);
848 }
849
850 virtual void Lsr(Register rd, Register rm, Register rn,
851 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
852
853 void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) {
854 Lsr(rd, rm, rn, cond, kCcSet);
855 }
856
857 virtual void Asr(Register rd, Register rm, Register rn,
858 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
859
860 void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) {
861 Asr(rd, rm, rn, cond, kCcSet);
862 }
863
864 virtual void Ror(Register rd, Register rm, Register rn,
865 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
866
867 void Rors(Register rd, Register rm, Register rn, Condition cond = AL) {
868 Ror(rd, rm, rn, cond, kCcSet);
869 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700870
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000871 // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
872 // `shifter_op` contains the operand.
873 virtual bool ShifterOperandCanHold(Register rd,
874 Register rn,
875 Opcode opcode,
876 uint32_t immediate,
Vladimir Markof5c09c32015-12-17 12:08:08 +0000877 SetCc set_cc,
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000878 ShifterOperand* shifter_op) = 0;
Vladimir Markof5c09c32015-12-17 12:08:08 +0000879 bool ShifterOperandCanHold(Register rd,
880 Register rn,
881 Opcode opcode,
882 uint32_t immediate,
883 ShifterOperand* shifter_op) {
884 return ShifterOperandCanHold(rd, rn, opcode, immediate, kCcDontCare, shifter_op);
885 }
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000886
Nicolas Geoffray0ccb3832015-10-14 11:44:23 +0100887 virtual bool ShifterOperandCanAlwaysHold(uint32_t immediate) = 0;
Nicolas Geoffray5bd05a52015-10-13 09:48:30 +0100888
Ian Rogers13735952014-10-08 12:43:28 -0700889 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700890
Dave Allison65fcc2c2014-04-28 13:45:27 -0700891 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
892 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700893
Ian Rogers2c8f6532011-09-02 17:16:34 -0700894 //
895 // Overridden common assembler high-level functionality
896 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700897
Ian Rogers2c8f6532011-09-02 17:16:34 -0700898 // Emit code that will create an activation on the stack
Vladimir Marko32248382016-05-19 10:37:24 +0100899 void BuildFrame(size_t frame_size,
900 ManagedRegister method_reg,
901 ArrayRef<const ManagedRegister> callee_save_regs,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700902 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700903
Ian Rogers2c8f6532011-09-02 17:16:34 -0700904 // Emit code that will remove an activation from the stack
Vladimir Marko32248382016-05-19 10:37:24 +0100905 void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700906 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700907
Ian Rogersdd7624d2014-03-14 17:43:00 -0700908 void IncreaseFrameSize(size_t adjust) OVERRIDE;
909 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700910
911 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700912 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
913 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
914 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700915
Ian Rogersdd7624d2014-03-14 17:43:00 -0700916 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700917
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700918 void StoreStackOffsetToThread(ThreadOffset32 thr_offs,
919 FrameOffset fr_offs,
920 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700921
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700922 void StoreStackPointerToThread(ThreadOffset32 thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700923
Ian Rogersdd7624d2014-03-14 17:43:00 -0700924 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
925 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700926
Ian Rogers2c8f6532011-09-02 17:16:34 -0700927 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700928 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700929
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700930 void LoadFromThread(ManagedRegister dest, ThreadOffset32 src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700931
Mathieu Chartiere401d142015-04-22 13:56:20 -0700932 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700933
Mathieu Chartiere401d142015-04-22 13:56:20 -0700934 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
Roland Levillain4d027112015-07-01 15:41:14 +0100935 bool unpoison_reference) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700936
Ian Rogersdd7624d2014-03-14 17:43:00 -0700937 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700938
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700939 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset32 offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700940
941 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700942 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700943
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700944 void CopyRawPtrFromThread(FrameOffset fr_offs,
945 ThreadOffset32 thr_offs,
946 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700947
Andreas Gampe3b165bc2016-08-01 22:07:04 -0700948 void CopyRawPtrToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
Ian Rogersdd7624d2014-03-14 17:43:00 -0700949 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700950
Ian Rogersdd7624d2014-03-14 17:43:00 -0700951 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700952
Ian Rogersdd7624d2014-03-14 17:43:00 -0700953 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700954
Ian Rogersdd7624d2014-03-14 17:43:00 -0700955 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
956 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700957
Ian Rogersdd7624d2014-03-14 17:43:00 -0700958 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
959 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700960
Ian Rogersdd7624d2014-03-14 17:43:00 -0700961 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
962 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700963
Ian Rogersdd7624d2014-03-14 17:43:00 -0700964 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
965 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700966
Ian Rogersdd7624d2014-03-14 17:43:00 -0700967 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
968 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700969
jeffhao58136ca2012-05-24 13:40:11 -0700970 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700971 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700972
jeffhaocee4d0c2012-06-15 14:42:01 -0700973 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700974 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700975
Ian Rogers2c8f6532011-09-02 17:16:34 -0700976 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700977 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
978 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700979
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700980 // Set up out_reg to hold a Object** into the handle scope, or to be null if the
Ian Rogers2c8f6532011-09-02 17:16:34 -0700981 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700982 // that can be used to avoid loading the handle scope entry to see if the value is
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700983 // null.
984 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
985 ManagedRegister in_reg, bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700986
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700987 // Set up out_off to hold a Object** into the handle scope, or to be null if the
Ian Rogers2c8f6532011-09-02 17:16:34 -0700988 // value is null and null_allowed.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700989 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
990 ManagedRegister scratch, bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700991
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700992 // src holds a handle scope entry (Object**) load this into dst
993 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700994
995 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
996 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700997 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
998 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700999
1000 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -07001001 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
1002 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
Andreas Gampe3b165bc2016-08-01 22:07:04 -07001003 void CallFromThread(ThreadOffset32 offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -07001004
Ian Rogers2c8f6532011-09-02 17:16:34 -07001005 // Generate code to check if Thread::Current()->exception_ is non-null
1006 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -07001007 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -07001008
Dave Allison65fcc2c2014-04-28 13:45:27 -07001009 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001010
Dave Allison45fdb932014-06-25 12:37:10 -07001011 static bool IsLowRegister(Register r) {
1012 return r < R8;
1013 }
1014
1015 static bool IsHighRegister(Register r) {
1016 return r >= R8;
1017 }
1018
Roland Levillain4d027112015-07-01 15:41:14 +01001019 //
1020 // Heap poisoning.
1021 //
1022
1023 // Poison a heap reference contained in `reg`.
1024 void PoisonHeapReference(Register reg) {
1025 // reg = -reg.
1026 rsb(reg, reg, ShifterOperand(0));
1027 }
1028 // Unpoison a heap reference contained in `reg`.
1029 void UnpoisonHeapReference(Register reg) {
1030 // reg = -reg.
1031 rsb(reg, reg, ShifterOperand(0));
1032 }
1033 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
1034 void MaybeUnpoisonHeapReference(Register reg) {
1035 if (kPoisonHeapReferences) {
1036 UnpoisonHeapReference(reg);
1037 }
1038 }
1039
Andreas Gampe85b62f22015-09-09 13:15:38 -07001040 void Jump(Label* label) OVERRIDE {
1041 b(label);
1042 }
1043
Andreas Gampe7cffc3b2015-10-19 21:31:53 -07001044 // Jump table support. This is split into three functions:
1045 //
1046 // * CreateJumpTable creates the internal metadata to track the jump targets, and emits code to
1047 // load the base address of the jump table.
1048 //
1049 // * EmitJumpTableDispatch emits the code to actually jump, assuming that the right table value
1050 // has been loaded into a register already.
1051 //
1052 // * FinalizeTables emits the jump table into the literal pool. This can only be called after the
1053 // labels for the jump targets have been finalized.
1054
1055 // Create a jump table for the given labels that will be emitted when finalizing. Create a load
1056 // sequence (or placeholder) that stores the base address into the given register. When the table
1057 // is emitted, offsets will be relative to the location EmitJumpTableDispatch was called on (the
1058 // anchor).
1059 virtual JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) = 0;
1060
1061 // Emit the jump-table jump, assuming that the right value was loaded into displacement_reg.
1062 virtual void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) = 0;
1063
1064 // Bind a Label that needs to be updated by the assembler in FinalizeCode() if its position
1065 // changes due to branch/literal fixup.
1066 void BindTrackedLabel(Label* label) {
1067 Bind(label);
1068 tracked_labels_.push_back(label);
1069 }
1070
Dave Allison65fcc2c2014-04-28 13:45:27 -07001071 protected:
Vladimir Marko93205e32016-04-13 11:59:46 +01001072 explicit ArmAssembler(ArenaAllocator* arena)
1073 : Assembler(arena), tracked_labels_(arena->Adapter(kArenaAllocAssembler)) {}
1074
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001075 // Returns whether or not the given register is used for passing parameters.
1076 static int RegisterCompare(const Register* reg1, const Register* reg2) {
1077 return *reg1 - *reg2;
1078 }
Andreas Gampe7cffc3b2015-10-19 21:31:53 -07001079
1080 void FinalizeTrackedLabels();
1081
1082 // Tracked labels. Use a vector, as we need to sort before adjusting.
Vladimir Marko93205e32016-04-13 11:59:46 +01001083 ArenaVector<Label*> tracked_labels_;
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001084};
1085
Ian Rogers2c8f6532011-09-02 17:16:34 -07001086// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -07001087class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001088 public:
Roland Levillain3887c462015-08-12 18:15:42 +01001089 ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001090 : scratch_(scratch), stack_adjust_(stack_adjust) {
1091 }
Ian Rogersdd7624d2014-03-14 17:43:00 -07001092 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -07001093 private:
1094 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001095 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -07001096};
1097
Ian Rogers2c8f6532011-09-02 17:16:34 -07001098} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -07001099} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001100
Ian Rogers166db042013-07-26 12:05:57 -07001101#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_