blob: ee5811c3c0b38a78d7e9157fc651c85cc897e032 [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"
Artem Serov12e097c2016-08-08 15:13:26 +010031#include "utils/arm/assembler_arm_shared.h"
Ian Rogers166db042013-07-26 12:05:57 -070032#include "utils/arm/managed_register_arm.h"
33#include "utils/assembler.h"
Andreas Gampe3b165bc2016-08-01 22:07:04 -070034#include "utils/jni_macro_assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070035#include "offsets.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070036
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070037namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070038namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070039
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +000040class 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 Thumb2Assembler;
212
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700213#ifdef SOURCE_ASSEMBLER_SUPPORT
214 friend class BinaryAssembler;
215#endif
216};
217
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700218// Load/store multiple addressing mode.
219enum BlockAddressMode {
220 // bit encoding P U W
221 DA = (0|0|0) << 21, // decrement after
222 IA = (0|4|0) << 21, // increment after
223 DB = (8|0|0) << 21, // decrement before
224 IB = (8|4|0) << 21, // increment before
225 DA_W = (0|0|1) << 21, // decrement after with writeback to base
226 IA_W = (0|4|1) << 21, // increment after with writeback to base
227 DB_W = (8|0|1) << 21, // decrement before with writeback to base
228 IB_W = (8|4|1) << 21 // increment before with writeback to base
229};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700230inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
231 os << static_cast<int>(rhs);
232 return os;
233}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700234
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700235class Address : public ValueObject {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700236 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700237 // Memory operand addressing mode (in ARM encoding form. For others we need
238 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700239 enum Mode {
240 // bit encoding P U W
241 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
242 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
243 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
244 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
245 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
246 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
247 };
248
Chih-Hung Hsieha5931182016-09-01 15:08:13 -0700249 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
Dave Allison45fdb932014-06-25 12:37:10 -0700250 offset_(offset),
251 am_(am), is_immed_offset_(true), shift_(LSL) {
252 }
253
254 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
255 am_(am), is_immed_offset_(false), shift_(LSL) {
256 CHECK_NE(rm, PC);
257 }
258
259 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
260 rn_(rn), rm_(rm), offset_(count),
261 am_(am), is_immed_offset_(false), shift_(shift) {
262 CHECK_NE(rm, PC);
263 }
264
Vladimir Marko5f926052016-09-30 17:04:49 +0000265 // LDR(literal) - pc relative load.
266 explicit Address(int32_t offset) :
267 rn_(PC), rm_(R0), offset_(offset),
268 am_(Offset), is_immed_offset_(false), shift_(LSL) {
269 }
270
Dave Allison65fcc2c2014-04-28 13:45:27 -0700271 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
272 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
273
274 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
275 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
276
277 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700278 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700279
280 uint32_t encoding3() const;
281 uint32_t vencoding() const;
282
283 uint32_t encodingThumbLdrdStrd() const;
284
285 Register GetRegister() const {
286 return rn_;
287 }
288
Dave Allison45fdb932014-06-25 12:37:10 -0700289 Register GetRegisterOffset() const {
290 return rm_;
291 }
292
Dave Allison65fcc2c2014-04-28 13:45:27 -0700293 int32_t GetOffset() const {
294 return offset_;
295 }
296
297 Mode GetMode() const {
298 return am_;
299 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700300
Dave Allison45fdb932014-06-25 12:37:10 -0700301 bool IsImmediate() const {
302 return is_immed_offset_;
303 }
304
305 Shift GetShift() const {
306 return shift_;
307 }
308
309 int32_t GetShiftCount() const {
310 CHECK(!is_immed_offset_);
311 return offset_;
312 }
313
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700314 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700315 const Register rn_;
316 const Register rm_;
317 const int32_t offset_; // Used as shift amount for register offset.
318 const Mode am_;
319 const bool is_immed_offset_;
320 const Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700321};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700322inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
323 os << static_cast<int>(rhs);
324 return os;
325}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700326
Dave Allison65fcc2c2014-04-28 13:45:27 -0700327// Instruction encoding bits.
328enum {
329 H = 1 << 5, // halfword (or byte)
330 L = 1 << 20, // load (or store)
331 S = 1 << 20, // set condition code (or leave unchanged)
332 W = 1 << 21, // writeback base register (or leave unchanged)
333 A = 1 << 21, // accumulate in multiply instruction (or not)
334 B = 1 << 22, // unsigned byte (or word)
335 N = 1 << 22, // long (or short)
336 U = 1 << 23, // positive (or negative) offset/index
337 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
338 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700339
Dave Allison65fcc2c2014-04-28 13:45:27 -0700340 B0 = 1,
341 B1 = 1 << 1,
342 B2 = 1 << 2,
343 B3 = 1 << 3,
344 B4 = 1 << 4,
345 B5 = 1 << 5,
346 B6 = 1 << 6,
347 B7 = 1 << 7,
348 B8 = 1 << 8,
349 B9 = 1 << 9,
350 B10 = 1 << 10,
351 B11 = 1 << 11,
352 B12 = 1 << 12,
353 B13 = 1 << 13,
354 B14 = 1 << 14,
355 B15 = 1 << 15,
356 B16 = 1 << 16,
357 B17 = 1 << 17,
358 B18 = 1 << 18,
359 B19 = 1 << 19,
360 B20 = 1 << 20,
361 B21 = 1 << 21,
362 B22 = 1 << 22,
363 B23 = 1 << 23,
364 B24 = 1 << 24,
365 B25 = 1 << 25,
366 B26 = 1 << 26,
367 B27 = 1 << 27,
368 B28 = 1 << 28,
369 B29 = 1 << 29,
370 B30 = 1 << 30,
371 B31 = 1 << 31,
372
373 // Instruction bit masks.
374 RdMask = 15 << 12, // in str instruction
375 CondMask = 15 << 28,
376 CoprocessorMask = 15 << 8,
377 OpCodeMask = 15 << 21, // in data-processing instructions
378 Imm24Mask = (1 << 24) - 1,
379 Off12Mask = (1 << 12) - 1,
380
381 // ldrex/strex register field encodings.
382 kLdExRnShift = 16,
383 kLdExRtShift = 12,
384 kStrExRnShift = 16,
385 kStrExRdShift = 12,
386 kStrExRtShift = 0,
387};
388
389// IfThen state for IT instructions.
390enum ItState {
391 kItOmitted,
392 kItThen,
393 kItT = kItThen,
394 kItElse,
395 kItE = kItElse
396};
397
398constexpr uint32_t kNoItCondition = 3;
399constexpr uint32_t kInvalidModifiedImmediate = -1;
400
401extern const char* kRegisterNames[];
402extern const char* kConditionNames[];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700403
404// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
405// instruction sets (ARM32, Thumb2, etc.)
406//
Andreas Gampe60b1e1d2016-08-08 17:32:34 -0700407class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700408 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700409 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700410
Dave Allison65fcc2c2014-04-28 13:45:27 -0700411 // Is this assembler for the thumb instruction set?
412 virtual bool IsThumb() const = 0;
413
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700414 // Data-processing instructions.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100415 virtual void and_(Register rd, Register rn, const ShifterOperand& so,
416 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700417
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100418 virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
419 and_(rd, rn, so, cond, kCcSet);
420 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700421
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100422 virtual void eor(Register rd, Register rn, const ShifterOperand& so,
423 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700424
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100425 virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
426 eor(rd, rn, so, cond, kCcSet);
427 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700428
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100429 virtual void sub(Register rd, Register rn, const ShifterOperand& so,
430 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700431
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100432 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
433 sub(rd, rn, so, cond, kCcSet);
434 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700435
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100436 virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
437 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700438
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100439 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
440 rsb(rd, rn, so, cond, kCcSet);
441 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700442
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100443 virtual void add(Register rd, Register rn, const ShifterOperand& so,
444 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
445
446 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
447 add(rd, rn, so, cond, kCcSet);
448 }
449
450 virtual void adc(Register rd, Register rn, const ShifterOperand& so,
451 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
452
453 virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
454 adc(rd, rn, so, cond, kCcSet);
455 }
456
457 virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
458 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
459
460 virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
461 sbc(rd, rn, so, cond, kCcSet);
462 }
463
464 virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
465 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
466
467 virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
468 rsc(rd, rn, so, cond, kCcSet);
469 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700470
Dave Allison65fcc2c2014-04-28 13:45:27 -0700471 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700472
Dave Allison65fcc2c2014-04-28 13:45:27 -0700473 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700474
Dave Allison65fcc2c2014-04-28 13:45:27 -0700475 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700476
Vladimir Markoac6ac102015-12-17 12:14:00 +0000477 // Note: CMN updates flags based on addition of its operands. Do not confuse
478 // the "N" suffix with bitwise inversion performed by MVN.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700479 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700480
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100481 virtual void orr(Register rd, Register rn, const ShifterOperand& so,
482 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700483
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100484 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
485 orr(rd, rn, so, cond, kCcSet);
486 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700487
Vladimir Markod2b4ca22015-09-14 15:13:26 +0100488 virtual void orn(Register rd, Register rn, const ShifterOperand& so,
489 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
490
491 virtual void orns(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
492 orn(rd, rn, so, cond, kCcSet);
493 }
494
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100495 virtual void mov(Register rd, const ShifterOperand& so,
496 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700497
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100498 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) {
499 mov(rd, so, cond, kCcSet);
500 }
501
502 virtual void bic(Register rd, Register rn, const ShifterOperand& so,
503 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
504
505 virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
506 bic(rd, rn, so, cond, kCcSet);
507 }
508
509 virtual void mvn(Register rd, const ShifterOperand& so,
510 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
511
512 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) {
513 mvn(rd, so, cond, kCcSet);
514 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700515
516 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700517 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
518 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
519 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100520 virtual void rbit(Register rd, Register rm, Condition cond = AL) = 0;
Artem Serovc257da72016-02-02 13:49:43 +0000521 virtual void rev(Register rd, Register rm, Condition cond = AL) = 0;
522 virtual void rev16(Register rd, Register rm, Condition cond = AL) = 0;
523 virtual void revsh(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700524
525 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700526 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
527 virtual void mla(Register rd, Register rn, Register rm, Register ra,
528 Condition cond = AL) = 0;
529 virtual void mls(Register rd, Register rn, Register rm, Register ra,
530 Condition cond = AL) = 0;
Zheng Xuc6667102015-05-15 16:08:45 +0800531 virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
532 Condition cond = AL) = 0;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700533 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
534 Condition cond = AL) = 0;
535
536 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
537 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700538
Roland Levillain981e4542014-11-14 11:47:14 +0000539 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000540 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
541 Condition cond = AL) = 0;
Roland Levillain981e4542014-11-14 11:47:14 +0000542 virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
543 Condition cond = AL) = 0;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000544
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700545 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700546 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
547 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700548
Dave Allison65fcc2c2014-04-28 13:45:27 -0700549 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
550 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700551
Dave Allison65fcc2c2014-04-28 13:45:27 -0700552 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
553 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700554
Dave Allison65fcc2c2014-04-28 13:45:27 -0700555 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
556 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700557
Dave Allison65fcc2c2014-04-28 13:45:27 -0700558 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
559 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700560
Dave Allison65fcc2c2014-04-28 13:45:27 -0700561 virtual void ldm(BlockAddressMode am, Register base,
562 RegList regs, Condition cond = AL) = 0;
563 virtual void stm(BlockAddressMode am, Register base,
564 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700565
Dave Allison65fcc2c2014-04-28 13:45:27 -0700566 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
567 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Calin Juravle52c48962014-12-16 17:02:57 +0000568 virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
569 virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700570
571 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700572 virtual void clrex(Condition cond = AL) = 0;
573 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700574
575 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700576 virtual void bkpt(uint16_t imm16) = 0;
577 virtual void svc(uint32_t imm24) = 0;
578
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700579 virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
580 ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
581 ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
582 ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700583 // Ignored if not supported.
584 }
585
586 virtual void cbz(Register rn, Label* target) = 0;
587 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700588
589 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700590 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
591 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
592 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
593 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
594 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
595 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
596 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
597 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700598
599 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700600 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
601 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700602
Dave Allison65fcc2c2014-04-28 13:45:27 -0700603 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
604 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
605 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
606 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700607
Dave Allison65fcc2c2014-04-28 13:45:27 -0700608 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
609 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
610 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
611 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
612 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
613 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
614 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
615 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
616 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
617 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
618 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
619 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700620
Dave Allison65fcc2c2014-04-28 13:45:27 -0700621 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
622 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
623 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
624 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
625 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
626 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700627
Dave Allison65fcc2c2014-04-28 13:45:27 -0700628 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
629 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
630 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
631 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
632 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
633 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
634 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
635 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
636 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
637 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700638
Dave Allison65fcc2c2014-04-28 13:45:27 -0700639 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
640 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
641 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
642 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
643 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
644
xueliang.zhonge652c122016-06-13 14:42:27 +0100645 virtual void vcntd(DRegister dd, DRegister dm) = 0;
646 virtual void vpaddld(DRegister dd, DRegister dm, int32_t size, bool is_unsigned) = 0;
647
Dave Allison65fcc2c2014-04-28 13:45:27 -0700648 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
649 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
650 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
651 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Artem Serovcb3cf4a2016-07-15 15:01:13 +0100652 virtual void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0;
653 virtual void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700654
655 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700656 virtual void b(Label* label, Condition cond = AL) = 0;
657 virtual void bl(Label* label, Condition cond = AL) = 0;
658 virtual void blx(Register rm, Condition cond = AL) = 0;
659 virtual void bx(Register rm, Condition cond = AL) = 0;
660
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100661 // Memory barriers.
662 virtual void dmb(DmbOptions flavor) = 0;
663
Dave Allison65fcc2c2014-04-28 13:45:27 -0700664 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700665
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000666 // Adjust label position.
667 void AdjustLabelPosition(Label* label) {
668 DCHECK(label->IsBound());
669 uint32_t old_position = static_cast<uint32_t>(label->Position());
670 uint32_t new_position = GetAdjustedPosition(old_position);
671 label->Reinitialize();
672 DCHECK_GE(static_cast<int>(new_position), 0);
673 label->BindTo(static_cast<int>(new_position));
674 }
675
676 // Get the final position of a label after local fixup based on the old position
677 // recorded before FinalizeCode().
678 virtual uint32_t GetAdjustedPosition(uint32_t old_position) = 0;
679
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700680 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700681 // Most of these are pure virtual as they need to be implemented per instruction set.
682
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000683 // Create a new literal with a given value.
Vladimir Marko88b2b802015-12-04 14:19:04 +0000684 // NOTE: Force the template parameter to be explicitly specified.
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000685 template <typename T>
Vladimir Marko88b2b802015-12-04 14:19:04 +0000686 Literal* NewLiteral(typename Identity<T>::type value) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000687 static_assert(std::is_integral<T>::value, "T must be an integral type.");
688 return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
689 }
690
691 // Create a new literal with the given data.
692 virtual Literal* NewLiteral(size_t size, const uint8_t* data) = 0;
693
694 // Load literal.
695 virtual void LoadLiteral(Register rt, Literal* literal) = 0;
696 virtual void LoadLiteral(Register rt, Register rt2, Literal* literal) = 0;
697 virtual void LoadLiteral(SRegister sd, Literal* literal) = 0;
698 virtual void LoadLiteral(DRegister dd, Literal* literal) = 0;
699
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700700 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700701 virtual void AddConstant(Register rd, Register rn, int32_t value,
Vladimir Marko449b1092015-09-08 12:16:45 +0100702 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
703 void AddConstantSetFlags(Register rd, Register rn, int32_t value, Condition cond = AL) {
704 AddConstant(rd, rn, value, cond, kCcSet);
705 }
706 void AddConstant(Register rd, int32_t value, Condition cond = AL, SetCc set_cc = kCcDontCare) {
707 AddConstant(rd, rd, value, cond, set_cc);
708 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700709
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700710 virtual void CmpConstant(Register rn, int32_t value, Condition cond = AL) = 0;
711
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700712 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700713 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000714 void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
715 if (!vmovs(sd, value, cond)) {
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000716 int32_t int_value = bit_cast<int32_t, float>(value);
717 if (int_value == bit_cast<int32_t, float>(0.0f)) {
718 // 0.0 is quite common, so we special case it by loading
719 // 2.0 in `sd` and then substracting it.
720 bool success = vmovs(sd, 2.0, cond);
721 CHECK(success);
722 vsubs(sd, sd, sd, cond);
723 } else {
724 LoadImmediate(IP, int_value, cond);
725 vmovsr(sd, IP, cond);
726 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000727 }
728 }
729
Vladimir Markoebdbf4b2016-07-07 15:37:02 +0100730 virtual void LoadDImmediate(DRegister dd, double value, Condition cond = AL) = 0;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000731
Dave Allison65fcc2c2014-04-28 13:45:27 -0700732 virtual void MarkExceptionHandler(Label* label) = 0;
733 virtual void LoadFromOffset(LoadOperandType type,
734 Register reg,
735 Register base,
736 int32_t offset,
737 Condition cond = AL) = 0;
738 virtual void StoreToOffset(StoreOperandType type,
739 Register reg,
740 Register base,
741 int32_t offset,
742 Condition cond = AL) = 0;
743 virtual void LoadSFromOffset(SRegister reg,
744 Register base,
745 int32_t offset,
746 Condition cond = AL) = 0;
747 virtual void StoreSToOffset(SRegister reg,
748 Register base,
749 int32_t offset,
750 Condition cond = AL) = 0;
751 virtual void LoadDFromOffset(DRegister reg,
752 Register base,
753 int32_t offset,
754 Condition cond = AL) = 0;
755 virtual void StoreDToOffset(DRegister reg,
756 Register base,
757 int32_t offset,
758 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700759
Dave Allison65fcc2c2014-04-28 13:45:27 -0700760 virtual void Push(Register rd, Condition cond = AL) = 0;
761 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700762
Dave Allison65fcc2c2014-04-28 13:45:27 -0700763 virtual void PushList(RegList regs, Condition cond = AL) = 0;
764 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700765
Artem Serovf4d6aee2016-07-11 10:41:45 +0100766 virtual void StoreList(RegList regs, size_t stack_offset) = 0;
767 virtual void LoadList(RegList regs, size_t stack_offset) = 0;
768
Dave Allison65fcc2c2014-04-28 13:45:27 -0700769 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700770
771 // Convenience shift instructions. Use mov instruction with shifter operand
772 // for variants setting the status flags or using a register shift count.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100773 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
774 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
Dave Allison45fdb932014-06-25 12:37:10 -0700775
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100776 void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
777 Lsl(rd, rm, shift_imm, cond, kCcSet);
778 }
779
780 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
781 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
782
783 void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
784 Lsr(rd, rm, shift_imm, cond, kCcSet);
785 }
786
787 virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
788 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
789
790 void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
791 Asr(rd, rm, shift_imm, cond, kCcSet);
792 }
793
794 virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
795 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
796
797 void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
798 Ror(rd, rm, shift_imm, cond, kCcSet);
799 }
800
801 virtual void Rrx(Register rd, Register rm,
802 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
803
804 void Rrxs(Register rd, Register rm, Condition cond = AL) {
805 Rrx(rd, rm, cond, kCcSet);
806 }
807
808 virtual void Lsl(Register rd, Register rm, Register rn,
809 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
810
811 void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) {
812 Lsl(rd, rm, rn, cond, kCcSet);
813 }
814
815 virtual void Lsr(Register rd, Register rm, Register rn,
816 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
817
818 void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) {
819 Lsr(rd, rm, rn, cond, kCcSet);
820 }
821
822 virtual void Asr(Register rd, Register rm, Register rn,
823 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
824
825 void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) {
826 Asr(rd, rm, rn, cond, kCcSet);
827 }
828
829 virtual void Ror(Register rd, Register rm, Register rn,
830 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
831
832 void Rors(Register rd, Register rm, Register rn, Condition cond = AL) {
833 Ror(rd, rm, rn, cond, kCcSet);
834 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700835
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000836 // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
837 // `shifter_op` contains the operand.
838 virtual bool ShifterOperandCanHold(Register rd,
839 Register rn,
840 Opcode opcode,
841 uint32_t immediate,
Vladimir Markof5c09c32015-12-17 12:08:08 +0000842 SetCc set_cc,
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000843 ShifterOperand* shifter_op) = 0;
Vladimir Markof5c09c32015-12-17 12:08:08 +0000844 bool ShifterOperandCanHold(Register rd,
845 Register rn,
846 Opcode opcode,
847 uint32_t immediate,
848 ShifterOperand* shifter_op) {
849 return ShifterOperandCanHold(rd, rn, opcode, immediate, kCcDontCare, shifter_op);
850 }
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000851
Nicolas Geoffray0ccb3832015-10-14 11:44:23 +0100852 virtual bool ShifterOperandCanAlwaysHold(uint32_t immediate) = 0;
Nicolas Geoffray5bd05a52015-10-13 09:48:30 +0100853
Ian Rogers13735952014-10-08 12:43:28 -0700854 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700855
Dave Allison65fcc2c2014-04-28 13:45:27 -0700856 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
857 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700858
Dave Allison65fcc2c2014-04-28 13:45:27 -0700859 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700860
Dave Allison45fdb932014-06-25 12:37:10 -0700861 static bool IsLowRegister(Register r) {
862 return r < R8;
863 }
864
865 static bool IsHighRegister(Register r) {
866 return r >= R8;
867 }
868
Roland Levillain4d027112015-07-01 15:41:14 +0100869 //
870 // Heap poisoning.
871 //
872
873 // Poison a heap reference contained in `reg`.
874 void PoisonHeapReference(Register reg) {
875 // reg = -reg.
876 rsb(reg, reg, ShifterOperand(0));
877 }
878 // Unpoison a heap reference contained in `reg`.
879 void UnpoisonHeapReference(Register reg) {
880 // reg = -reg.
881 rsb(reg, reg, ShifterOperand(0));
882 }
Roland Levillain0b671c02016-08-19 12:02:34 +0100883 // Poison a heap reference contained in `reg` if heap poisoning is enabled.
884 void MaybePoisonHeapReference(Register reg) {
885 if (kPoisonHeapReferences) {
886 PoisonHeapReference(reg);
887 }
888 }
Roland Levillain4d027112015-07-01 15:41:14 +0100889 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
890 void MaybeUnpoisonHeapReference(Register reg) {
891 if (kPoisonHeapReferences) {
892 UnpoisonHeapReference(reg);
893 }
894 }
895
Andreas Gampe85b62f22015-09-09 13:15:38 -0700896 void Jump(Label* label) OVERRIDE {
897 b(label);
898 }
899
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700900 // Jump table support. This is split into three functions:
901 //
902 // * CreateJumpTable creates the internal metadata to track the jump targets, and emits code to
903 // load the base address of the jump table.
904 //
905 // * EmitJumpTableDispatch emits the code to actually jump, assuming that the right table value
906 // has been loaded into a register already.
907 //
908 // * FinalizeTables emits the jump table into the literal pool. This can only be called after the
909 // labels for the jump targets have been finalized.
910
911 // Create a jump table for the given labels that will be emitted when finalizing. Create a load
912 // sequence (or placeholder) that stores the base address into the given register. When the table
913 // is emitted, offsets will be relative to the location EmitJumpTableDispatch was called on (the
914 // anchor).
915 virtual JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) = 0;
916
917 // Emit the jump-table jump, assuming that the right value was loaded into displacement_reg.
918 virtual void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) = 0;
919
920 // Bind a Label that needs to be updated by the assembler in FinalizeCode() if its position
921 // changes due to branch/literal fixup.
922 void BindTrackedLabel(Label* label) {
923 Bind(label);
924 tracked_labels_.push_back(label);
925 }
926
Dave Allison65fcc2c2014-04-28 13:45:27 -0700927 protected:
Vladimir Marko93205e32016-04-13 11:59:46 +0100928 explicit ArmAssembler(ArenaAllocator* arena)
929 : Assembler(arena), tracked_labels_(arena->Adapter(kArenaAllocAssembler)) {}
930
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700931 // Returns whether or not the given register is used for passing parameters.
932 static int RegisterCompare(const Register* reg1, const Register* reg2) {
933 return *reg1 - *reg2;
934 }
Andreas Gampe7cffc3b2015-10-19 21:31:53 -0700935
936 void FinalizeTrackedLabels();
937
938 // Tracked labels. Use a vector, as we need to sort before adjusting.
Vladimir Marko93205e32016-04-13 11:59:46 +0100939 ArenaVector<Label*> tracked_labels_;
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700940};
941
Ian Rogers2c8f6532011-09-02 17:16:34 -0700942} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700943} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700944
Ian Rogers166db042013-07-26 12:05:57 -0700945#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_