blob: 911000aee8519c0955f6f78dcfc4ea62274b0a6c [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
Carl Shapiroa2e18e12011-06-21 18:57:55 -070033class ShifterOperand {
34 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -070035 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
36 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070037 }
38
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010039 explicit ShifterOperand(uint32_t immed);
Carl Shapiroa2e18e12011-06-21 18:57:55 -070040
41 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -070042 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
43 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070044 }
45
Dave Allison65fcc2c2014-04-28 13:45:27 -070046 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
47 rs_(kNoRegister),
48 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
49 }
50
51 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
52 rs_(kNoRegister),
53 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070054 }
55
56 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -070057 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm),
58 rs_(rs),
59 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070060 }
61
Dave Allison65fcc2c2014-04-28 13:45:27 -070062 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070063
64 uint32_t type() const {
65 CHECK(is_valid());
66 return type_;
67 }
68
Dave Allison65fcc2c2014-04-28 13:45:27 -070069 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -070070 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -070071
72 bool IsEmpty() const {
73 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070074 }
75
Dave Allison65fcc2c2014-04-28 13:45:27 -070076 bool IsImmediate() const {
77 return type_ == kImmediate;
78 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070079
Dave Allison65fcc2c2014-04-28 13:45:27 -070080 bool IsRegister() const {
81 return type_ == kRegister;
82 }
83
84 bool IsShift() const {
85 return is_shift_;
86 }
87
88 uint32_t GetImmediate() const {
89 return immed_;
90 }
91
92 Shift GetShift() const {
93 return shift_;
94 }
95
96 Register GetRegister() const {
97 return rm_;
98 }
99
100 enum Type {
101 kUnknown = -1,
102 kRegister,
103 kImmediate
104 };
105
106 static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) {
107 // Avoid the more expensive test for frequent small immediate values.
108 if (immediate < (1 << kImmed8Bits)) {
109 shifter_op->type_ = kImmediate;
110 shifter_op->is_rotate_ = true;
111 shifter_op->rotate_ = 0;
112 shifter_op->immed_ = immediate;
113 return true;
114 }
115 // Note that immediate must be unsigned for the test to work correctly.
116 for (int rot = 0; rot < 16; rot++) {
117 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
118 if (imm8 < (1 << kImmed8Bits)) {
119 shifter_op->type_ = kImmediate;
120 shifter_op->is_rotate_ = true;
121 shifter_op->rotate_ = rot;
122 shifter_op->immed_ = imm8;
123 return true;
124 }
125 }
126 return false;
127 }
128
129 static bool CanHoldThumb(Register rd, Register rn, Opcode opcode,
130 uint32_t immediate, ShifterOperand* shifter_op);
131
132
133 private:
134 Type type_;
135 Register rm_;
136 Register rs_;
137 bool is_rotate_;
138 bool is_shift_;
139 Shift shift_;
140 uint32_t rotate_;
141 uint32_t immed_;
142
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700143#ifdef SOURCE_ASSEMBLER_SUPPORT
144 friend class BinaryAssembler;
145#endif
146};
147
148
149enum LoadOperandType {
150 kLoadSignedByte,
151 kLoadUnsignedByte,
152 kLoadSignedHalfword,
153 kLoadUnsignedHalfword,
154 kLoadWord,
155 kLoadWordPair,
156 kLoadSWord,
157 kLoadDWord
158};
159
160
161enum StoreOperandType {
162 kStoreByte,
163 kStoreHalfword,
164 kStoreWord,
165 kStoreWordPair,
166 kStoreSWord,
167 kStoreDWord
168};
169
170
171// Load/store multiple addressing mode.
172enum BlockAddressMode {
173 // bit encoding P U W
174 DA = (0|0|0) << 21, // decrement after
175 IA = (0|4|0) << 21, // increment after
176 DB = (8|0|0) << 21, // decrement before
177 IB = (8|4|0) << 21, // increment before
178 DA_W = (0|0|1) << 21, // decrement after with writeback to base
179 IA_W = (0|4|1) << 21, // increment after with writeback to base
180 DB_W = (8|0|1) << 21, // decrement before with writeback to base
181 IB_W = (8|4|1) << 21 // increment before with writeback to base
182};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700183inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
184 os << static_cast<int>(rhs);
185 return os;
186}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700187
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700188class Address : public ValueObject {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700189 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700190 // Memory operand addressing mode (in ARM encoding form. For others we need
191 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700192 enum Mode {
193 // bit encoding P U W
194 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
195 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
196 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
197 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
198 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
199 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
200 };
201
Dave Allison45fdb932014-06-25 12:37:10 -0700202 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
203 offset_(offset),
204 am_(am), is_immed_offset_(true), shift_(LSL) {
205 }
206
207 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
208 am_(am), is_immed_offset_(false), shift_(LSL) {
209 CHECK_NE(rm, PC);
210 }
211
212 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
213 rn_(rn), rm_(rm), offset_(count),
214 am_(am), is_immed_offset_(false), shift_(shift) {
215 CHECK_NE(rm, PC);
216 }
217
218 // LDR(literal) - pc relative load.
219 explicit Address(int32_t offset) :
220 rn_(PC), rm_(R0), offset_(offset),
221 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700222 }
223
Dave Allison65fcc2c2014-04-28 13:45:27 -0700224 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
225 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
226
227 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
228 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
229
230 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700231 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700232
233 uint32_t encoding3() const;
234 uint32_t vencoding() const;
235
236 uint32_t encodingThumbLdrdStrd() const;
237
238 Register GetRegister() const {
239 return rn_;
240 }
241
Dave Allison45fdb932014-06-25 12:37:10 -0700242 Register GetRegisterOffset() const {
243 return rm_;
244 }
245
Dave Allison65fcc2c2014-04-28 13:45:27 -0700246 int32_t GetOffset() const {
247 return offset_;
248 }
249
250 Mode GetMode() const {
251 return am_;
252 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700253
Dave Allison45fdb932014-06-25 12:37:10 -0700254 bool IsImmediate() const {
255 return is_immed_offset_;
256 }
257
258 Shift GetShift() const {
259 return shift_;
260 }
261
262 int32_t GetShiftCount() const {
263 CHECK(!is_immed_offset_);
264 return offset_;
265 }
266
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700267 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700268 const Register rn_;
269 const Register rm_;
270 const int32_t offset_; // Used as shift amount for register offset.
271 const Mode am_;
272 const bool is_immed_offset_;
273 const Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700274};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700275inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
276 os << static_cast<int>(rhs);
277 return os;
278}
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700279
Dave Allison65fcc2c2014-04-28 13:45:27 -0700280// Instruction encoding bits.
281enum {
282 H = 1 << 5, // halfword (or byte)
283 L = 1 << 20, // load (or store)
284 S = 1 << 20, // set condition code (or leave unchanged)
285 W = 1 << 21, // writeback base register (or leave unchanged)
286 A = 1 << 21, // accumulate in multiply instruction (or not)
287 B = 1 << 22, // unsigned byte (or word)
288 N = 1 << 22, // long (or short)
289 U = 1 << 23, // positive (or negative) offset/index
290 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
291 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700292
Dave Allison65fcc2c2014-04-28 13:45:27 -0700293 B0 = 1,
294 B1 = 1 << 1,
295 B2 = 1 << 2,
296 B3 = 1 << 3,
297 B4 = 1 << 4,
298 B5 = 1 << 5,
299 B6 = 1 << 6,
300 B7 = 1 << 7,
301 B8 = 1 << 8,
302 B9 = 1 << 9,
303 B10 = 1 << 10,
304 B11 = 1 << 11,
305 B12 = 1 << 12,
306 B13 = 1 << 13,
307 B14 = 1 << 14,
308 B15 = 1 << 15,
309 B16 = 1 << 16,
310 B17 = 1 << 17,
311 B18 = 1 << 18,
312 B19 = 1 << 19,
313 B20 = 1 << 20,
314 B21 = 1 << 21,
315 B22 = 1 << 22,
316 B23 = 1 << 23,
317 B24 = 1 << 24,
318 B25 = 1 << 25,
319 B26 = 1 << 26,
320 B27 = 1 << 27,
321 B28 = 1 << 28,
322 B29 = 1 << 29,
323 B30 = 1 << 30,
324 B31 = 1 << 31,
325
326 // Instruction bit masks.
327 RdMask = 15 << 12, // in str instruction
328 CondMask = 15 << 28,
329 CoprocessorMask = 15 << 8,
330 OpCodeMask = 15 << 21, // in data-processing instructions
331 Imm24Mask = (1 << 24) - 1,
332 Off12Mask = (1 << 12) - 1,
333
334 // ldrex/strex register field encodings.
335 kLdExRnShift = 16,
336 kLdExRtShift = 12,
337 kStrExRnShift = 16,
338 kStrExRdShift = 12,
339 kStrExRtShift = 0,
340};
341
342// IfThen state for IT instructions.
343enum ItState {
344 kItOmitted,
345 kItThen,
346 kItT = kItThen,
347 kItElse,
348 kItE = kItElse
349};
350
351constexpr uint32_t kNoItCondition = 3;
352constexpr uint32_t kInvalidModifiedImmediate = -1;
353
354extern const char* kRegisterNames[];
355extern const char* kConditionNames[];
Dave Allison65fcc2c2014-04-28 13:45:27 -0700356
357// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
358// instruction sets (ARM32, Thumb2, etc.)
359//
360class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700361 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700362 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700363
Dave Allison65fcc2c2014-04-28 13:45:27 -0700364 // Is this assembler for the thumb instruction set?
365 virtual bool IsThumb() const = 0;
366
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700367 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700368 virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700369
Dave Allison65fcc2c2014-04-28 13:45:27 -0700370 virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700371
Dave Allison65fcc2c2014-04-28 13:45:27 -0700372 virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
373 virtual void subs(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 rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
376 virtual void rsbs(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 add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700379
Dave Allison65fcc2c2014-04-28 13:45:27 -0700380 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700381
Dave Allison65fcc2c2014-04-28 13:45:27 -0700382 virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700383
Dave Allison65fcc2c2014-04-28 13:45:27 -0700384 virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700385
Dave Allison65fcc2c2014-04-28 13:45:27 -0700386 virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700387
Dave Allison65fcc2c2014-04-28 13:45:27 -0700388 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700389
Dave Allison65fcc2c2014-04-28 13:45:27 -0700390 virtual void teq(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 cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700393
Dave Allison65fcc2c2014-04-28 13:45:27 -0700394 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700395
Dave Allison65fcc2c2014-04-28 13:45:27 -0700396 virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
397 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700398
Dave Allison65fcc2c2014-04-28 13:45:27 -0700399 virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
400 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700401
Dave Allison65fcc2c2014-04-28 13:45:27 -0700402 virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700403
Dave Allison65fcc2c2014-04-28 13:45:27 -0700404 virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
405 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700406
407 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700408 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
409 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
410 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700411
412 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700413 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
414 virtual void mla(Register rd, Register rn, Register rm, Register ra,
415 Condition cond = AL) = 0;
416 virtual void mls(Register rd, Register rn, Register rm, Register ra,
417 Condition cond = AL) = 0;
418 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
419 Condition cond = AL) = 0;
420
421 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
422 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700423
Roland Levillain51d3fc42014-11-13 14:11:42 +0000424 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
425 Condition cond = AL) = 0;
426
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700427 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700428 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
429 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700430
Dave Allison65fcc2c2014-04-28 13:45:27 -0700431 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
432 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700433
Dave Allison65fcc2c2014-04-28 13:45:27 -0700434 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
435 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700436
Dave Allison65fcc2c2014-04-28 13:45:27 -0700437 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
438 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700439
Dave Allison65fcc2c2014-04-28 13:45:27 -0700440 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
441 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700442
Dave Allison65fcc2c2014-04-28 13:45:27 -0700443 virtual void ldm(BlockAddressMode am, Register base,
444 RegList regs, Condition cond = AL) = 0;
445 virtual void stm(BlockAddressMode am, Register base,
446 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700447
Dave Allison65fcc2c2014-04-28 13:45:27 -0700448 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
449 virtual void strex(Register rd, Register rt, 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;
532 virtual void bl(Label* label, Condition cond = AL) = 0;
533 virtual void blx(Register rm, Condition cond = AL) = 0;
534 virtual void bx(Register rm, Condition cond = AL) = 0;
535
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100536 // Memory barriers.
537 virtual void dmb(DmbOptions flavor) = 0;
538
Dave Allison65fcc2c2014-04-28 13:45:27 -0700539 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700540
541 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700542 // Most of these are pure virtual as they need to be implemented per instruction set.
543
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700544 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700545 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
546 virtual void AddConstant(Register rd, Register rn, int32_t value,
547 Condition cond = AL) = 0;
548 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
549 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700550
551 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700552 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700553 virtual void MarkExceptionHandler(Label* label) = 0;
554 virtual void LoadFromOffset(LoadOperandType type,
555 Register reg,
556 Register base,
557 int32_t offset,
558 Condition cond = AL) = 0;
559 virtual void StoreToOffset(StoreOperandType type,
560 Register reg,
561 Register base,
562 int32_t offset,
563 Condition cond = AL) = 0;
564 virtual void LoadSFromOffset(SRegister reg,
565 Register base,
566 int32_t offset,
567 Condition cond = AL) = 0;
568 virtual void StoreSToOffset(SRegister reg,
569 Register base,
570 int32_t offset,
571 Condition cond = AL) = 0;
572 virtual void LoadDFromOffset(DRegister reg,
573 Register base,
574 int32_t offset,
575 Condition cond = AL) = 0;
576 virtual void StoreDToOffset(DRegister reg,
577 Register base,
578 int32_t offset,
579 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700580
Dave Allison65fcc2c2014-04-28 13:45:27 -0700581 virtual void Push(Register rd, Condition cond = AL) = 0;
582 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700583
Dave Allison65fcc2c2014-04-28 13:45:27 -0700584 virtual void PushList(RegList regs, Condition cond = AL) = 0;
585 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700586
Dave Allison65fcc2c2014-04-28 13:45:27 -0700587 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700588
589 // Convenience shift instructions. Use mov instruction with shifter operand
590 // for variants setting the status flags or using a register shift count.
Dave Allison45fdb932014-06-25 12:37:10 -0700591 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
592 Condition cond = AL) = 0;
593 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
594 Condition cond = AL) = 0;
595 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
596 Condition cond = AL) = 0;
597 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
598 Condition cond = AL) = 0;
599 virtual void Rrx(Register rd, Register rm, bool setcc = false,
600 Condition cond = AL) = 0;
601
602 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
603 Condition cond = AL) = 0;
604 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
605 Condition cond = AL) = 0;
606 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
607 Condition cond = AL) = 0;
608 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
609 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700610
Ian Rogers13735952014-10-08 12:43:28 -0700611 static bool IsInstructionForExceptionHandling(uintptr_t pc);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700612
Dave Allison65fcc2c2014-04-28 13:45:27 -0700613 virtual void Bind(Label* label) = 0;
614
615 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
616 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700617
Ian Rogers2c8f6532011-09-02 17:16:34 -0700618 //
619 // Overridden common assembler high-level functionality
620 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700621
Ian Rogers2c8f6532011-09-02 17:16:34 -0700622 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700623 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
624 const std::vector<ManagedRegister>& callee_save_regs,
625 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700626
Ian Rogers2c8f6532011-09-02 17:16:34 -0700627 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700628 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700629 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700630
Ian Rogersdd7624d2014-03-14 17:43:00 -0700631 void IncreaseFrameSize(size_t adjust) OVERRIDE;
632 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700633
634 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700635 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
636 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
637 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700638
Ian Rogersdd7624d2014-03-14 17:43:00 -0700639 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700640
Ian Rogersdd7624d2014-03-14 17:43:00 -0700641 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
642 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700643
Ian Rogersdd7624d2014-03-14 17:43:00 -0700644 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
645 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700646
Ian Rogersdd7624d2014-03-14 17:43:00 -0700647 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700648
Ian Rogersdd7624d2014-03-14 17:43:00 -0700649 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
650 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700651
Ian Rogers2c8f6532011-09-02 17:16:34 -0700652 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700653 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654
Ian Rogersdd7624d2014-03-14 17:43:00 -0700655 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700656
Ian Rogersdd7624d2014-03-14 17:43:00 -0700657 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700658
Ian Rogersdd7624d2014-03-14 17:43:00 -0700659 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700660
Ian Rogersdd7624d2014-03-14 17:43:00 -0700661 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700662
Ian Rogersdd7624d2014-03-14 17:43:00 -0700663 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700664
665 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700666 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700667
Ian Rogersdd7624d2014-03-14 17:43:00 -0700668 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
669 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700670
Ian Rogersdd7624d2014-03-14 17:43:00 -0700671 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
672 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700673
Ian Rogersdd7624d2014-03-14 17:43:00 -0700674 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700675
Ian Rogersdd7624d2014-03-14 17:43:00 -0700676 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700677
Ian Rogersdd7624d2014-03-14 17:43:00 -0700678 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
679 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700680
Ian Rogersdd7624d2014-03-14 17:43:00 -0700681 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
682 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700683
Ian Rogersdd7624d2014-03-14 17:43:00 -0700684 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
685 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700686
Ian Rogersdd7624d2014-03-14 17:43:00 -0700687 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
688 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700689
Ian Rogersdd7624d2014-03-14 17:43:00 -0700690 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
691 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700692
jeffhao58136ca2012-05-24 13:40:11 -0700693 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700694 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700695
jeffhaocee4d0c2012-06-15 14:42:01 -0700696 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700697 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700698
Ian Rogers2c8f6532011-09-02 17:16:34 -0700699 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700700 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
701 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700702
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700703 // 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 -0700704 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700705 // that can be used to avoid loading the handle scope entry to see if the value is
Ian Rogers2c8f6532011-09-02 17:16:34 -0700706 // NULL.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700707 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700708 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700709
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700710 // 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 -0700711 // value is null and null_allowed.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700712 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700713 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700714
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700715 // src holds a handle scope entry (Object**) load this into dst
716 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700717
718 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
719 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700720 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
721 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700722
723 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700724 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
725 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
726 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700727
Ian Rogers2c8f6532011-09-02 17:16:34 -0700728 // Generate code to check if Thread::Current()->exception_ is non-null
729 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700730 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700731
Dave Allison65fcc2c2014-04-28 13:45:27 -0700732 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700733
Dave Allison45fdb932014-06-25 12:37:10 -0700734 static bool IsLowRegister(Register r) {
735 return r < R8;
736 }
737
738 static bool IsHighRegister(Register r) {
739 return r >= R8;
740 }
741
Dave Allison65fcc2c2014-04-28 13:45:27 -0700742 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700743 // Returns whether or not the given register is used for passing parameters.
744 static int RegisterCompare(const Register* reg1, const Register* reg2) {
745 return *reg1 - *reg2;
746 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700747};
748
Ian Rogers2c8f6532011-09-02 17:16:34 -0700749// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700750class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700751 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700752 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
753 : scratch_(scratch), stack_adjust_(stack_adjust) {
754 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700755 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700756 private:
757 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700758 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700759};
760
Ian Rogers2c8f6532011-09-02 17:16:34 -0700761} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700762} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700763
Ian Rogers166db042013-07-26 12:05:57 -0700764#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_