blob: 350efca3e2423f74d677b329d7c3bcf3523b2a8f [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
Elliott Hughes07ed66b2012-12-12 18:34:25 -080020#include <vector>
21
Vladimir Marko80afd022015-05-19 18:08:00 +010022#include "base/bit_utils.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080023#include "base/logging.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070024#include "base/value_object.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070025#include "constants_arm.h"
Ian Rogers166db042013-07-26 12:05:57 -070026#include "utils/arm/managed_register_arm.h"
27#include "utils/assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070028#include "offsets.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070029
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070030namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070031namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070032
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +000033class Arm32Assembler;
34class Thumb2Assembler;
35
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +000036// This class indicates that the label and its uses
37// will fall into a range that is encodable in 16bits on thumb2.
38class NearLabel : public Label {
39 public:
40 NearLabel() {}
41
42 private:
43 DISALLOW_COPY_AND_ASSIGN(NearLabel);
44};
45
Carl Shapiroa2e18e12011-06-21 18:57:55 -070046class ShifterOperand {
47 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -070048 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
49 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070050 }
51
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010052 explicit ShifterOperand(uint32_t immed);
Carl Shapiroa2e18e12011-06-21 18:57:55 -070053
54 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -070055 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
56 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070057 }
58
Dave Allison65fcc2c2014-04-28 13:45:27 -070059 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
60 rs_(kNoRegister),
61 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
62 }
63
64 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
65 rs_(kNoRegister),
66 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070067 }
68
69 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -070070 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm),
71 rs_(rs),
72 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070073 }
74
Dave Allison65fcc2c2014-04-28 13:45:27 -070075 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070076
77 uint32_t type() const {
78 CHECK(is_valid());
79 return type_;
80 }
81
Dave Allison65fcc2c2014-04-28 13:45:27 -070082 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -070083 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -070084
85 bool IsEmpty() const {
86 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070087 }
88
Dave Allison65fcc2c2014-04-28 13:45:27 -070089 bool IsImmediate() const {
90 return type_ == kImmediate;
91 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070092
Dave Allison65fcc2c2014-04-28 13:45:27 -070093 bool IsRegister() const {
94 return type_ == kRegister;
95 }
96
97 bool IsShift() const {
98 return is_shift_;
99 }
100
101 uint32_t GetImmediate() const {
102 return immed_;
103 }
104
105 Shift GetShift() const {
106 return shift_;
107 }
108
109 Register GetRegister() const {
110 return rm_;
111 }
112
Guillaume "Vermeille" Sanchezab4a2f52015-03-11 14:00:30 +0000113 Register GetSecondRegister() const {
114 return rs_;
115 }
116
Dave Allison65fcc2c2014-04-28 13:45:27 -0700117 enum Type {
118 kUnknown = -1,
119 kRegister,
120 kImmediate
121 };
122
Dave Allison65fcc2c2014-04-28 13:45:27 -0700123 private:
124 Type type_;
125 Register rm_;
126 Register rs_;
127 bool is_rotate_;
128 bool is_shift_;
129 Shift shift_;
130 uint32_t rotate_;
131 uint32_t immed_;
132
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000133 friend class Arm32Assembler;
134 friend class Thumb2Assembler;
135
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700136#ifdef SOURCE_ASSEMBLER_SUPPORT
137 friend class BinaryAssembler;
138#endif
139};
140
141
142enum LoadOperandType {
143 kLoadSignedByte,
144 kLoadUnsignedByte,
145 kLoadSignedHalfword,
146 kLoadUnsignedHalfword,
147 kLoadWord,
148 kLoadWordPair,
149 kLoadSWord,
150 kLoadDWord
151};
152
153
154enum StoreOperandType {
155 kStoreByte,
156 kStoreHalfword,
157 kStoreWord,
158 kStoreWordPair,
159 kStoreSWord,
160 kStoreDWord
161};
162
163
164// Load/store multiple addressing mode.
165enum BlockAddressMode {
166 // bit encoding P U W
167 DA = (0|0|0) << 21, // decrement after
168 IA = (0|4|0) << 21, // increment after
169 DB = (8|0|0) << 21, // decrement before
170 IB = (8|4|0) << 21, // increment before
171 DA_W = (0|0|1) << 21, // decrement after with writeback to base
172 IA_W = (0|4|1) << 21, // increment after with writeback to base
173 DB_W = (8|0|1) << 21, // decrement before with writeback to base
174 IB_W = (8|4|1) << 21 // increment before with writeback to base
175};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700176inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
177 os << static_cast<int>(rhs);
178 return os;
179}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700180
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700181class Address : public ValueObject {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700182 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700183 // Memory operand addressing mode (in ARM encoding form. For others we need
184 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700185 enum Mode {
186 // bit encoding P U W
187 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
188 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
189 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
190 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
191 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
192 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
193 };
194
Dave Allison45fdb932014-06-25 12:37:10 -0700195 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
196 offset_(offset),
197 am_(am), is_immed_offset_(true), shift_(LSL) {
198 }
199
200 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
201 am_(am), is_immed_offset_(false), shift_(LSL) {
202 CHECK_NE(rm, PC);
203 }
204
205 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
206 rn_(rn), rm_(rm), offset_(count),
207 am_(am), is_immed_offset_(false), shift_(shift) {
208 CHECK_NE(rm, PC);
209 }
210
211 // LDR(literal) - pc relative load.
212 explicit Address(int32_t offset) :
213 rn_(PC), rm_(R0), offset_(offset),
214 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700215 }
216
Dave Allison65fcc2c2014-04-28 13:45:27 -0700217 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
218 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
219
220 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
221 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
222
223 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700224 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700225
226 uint32_t encoding3() const;
227 uint32_t vencoding() const;
228
229 uint32_t encodingThumbLdrdStrd() const;
230
231 Register GetRegister() const {
232 return rn_;
233 }
234
Dave Allison45fdb932014-06-25 12:37:10 -0700235 Register GetRegisterOffset() const {
236 return rm_;
237 }
238
Dave Allison65fcc2c2014-04-28 13:45:27 -0700239 int32_t GetOffset() const {
240 return offset_;
241 }
242
243 Mode GetMode() const {
244 return am_;
245 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700246
Dave Allison45fdb932014-06-25 12:37:10 -0700247 bool IsImmediate() const {
248 return is_immed_offset_;
249 }
250
251 Shift GetShift() const {
252 return shift_;
253 }
254
255 int32_t GetShiftCount() const {
256 CHECK(!is_immed_offset_);
257 return offset_;
258 }
259
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700260 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700261 const Register rn_;
262 const Register rm_;
263 const int32_t offset_; // Used as shift amount for register offset.
264 const Mode am_;
265 const bool is_immed_offset_;
266 const Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700267};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700268inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
269 os << static_cast<int>(rhs);
270 return os;
271}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700272
Dave Allison65fcc2c2014-04-28 13:45:27 -0700273// Instruction encoding bits.
274enum {
275 H = 1 << 5, // halfword (or byte)
276 L = 1 << 20, // load (or store)
277 S = 1 << 20, // set condition code (or leave unchanged)
278 W = 1 << 21, // writeback base register (or leave unchanged)
279 A = 1 << 21, // accumulate in multiply instruction (or not)
280 B = 1 << 22, // unsigned byte (or word)
281 N = 1 << 22, // long (or short)
282 U = 1 << 23, // positive (or negative) offset/index
283 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
284 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700285
Dave Allison65fcc2c2014-04-28 13:45:27 -0700286 B0 = 1,
287 B1 = 1 << 1,
288 B2 = 1 << 2,
289 B3 = 1 << 3,
290 B4 = 1 << 4,
291 B5 = 1 << 5,
292 B6 = 1 << 6,
293 B7 = 1 << 7,
294 B8 = 1 << 8,
295 B9 = 1 << 9,
296 B10 = 1 << 10,
297 B11 = 1 << 11,
298 B12 = 1 << 12,
299 B13 = 1 << 13,
300 B14 = 1 << 14,
301 B15 = 1 << 15,
302 B16 = 1 << 16,
303 B17 = 1 << 17,
304 B18 = 1 << 18,
305 B19 = 1 << 19,
306 B20 = 1 << 20,
307 B21 = 1 << 21,
308 B22 = 1 << 22,
309 B23 = 1 << 23,
310 B24 = 1 << 24,
311 B25 = 1 << 25,
312 B26 = 1 << 26,
313 B27 = 1 << 27,
314 B28 = 1 << 28,
315 B29 = 1 << 29,
316 B30 = 1 << 30,
317 B31 = 1 << 31,
318
319 // Instruction bit masks.
320 RdMask = 15 << 12, // in str instruction
321 CondMask = 15 << 28,
322 CoprocessorMask = 15 << 8,
323 OpCodeMask = 15 << 21, // in data-processing instructions
324 Imm24Mask = (1 << 24) - 1,
325 Off12Mask = (1 << 12) - 1,
326
327 // ldrex/strex register field encodings.
328 kLdExRnShift = 16,
329 kLdExRtShift = 12,
330 kStrExRnShift = 16,
331 kStrExRdShift = 12,
332 kStrExRtShift = 0,
333};
334
335// IfThen state for IT instructions.
336enum ItState {
337 kItOmitted,
338 kItThen,
339 kItT = kItThen,
340 kItElse,
341 kItE = kItElse
342};
343
344constexpr uint32_t kNoItCondition = 3;
345constexpr uint32_t kInvalidModifiedImmediate = -1;
346
347extern const char* kRegisterNames[];
348extern const char* kConditionNames[];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700349
350// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
351// instruction sets (ARM32, Thumb2, etc.)
352//
353class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700354 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700355 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700356
Dave Allison65fcc2c2014-04-28 13:45:27 -0700357 // Is this assembler for the thumb instruction set?
358 virtual bool IsThumb() const = 0;
359
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700360 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700361 virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700362
Dave Allison65fcc2c2014-04-28 13:45:27 -0700363 virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700364
Dave Allison65fcc2c2014-04-28 13:45:27 -0700365 virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
366 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700367
Dave Allison65fcc2c2014-04-28 13:45:27 -0700368 virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
369 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700370
Dave Allison65fcc2c2014-04-28 13:45:27 -0700371 virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700372
Dave Allison65fcc2c2014-04-28 13:45:27 -0700373 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700374
Dave Allison65fcc2c2014-04-28 13:45:27 -0700375 virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700376
Dave Allison65fcc2c2014-04-28 13:45:27 -0700377 virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700378
Dave Allison65fcc2c2014-04-28 13:45:27 -0700379 virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700380
Dave Allison65fcc2c2014-04-28 13:45:27 -0700381 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700382
Dave Allison65fcc2c2014-04-28 13:45:27 -0700383 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700384
Dave Allison65fcc2c2014-04-28 13:45:27 -0700385 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700386
Dave Allison65fcc2c2014-04-28 13:45:27 -0700387 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700388
Dave Allison65fcc2c2014-04-28 13:45:27 -0700389 virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
390 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700391
Dave Allison65fcc2c2014-04-28 13:45:27 -0700392 virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
393 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700394
Dave Allison65fcc2c2014-04-28 13:45:27 -0700395 virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700396
Dave Allison65fcc2c2014-04-28 13:45:27 -0700397 virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
398 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700399
400 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700401 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
402 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
403 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700404
405 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700406 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
407 virtual void mla(Register rd, Register rn, Register rm, Register ra,
408 Condition cond = AL) = 0;
409 virtual void mls(Register rd, Register rn, Register rm, Register ra,
410 Condition cond = AL) = 0;
Zheng Xuc6667102015-05-15 16:08:45 +0800411 virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
412 Condition cond = AL) = 0;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700413 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
414 Condition cond = AL) = 0;
415
416 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
417 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700418
Roland Levillain981e4542014-11-14 11:47:14 +0000419 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000420 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
421 Condition cond = AL) = 0;
Roland Levillain981e4542014-11-14 11:47:14 +0000422 virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
423 Condition cond = AL) = 0;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000424
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700425 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700426 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
427 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700428
Dave Allison65fcc2c2014-04-28 13:45:27 -0700429 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
430 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700431
Dave Allison65fcc2c2014-04-28 13:45:27 -0700432 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
433 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700434
Dave Allison65fcc2c2014-04-28 13:45:27 -0700435 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
436 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700437
Dave Allison65fcc2c2014-04-28 13:45:27 -0700438 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
439 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700440
Dave Allison65fcc2c2014-04-28 13:45:27 -0700441 virtual void ldm(BlockAddressMode am, Register base,
442 RegList regs, Condition cond = AL) = 0;
443 virtual void stm(BlockAddressMode am, Register base,
444 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700445
Dave Allison65fcc2c2014-04-28 13:45:27 -0700446 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
447 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Calin Juravle52c48962014-12-16 17:02:57 +0000448 virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
449 virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700450
451 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700452 virtual void clrex(Condition cond = AL) = 0;
453 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700454
455 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700456 virtual void bkpt(uint16_t imm16) = 0;
457 virtual void svc(uint32_t imm24) = 0;
458
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700459 virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
460 ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
461 ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
462 ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700463 // Ignored if not supported.
464 }
465
466 virtual void cbz(Register rn, Label* target) = 0;
467 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700468
469 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700470 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
471 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
472 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
473 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
474 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
475 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
476 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
477 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700478
479 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700480 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
481 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700482
Dave Allison65fcc2c2014-04-28 13:45:27 -0700483 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
484 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
485 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
486 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700487
Dave Allison65fcc2c2014-04-28 13:45:27 -0700488 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
489 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
490 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
491 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
492 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
493 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
494 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
495 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
496 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
497 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
498 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
499 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700500
Dave Allison65fcc2c2014-04-28 13:45:27 -0700501 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
502 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
503 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
504 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
505 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
506 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700507
Dave Allison65fcc2c2014-04-28 13:45:27 -0700508 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
509 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
510 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
511 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
512 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
513 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
514 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
515 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
516 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
517 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700518
Dave Allison65fcc2c2014-04-28 13:45:27 -0700519 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
520 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
521 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
522 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
523 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
524
525 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
526 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
527 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
528 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700529
530 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700531 virtual void b(Label* label, Condition cond = AL) = 0;
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +0000532 virtual void b(NearLabel* label, Condition cond = AL) {
533 b(static_cast<Label*>(label), cond);
534 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700535 virtual void bl(Label* label, Condition cond = AL) = 0;
536 virtual void blx(Register rm, Condition cond = AL) = 0;
537 virtual void bx(Register rm, Condition cond = AL) = 0;
538
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100539 // Memory barriers.
540 virtual void dmb(DmbOptions flavor) = 0;
541
Dave Allison65fcc2c2014-04-28 13:45:27 -0700542 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700543
544 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700545 // Most of these are pure virtual as they need to be implemented per instruction set.
546
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700547 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700548 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
549 virtual void AddConstant(Register rd, Register rn, int32_t value,
550 Condition cond = AL) = 0;
551 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
552 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700553
554 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700555 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000556 void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
557 if (!vmovs(sd, value, cond)) {
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000558 int32_t int_value = bit_cast<int32_t, float>(value);
559 if (int_value == bit_cast<int32_t, float>(0.0f)) {
560 // 0.0 is quite common, so we special case it by loading
561 // 2.0 in `sd` and then substracting it.
562 bool success = vmovs(sd, 2.0, cond);
563 CHECK(success);
564 vsubs(sd, sd, sd, cond);
565 } else {
566 LoadImmediate(IP, int_value, cond);
567 vmovsr(sd, IP, cond);
568 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000569 }
570 }
571
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000572 void LoadDImmediate(DRegister sd, double value, Condition cond = AL) {
573 if (!vmovd(sd, value, cond)) {
574 uint64_t int_value = bit_cast<uint64_t, double>(value);
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000575 if (int_value == bit_cast<uint64_t, double>(0.0)) {
576 // 0.0 is quite common, so we special case it by loading
577 // 2.0 in `sd` and then substracting it.
578 bool success = vmovd(sd, 2.0, cond);
579 CHECK(success);
580 vsubd(sd, sd, sd, cond);
581 } else {
582 if (sd < 16) {
583 SRegister low = static_cast<SRegister>(sd << 1);
584 SRegister high = static_cast<SRegister>(low + 1);
585 LoadSImmediate(low, bit_cast<float, uint32_t>(Low32Bits(int_value)), cond);
586 if (High32Bits(int_value) == Low32Bits(int_value)) {
587 vmovs(high, low);
588 } else {
589 LoadSImmediate(high, bit_cast<float, uint32_t>(High32Bits(int_value)), cond);
590 }
591 } else {
592 LOG(FATAL) << "Unimplemented loading of double into a D register "
593 << "that cannot be split into two S registers";
594 }
595 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000596 }
597 }
598
Dave Allison65fcc2c2014-04-28 13:45:27 -0700599 virtual void MarkExceptionHandler(Label* label) = 0;
600 virtual void LoadFromOffset(LoadOperandType type,
601 Register reg,
602 Register base,
603 int32_t offset,
604 Condition cond = AL) = 0;
605 virtual void StoreToOffset(StoreOperandType type,
606 Register reg,
607 Register base,
608 int32_t offset,
609 Condition cond = AL) = 0;
610 virtual void LoadSFromOffset(SRegister reg,
611 Register base,
612 int32_t offset,
613 Condition cond = AL) = 0;
614 virtual void StoreSToOffset(SRegister reg,
615 Register base,
616 int32_t offset,
617 Condition cond = AL) = 0;
618 virtual void LoadDFromOffset(DRegister reg,
619 Register base,
620 int32_t offset,
621 Condition cond = AL) = 0;
622 virtual void StoreDToOffset(DRegister reg,
623 Register base,
624 int32_t offset,
625 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700626
Dave Allison65fcc2c2014-04-28 13:45:27 -0700627 virtual void Push(Register rd, Condition cond = AL) = 0;
628 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700629
Dave Allison65fcc2c2014-04-28 13:45:27 -0700630 virtual void PushList(RegList regs, Condition cond = AL) = 0;
631 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700632
Dave Allison65fcc2c2014-04-28 13:45:27 -0700633 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700634
635 // Convenience shift instructions. Use mov instruction with shifter operand
636 // for variants setting the status flags or using a register shift count.
Dave Allison45fdb932014-06-25 12:37:10 -0700637 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
638 Condition cond = AL) = 0;
639 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
640 Condition cond = AL) = 0;
641 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
642 Condition cond = AL) = 0;
643 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
644 Condition cond = AL) = 0;
645 virtual void Rrx(Register rd, Register rm, bool setcc = false,
646 Condition cond = AL) = 0;
647
648 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
649 Condition cond = AL) = 0;
650 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
651 Condition cond = AL) = 0;
652 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
653 Condition cond = AL) = 0;
654 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
655 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700656
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000657 // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
658 // `shifter_op` contains the operand.
659 virtual bool ShifterOperandCanHold(Register rd,
660 Register rn,
661 Opcode opcode,
662 uint32_t immediate,
663 ShifterOperand* shifter_op) = 0;
664
Ian Rogers13735952014-10-08 12:43:28 -0700665 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700666
Dave Allison65fcc2c2014-04-28 13:45:27 -0700667 virtual void Bind(Label* label) = 0;
668
669 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
Nicolas Geoffrayd56376c2015-05-21 12:32:34 +0000670 virtual void CompareAndBranchIfZero(Register r, NearLabel* label) {
671 CompareAndBranchIfZero(r, static_cast<Label*>(label));
672 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700673 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700674
Ian Rogers2c8f6532011-09-02 17:16:34 -0700675 //
676 // Overridden common assembler high-level functionality
677 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700678
Ian Rogers2c8f6532011-09-02 17:16:34 -0700679 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700680 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
681 const std::vector<ManagedRegister>& callee_save_regs,
682 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700683
Ian Rogers2c8f6532011-09-02 17:16:34 -0700684 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700685 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700686 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700687
Ian Rogersdd7624d2014-03-14 17:43:00 -0700688 void IncreaseFrameSize(size_t adjust) OVERRIDE;
689 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700690
691 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700692 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
693 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
694 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700695
Ian Rogersdd7624d2014-03-14 17:43:00 -0700696 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700697
Ian Rogersdd7624d2014-03-14 17:43:00 -0700698 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
699 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700700
Ian Rogersdd7624d2014-03-14 17:43:00 -0700701 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
702 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700703
Ian Rogersdd7624d2014-03-14 17:43:00 -0700704 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700705
Ian Rogersdd7624d2014-03-14 17:43:00 -0700706 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
707 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700708
Ian Rogers2c8f6532011-09-02 17:16:34 -0700709 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700710 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700711
Ian Rogersdd7624d2014-03-14 17:43:00 -0700712 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700713
Mathieu Chartiere401d142015-04-22 13:56:20 -0700714 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700715
Mathieu Chartiere401d142015-04-22 13:56:20 -0700716 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
717 bool poison_reference) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700718
Ian Rogersdd7624d2014-03-14 17:43:00 -0700719 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700720
Ian Rogersdd7624d2014-03-14 17:43:00 -0700721 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700722
723 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700724 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700725
Ian Rogersdd7624d2014-03-14 17:43:00 -0700726 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
727 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700728
Ian Rogersdd7624d2014-03-14 17:43:00 -0700729 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
730 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700731
Ian Rogersdd7624d2014-03-14 17:43:00 -0700732 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700733
Ian Rogersdd7624d2014-03-14 17:43:00 -0700734 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700735
Ian Rogersdd7624d2014-03-14 17:43:00 -0700736 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
737 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700738
Ian Rogersdd7624d2014-03-14 17:43:00 -0700739 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
740 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700741
Ian Rogersdd7624d2014-03-14 17:43:00 -0700742 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
743 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700744
Ian Rogersdd7624d2014-03-14 17:43:00 -0700745 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
746 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700747
Ian Rogersdd7624d2014-03-14 17:43:00 -0700748 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
749 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700750
jeffhao58136ca2012-05-24 13:40:11 -0700751 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700752 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700753
jeffhaocee4d0c2012-06-15 14:42:01 -0700754 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700755 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700756
Ian Rogers2c8f6532011-09-02 17:16:34 -0700757 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700758 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
759 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700760
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700761 // 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 -0700762 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700763 // that can be used to avoid loading the handle scope entry to see if the value is
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700764 // null.
765 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
766 ManagedRegister in_reg, bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700767
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700768 // 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 -0700769 // value is null and null_allowed.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700770 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
771 ManagedRegister scratch, bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700772
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700773 // src holds a handle scope entry (Object**) load this into dst
774 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700775
776 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
777 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700778 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
779 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700780
781 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700782 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
783 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
784 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700785
Ian Rogers2c8f6532011-09-02 17:16:34 -0700786 // Generate code to check if Thread::Current()->exception_ is non-null
787 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700788 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700789
Dave Allison65fcc2c2014-04-28 13:45:27 -0700790 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700791
Dave Allison45fdb932014-06-25 12:37:10 -0700792 static bool IsLowRegister(Register r) {
793 return r < R8;
794 }
795
796 static bool IsHighRegister(Register r) {
797 return r >= R8;
798 }
799
Dave Allison65fcc2c2014-04-28 13:45:27 -0700800 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700801 // Returns whether or not the given register is used for passing parameters.
802 static int RegisterCompare(const Register* reg1, const Register* reg2) {
803 return *reg1 - *reg2;
804 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700805};
806
Ian Rogers2c8f6532011-09-02 17:16:34 -0700807// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700808class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700809 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700810 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
811 : scratch_(scratch), stack_adjust_(stack_adjust) {
812 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700813 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700814 private:
815 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700816 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700817};
818
Ian Rogers2c8f6532011-09-02 17:16:34 -0700819} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700820} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700821
Ian Rogers166db042013-07-26 12:05:57 -0700822#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_