blob: be1917409384c42e6dfeb7db1b39b8170430be44 [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"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070023#include "constants_arm.h"
Ian Rogers166db042013-07-26 12:05:57 -070024#include "utils/arm/managed_register_arm.h"
25#include "utils/assembler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070026#include "offsets.h"
27#include "utils.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -070028
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070029namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070030namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070031
Carl Shapiroa2e18e12011-06-21 18:57:55 -070032class ShifterOperand {
33 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -070034 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
35 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070036 }
37
Dave Allison65fcc2c2014-04-28 13:45:27 -070038 explicit ShifterOperand(uint32_t immed) : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister),
39 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070040 }
41
42 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -070043 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
44 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070045 }
46
Dave Allison65fcc2c2014-04-28 13:45:27 -070047 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
48 rs_(kNoRegister),
49 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
50 }
51
52 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
53 rs_(kNoRegister),
54 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070055 }
56
57 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -070058 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm),
59 rs_(rs),
60 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070061 }
62
Dave Allison65fcc2c2014-04-28 13:45:27 -070063 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070064
65 uint32_t type() const {
66 CHECK(is_valid());
67 return type_;
68 }
69
Dave Allison65fcc2c2014-04-28 13:45:27 -070070 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -070071 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -070072
73 bool IsEmpty() const {
74 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070075 }
76
Dave Allison65fcc2c2014-04-28 13:45:27 -070077 bool IsImmediate() const {
78 return type_ == kImmediate;
79 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070080
Dave Allison65fcc2c2014-04-28 13:45:27 -070081 bool IsRegister() const {
82 return type_ == kRegister;
83 }
84
85 bool IsShift() const {
86 return is_shift_;
87 }
88
89 uint32_t GetImmediate() const {
90 return immed_;
91 }
92
93 Shift GetShift() const {
94 return shift_;
95 }
96
97 Register GetRegister() const {
98 return rm_;
99 }
100
101 enum Type {
102 kUnknown = -1,
103 kRegister,
104 kImmediate
105 };
106
107 static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) {
108 // Avoid the more expensive test for frequent small immediate values.
109 if (immediate < (1 << kImmed8Bits)) {
110 shifter_op->type_ = kImmediate;
111 shifter_op->is_rotate_ = true;
112 shifter_op->rotate_ = 0;
113 shifter_op->immed_ = immediate;
114 return true;
115 }
116 // Note that immediate must be unsigned for the test to work correctly.
117 for (int rot = 0; rot < 16; rot++) {
118 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
119 if (imm8 < (1 << kImmed8Bits)) {
120 shifter_op->type_ = kImmediate;
121 shifter_op->is_rotate_ = true;
122 shifter_op->rotate_ = rot;
123 shifter_op->immed_ = imm8;
124 return true;
125 }
126 }
127 return false;
128 }
129
130 static bool CanHoldThumb(Register rd, Register rn, Opcode opcode,
131 uint32_t immediate, ShifterOperand* shifter_op);
132
133
134 private:
135 Type type_;
136 Register rm_;
137 Register rs_;
138 bool is_rotate_;
139 bool is_shift_;
140 Shift shift_;
141 uint32_t rotate_;
142 uint32_t immed_;
143
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700144#ifdef SOURCE_ASSEMBLER_SUPPORT
145 friend class BinaryAssembler;
146#endif
147};
148
149
150enum LoadOperandType {
151 kLoadSignedByte,
152 kLoadUnsignedByte,
153 kLoadSignedHalfword,
154 kLoadUnsignedHalfword,
155 kLoadWord,
156 kLoadWordPair,
157 kLoadSWord,
158 kLoadDWord
159};
160
161
162enum StoreOperandType {
163 kStoreByte,
164 kStoreHalfword,
165 kStoreWord,
166 kStoreWordPair,
167 kStoreSWord,
168 kStoreDWord
169};
170
171
172// Load/store multiple addressing mode.
173enum BlockAddressMode {
174 // bit encoding P U W
175 DA = (0|0|0) << 21, // decrement after
176 IA = (0|4|0) << 21, // increment after
177 DB = (8|0|0) << 21, // decrement before
178 IB = (8|4|0) << 21, // increment before
179 DA_W = (0|0|1) << 21, // decrement after with writeback to base
180 IA_W = (0|4|1) << 21, // increment after with writeback to base
181 DB_W = (8|0|1) << 21, // decrement before with writeback to base
182 IB_W = (8|4|1) << 21 // increment before with writeback to base
183};
184
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700185class Address {
186 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700187 // Memory operand addressing mode (in ARM encoding form. For others we need
188 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700189 enum Mode {
190 // bit encoding P U W
191 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
192 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
193 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
194 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
195 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
196 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
197 };
198
Dave Allison45fdb932014-06-25 12:37:10 -0700199 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
200 offset_(offset),
201 am_(am), is_immed_offset_(true), shift_(LSL) {
202 }
203
204 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
205 am_(am), is_immed_offset_(false), shift_(LSL) {
206 CHECK_NE(rm, PC);
207 }
208
209 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
210 rn_(rn), rm_(rm), offset_(count),
211 am_(am), is_immed_offset_(false), shift_(shift) {
212 CHECK_NE(rm, PC);
213 }
214
215 // LDR(literal) - pc relative load.
216 explicit Address(int32_t offset) :
217 rn_(PC), rm_(R0), offset_(offset),
218 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700219 }
220
Dave Allison65fcc2c2014-04-28 13:45:27 -0700221 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
222 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
223
224 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
225 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
226
227 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700228 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700229
230 uint32_t encoding3() const;
231 uint32_t vencoding() const;
232
233 uint32_t encodingThumbLdrdStrd() const;
234
235 Register GetRegister() const {
236 return rn_;
237 }
238
Dave Allison45fdb932014-06-25 12:37:10 -0700239 Register GetRegisterOffset() const {
240 return rm_;
241 }
242
Dave Allison65fcc2c2014-04-28 13:45:27 -0700243 int32_t GetOffset() const {
244 return offset_;
245 }
246
247 Mode GetMode() const {
248 return am_;
249 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700250
Dave Allison45fdb932014-06-25 12:37:10 -0700251 bool IsImmediate() const {
252 return is_immed_offset_;
253 }
254
255 Shift GetShift() const {
256 return shift_;
257 }
258
259 int32_t GetShiftCount() const {
260 CHECK(!is_immed_offset_);
261 return offset_;
262 }
263
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700264 private:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700265 Register rn_;
Dave Allison45fdb932014-06-25 12:37:10 -0700266 Register rm_;
267 int32_t offset_; // Used as shift amount for register offset.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700268 Mode am_;
Dave Allison45fdb932014-06-25 12:37:10 -0700269 bool is_immed_offset_;
270 Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700271};
272
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[];
349extern std::ostream& operator<<(std::ostream& os, const Register& rhs);
350extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs);
351extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
352extern std::ostream& operator<<(std::ostream& os, const Condition& rhs);
353
354// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
355// instruction sets (ARM32, Thumb2, etc.)
356//
357class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700358 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700359 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700360
Dave Allison65fcc2c2014-04-28 13:45:27 -0700361 // Is this assembler for the thumb instruction set?
362 virtual bool IsThumb() const = 0;
363
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700364 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700365 virtual void and_(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 eor(Register rd, 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 sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
370 virtual void subs(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 rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
373 virtual void rsbs(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 add(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 adds(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 adc(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 sbc(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 rsc(Register rd, 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 tst(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 teq(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 cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700390
Dave Allison65fcc2c2014-04-28 13:45:27 -0700391 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700392
Dave Allison65fcc2c2014-04-28 13:45:27 -0700393 virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
394 virtual void orrs(Register rd, 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 mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
397 virtual void movs(Register rd, 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 bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700400
Dave Allison65fcc2c2014-04-28 13:45:27 -0700401 virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
402 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700403
404 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700405 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
406 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
407 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700408
409 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700410 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
411 virtual void mla(Register rd, Register rn, Register rm, Register ra,
412 Condition cond = AL) = 0;
413 virtual void mls(Register rd, Register rn, Register rm, Register ra,
414 Condition cond = AL) = 0;
415 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
416 Condition cond = AL) = 0;
417
418 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
419 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700420
421 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700422 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
423 virtual void str(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 ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
426 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700427
Dave Allison65fcc2c2014-04-28 13:45:27 -0700428 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
429 virtual void strh(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 ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
432 virtual void ldrsh(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 ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
435 virtual void strd(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 ldm(BlockAddressMode am, Register base,
438 RegList regs, Condition cond = AL) = 0;
439 virtual void stm(BlockAddressMode am, Register base,
440 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700441
Dave Allison65fcc2c2014-04-28 13:45:27 -0700442 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
443 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700444
445 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700446 virtual void clrex(Condition cond = AL) = 0;
447 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700448
449 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700450 virtual void bkpt(uint16_t imm16) = 0;
451 virtual void svc(uint32_t imm24) = 0;
452
453 virtual void it(Condition firstcond, ItState i1 = kItOmitted,
454 ItState i2 = kItOmitted, ItState i3 = kItOmitted) {
455 // Ignored if not supported.
456 }
457
458 virtual void cbz(Register rn, Label* target) = 0;
459 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700460
461 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700462 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
463 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
464 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
465 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
466 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
467 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
468 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
469 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700470
471 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700472 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
473 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700474
Dave Allison65fcc2c2014-04-28 13:45:27 -0700475 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
476 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
477 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
478 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700479
Dave Allison65fcc2c2014-04-28 13:45:27 -0700480 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
481 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
482 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
483 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
484 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
485 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
486 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
487 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
488 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
489 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
490 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
491 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700492
Dave Allison65fcc2c2014-04-28 13:45:27 -0700493 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
494 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
495 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
496 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
497 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
498 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700499
Dave Allison65fcc2c2014-04-28 13:45:27 -0700500 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
501 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
502 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
503 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
504 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
505 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
506 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
507 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
508 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
509 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700510
Dave Allison65fcc2c2014-04-28 13:45:27 -0700511 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
512 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
513 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
514 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
515 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
516
517 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
518 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
519 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
520 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700521
522 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700523 virtual void b(Label* label, Condition cond = AL) = 0;
524 virtual void bl(Label* label, Condition cond = AL) = 0;
525 virtual void blx(Register rm, Condition cond = AL) = 0;
526 virtual void bx(Register rm, Condition cond = AL) = 0;
527
528 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700529
530 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700531 // Most of these are pure virtual as they need to be implemented per instruction set.
532
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700533 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700534 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
535 virtual void AddConstant(Register rd, Register rn, int32_t value,
536 Condition cond = AL) = 0;
537 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
538 Condition cond = AL) = 0;
539 virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value,
540 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700541
542 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700543 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
544 virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0;
545 virtual void LoadDImmediate(DRegister dd, double value,
546 Register scratch, Condition cond = AL) = 0;
547 virtual void MarkExceptionHandler(Label* label) = 0;
548 virtual void LoadFromOffset(LoadOperandType type,
549 Register reg,
550 Register base,
551 int32_t offset,
552 Condition cond = AL) = 0;
553 virtual void StoreToOffset(StoreOperandType type,
554 Register reg,
555 Register base,
556 int32_t offset,
557 Condition cond = AL) = 0;
558 virtual void LoadSFromOffset(SRegister reg,
559 Register base,
560 int32_t offset,
561 Condition cond = AL) = 0;
562 virtual void StoreSToOffset(SRegister reg,
563 Register base,
564 int32_t offset,
565 Condition cond = AL) = 0;
566 virtual void LoadDFromOffset(DRegister reg,
567 Register base,
568 int32_t offset,
569 Condition cond = AL) = 0;
570 virtual void StoreDToOffset(DRegister reg,
571 Register base,
572 int32_t offset,
573 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700574
Dave Allison65fcc2c2014-04-28 13:45:27 -0700575 virtual void Push(Register rd, Condition cond = AL) = 0;
576 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700577
Dave Allison65fcc2c2014-04-28 13:45:27 -0700578 virtual void PushList(RegList regs, Condition cond = AL) = 0;
579 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700580
Dave Allison65fcc2c2014-04-28 13:45:27 -0700581 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700582
583 // Convenience shift instructions. Use mov instruction with shifter operand
584 // for variants setting the status flags or using a register shift count.
Dave Allison45fdb932014-06-25 12:37:10 -0700585 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
586 Condition cond = AL) = 0;
587 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
588 Condition cond = AL) = 0;
589 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
590 Condition cond = AL) = 0;
591 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
592 Condition cond = AL) = 0;
593 virtual void Rrx(Register rd, Register rm, bool setcc = false,
594 Condition cond = AL) = 0;
595
596 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
597 Condition cond = AL) = 0;
598 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
599 Condition cond = AL) = 0;
600 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
601 Condition cond = AL) = 0;
602 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
603 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700604
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700605 static bool IsInstructionForExceptionHandling(uword pc);
606
Dave Allison65fcc2c2014-04-28 13:45:27 -0700607 virtual void Bind(Label* label) = 0;
608
609 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
610 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700611
Ian Rogers2c8f6532011-09-02 17:16:34 -0700612 //
613 // Overridden common assembler high-level functionality
614 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700615
Ian Rogers2c8f6532011-09-02 17:16:34 -0700616 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700617 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
618 const std::vector<ManagedRegister>& callee_save_regs,
619 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700620
Ian Rogers2c8f6532011-09-02 17:16:34 -0700621 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700622 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700623 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700624
Ian Rogersdd7624d2014-03-14 17:43:00 -0700625 void IncreaseFrameSize(size_t adjust) OVERRIDE;
626 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700627
628 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700629 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
630 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
631 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700632
Ian Rogersdd7624d2014-03-14 17:43:00 -0700633 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700634
Ian Rogersdd7624d2014-03-14 17:43:00 -0700635 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
636 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700637
Ian Rogersdd7624d2014-03-14 17:43:00 -0700638 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
639 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700640
Ian Rogersdd7624d2014-03-14 17:43:00 -0700641 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700642
Ian Rogersdd7624d2014-03-14 17:43:00 -0700643 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
644 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700645
Ian Rogers2c8f6532011-09-02 17:16:34 -0700646 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700647 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700648
Ian Rogersdd7624d2014-03-14 17:43:00 -0700649 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700650
Ian Rogersdd7624d2014-03-14 17:43:00 -0700651 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700652
Ian Rogersdd7624d2014-03-14 17:43:00 -0700653 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654
Ian Rogersdd7624d2014-03-14 17:43:00 -0700655 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700656
Ian Rogersdd7624d2014-03-14 17:43:00 -0700657 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700658
659 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700660 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700661
Ian Rogersdd7624d2014-03-14 17:43:00 -0700662 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
663 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700664
Ian Rogersdd7624d2014-03-14 17:43:00 -0700665 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
666 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700667
Ian Rogersdd7624d2014-03-14 17:43:00 -0700668 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700669
Ian Rogersdd7624d2014-03-14 17:43:00 -0700670 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700671
Ian Rogersdd7624d2014-03-14 17:43:00 -0700672 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
673 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700674
Ian Rogersdd7624d2014-03-14 17:43:00 -0700675 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
676 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700677
Ian Rogersdd7624d2014-03-14 17:43:00 -0700678 void Copy(FrameOffset dest, FrameOffset 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, Offset dest_offset, ManagedRegister src, Offset src_offset,
682 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700683
Ian Rogersdd7624d2014-03-14 17:43:00 -0700684 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
685 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700686
jeffhao58136ca2012-05-24 13:40:11 -0700687 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700688 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700689
jeffhaocee4d0c2012-06-15 14:42:01 -0700690 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700691 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700692
Ian Rogers2c8f6532011-09-02 17:16:34 -0700693 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700694 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
695 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700696
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700697 // 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 -0700698 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700699 // that can be used to avoid loading the handle scope entry to see if the value is
Ian Rogers2c8f6532011-09-02 17:16:34 -0700700 // NULL.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700701 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700702 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700703
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700704 // 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 -0700705 // value is null and null_allowed.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700706 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700707 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700708
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700709 // src holds a handle scope entry (Object**) load this into dst
710 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700711
712 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
713 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700714 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
715 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700716
717 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700718 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
719 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
720 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700721
Ian Rogers2c8f6532011-09-02 17:16:34 -0700722 // Generate code to check if Thread::Current()->exception_ is non-null
723 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700724 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700725
Dave Allison65fcc2c2014-04-28 13:45:27 -0700726 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700727
Dave Allison45fdb932014-06-25 12:37:10 -0700728 static bool IsLowRegister(Register r) {
729 return r < R8;
730 }
731
732 static bool IsHighRegister(Register r) {
733 return r >= R8;
734 }
735
Dave Allison65fcc2c2014-04-28 13:45:27 -0700736 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700737 // Returns whether or not the given register is used for passing parameters.
738 static int RegisterCompare(const Register* reg1, const Register* reg2) {
739 return *reg1 - *reg2;
740 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700741};
742
Ian Rogers2c8f6532011-09-02 17:16:34 -0700743// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700744class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700745 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700746 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
747 : scratch_(scratch), stack_adjust_(stack_adjust) {
748 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700749 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700750 private:
751 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700752 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700753};
754
Ian Rogers2c8f6532011-09-02 17:16:34 -0700755} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700756} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700757
Ian Rogers166db042013-07-26 12:05:57 -0700758#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_