blob: 7b662e15000dfac0d3bf061475ccf13e9e13d35c [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;
71 uint32_t encodingThumb(int version) const;
72
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 Allison65fcc2c2014-04-28 13:45:27 -0700199 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), offset_(offset),
200 am_(am) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700201 }
202
Dave Allison65fcc2c2014-04-28 13:45:27 -0700203 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
204 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
205
206 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
207 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
208
209 uint32_t encodingArm() const;
210 uint32_t encodingThumb(int version) const;
211
212 uint32_t encoding3() const;
213 uint32_t vencoding() const;
214
215 uint32_t encodingThumbLdrdStrd() const;
216
217 Register GetRegister() const {
218 return rn_;
219 }
220
221 int32_t GetOffset() const {
222 return offset_;
223 }
224
225 Mode GetMode() const {
226 return am_;
227 }
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700228
229 private:
Dave Allison65fcc2c2014-04-28 13:45:27 -0700230 Register rn_;
231 int32_t offset_;
232 Mode am_;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700233};
234
Dave Allison65fcc2c2014-04-28 13:45:27 -0700235// Instruction encoding bits.
236enum {
237 H = 1 << 5, // halfword (or byte)
238 L = 1 << 20, // load (or store)
239 S = 1 << 20, // set condition code (or leave unchanged)
240 W = 1 << 21, // writeback base register (or leave unchanged)
241 A = 1 << 21, // accumulate in multiply instruction (or not)
242 B = 1 << 22, // unsigned byte (or word)
243 N = 1 << 22, // long (or short)
244 U = 1 << 23, // positive (or negative) offset/index
245 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
246 I = 1 << 25, // immediate shifter operand (or not)
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700247
Dave Allison65fcc2c2014-04-28 13:45:27 -0700248 B0 = 1,
249 B1 = 1 << 1,
250 B2 = 1 << 2,
251 B3 = 1 << 3,
252 B4 = 1 << 4,
253 B5 = 1 << 5,
254 B6 = 1 << 6,
255 B7 = 1 << 7,
256 B8 = 1 << 8,
257 B9 = 1 << 9,
258 B10 = 1 << 10,
259 B11 = 1 << 11,
260 B12 = 1 << 12,
261 B13 = 1 << 13,
262 B14 = 1 << 14,
263 B15 = 1 << 15,
264 B16 = 1 << 16,
265 B17 = 1 << 17,
266 B18 = 1 << 18,
267 B19 = 1 << 19,
268 B20 = 1 << 20,
269 B21 = 1 << 21,
270 B22 = 1 << 22,
271 B23 = 1 << 23,
272 B24 = 1 << 24,
273 B25 = 1 << 25,
274 B26 = 1 << 26,
275 B27 = 1 << 27,
276 B28 = 1 << 28,
277 B29 = 1 << 29,
278 B30 = 1 << 30,
279 B31 = 1 << 31,
280
281 // Instruction bit masks.
282 RdMask = 15 << 12, // in str instruction
283 CondMask = 15 << 28,
284 CoprocessorMask = 15 << 8,
285 OpCodeMask = 15 << 21, // in data-processing instructions
286 Imm24Mask = (1 << 24) - 1,
287 Off12Mask = (1 << 12) - 1,
288
289 // ldrex/strex register field encodings.
290 kLdExRnShift = 16,
291 kLdExRtShift = 12,
292 kStrExRnShift = 16,
293 kStrExRdShift = 12,
294 kStrExRtShift = 0,
295};
296
297// IfThen state for IT instructions.
298enum ItState {
299 kItOmitted,
300 kItThen,
301 kItT = kItThen,
302 kItElse,
303 kItE = kItElse
304};
305
306constexpr uint32_t kNoItCondition = 3;
307constexpr uint32_t kInvalidModifiedImmediate = -1;
308
309extern const char* kRegisterNames[];
310extern const char* kConditionNames[];
311extern std::ostream& operator<<(std::ostream& os, const Register& rhs);
312extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs);
313extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
314extern std::ostream& operator<<(std::ostream& os, const Condition& rhs);
315
316// This is an abstract ARM assembler. Subclasses provide assemblers for the individual
317// instruction sets (ARM32, Thumb2, etc.)
318//
319class ArmAssembler : public Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700320 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700321 virtual ~ArmAssembler() {}
buzbeec143c552011-08-20 17:38:58 -0700322
Dave Allison65fcc2c2014-04-28 13:45:27 -0700323 // Is this assembler for the thumb instruction set?
324 virtual bool IsThumb() const = 0;
325
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700326 // Data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700327 virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700328
Dave Allison65fcc2c2014-04-28 13:45:27 -0700329 virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700330
Dave Allison65fcc2c2014-04-28 13:45:27 -0700331 virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
332 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700333
Dave Allison65fcc2c2014-04-28 13:45:27 -0700334 virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
335 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700336
Dave Allison65fcc2c2014-04-28 13:45:27 -0700337 virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700338
Dave Allison65fcc2c2014-04-28 13:45:27 -0700339 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700340
Dave Allison65fcc2c2014-04-28 13:45:27 -0700341 virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700342
Dave Allison65fcc2c2014-04-28 13:45:27 -0700343 virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700344
Dave Allison65fcc2c2014-04-28 13:45:27 -0700345 virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700346
Dave Allison65fcc2c2014-04-28 13:45:27 -0700347 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700348
Dave Allison65fcc2c2014-04-28 13:45:27 -0700349 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700350
Dave Allison65fcc2c2014-04-28 13:45:27 -0700351 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700352
Dave Allison65fcc2c2014-04-28 13:45:27 -0700353 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700354
Dave Allison65fcc2c2014-04-28 13:45:27 -0700355 virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
356 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700357
Dave Allison65fcc2c2014-04-28 13:45:27 -0700358 virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
359 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700360
Dave Allison65fcc2c2014-04-28 13:45:27 -0700361 virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700362
Dave Allison65fcc2c2014-04-28 13:45:27 -0700363 virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
364 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700365
366 // Miscellaneous data-processing instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700367 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
368 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
369 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700370
371 // Multiply instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700372 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
373 virtual void mla(Register rd, Register rn, Register rm, Register ra,
374 Condition cond = AL) = 0;
375 virtual void mls(Register rd, Register rn, Register rm, Register ra,
376 Condition cond = AL) = 0;
377 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
378 Condition cond = AL) = 0;
379
380 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
381 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700382
383 // Load/store instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700384 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
385 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700386
Dave Allison65fcc2c2014-04-28 13:45:27 -0700387 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
388 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700389
Dave Allison65fcc2c2014-04-28 13:45:27 -0700390 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
391 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700392
Dave Allison65fcc2c2014-04-28 13:45:27 -0700393 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
394 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700395
Dave Allison65fcc2c2014-04-28 13:45:27 -0700396 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
397 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700398
Dave Allison65fcc2c2014-04-28 13:45:27 -0700399 virtual void ldm(BlockAddressMode am, Register base,
400 RegList regs, Condition cond = AL) = 0;
401 virtual void stm(BlockAddressMode am, Register base,
402 RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700403
Dave Allison65fcc2c2014-04-28 13:45:27 -0700404 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
405 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700406
407 // Miscellaneous instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700408 virtual void clrex(Condition cond = AL) = 0;
409 virtual void nop(Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700410
411 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700412 virtual void bkpt(uint16_t imm16) = 0;
413 virtual void svc(uint32_t imm24) = 0;
414
415 virtual void it(Condition firstcond, ItState i1 = kItOmitted,
416 ItState i2 = kItOmitted, ItState i3 = kItOmitted) {
417 // Ignored if not supported.
418 }
419
420 virtual void cbz(Register rn, Label* target) = 0;
421 virtual void cbnz(Register rn, Label* target) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700422
423 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
Dave Allison65fcc2c2014-04-28 13:45:27 -0700424 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
425 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
426 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
427 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
428 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
429 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
430 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
431 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700432
433 // Returns false if the immediate cannot be encoded.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700434 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
435 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700436
Dave Allison65fcc2c2014-04-28 13:45:27 -0700437 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
438 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
439 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
440 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700441
Dave Allison65fcc2c2014-04-28 13:45:27 -0700442 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
443 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
444 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
445 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
446 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
447 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
448 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
449 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
450 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
451 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
452 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
453 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700454
Dave Allison65fcc2c2014-04-28 13:45:27 -0700455 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
456 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
457 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
458 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
459 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
460 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700461
Dave Allison65fcc2c2014-04-28 13:45:27 -0700462 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
463 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
464 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
465 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
466 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
467 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
468 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
469 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
470 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
471 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700472
Dave Allison65fcc2c2014-04-28 13:45:27 -0700473 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
474 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
475 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
476 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
477 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR
478
479 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
480 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
481 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
482 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700483
484 // Branch instructions.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700485 virtual void b(Label* label, Condition cond = AL) = 0;
486 virtual void bl(Label* label, Condition cond = AL) = 0;
487 virtual void blx(Register rm, Condition cond = AL) = 0;
488 virtual void bx(Register rm, Condition cond = AL) = 0;
489
490 void Pad(uint32_t bytes);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700491
492 // Macros.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700493 // Most of these are pure virtual as they need to be implemented per instruction set.
494
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700495 // Add signed constant value to rd. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700496 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
497 virtual void AddConstant(Register rd, Register rn, int32_t value,
498 Condition cond = AL) = 0;
499 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
500 Condition cond = AL) = 0;
501 virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value,
502 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700503
504 // Load and Store. May clobber IP.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700505 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
506 virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0;
507 virtual void LoadDImmediate(DRegister dd, double value,
508 Register scratch, Condition cond = AL) = 0;
509 virtual void MarkExceptionHandler(Label* label) = 0;
510 virtual void LoadFromOffset(LoadOperandType type,
511 Register reg,
512 Register base,
513 int32_t offset,
514 Condition cond = AL) = 0;
515 virtual void StoreToOffset(StoreOperandType type,
516 Register reg,
517 Register base,
518 int32_t offset,
519 Condition cond = AL) = 0;
520 virtual void LoadSFromOffset(SRegister reg,
521 Register base,
522 int32_t offset,
523 Condition cond = AL) = 0;
524 virtual void StoreSToOffset(SRegister reg,
525 Register base,
526 int32_t offset,
527 Condition cond = AL) = 0;
528 virtual void LoadDFromOffset(DRegister reg,
529 Register base,
530 int32_t offset,
531 Condition cond = AL) = 0;
532 virtual void StoreDToOffset(DRegister reg,
533 Register base,
534 int32_t offset,
535 Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700536
Dave Allison65fcc2c2014-04-28 13:45:27 -0700537 virtual void Push(Register rd, Condition cond = AL) = 0;
538 virtual void Pop(Register rd, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700539
Dave Allison65fcc2c2014-04-28 13:45:27 -0700540 virtual void PushList(RegList regs, Condition cond = AL) = 0;
541 virtual void PopList(RegList regs, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700542
Dave Allison65fcc2c2014-04-28 13:45:27 -0700543 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700544
545 // Convenience shift instructions. Use mov instruction with shifter operand
546 // for variants setting the status flags or using a register shift count.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700547 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0;
548 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0;
549 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0;
550 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0;
551 virtual void Rrx(Register rd, Register rm, Condition cond = AL) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700552
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700553 static bool IsInstructionForExceptionHandling(uword pc);
554
Dave Allison65fcc2c2014-04-28 13:45:27 -0700555 virtual void Bind(Label* label) = 0;
556
557 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
558 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700559
Ian Rogers2c8f6532011-09-02 17:16:34 -0700560 //
561 // Overridden common assembler high-level functionality
562 //
Ian Rogers45a76cb2011-07-21 22:00:15 -0700563
Ian Rogers2c8f6532011-09-02 17:16:34 -0700564 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700565 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
566 const std::vector<ManagedRegister>& callee_save_regs,
567 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700568
Ian Rogers2c8f6532011-09-02 17:16:34 -0700569 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700570 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
Dave Allison65fcc2c2014-04-28 13:45:27 -0700571 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700572
Ian Rogersdd7624d2014-03-14 17:43:00 -0700573 void IncreaseFrameSize(size_t adjust) OVERRIDE;
574 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700575
576 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700577 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
578 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
579 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700580
Ian Rogersdd7624d2014-03-14 17:43:00 -0700581 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700582
Ian Rogersdd7624d2014-03-14 17:43:00 -0700583 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
584 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700585
Ian Rogersdd7624d2014-03-14 17:43:00 -0700586 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
587 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700588
Ian Rogersdd7624d2014-03-14 17:43:00 -0700589 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700590
Ian Rogersdd7624d2014-03-14 17:43:00 -0700591 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
592 ManagedRegister scratch) OVERRIDE;
Ian Rogersbdb03912011-09-14 00:55:44 -0700593
Ian Rogers2c8f6532011-09-02 17:16:34 -0700594 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700595 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700596
Ian Rogersdd7624d2014-03-14 17:43:00 -0700597 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700598
Ian Rogersdd7624d2014-03-14 17:43:00 -0700599 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700600
Ian Rogersdd7624d2014-03-14 17:43:00 -0700601 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700602
Ian Rogersdd7624d2014-03-14 17:43:00 -0700603 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700604
Ian Rogersdd7624d2014-03-14 17:43:00 -0700605 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700606
607 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700608 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700609
Ian Rogersdd7624d2014-03-14 17:43:00 -0700610 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
611 ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700612
Ian Rogersdd7624d2014-03-14 17:43:00 -0700613 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
614 OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700615
Ian Rogersdd7624d2014-03-14 17:43:00 -0700616 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700617
Ian Rogersdd7624d2014-03-14 17:43:00 -0700618 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700619
Ian Rogersdd7624d2014-03-14 17:43:00 -0700620 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
621 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700622
Ian Rogersdd7624d2014-03-14 17:43:00 -0700623 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
624 size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700625
Ian Rogersdd7624d2014-03-14 17:43:00 -0700626 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
627 size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700628
Ian Rogersdd7624d2014-03-14 17:43:00 -0700629 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
630 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700631
Ian Rogersdd7624d2014-03-14 17:43:00 -0700632 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
633 ManagedRegister scratch, size_t size) OVERRIDE;
Ian Rogersdc51b792011-09-22 20:41:37 -0700634
jeffhao58136ca2012-05-24 13:40:11 -0700635 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700636 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao58136ca2012-05-24 13:40:11 -0700637
jeffhaocee4d0c2012-06-15 14:42:01 -0700638 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700639 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhaocee4d0c2012-06-15 14:42:01 -0700640
Ian Rogers2c8f6532011-09-02 17:16:34 -0700641 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700642 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
643 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700644
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700645 // 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 -0700646 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700647 // that can be used to avoid loading the handle scope entry to see if the value is
Ian Rogers2c8f6532011-09-02 17:16:34 -0700648 // NULL.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700649 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700650 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700651
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700652 // 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 -0700653 // value is null and null_allowed.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700654 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700655 bool null_allowed) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700656
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700657 // src holds a handle scope entry (Object**) load this into dst
658 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700659
660 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
661 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700662 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
663 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700664
665 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700666 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
667 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
668 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700669
Ian Rogers2c8f6532011-09-02 17:16:34 -0700670 // Generate code to check if Thread::Current()->exception_ is non-null
671 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700672 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Ian Rogersb033c752011-07-20 12:22:35 -0700673
Dave Allison65fcc2c2014-04-28 13:45:27 -0700674 static uint32_t ModifiedImmediate(uint32_t value);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700675
Dave Allison65fcc2c2014-04-28 13:45:27 -0700676 protected:
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700677 // Returns whether or not the given register is used for passing parameters.
678 static int RegisterCompare(const Register* reg1, const Register* reg2) {
679 return *reg1 - *reg2;
680 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700681};
682
Ian Rogers2c8f6532011-09-02 17:16:34 -0700683// Slowpath entered when Thread::Current()->_exception is non-null
Ian Rogersdd7624d2014-03-14 17:43:00 -0700684class ArmExceptionSlowPath FINAL : public SlowPath {
Ian Rogers2c8f6532011-09-02 17:16:34 -0700685 public:
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700686 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
687 : scratch_(scratch), stack_adjust_(stack_adjust) {
688 }
Ian Rogersdd7624d2014-03-14 17:43:00 -0700689 void Emit(Assembler *sp_asm) OVERRIDE;
Ian Rogers67375ac2011-09-14 00:55:44 -0700690 private:
691 const ArmManagedRegister scratch_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700692 const size_t stack_adjust_;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700693};
694
Ian Rogers2c8f6532011-09-02 17:16:34 -0700695} // namespace arm
Ian Rogersb033c752011-07-20 12:22:35 -0700696} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700697
Ian Rogers166db042013-07-26 12:05:57 -0700698#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_