blob: 8730f52ecab2e96672475e214dbdfc6ca206a51c [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
22#include "base/logging.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070023#include "base/value_object.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070024#include "constants_arm.h"
Ian Rogers166db042013-07-26 12:05:57 -070025#include "utils/arm/managed_register_arm.h"
26#include "utils/assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070027#include "offsets.h"
28#include "utils.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
Carl Shapiroa2e18e12011-06-21 18:57:55 -070036class ShifterOperand {
37 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -070038 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
39 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070040 }
41
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010042 explicit ShifterOperand(uint32_t immed);
Carl Shapiroa2e18e12011-06-21 18:57:55 -070043
44 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -070045 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
46 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070047 }
48
Dave Allison65fcc2c2014-04-28 13:45:27 -070049 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
50 rs_(kNoRegister),
51 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
52 }
53
54 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
55 rs_(kNoRegister),
56 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070057 }
58
59 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -070060 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm),
61 rs_(rs),
62 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070063 }
64
Dave Allison65fcc2c2014-04-28 13:45:27 -070065 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070066
67 uint32_t type() const {
68 CHECK(is_valid());
69 return type_;
70 }
71
Dave Allison65fcc2c2014-04-28 13:45:27 -070072 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -070073 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -070074
75 bool IsEmpty() const {
76 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070077 }
78
Dave Allison65fcc2c2014-04-28 13:45:27 -070079 bool IsImmediate() const {
80 return type_ == kImmediate;
81 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070082
Dave Allison65fcc2c2014-04-28 13:45:27 -070083 bool IsRegister() const {
84 return type_ == kRegister;
85 }
86
87 bool IsShift() const {
88 return is_shift_;
89 }
90
91 uint32_t GetImmediate() const {
92 return immed_;
93 }
94
95 Shift GetShift() const {
96 return shift_;
97 }
98
99 Register GetRegister() const {
100 return rm_;
101 }
102
103 enum Type {
104 kUnknown = -1,
105 kRegister,
106 kImmediate
107 };
108
Dave Allison65fcc2c2014-04-28 13:45:27 -0700109 private:
110 Type type_;
111 Register rm_;
112 Register rs_;
113 bool is_rotate_;
114 bool is_shift_;
115 Shift shift_;
116 uint32_t rotate_;
117 uint32_t immed_;
118
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000119 friend class Arm32Assembler;
120 friend class Thumb2Assembler;
121
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700122#ifdef SOURCE_ASSEMBLER_SUPPORT
123 friend class BinaryAssembler;
124#endif
125};
126
127
128enum LoadOperandType {
129 kLoadSignedByte,
130 kLoadUnsignedByte,
131 kLoadSignedHalfword,
132 kLoadUnsignedHalfword,
133 kLoadWord,
134 kLoadWordPair,
135 kLoadSWord,
136 kLoadDWord
137};
138
139
140enum StoreOperandType {
141 kStoreByte,
142 kStoreHalfword,
143 kStoreWord,
144 kStoreWordPair,
145 kStoreSWord,
146 kStoreDWord
147};
148
149
150// Load/store multiple addressing mode.
151enum BlockAddressMode {
152 // bit encoding P U W
153 DA = (0|0|0) << 21, // decrement after
154 IA = (0|4|0) << 21, // increment after
155 DB = (8|0|0) << 21, // decrement before
156 IB = (8|4|0) << 21, // increment before
157 DA_W = (0|0|1) << 21, // decrement after with writeback to base
158 IA_W = (0|4|1) << 21, // increment after with writeback to base
159 DB_W = (8|0|1) << 21, // decrement before with writeback to base
160 IB_W = (8|4|1) << 21 // increment before with writeback to base
161};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700162inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
163 os << static_cast<int>(rhs);
164 return os;
165}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700166
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700167class Address : public ValueObject {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700168 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700169 // Memory operand addressing mode (in ARM encoding form. For others we need
170 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700171 enum Mode {
172 // bit encoding P U W
173 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
174 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
175 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
176 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
177 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
178 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
179 };
180
Dave Allison45fdb932014-06-25 12:37:10 -0700181 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
182 offset_(offset),
183 am_(am), is_immed_offset_(true), shift_(LSL) {
184 }
185
186 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
187 am_(am), is_immed_offset_(false), shift_(LSL) {
188 CHECK_NE(rm, PC);
189 }
190
191 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
192 rn_(rn), rm_(rm), offset_(count),
193 am_(am), is_immed_offset_(false), shift_(shift) {
194 CHECK_NE(rm, PC);
195 }
196
197 // LDR(literal) - pc relative load.
198 explicit Address(int32_t offset) :
199 rn_(PC), rm_(R0), offset_(offset),
200 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700201 }
202
Dave Allison65fcc2c2014-04-28 13:45:27 -0700203 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
204 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
205
206 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
207 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
208
209 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700210 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700211
212 uint32_t encoding3() const;
213 uint32_t vencoding() const;
214
215 uint32_t encodingThumbLdrdStrd() const;
216
217 Register GetRegister() const {
218 return rn_;
219 }
220
Dave Allison45fdb932014-06-25 12:37:10 -0700221 Register GetRegisterOffset() const {
222 return rm_;
223 }
224
Dave Allison65fcc2c2014-04-28 13:45:27 -0700225 int32_t GetOffset() const {
226 return offset_;
227 }
228
229 Mode GetMode() const {
230 return am_;
231 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700232
Dave Allison45fdb932014-06-25 12:37:10 -0700233 bool IsImmediate() const {
234 return is_immed_offset_;
235 }
236
237 Shift GetShift() const {
238 return shift_;
239 }
240
241 int32_t GetShiftCount() const {
242 CHECK(!is_immed_offset_);
243 return offset_;
244 }
245
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700246 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700247 const Register rn_;
248 const Register rm_;
249 const int32_t offset_; // Used as shift amount for register offset.
250 const Mode am_;
251 const bool is_immed_offset_;
252 const Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700253};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700254inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
255 os << static_cast<int>(rhs);
256 return os;
257}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700258
Dave Allison65fcc2c2014-04-28 13:45:27 -0700259// Instruction encoding bits.
260enum {
261 H = 1 << 5, // halfword (or byte)
262 L = 1 << 20, // load (or store)
263 S = 1 << 20, // set condition code (or leave unchanged)
264 W = 1 << 21, // writeback base register (or leave unchanged)
265 A = 1 << 21, // accumulate in multiply instruction (or not)
266 B = 1 << 22, // unsigned byte (or word)
267 N = 1 << 22, // long (or short)
268 U = 1 << 23, // positive (or negative) offset/index
269 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
270 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700271
Dave Allison65fcc2c2014-04-28 13:45:27 -0700272 B0 = 1,
273 B1 = 1 << 1,
274 B2 = 1 << 2,
275 B3 = 1 << 3,
276 B4 = 1 << 4,
277 B5 = 1 << 5,
278 B6 = 1 << 6,
279 B7 = 1 << 7,
280 B8 = 1 << 8,
281 B9 = 1 << 9,
282 B10 = 1 << 10,
283 B11 = 1 << 11,
284 B12 = 1 << 12,
285 B13 = 1 << 13,
286 B14 = 1 << 14,
287 B15 = 1 << 15,
288 B16 = 1 << 16,
289 B17 = 1 << 17,
290 B18 = 1 << 18,
291 B19 = 1 << 19,
292 B20 = 1 << 20,
293 B21 = 1 << 21,
294 B22 = 1 << 22,
295 B23 = 1 << 23,
296 B24 = 1 << 24,
297 B25 = 1 << 25,
298 B26 = 1 << 26,
299 B27 = 1 << 27,
300 B28 = 1 << 28,
301 B29 = 1 << 29,
302 B30 = 1 << 30,
303 B31 = 1 << 31,
304
305 // Instruction bit masks.
306 RdMask = 15 << 12, // in str instruction
307 CondMask = 15 << 28,
308 CoprocessorMask = 15 << 8,
309 OpCodeMask = 15 << 21, // in data-processing instructions
310 Imm24Mask = (1 << 24) - 1,
311 Off12Mask = (1 << 12) - 1,
312
313 // ldrex/strex register field encodings.
314 kLdExRnShift = 16,
315 kLdExRtShift = 12,
316 kStrExRnShift = 16,
317 kStrExRdShift = 12,
318 kStrExRtShift = 0,
319};
320
321// IfThen state for IT instructions.
322enum ItState {
323 kItOmitted,
324 kItThen,
325 kItT = kItThen,
326 kItElse,
327 kItE = kItElse
328};
329
330constexpr uint32_t kNoItCondition = 3;
331constexpr uint32_t kInvalidModifiedImmediate = -1;
332
333extern const char* kRegisterNames[];
334extern const char* kConditionNames[];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700335
336// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
337// instruction sets (ARM32, Thumb2, etc.)
338//
339class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700340 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700341 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700342
Dave Allison65fcc2c2014-04-28 13:45:27 -0700343 // Is this assembler for the thumb instruction set?
344 virtual bool IsThumb() const = 0;
345
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700346 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700347 virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700348
Dave Allison65fcc2c2014-04-28 13:45:27 -0700349 virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700350
Dave Allison65fcc2c2014-04-28 13:45:27 -0700351 virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
352 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700353
Dave Allison65fcc2c2014-04-28 13:45:27 -0700354 virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
355 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700356
Dave Allison65fcc2c2014-04-28 13:45:27 -0700357 virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700358
Dave Allison65fcc2c2014-04-28 13:45:27 -0700359 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700360
Dave Allison65fcc2c2014-04-28 13:45:27 -0700361 virtual void adc(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 sbc(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 rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700366
Dave Allison65fcc2c2014-04-28 13:45:27 -0700367 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700368
Dave Allison65fcc2c2014-04-28 13:45:27 -0700369 virtual void teq(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 cmp(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 cmn(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 orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
376 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700377
Dave Allison65fcc2c2014-04-28 13:45:27 -0700378 virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
379 virtual void movs(Register rd, 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 bic(Register rd, 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 mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
384 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700385
386 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700387 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
388 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
389 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700390
391 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700392 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
393 virtual void mla(Register rd, Register rn, Register rm, Register ra,
394 Condition cond = AL) = 0;
395 virtual void mls(Register rd, Register rn, Register rm, Register ra,
396 Condition cond = AL) = 0;
397 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
398 Condition cond = AL) = 0;
399
400 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
401 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700402
Roland Levillain981e4542014-11-14 11:47:14 +0000403 // Bit field extract instructions.
Roland Levillain51d3fc42014-11-13 14:11:42 +0000404 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
405 Condition cond = AL) = 0;
Roland Levillain981e4542014-11-14 11:47:14 +0000406 virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
407 Condition cond = AL) = 0;
Roland Levillain51d3fc42014-11-13 14:11:42 +0000408
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700409 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700410 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
411 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700412
Dave Allison65fcc2c2014-04-28 13:45:27 -0700413 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
414 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700415
Dave Allison65fcc2c2014-04-28 13:45:27 -0700416 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
417 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700418
Dave Allison65fcc2c2014-04-28 13:45:27 -0700419 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
420 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700421
Dave Allison65fcc2c2014-04-28 13:45:27 -0700422 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
423 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700424
Dave Allison65fcc2c2014-04-28 13:45:27 -0700425 virtual void ldm(BlockAddressMode am, Register base,
426 RegList regs, Condition cond = AL) = 0;
427 virtual void stm(BlockAddressMode am, Register base,
428 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700429
Dave Allison65fcc2c2014-04-28 13:45:27 -0700430 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
431 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Calin Juravle52c48962014-12-16 17:02:57 +0000432 virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
433 virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700434
435 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700436 virtual void clrex(Condition cond = AL) = 0;
437 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700438
439 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700440 virtual void bkpt(uint16_t imm16) = 0;
441 virtual void svc(uint32_t imm24) = 0;
442
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700443 virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
444 ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
445 ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
446 ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700447 // Ignored if not supported.
448 }
449
450 virtual void cbz(Register rn, Label* target) = 0;
451 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700452
453 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700454 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
455 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
456 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
457 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
458 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
459 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
460 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
461 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700462
463 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700464 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
465 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700466
Dave Allison65fcc2c2014-04-28 13:45:27 -0700467 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
468 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
469 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
470 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700471
Dave Allison65fcc2c2014-04-28 13:45:27 -0700472 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
473 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
474 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
475 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
476 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
477 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
478 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
479 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
480 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
481 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
482 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
483 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700484
Dave Allison65fcc2c2014-04-28 13:45:27 -0700485 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
486 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
487 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
488 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
489 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
490 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700491
Dave Allison65fcc2c2014-04-28 13:45:27 -0700492 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
493 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
494 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
495 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
496 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
497 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
498 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
499 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
500 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
501 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700502
Dave Allison65fcc2c2014-04-28 13:45:27 -0700503 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
504 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
505 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
506 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
507 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
508
509 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
510 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
511 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
512 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700513
514 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700515 virtual void b(Label* label, Condition cond = AL) = 0;
516 virtual void bl(Label* label, Condition cond = AL) = 0;
517 virtual void blx(Register rm, Condition cond = AL) = 0;
518 virtual void bx(Register rm, Condition cond = AL) = 0;
519
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100520 // Memory barriers.
521 virtual void dmb(DmbOptions flavor) = 0;
522
Dave Allison65fcc2c2014-04-28 13:45:27 -0700523 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700524
525 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700526 // Most of these are pure virtual as they need to be implemented per instruction set.
527
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700528 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700529 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
530 virtual void AddConstant(Register rd, Register rn, int32_t value,
531 Condition cond = AL) = 0;
532 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
533 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700534
535 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700536 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000537 void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
538 if (!vmovs(sd, value, cond)) {
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000539 int32_t int_value = bit_cast<int32_t, float>(value);
540 if (int_value == bit_cast<int32_t, float>(0.0f)) {
541 // 0.0 is quite common, so we special case it by loading
542 // 2.0 in `sd` and then substracting it.
543 bool success = vmovs(sd, 2.0, cond);
544 CHECK(success);
545 vsubs(sd, sd, sd, cond);
546 } else {
547 LoadImmediate(IP, int_value, cond);
548 vmovsr(sd, IP, cond);
549 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000550 }
551 }
552
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000553 void LoadDImmediate(DRegister sd, double value, Condition cond = AL) {
554 if (!vmovd(sd, value, cond)) {
555 uint64_t int_value = bit_cast<uint64_t, double>(value);
Nicolas Geoffrayffe8a572015-02-11 01:10:39 +0000556 if (int_value == bit_cast<uint64_t, double>(0.0)) {
557 // 0.0 is quite common, so we special case it by loading
558 // 2.0 in `sd` and then substracting it.
559 bool success = vmovd(sd, 2.0, cond);
560 CHECK(success);
561 vsubd(sd, sd, sd, cond);
562 } else {
563 if (sd < 16) {
564 SRegister low = static_cast<SRegister>(sd << 1);
565 SRegister high = static_cast<SRegister>(low + 1);
566 LoadSImmediate(low, bit_cast<float, uint32_t>(Low32Bits(int_value)), cond);
567 if (High32Bits(int_value) == Low32Bits(int_value)) {
568 vmovs(high, low);
569 } else {
570 LoadSImmediate(high, bit_cast<float, uint32_t>(High32Bits(int_value)), cond);
571 }
572 } else {
573 LOG(FATAL) << "Unimplemented loading of double into a D register "
574 << "that cannot be split into two S registers";
575 }
576 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000577 }
578 }
579
Dave Allison65fcc2c2014-04-28 13:45:27 -0700580 virtual void MarkExceptionHandler(Label* label) = 0;
581 virtual void LoadFromOffset(LoadOperandType type,
582 Register reg,
583 Register base,
584 int32_t offset,
585 Condition cond = AL) = 0;
586 virtual void StoreToOffset(StoreOperandType type,
587 Register reg,
588 Register base,
589 int32_t offset,
590 Condition cond = AL) = 0;
591 virtual void LoadSFromOffset(SRegister reg,
592 Register base,
593 int32_t offset,
594 Condition cond = AL) = 0;
595 virtual void StoreSToOffset(SRegister reg,
596 Register base,
597 int32_t offset,
598 Condition cond = AL) = 0;
599 virtual void LoadDFromOffset(DRegister reg,
600 Register base,
601 int32_t offset,
602 Condition cond = AL) = 0;
603 virtual void StoreDToOffset(DRegister reg,
604 Register base,
605 int32_t offset,
606 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700607
Dave Allison65fcc2c2014-04-28 13:45:27 -0700608 virtual void Push(Register rd, Condition cond = AL) = 0;
609 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700610
Dave Allison65fcc2c2014-04-28 13:45:27 -0700611 virtual void PushList(RegList regs, Condition cond = AL) = 0;
612 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700613
Dave Allison65fcc2c2014-04-28 13:45:27 -0700614 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700615
616 // Convenience shift instructions. Use mov instruction with shifter operand
617 // for variants setting the status flags or using a register shift count.
Dave Allison45fdb932014-06-25 12:37:10 -0700618 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
619 Condition cond = AL) = 0;
620 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
621 Condition cond = AL) = 0;
622 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
623 Condition cond = AL) = 0;
624 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
625 Condition cond = AL) = 0;
626 virtual void Rrx(Register rd, Register rm, bool setcc = false,
627 Condition cond = AL) = 0;
628
629 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
630 Condition cond = AL) = 0;
631 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
632 Condition cond = AL) = 0;
633 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
634 Condition cond = AL) = 0;
635 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
636 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700637
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +0000638 // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
639 // `shifter_op` contains the operand.
640 virtual bool ShifterOperandCanHold(Register rd,
641 Register rn,
642 Opcode opcode,
643 uint32_t immediate,
644 ShifterOperand* shifter_op) = 0;
645
Ian Rogers13735952014-10-08 12:43:28 -0700646 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700647
Dave Allison65fcc2c2014-04-28 13:45:27 -0700648 virtual void Bind(Label* label) = 0;
649
650 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
651 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700652
Ian Rogers2c8f6532011-09-02 17:16:34 -0700653 //
654 // Overridden common assembler high-level functionality
655 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700656
Ian Rogers2c8f6532011-09-02 17:16:34 -0700657 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700658 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
659 const std::vector<ManagedRegister>& callee_save_regs,
660 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700661
Ian Rogers2c8f6532011-09-02 17:16:34 -0700662 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700663 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700664 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700665
Ian Rogersdd7624d2014-03-14 17:43:00 -0700666 void IncreaseFrameSize(size_t adjust) OVERRIDE;
667 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700668
669 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700670 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
671 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
672 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700673
Ian Rogersdd7624d2014-03-14 17:43:00 -0700674 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700675
Ian Rogersdd7624d2014-03-14 17:43:00 -0700676 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
677 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700678
Ian Rogersdd7624d2014-03-14 17:43:00 -0700679 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
680 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700681
Ian Rogersdd7624d2014-03-14 17:43:00 -0700682 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700683
Ian Rogersdd7624d2014-03-14 17:43:00 -0700684 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
685 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700686
Ian Rogers2c8f6532011-09-02 17:16:34 -0700687 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700688 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700689
Ian Rogersdd7624d2014-03-14 17:43:00 -0700690 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700691
Ian Rogersdd7624d2014-03-14 17:43:00 -0700692 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700693
Ian Rogersdd7624d2014-03-14 17:43:00 -0700694 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700695
Ian Rogersdd7624d2014-03-14 17:43:00 -0700696 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700697
Ian Rogersdd7624d2014-03-14 17:43:00 -0700698 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700699
700 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700701 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700702
Ian Rogersdd7624d2014-03-14 17:43:00 -0700703 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
704 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700705
Ian Rogersdd7624d2014-03-14 17:43:00 -0700706 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
707 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700708
Ian Rogersdd7624d2014-03-14 17:43:00 -0700709 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700710
Ian Rogersdd7624d2014-03-14 17:43:00 -0700711 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700712
Ian Rogersdd7624d2014-03-14 17:43:00 -0700713 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
714 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700715
Ian Rogersdd7624d2014-03-14 17:43:00 -0700716 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
717 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700718
Ian Rogersdd7624d2014-03-14 17:43:00 -0700719 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
720 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700721
Ian Rogersdd7624d2014-03-14 17:43:00 -0700722 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
723 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700724
Ian Rogersdd7624d2014-03-14 17:43:00 -0700725 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
726 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700727
jeffhao58136ca2012-05-24 13:40:11 -0700728 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700729 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700730
jeffhaocee4d0c2012-06-15 14:42:01 -0700731 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700732 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700733
Ian Rogers2c8f6532011-09-02 17:16:34 -0700734 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700735 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
736 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700737
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700738 // 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 -0700739 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700740 // that can be used to avoid loading the handle scope entry to see if the value is
Ian Rogers2c8f6532011-09-02 17:16:34 -0700741 // NULL.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700742 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700743 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700744
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700745 // 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 -0700746 // value is null and null_allowed.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700747 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700748 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700749
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700750 // src holds a handle scope entry (Object**) load this into dst
751 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700752
753 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
754 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700755 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
756 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700757
758 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700759 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
760 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
761 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700762
Ian Rogers2c8f6532011-09-02 17:16:34 -0700763 // Generate code to check if Thread::Current()->exception_ is non-null
764 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700765 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700766
Dave Allison65fcc2c2014-04-28 13:45:27 -0700767 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700768
Dave Allison45fdb932014-06-25 12:37:10 -0700769 static bool IsLowRegister(Register r) {
770 return r < R8;
771 }
772
773 static bool IsHighRegister(Register r) {
774 return r >= R8;
775 }
776
Dave Allison65fcc2c2014-04-28 13:45:27 -0700777 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700778 // Returns whether or not the given register is used for passing parameters.
779 static int RegisterCompare(const Register* reg1, const Register* reg2) {
780 return *reg1 - *reg2;
781 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700782};
783
Ian Rogers2c8f6532011-09-02 17:16:34 -0700784// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700785class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700786 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700787 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
788 : scratch_(scratch), stack_adjust_(stack_adjust) {
789 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700790 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700791 private:
792 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700793 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700794};
795
Ian Rogers2c8f6532011-09-02 17:16:34 -0700796} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700797} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700798
Ian Rogers166db042013-07-26 12:05:57 -0700799#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_