blob: 54965f678f58a900e0c2eb8900b6f8dd3552f22e [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
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010038 explicit ShifterOperand(uint32_t immed);
Carl Shapiroa2e18e12011-06-21 18:57:55 -070039
40 // Data-processing operands - Register
Dave Allison65fcc2c2014-04-28 13:45:27 -070041 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
42 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070043 }
44
Dave Allison65fcc2c2014-04-28 13:45:27 -070045 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
46 rs_(kNoRegister),
47 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
48 }
49
50 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
51 rs_(kNoRegister),
52 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070053 }
54
55 // Data-processing operands - Logical shift/rotate by register
Dave Allison65fcc2c2014-04-28 13:45:27 -070056 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm),
57 rs_(rs),
58 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -070059 }
60
Dave Allison65fcc2c2014-04-28 13:45:27 -070061 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070062
63 uint32_t type() const {
64 CHECK(is_valid());
65 return type_;
66 }
67
Dave Allison65fcc2c2014-04-28 13:45:27 -070068 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -070069 uint32_t encodingThumb() const;
Dave Allison65fcc2c2014-04-28 13:45:27 -070070
71 bool IsEmpty() const {
72 return type_ == kUnknown;
Carl Shapiroa2e18e12011-06-21 18:57:55 -070073 }
74
Dave Allison65fcc2c2014-04-28 13:45:27 -070075 bool IsImmediate() const {
76 return type_ == kImmediate;
77 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -070078
Dave Allison65fcc2c2014-04-28 13:45:27 -070079 bool IsRegister() const {
80 return type_ == kRegister;
81 }
82
83 bool IsShift() const {
84 return is_shift_;
85 }
86
87 uint32_t GetImmediate() const {
88 return immed_;
89 }
90
91 Shift GetShift() const {
92 return shift_;
93 }
94
95 Register GetRegister() const {
96 return rm_;
97 }
98
99 enum Type {
100 kUnknown = -1,
101 kRegister,
102 kImmediate
103 };
104
105 static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) {
106 // Avoid the more expensive test for frequent small immediate values.
107 if (immediate < (1 << kImmed8Bits)) {
108 shifter_op->type_ = kImmediate;
109 shifter_op->is_rotate_ = true;
110 shifter_op->rotate_ = 0;
111 shifter_op->immed_ = immediate;
112 return true;
113 }
114 // Note that immediate must be unsigned for the test to work correctly.
115 for (int rot = 0; rot < 16; rot++) {
116 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
117 if (imm8 < (1 << kImmed8Bits)) {
118 shifter_op->type_ = kImmediate;
119 shifter_op->is_rotate_ = true;
120 shifter_op->rotate_ = rot;
121 shifter_op->immed_ = imm8;
122 return true;
123 }
124 }
125 return false;
126 }
127
128 static bool CanHoldThumb(Register rd, Register rn, Opcode opcode,
129 uint32_t immediate, ShifterOperand* shifter_op);
130
131
132 private:
133 Type type_;
134 Register rm_;
135 Register rs_;
136 bool is_rotate_;
137 bool is_shift_;
138 Shift shift_;
139 uint32_t rotate_;
140 uint32_t immed_;
141
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700142#ifdef SOURCE_ASSEMBLER_SUPPORT
143 friend class BinaryAssembler;
144#endif
145};
146
147
148enum LoadOperandType {
149 kLoadSignedByte,
150 kLoadUnsignedByte,
151 kLoadSignedHalfword,
152 kLoadUnsignedHalfword,
153 kLoadWord,
154 kLoadWordPair,
155 kLoadSWord,
156 kLoadDWord
157};
158
159
160enum StoreOperandType {
161 kStoreByte,
162 kStoreHalfword,
163 kStoreWord,
164 kStoreWordPair,
165 kStoreSWord,
166 kStoreDWord
167};
168
169
170// Load/store multiple addressing mode.
171enum BlockAddressMode {
172 // bit encoding P U W
173 DA = (0|0|0) << 21, // decrement after
174 IA = (0|4|0) << 21, // increment after
175 DB = (8|0|0) << 21, // decrement before
176 IB = (8|4|0) << 21, // increment before
177 DA_W = (0|0|1) << 21, // decrement after with writeback to base
178 IA_W = (0|4|1) << 21, // increment after with writeback to base
179 DB_W = (8|0|1) << 21, // decrement before with writeback to base
180 IB_W = (8|4|1) << 21 // increment before with writeback to base
181};
182
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700183class Address {
184 public:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700185 // Memory operand addressing mode (in ARM encoding form. For others we need
186 // to adjust)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700187 enum Mode {
188 // bit encoding P U W
189 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
190 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
191 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
192 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
193 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
194 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
195 };
196
Dave Allison45fdb932014-06-25 12:37:10 -0700197 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
198 offset_(offset),
199 am_(am), is_immed_offset_(true), shift_(LSL) {
200 }
201
202 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
203 am_(am), is_immed_offset_(false), shift_(LSL) {
204 CHECK_NE(rm, PC);
205 }
206
207 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
208 rn_(rn), rm_(rm), offset_(count),
209 am_(am), is_immed_offset_(false), shift_(shift) {
210 CHECK_NE(rm, PC);
211 }
212
213 // LDR(literal) - pc relative load.
214 explicit Address(int32_t offset) :
215 rn_(PC), rm_(R0), offset_(offset),
216 am_(Offset), is_immed_offset_(false), shift_(LSL) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700217 }
218
Dave Allison65fcc2c2014-04-28 13:45:27 -0700219 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
220 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
221
222 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
223 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
224
225 uint32_t encodingArm() const;
Dave Allison45fdb932014-06-25 12:37:10 -0700226 uint32_t encodingThumb(bool is_32bit) const;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700227
228 uint32_t encoding3() const;
229 uint32_t vencoding() const;
230
231 uint32_t encodingThumbLdrdStrd() const;
232
233 Register GetRegister() const {
234 return rn_;
235 }
236
Dave Allison45fdb932014-06-25 12:37:10 -0700237 Register GetRegisterOffset() const {
238 return rm_;
239 }
240
Dave Allison65fcc2c2014-04-28 13:45:27 -0700241 int32_t GetOffset() const {
242 return offset_;
243 }
244
245 Mode GetMode() const {
246 return am_;
247 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700248
Dave Allison45fdb932014-06-25 12:37:10 -0700249 bool IsImmediate() const {
250 return is_immed_offset_;
251 }
252
253 Shift GetShift() const {
254 return shift_;
255 }
256
257 int32_t GetShiftCount() const {
258 CHECK(!is_immed_offset_);
259 return offset_;
260 }
261
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700262 private:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700263 Register rn_;
Dave Allison45fdb932014-06-25 12:37:10 -0700264 Register rm_;
265 int32_t offset_; // Used as shift amount for register offset.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700266 Mode am_;
Dave Allison45fdb932014-06-25 12:37:10 -0700267 bool is_immed_offset_;
268 Shift shift_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700269};
270
Dave Allison65fcc2c2014-04-28 13:45:27 -0700271// Instruction encoding bits.
272enum {
273 H = 1 << 5, // halfword (or byte)
274 L = 1 << 20, // load (or store)
275 S = 1 << 20, // set condition code (or leave unchanged)
276 W = 1 << 21, // writeback base register (or leave unchanged)
277 A = 1 << 21, // accumulate in multiply instruction (or not)
278 B = 1 << 22, // unsigned byte (or word)
279 N = 1 << 22, // long (or short)
280 U = 1 << 23, // positive (or negative) offset/index
281 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
282 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700283
Dave Allison65fcc2c2014-04-28 13:45:27 -0700284 B0 = 1,
285 B1 = 1 << 1,
286 B2 = 1 << 2,
287 B3 = 1 << 3,
288 B4 = 1 << 4,
289 B5 = 1 << 5,
290 B6 = 1 << 6,
291 B7 = 1 << 7,
292 B8 = 1 << 8,
293 B9 = 1 << 9,
294 B10 = 1 << 10,
295 B11 = 1 << 11,
296 B12 = 1 << 12,
297 B13 = 1 << 13,
298 B14 = 1 << 14,
299 B15 = 1 << 15,
300 B16 = 1 << 16,
301 B17 = 1 << 17,
302 B18 = 1 << 18,
303 B19 = 1 << 19,
304 B20 = 1 << 20,
305 B21 = 1 << 21,
306 B22 = 1 << 22,
307 B23 = 1 << 23,
308 B24 = 1 << 24,
309 B25 = 1 << 25,
310 B26 = 1 << 26,
311 B27 = 1 << 27,
312 B28 = 1 << 28,
313 B29 = 1 << 29,
314 B30 = 1 << 30,
315 B31 = 1 << 31,
316
317 // Instruction bit masks.
318 RdMask = 15 << 12, // in str instruction
319 CondMask = 15 << 28,
320 CoprocessorMask = 15 << 8,
321 OpCodeMask = 15 << 21, // in data-processing instructions
322 Imm24Mask = (1 << 24) - 1,
323 Off12Mask = (1 << 12) - 1,
324
325 // ldrex/strex register field encodings.
326 kLdExRnShift = 16,
327 kLdExRtShift = 12,
328 kStrExRnShift = 16,
329 kStrExRdShift = 12,
330 kStrExRtShift = 0,
331};
332
333// IfThen state for IT instructions.
334enum ItState {
335 kItOmitted,
336 kItThen,
337 kItT = kItThen,
338 kItElse,
339 kItE = kItElse
340};
341
342constexpr uint32_t kNoItCondition = 3;
343constexpr uint32_t kInvalidModifiedImmediate = -1;
344
345extern const char* kRegisterNames[];
346extern const char* kConditionNames[];
347extern std::ostream& operator<<(std::ostream& os, const Register& rhs);
348extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs);
349extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
350extern std::ostream& operator<<(std::ostream& os, const Condition& rhs);
351
352// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
353// instruction sets (ARM32, Thumb2, etc.)
354//
355class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700356 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700357 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700358
Dave Allison65fcc2c2014-04-28 13:45:27 -0700359 // Is this assembler for the thumb instruction set?
360 virtual bool IsThumb() const = 0;
361
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700362 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700363 virtual void and_(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 eor(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 sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
368 virtual void subs(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 rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
371 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700372
Dave Allison65fcc2c2014-04-28 13:45:27 -0700373 virtual void add(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 adds(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 adc(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 sbc(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 rsc(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 tst(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 teq(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 cmp(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 cmn(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 orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
392 virtual void orrs(Register rd, 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 mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
395 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700396
Dave Allison65fcc2c2014-04-28 13:45:27 -0700397 virtual void bic(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 mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
400 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700401
402 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700403 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
404 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
405 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700406
407 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700408 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
409 virtual void mla(Register rd, Register rn, Register rm, Register ra,
410 Condition cond = AL) = 0;
411 virtual void mls(Register rd, Register rn, Register rm, Register ra,
412 Condition cond = AL) = 0;
413 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
414 Condition cond = AL) = 0;
415
416 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
417 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700418
419 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700420 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
421 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700422
Dave Allison65fcc2c2014-04-28 13:45:27 -0700423 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
424 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700425
Dave Allison65fcc2c2014-04-28 13:45:27 -0700426 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
427 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700428
Dave Allison65fcc2c2014-04-28 13:45:27 -0700429 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
430 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700431
Dave Allison65fcc2c2014-04-28 13:45:27 -0700432 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
433 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700434
Dave Allison65fcc2c2014-04-28 13:45:27 -0700435 virtual void ldm(BlockAddressMode am, Register base,
436 RegList regs, Condition cond = AL) = 0;
437 virtual void stm(BlockAddressMode am, Register base,
438 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700439
Dave Allison65fcc2c2014-04-28 13:45:27 -0700440 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
441 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700442
443 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700444 virtual void clrex(Condition cond = AL) = 0;
445 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700446
447 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700448 virtual void bkpt(uint16_t imm16) = 0;
449 virtual void svc(uint32_t imm24) = 0;
450
451 virtual void it(Condition firstcond, ItState i1 = kItOmitted,
452 ItState i2 = kItOmitted, ItState i3 = kItOmitted) {
453 // Ignored if not supported.
454 }
455
456 virtual void cbz(Register rn, Label* target) = 0;
457 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700458
459 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700460 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
461 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
462 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
463 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
464 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
465 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
466 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
467 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700468
469 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700470 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
471 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700472
Dave Allison65fcc2c2014-04-28 13:45:27 -0700473 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
474 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
475 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
476 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700477
Dave Allison65fcc2c2014-04-28 13:45:27 -0700478 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
479 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
480 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
481 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
482 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
483 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
484 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
485 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
486 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
487 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
488 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
489 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700490
Dave Allison65fcc2c2014-04-28 13:45:27 -0700491 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
492 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
493 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
494 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
495 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
496 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700497
Dave Allison65fcc2c2014-04-28 13:45:27 -0700498 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
499 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
500 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
501 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
502 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
503 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
504 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
505 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
506 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
507 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700508
Dave Allison65fcc2c2014-04-28 13:45:27 -0700509 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
510 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
511 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
512 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
513 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
514
515 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
516 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
517 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
518 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700519
520 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700521 virtual void b(Label* label, Condition cond = AL) = 0;
522 virtual void bl(Label* label, Condition cond = AL) = 0;
523 virtual void blx(Register rm, Condition cond = AL) = 0;
524 virtual void bx(Register rm, Condition cond = AL) = 0;
525
526 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700527
528 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700529 // Most of these are pure virtual as they need to be implemented per instruction set.
530
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700531 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700532 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
533 virtual void AddConstant(Register rd, Register rn, int32_t value,
534 Condition cond = AL) = 0;
535 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
536 Condition cond = AL) = 0;
537 virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value,
538 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700539
540 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700541 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
542 virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0;
543 virtual void LoadDImmediate(DRegister dd, double value,
544 Register scratch, Condition cond = AL) = 0;
545 virtual void MarkExceptionHandler(Label* label) = 0;
546 virtual void LoadFromOffset(LoadOperandType type,
547 Register reg,
548 Register base,
549 int32_t offset,
550 Condition cond = AL) = 0;
551 virtual void StoreToOffset(StoreOperandType type,
552 Register reg,
553 Register base,
554 int32_t offset,
555 Condition cond = AL) = 0;
556 virtual void LoadSFromOffset(SRegister reg,
557 Register base,
558 int32_t offset,
559 Condition cond = AL) = 0;
560 virtual void StoreSToOffset(SRegister reg,
561 Register base,
562 int32_t offset,
563 Condition cond = AL) = 0;
564 virtual void LoadDFromOffset(DRegister reg,
565 Register base,
566 int32_t offset,
567 Condition cond = AL) = 0;
568 virtual void StoreDToOffset(DRegister reg,
569 Register base,
570 int32_t offset,
571 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700572
Dave Allison65fcc2c2014-04-28 13:45:27 -0700573 virtual void Push(Register rd, Condition cond = AL) = 0;
574 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700575
Dave Allison65fcc2c2014-04-28 13:45:27 -0700576 virtual void PushList(RegList regs, Condition cond = AL) = 0;
577 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700578
Dave Allison65fcc2c2014-04-28 13:45:27 -0700579 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700580
581 // Convenience shift instructions. Use mov instruction with shifter operand
582 // for variants setting the status flags or using a register shift count.
Dave Allison45fdb932014-06-25 12:37:10 -0700583 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
584 Condition cond = AL) = 0;
585 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
586 Condition cond = AL) = 0;
587 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
588 Condition cond = AL) = 0;
589 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
590 Condition cond = AL) = 0;
591 virtual void Rrx(Register rd, Register rm, bool setcc = false,
592 Condition cond = AL) = 0;
593
594 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
595 Condition cond = AL) = 0;
596 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
597 Condition cond = AL) = 0;
598 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
599 Condition cond = AL) = 0;
600 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
601 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700602
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700603 static bool IsInstructionForExceptionHandling(uword pc);
604
Dave Allison65fcc2c2014-04-28 13:45:27 -0700605 virtual void Bind(Label* label) = 0;
606
607 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
608 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700609
Ian Rogers2c8f6532011-09-02 17:16:34 -0700610 //
611 // Overridden common assembler high-level functionality
612 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700613
Ian Rogers2c8f6532011-09-02 17:16:34 -0700614 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700615 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
616 const std::vector<ManagedRegister>& callee_save_regs,
617 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700618
Ian Rogers2c8f6532011-09-02 17:16:34 -0700619 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700620 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700621 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700622
Ian Rogersdd7624d2014-03-14 17:43:00 -0700623 void IncreaseFrameSize(size_t adjust) OVERRIDE;
624 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700625
626 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700627 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
628 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
629 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700630
Ian Rogersdd7624d2014-03-14 17:43:00 -0700631 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700632
Ian Rogersdd7624d2014-03-14 17:43:00 -0700633 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
634 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700635
Ian Rogersdd7624d2014-03-14 17:43:00 -0700636 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
637 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700638
Ian Rogersdd7624d2014-03-14 17:43:00 -0700639 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700640
Ian Rogersdd7624d2014-03-14 17:43:00 -0700641 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
642 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700643
Ian Rogers2c8f6532011-09-02 17:16:34 -0700644 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700645 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700646
Ian Rogersdd7624d2014-03-14 17:43:00 -0700647 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700648
Ian Rogersdd7624d2014-03-14 17:43:00 -0700649 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700650
Ian Rogersdd7624d2014-03-14 17:43:00 -0700651 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700652
Ian Rogersdd7624d2014-03-14 17:43:00 -0700653 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654
Ian Rogersdd7624d2014-03-14 17:43:00 -0700655 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700656
657 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700658 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700659
Ian Rogersdd7624d2014-03-14 17:43:00 -0700660 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
661 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700662
Ian Rogersdd7624d2014-03-14 17:43:00 -0700663 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
664 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700665
Ian Rogersdd7624d2014-03-14 17:43:00 -0700666 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700667
Ian Rogersdd7624d2014-03-14 17:43:00 -0700668 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700669
Ian Rogersdd7624d2014-03-14 17:43:00 -0700670 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
671 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700672
Ian Rogersdd7624d2014-03-14 17:43:00 -0700673 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
674 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700675
Ian Rogersdd7624d2014-03-14 17:43:00 -0700676 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
677 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700678
Ian Rogersdd7624d2014-03-14 17:43:00 -0700679 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
680 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700681
Ian Rogersdd7624d2014-03-14 17:43:00 -0700682 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
683 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700684
jeffhao58136ca2012-05-24 13:40:11 -0700685 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700686 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700687
jeffhaocee4d0c2012-06-15 14:42:01 -0700688 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700689 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700690
Ian Rogers2c8f6532011-09-02 17:16:34 -0700691 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700692 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
693 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700694
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700695 // 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 -0700696 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700697 // that can be used to avoid loading the handle scope entry to see if the value is
Ian Rogers2c8f6532011-09-02 17:16:34 -0700698 // NULL.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700699 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700700 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700701
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700702 // 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 -0700703 // value is null and null_allowed.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700704 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700705 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700706
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700707 // src holds a handle scope entry (Object**) load this into dst
708 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700709
710 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
711 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700712 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
713 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700714
715 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700716 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
717 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
718 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700719
Ian Rogers2c8f6532011-09-02 17:16:34 -0700720 // Generate code to check if Thread::Current()->exception_ is non-null
721 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700722 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700723
Dave Allison65fcc2c2014-04-28 13:45:27 -0700724 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700725
Dave Allison45fdb932014-06-25 12:37:10 -0700726 static bool IsLowRegister(Register r) {
727 return r < R8;
728 }
729
730 static bool IsHighRegister(Register r) {
731 return r >= R8;
732 }
733
Dave Allison65fcc2c2014-04-28 13:45:27 -0700734 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700735 // Returns whether or not the given register is used for passing parameters.
736 static int RegisterCompare(const Register* reg1, const Register* reg2) {
737 return *reg1 - *reg2;
738 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700739};
740
Ian Rogers2c8f6532011-09-02 17:16:34 -0700741// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700742class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700743 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700744 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
745 : scratch_(scratch), stack_adjust_(stack_adjust) {
746 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700747 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700748 private:
749 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700750 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700751};
752
Ian Rogers2c8f6532011-09-02 17:16:34 -0700753} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700754} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700755
Ian Rogers166db042013-07-26 12:05:57 -0700756#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_