blob: 5c839dd54e416de053887d048c1ae48781ec63a3 [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 Rogers2c8f6532011-09-02 17:16:34 -070017#include "assembler_arm.h"
18
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Ian Rogers166db042013-07-26 12:05:57 -070020#include "entrypoints/quick/quick_entrypoints.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070021#include "offsets.h"
Carl Shapiroe2d373e2011-07-25 15:20:06 -070022#include "thread.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070023#include "utils.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070024
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070025namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070026namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070027
Carl Shapiroa2e18e12011-06-21 18:57:55 -070028// Instruction encoding bits.
29enum {
30 H = 1 << 5, // halfword (or byte)
31 L = 1 << 20, // load (or store)
32 S = 1 << 20, // set condition code (or leave unchanged)
33 W = 1 << 21, // writeback base register (or leave unchanged)
34 A = 1 << 21, // accumulate in multiply instruction (or not)
35 B = 1 << 22, // unsigned byte (or word)
36 N = 1 << 22, // long (or short)
37 U = 1 << 23, // positive (or negative) offset/index
38 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
39 I = 1 << 25, // immediate shifter operand (or not)
40
41 B0 = 1,
42 B1 = 1 << 1,
43 B2 = 1 << 2,
44 B3 = 1 << 3,
45 B4 = 1 << 4,
46 B5 = 1 << 5,
47 B6 = 1 << 6,
48 B7 = 1 << 7,
49 B8 = 1 << 8,
50 B9 = 1 << 9,
51 B10 = 1 << 10,
52 B11 = 1 << 11,
53 B12 = 1 << 12,
54 B16 = 1 << 16,
55 B17 = 1 << 17,
56 B18 = 1 << 18,
57 B19 = 1 << 19,
58 B20 = 1 << 20,
59 B21 = 1 << 21,
60 B22 = 1 << 22,
61 B23 = 1 << 23,
62 B24 = 1 << 24,
63 B25 = 1 << 25,
64 B26 = 1 << 26,
65 B27 = 1 << 27,
66
67 // Instruction bit masks.
68 RdMask = 15 << 12, // in str instruction
69 CondMask = 15 << 28,
70 CoprocessorMask = 15 << 8,
71 OpCodeMask = 15 << 21, // in data-processing instructions
72 Imm24Mask = (1 << 24) - 1,
73 Off12Mask = (1 << 12) - 1,
74
75 // ldrex/strex register field encodings.
76 kLdExRnShift = 16,
77 kLdExRtShift = 12,
78 kStrExRnShift = 16,
79 kStrExRdShift = 12,
80 kStrExRtShift = 0,
81};
82
83
Elliott Hughes1f359b02011-07-17 14:27:17 -070084static const char* kRegisterNames[] = {
85 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
86 "fp", "ip", "sp", "lr", "pc"
87};
88std::ostream& operator<<(std::ostream& os, const Register& rhs) {
89 if (rhs >= R0 && rhs <= PC) {
90 os << kRegisterNames[rhs];
91 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070092 os << "Register[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070093 }
94 return os;
95}
96
97
98std::ostream& operator<<(std::ostream& os, const SRegister& rhs) {
99 if (rhs >= S0 && rhs < kNumberOfSRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -0700100 os << "s" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700101 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700102 os << "SRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700103 }
104 return os;
105}
106
107
108std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
109 if (rhs >= D0 && rhs < kNumberOfDRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -0700110 os << "d" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700111 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700112 os << "DRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700113 }
114 return os;
115}
116
117
118static const char* kConditionNames[] = {
Ian Rogersb033c752011-07-20 12:22:35 -0700119 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT",
120 "LE", "AL",
Elliott Hughes1f359b02011-07-17 14:27:17 -0700121};
122std::ostream& operator<<(std::ostream& os, const Condition& rhs) {
123 if (rhs >= EQ && rhs <= AL) {
124 os << kConditionNames[rhs];
125 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700126 os << "Condition[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700127 }
128 return os;
129}
130
Ian Rogers2c8f6532011-09-02 17:16:34 -0700131void ArmAssembler::Emit(int32_t value) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700132 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
133 buffer_.Emit<int32_t>(value);
134}
135
136
Ian Rogers2c8f6532011-09-02 17:16:34 -0700137void ArmAssembler::EmitType01(Condition cond,
138 int type,
139 Opcode opcode,
140 int set_cc,
141 Register rn,
142 Register rd,
143 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700144 CHECK_NE(rd, kNoRegister);
145 CHECK_NE(cond, kNoCondition);
146 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
147 type << kTypeShift |
148 static_cast<int32_t>(opcode) << kOpcodeShift |
149 set_cc << kSShift |
150 static_cast<int32_t>(rn) << kRnShift |
151 static_cast<int32_t>(rd) << kRdShift |
152 so.encoding();
153 Emit(encoding);
154}
155
156
Ian Rogers2c8f6532011-09-02 17:16:34 -0700157void ArmAssembler::EmitType5(Condition cond, int offset, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700158 CHECK_NE(cond, kNoCondition);
159 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
160 5 << kTypeShift |
161 (link ? 1 : 0) << kLinkShift;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700162 Emit(ArmAssembler::EncodeBranchOffset(offset, encoding));
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700163}
164
165
Ian Rogers2c8f6532011-09-02 17:16:34 -0700166void ArmAssembler::EmitMemOp(Condition cond,
167 bool load,
168 bool byte,
169 Register rd,
170 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700171 CHECK_NE(rd, kNoRegister);
172 CHECK_NE(cond, kNoCondition);
173 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
174 B26 |
175 (load ? L : 0) |
176 (byte ? B : 0) |
177 (static_cast<int32_t>(rd) << kRdShift) |
178 ad.encoding();
179 Emit(encoding);
180}
181
182
Ian Rogers2c8f6532011-09-02 17:16:34 -0700183void ArmAssembler::EmitMemOpAddressMode3(Condition cond,
184 int32_t mode,
185 Register rd,
186 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700187 CHECK_NE(rd, kNoRegister);
188 CHECK_NE(cond, kNoCondition);
189 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
190 B22 |
191 mode |
192 (static_cast<int32_t>(rd) << kRdShift) |
193 ad.encoding3();
194 Emit(encoding);
195}
196
197
Ian Rogers2c8f6532011-09-02 17:16:34 -0700198void ArmAssembler::EmitMultiMemOp(Condition cond,
199 BlockAddressMode am,
200 bool load,
201 Register base,
202 RegList regs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700203 CHECK_NE(base, kNoRegister);
204 CHECK_NE(cond, kNoCondition);
205 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
206 B27 |
207 am |
208 (load ? L : 0) |
209 (static_cast<int32_t>(base) << kRnShift) |
210 regs;
211 Emit(encoding);
212}
213
214
Ian Rogers2c8f6532011-09-02 17:16:34 -0700215void ArmAssembler::EmitShiftImmediate(Condition cond,
216 Shift opcode,
217 Register rd,
218 Register rm,
219 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700220 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700221 CHECK_EQ(so.type(), 1U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700222 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
223 static_cast<int32_t>(MOV) << kOpcodeShift |
224 static_cast<int32_t>(rd) << kRdShift |
225 so.encoding() << kShiftImmShift |
226 static_cast<int32_t>(opcode) << kShiftShift |
227 static_cast<int32_t>(rm);
228 Emit(encoding);
229}
230
231
Ian Rogers2c8f6532011-09-02 17:16:34 -0700232void ArmAssembler::EmitShiftRegister(Condition cond,
233 Shift opcode,
234 Register rd,
235 Register rm,
236 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700237 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700238 CHECK_EQ(so.type(), 0U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700239 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
240 static_cast<int32_t>(MOV) << kOpcodeShift |
241 static_cast<int32_t>(rd) << kRdShift |
242 so.encoding() << kShiftRegisterShift |
243 static_cast<int32_t>(opcode) << kShiftShift |
244 B4 |
245 static_cast<int32_t>(rm);
246 Emit(encoding);
247}
248
249
Ian Rogers2c8f6532011-09-02 17:16:34 -0700250void ArmAssembler::EmitBranch(Condition cond, Label* label, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700251 if (label->IsBound()) {
252 EmitType5(cond, label->Position() - buffer_.Size(), link);
253 } else {
254 int position = buffer_.Size();
255 // Use the offset field of the branch instruction for linking the sites.
256 EmitType5(cond, label->position_, link);
257 label->LinkTo(position);
258 }
259}
260
Ian Rogers2c8f6532011-09-02 17:16:34 -0700261void ArmAssembler::and_(Register rd, Register rn, ShifterOperand so,
262 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700263 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
264}
265
266
Ian Rogers2c8f6532011-09-02 17:16:34 -0700267void ArmAssembler::eor(Register rd, Register rn, ShifterOperand so,
268 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700269 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
270}
271
272
Ian Rogers2c8f6532011-09-02 17:16:34 -0700273void ArmAssembler::sub(Register rd, Register rn, ShifterOperand so,
274 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700275 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
276}
277
Ian Rogers2c8f6532011-09-02 17:16:34 -0700278void ArmAssembler::rsb(Register rd, Register rn, ShifterOperand so,
279 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700280 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
281}
282
Ian Rogers2c8f6532011-09-02 17:16:34 -0700283void ArmAssembler::rsbs(Register rd, Register rn, ShifterOperand so,
284 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700285 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
286}
287
288
Ian Rogers2c8f6532011-09-02 17:16:34 -0700289void ArmAssembler::add(Register rd, Register rn, ShifterOperand so,
290 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700291 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
292}
293
294
Ian Rogers2c8f6532011-09-02 17:16:34 -0700295void ArmAssembler::adds(Register rd, Register rn, ShifterOperand so,
296 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700297 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
298}
299
300
Ian Rogers2c8f6532011-09-02 17:16:34 -0700301void ArmAssembler::subs(Register rd, Register rn, ShifterOperand so,
302 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700303 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
304}
305
306
Ian Rogers2c8f6532011-09-02 17:16:34 -0700307void ArmAssembler::adc(Register rd, Register rn, ShifterOperand so,
308 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700309 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
310}
311
312
Ian Rogers2c8f6532011-09-02 17:16:34 -0700313void ArmAssembler::sbc(Register rd, Register rn, ShifterOperand so,
314 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700315 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
316}
317
318
Ian Rogers2c8f6532011-09-02 17:16:34 -0700319void ArmAssembler::rsc(Register rd, Register rn, ShifterOperand so,
320 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700321 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
322}
323
324
Ian Rogers2c8f6532011-09-02 17:16:34 -0700325void ArmAssembler::tst(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700326 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
327 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
328}
329
330
Ian Rogers2c8f6532011-09-02 17:16:34 -0700331void ArmAssembler::teq(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700332 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
333 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
334}
335
336
Ian Rogers2c8f6532011-09-02 17:16:34 -0700337void ArmAssembler::cmp(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700338 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
339}
340
341
Ian Rogers2c8f6532011-09-02 17:16:34 -0700342void ArmAssembler::cmn(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700343 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
344}
345
346
Ian Rogers2c8f6532011-09-02 17:16:34 -0700347void ArmAssembler::orr(Register rd, Register rn,
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700348 ShifterOperand so, Condition cond) {
349 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
350}
351
352
Ian Rogers2c8f6532011-09-02 17:16:34 -0700353void ArmAssembler::orrs(Register rd, Register rn,
354 ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700355 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
356}
357
358
Ian Rogers2c8f6532011-09-02 17:16:34 -0700359void ArmAssembler::mov(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700360 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
361}
362
363
Ian Rogers2c8f6532011-09-02 17:16:34 -0700364void ArmAssembler::movs(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700365 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
366}
367
368
Ian Rogers2c8f6532011-09-02 17:16:34 -0700369void ArmAssembler::bic(Register rd, Register rn, ShifterOperand so,
370 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700371 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
372}
373
374
Ian Rogers2c8f6532011-09-02 17:16:34 -0700375void ArmAssembler::mvn(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700376 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
377}
378
379
Ian Rogers2c8f6532011-09-02 17:16:34 -0700380void ArmAssembler::mvns(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700381 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
382}
383
384
Ian Rogers2c8f6532011-09-02 17:16:34 -0700385void ArmAssembler::clz(Register rd, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700386 CHECK_NE(rd, kNoRegister);
387 CHECK_NE(rm, kNoRegister);
388 CHECK_NE(cond, kNoCondition);
389 CHECK_NE(rd, PC);
390 CHECK_NE(rm, PC);
391 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
392 B24 | B22 | B21 | (0xf << 16) |
393 (static_cast<int32_t>(rd) << kRdShift) |
394 (0xf << 8) | B4 | static_cast<int32_t>(rm);
395 Emit(encoding);
396}
397
398
Ian Rogers2c8f6532011-09-02 17:16:34 -0700399void ArmAssembler::movw(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700400 CHECK_NE(cond, kNoCondition);
401 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
402 B25 | B24 | ((imm16 >> 12) << 16) |
403 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
404 Emit(encoding);
405}
406
407
Ian Rogers2c8f6532011-09-02 17:16:34 -0700408void ArmAssembler::movt(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700409 CHECK_NE(cond, kNoCondition);
410 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
411 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
412 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
413 Emit(encoding);
414}
415
416
Ian Rogers2c8f6532011-09-02 17:16:34 -0700417void ArmAssembler::EmitMulOp(Condition cond, int32_t opcode,
418 Register rd, Register rn,
419 Register rm, Register rs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700420 CHECK_NE(rd, kNoRegister);
421 CHECK_NE(rn, kNoRegister);
422 CHECK_NE(rm, kNoRegister);
423 CHECK_NE(rs, kNoRegister);
424 CHECK_NE(cond, kNoCondition);
425 int32_t encoding = opcode |
426 (static_cast<int32_t>(cond) << kConditionShift) |
427 (static_cast<int32_t>(rn) << kRnShift) |
428 (static_cast<int32_t>(rd) << kRdShift) |
429 (static_cast<int32_t>(rs) << kRsShift) |
430 B7 | B4 |
431 (static_cast<int32_t>(rm) << kRmShift);
432 Emit(encoding);
433}
434
435
Ian Rogers2c8f6532011-09-02 17:16:34 -0700436void ArmAssembler::mul(Register rd, Register rn, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700437 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
438 EmitMulOp(cond, 0, R0, rd, rn, rm);
439}
440
441
Ian Rogers2c8f6532011-09-02 17:16:34 -0700442void ArmAssembler::mla(Register rd, Register rn, Register rm, Register ra,
443 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700444 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
445 EmitMulOp(cond, B21, ra, rd, rn, rm);
446}
447
448
Ian Rogers2c8f6532011-09-02 17:16:34 -0700449void ArmAssembler::mls(Register rd, Register rn, Register rm, Register ra,
450 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700451 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
452 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
453}
454
455
Ian Rogers2c8f6532011-09-02 17:16:34 -0700456void ArmAssembler::umull(Register rd_lo, Register rd_hi, Register rn,
457 Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700458 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
459 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
460}
461
462
Ian Rogers2c8f6532011-09-02 17:16:34 -0700463void ArmAssembler::ldr(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700464 EmitMemOp(cond, true, false, rd, ad);
465}
466
467
Ian Rogers2c8f6532011-09-02 17:16:34 -0700468void ArmAssembler::str(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700469 EmitMemOp(cond, false, false, rd, ad);
470}
471
472
Ian Rogers2c8f6532011-09-02 17:16:34 -0700473void ArmAssembler::ldrb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700474 EmitMemOp(cond, true, true, rd, ad);
475}
476
477
Ian Rogers2c8f6532011-09-02 17:16:34 -0700478void ArmAssembler::strb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700479 EmitMemOp(cond, false, true, rd, ad);
480}
481
482
Ian Rogers2c8f6532011-09-02 17:16:34 -0700483void ArmAssembler::ldrh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700484 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
485}
486
487
Ian Rogers2c8f6532011-09-02 17:16:34 -0700488void ArmAssembler::strh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700489 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
490}
491
492
Ian Rogers2c8f6532011-09-02 17:16:34 -0700493void ArmAssembler::ldrsb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700494 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
495}
496
497
Ian Rogers2c8f6532011-09-02 17:16:34 -0700498void ArmAssembler::ldrsh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700499 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
500}
501
502
Ian Rogers2c8f6532011-09-02 17:16:34 -0700503void ArmAssembler::ldrd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700504 CHECK_EQ(rd % 2, 0);
505 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
506}
507
508
Ian Rogers2c8f6532011-09-02 17:16:34 -0700509void ArmAssembler::strd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700510 CHECK_EQ(rd % 2, 0);
511 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
512}
513
514
Ian Rogers2c8f6532011-09-02 17:16:34 -0700515void ArmAssembler::ldm(BlockAddressMode am,
516 Register base,
517 RegList regs,
518 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700519 EmitMultiMemOp(cond, am, true, base, regs);
520}
521
522
Ian Rogers2c8f6532011-09-02 17:16:34 -0700523void ArmAssembler::stm(BlockAddressMode am,
524 Register base,
525 RegList regs,
526 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700527 EmitMultiMemOp(cond, am, false, base, regs);
528}
529
530
Ian Rogers2c8f6532011-09-02 17:16:34 -0700531void ArmAssembler::ldrex(Register rt, Register rn, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700532 CHECK_NE(rn, kNoRegister);
533 CHECK_NE(rt, kNoRegister);
534 CHECK_NE(cond, kNoCondition);
535 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
536 B24 |
537 B23 |
538 L |
539 (static_cast<int32_t>(rn) << kLdExRnShift) |
540 (static_cast<int32_t>(rt) << kLdExRtShift) |
541 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
542 Emit(encoding);
543}
544
545
Ian Rogers2c8f6532011-09-02 17:16:34 -0700546void ArmAssembler::strex(Register rd,
547 Register rt,
548 Register rn,
549 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700550 CHECK_NE(rn, kNoRegister);
551 CHECK_NE(rd, kNoRegister);
552 CHECK_NE(rt, kNoRegister);
553 CHECK_NE(cond, kNoCondition);
554 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
555 B24 |
556 B23 |
557 (static_cast<int32_t>(rn) << kStrExRnShift) |
558 (static_cast<int32_t>(rd) << kStrExRdShift) |
559 B11 | B10 | B9 | B8 | B7 | B4 |
560 (static_cast<int32_t>(rt) << kStrExRtShift);
561 Emit(encoding);
562}
563
564
Ian Rogers2c8f6532011-09-02 17:16:34 -0700565void ArmAssembler::clrex() {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700566 int32_t encoding = (kSpecialCondition << kConditionShift) |
567 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
568 Emit(encoding);
569}
570
571
Ian Rogers2c8f6532011-09-02 17:16:34 -0700572void ArmAssembler::nop(Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700573 CHECK_NE(cond, kNoCondition);
574 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
575 B25 | B24 | B21 | (0xf << 12);
576 Emit(encoding);
577}
578
579
Ian Rogers2c8f6532011-09-02 17:16:34 -0700580void ArmAssembler::vmovsr(SRegister sn, Register rt, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700581 CHECK_NE(sn, kNoSRegister);
582 CHECK_NE(rt, kNoRegister);
583 CHECK_NE(rt, SP);
584 CHECK_NE(rt, PC);
585 CHECK_NE(cond, kNoCondition);
586 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
587 B27 | B26 | B25 |
588 ((static_cast<int32_t>(sn) >> 1)*B16) |
589 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
590 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
591 Emit(encoding);
592}
593
594
Ian Rogers2c8f6532011-09-02 17:16:34 -0700595void ArmAssembler::vmovrs(Register rt, SRegister sn, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700596 CHECK_NE(sn, kNoSRegister);
597 CHECK_NE(rt, kNoRegister);
598 CHECK_NE(rt, SP);
599 CHECK_NE(rt, PC);
600 CHECK_NE(cond, kNoCondition);
601 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
602 B27 | B26 | B25 | B20 |
603 ((static_cast<int32_t>(sn) >> 1)*B16) |
604 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
605 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
606 Emit(encoding);
607}
608
609
Ian Rogers2c8f6532011-09-02 17:16:34 -0700610void ArmAssembler::vmovsrr(SRegister sm, Register rt, Register rt2,
611 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700612 CHECK_NE(sm, kNoSRegister);
613 CHECK_NE(sm, S31);
614 CHECK_NE(rt, kNoRegister);
615 CHECK_NE(rt, SP);
616 CHECK_NE(rt, PC);
617 CHECK_NE(rt2, kNoRegister);
618 CHECK_NE(rt2, SP);
619 CHECK_NE(rt2, PC);
620 CHECK_NE(cond, kNoCondition);
621 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
622 B27 | B26 | B22 |
623 (static_cast<int32_t>(rt2)*B16) |
624 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
625 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
626 (static_cast<int32_t>(sm) >> 1);
627 Emit(encoding);
628}
629
630
Ian Rogers2c8f6532011-09-02 17:16:34 -0700631void ArmAssembler::vmovrrs(Register rt, Register rt2, SRegister sm,
632 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700633 CHECK_NE(sm, kNoSRegister);
634 CHECK_NE(sm, S31);
635 CHECK_NE(rt, kNoRegister);
636 CHECK_NE(rt, SP);
637 CHECK_NE(rt, PC);
638 CHECK_NE(rt2, kNoRegister);
639 CHECK_NE(rt2, SP);
640 CHECK_NE(rt2, PC);
641 CHECK_NE(rt, rt2);
642 CHECK_NE(cond, kNoCondition);
643 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
644 B27 | B26 | B22 | B20 |
645 (static_cast<int32_t>(rt2)*B16) |
646 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
647 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
648 (static_cast<int32_t>(sm) >> 1);
649 Emit(encoding);
650}
651
652
Ian Rogers2c8f6532011-09-02 17:16:34 -0700653void ArmAssembler::vmovdrr(DRegister dm, Register rt, Register rt2,
654 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700655 CHECK_NE(dm, kNoDRegister);
656 CHECK_NE(rt, kNoRegister);
657 CHECK_NE(rt, SP);
658 CHECK_NE(rt, PC);
659 CHECK_NE(rt2, kNoRegister);
660 CHECK_NE(rt2, SP);
661 CHECK_NE(rt2, PC);
662 CHECK_NE(cond, kNoCondition);
663 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
664 B27 | B26 | B22 |
665 (static_cast<int32_t>(rt2)*B16) |
666 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
667 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
668 (static_cast<int32_t>(dm) & 0xf);
669 Emit(encoding);
670}
671
672
Ian Rogers2c8f6532011-09-02 17:16:34 -0700673void ArmAssembler::vmovrrd(Register rt, Register rt2, DRegister dm,
674 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700675 CHECK_NE(dm, kNoDRegister);
676 CHECK_NE(rt, kNoRegister);
677 CHECK_NE(rt, SP);
678 CHECK_NE(rt, PC);
679 CHECK_NE(rt2, kNoRegister);
680 CHECK_NE(rt2, SP);
681 CHECK_NE(rt2, PC);
682 CHECK_NE(rt, rt2);
683 CHECK_NE(cond, kNoCondition);
684 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
685 B27 | B26 | B22 | B20 |
686 (static_cast<int32_t>(rt2)*B16) |
687 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
688 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
689 (static_cast<int32_t>(dm) & 0xf);
690 Emit(encoding);
691}
692
693
Ian Rogers2c8f6532011-09-02 17:16:34 -0700694void ArmAssembler::vldrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700695 CHECK_NE(sd, kNoSRegister);
696 CHECK_NE(cond, kNoCondition);
697 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
698 B27 | B26 | B24 | B20 |
699 ((static_cast<int32_t>(sd) & 1)*B22) |
700 ((static_cast<int32_t>(sd) >> 1)*B12) |
701 B11 | B9 | ad.vencoding();
702 Emit(encoding);
703}
704
705
Ian Rogers2c8f6532011-09-02 17:16:34 -0700706void ArmAssembler::vstrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700707 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
708 CHECK_NE(sd, kNoSRegister);
709 CHECK_NE(cond, kNoCondition);
710 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
711 B27 | B26 | B24 |
712 ((static_cast<int32_t>(sd) & 1)*B22) |
713 ((static_cast<int32_t>(sd) >> 1)*B12) |
714 B11 | B9 | ad.vencoding();
715 Emit(encoding);
716}
717
718
Ian Rogers2c8f6532011-09-02 17:16:34 -0700719void ArmAssembler::vldrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700720 CHECK_NE(dd, kNoDRegister);
721 CHECK_NE(cond, kNoCondition);
722 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
723 B27 | B26 | B24 | B20 |
724 ((static_cast<int32_t>(dd) >> 4)*B22) |
725 ((static_cast<int32_t>(dd) & 0xf)*B12) |
726 B11 | B9 | B8 | ad.vencoding();
727 Emit(encoding);
728}
729
730
Ian Rogers2c8f6532011-09-02 17:16:34 -0700731void ArmAssembler::vstrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700732 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
733 CHECK_NE(dd, kNoDRegister);
734 CHECK_NE(cond, kNoCondition);
735 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
736 B27 | B26 | B24 |
737 ((static_cast<int32_t>(dd) >> 4)*B22) |
738 ((static_cast<int32_t>(dd) & 0xf)*B12) |
739 B11 | B9 | B8 | ad.vencoding();
740 Emit(encoding);
741}
742
743
Ian Rogers2c8f6532011-09-02 17:16:34 -0700744void ArmAssembler::EmitVFPsss(Condition cond, int32_t opcode,
745 SRegister sd, SRegister sn, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700746 CHECK_NE(sd, kNoSRegister);
747 CHECK_NE(sn, kNoSRegister);
748 CHECK_NE(sm, kNoSRegister);
749 CHECK_NE(cond, kNoCondition);
750 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
751 B27 | B26 | B25 | B11 | B9 | opcode |
752 ((static_cast<int32_t>(sd) & 1)*B22) |
753 ((static_cast<int32_t>(sn) >> 1)*B16) |
754 ((static_cast<int32_t>(sd) >> 1)*B12) |
755 ((static_cast<int32_t>(sn) & 1)*B7) |
756 ((static_cast<int32_t>(sm) & 1)*B5) |
757 (static_cast<int32_t>(sm) >> 1);
758 Emit(encoding);
759}
760
761
Ian Rogers2c8f6532011-09-02 17:16:34 -0700762void ArmAssembler::EmitVFPddd(Condition cond, int32_t opcode,
763 DRegister dd, DRegister dn, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700764 CHECK_NE(dd, kNoDRegister);
765 CHECK_NE(dn, kNoDRegister);
766 CHECK_NE(dm, kNoDRegister);
767 CHECK_NE(cond, kNoCondition);
768 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
769 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
770 ((static_cast<int32_t>(dd) >> 4)*B22) |
771 ((static_cast<int32_t>(dn) & 0xf)*B16) |
772 ((static_cast<int32_t>(dd) & 0xf)*B12) |
773 ((static_cast<int32_t>(dn) >> 4)*B7) |
774 ((static_cast<int32_t>(dm) >> 4)*B5) |
775 (static_cast<int32_t>(dm) & 0xf);
776 Emit(encoding);
777}
778
779
Ian Rogers2c8f6532011-09-02 17:16:34 -0700780void ArmAssembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700781 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
782}
783
784
Ian Rogers2c8f6532011-09-02 17:16:34 -0700785void ArmAssembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700786 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
787}
788
789
Ian Rogers2c8f6532011-09-02 17:16:34 -0700790bool ArmAssembler::vmovs(SRegister sd, float s_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700791 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
792 if (((imm32 & ((1 << 19) - 1)) == 0) &&
793 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
794 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
795 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
796 ((imm32 >> 19) & ((1 << 6) -1));
797 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
798 sd, S0, S0);
799 return true;
800 }
801 return false;
802}
803
804
Ian Rogers2c8f6532011-09-02 17:16:34 -0700805bool ArmAssembler::vmovd(DRegister dd, double d_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700806 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
807 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
808 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
809 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
810 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
811 ((imm64 >> 48) & ((1 << 6) -1));
812 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
813 dd, D0, D0);
814 return true;
815 }
816 return false;
817}
818
819
Ian Rogers2c8f6532011-09-02 17:16:34 -0700820void ArmAssembler::vadds(SRegister sd, SRegister sn, SRegister sm,
821 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700822 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
823}
824
825
Ian Rogers2c8f6532011-09-02 17:16:34 -0700826void ArmAssembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
827 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700828 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
829}
830
831
Ian Rogers2c8f6532011-09-02 17:16:34 -0700832void ArmAssembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
833 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700834 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
835}
836
837
Ian Rogers2c8f6532011-09-02 17:16:34 -0700838void ArmAssembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
839 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700840 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
841}
842
843
Ian Rogers2c8f6532011-09-02 17:16:34 -0700844void ArmAssembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
845 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700846 EmitVFPsss(cond, B21, sd, sn, sm);
847}
848
849
Ian Rogers2c8f6532011-09-02 17:16:34 -0700850void ArmAssembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
851 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700852 EmitVFPddd(cond, B21, dd, dn, dm);
853}
854
855
Ian Rogers2c8f6532011-09-02 17:16:34 -0700856void ArmAssembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
857 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700858 EmitVFPsss(cond, 0, sd, sn, sm);
859}
860
861
Ian Rogers2c8f6532011-09-02 17:16:34 -0700862void ArmAssembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
863 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700864 EmitVFPddd(cond, 0, dd, dn, dm);
865}
866
867
Ian Rogers2c8f6532011-09-02 17:16:34 -0700868void ArmAssembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
869 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700870 EmitVFPsss(cond, B6, sd, sn, sm);
871}
872
873
Ian Rogers2c8f6532011-09-02 17:16:34 -0700874void ArmAssembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
875 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700876 EmitVFPddd(cond, B6, dd, dn, dm);
877}
878
879
Ian Rogers2c8f6532011-09-02 17:16:34 -0700880void ArmAssembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
881 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700882 EmitVFPsss(cond, B23, sd, sn, sm);
883}
884
885
Ian Rogers2c8f6532011-09-02 17:16:34 -0700886void ArmAssembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
887 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700888 EmitVFPddd(cond, B23, dd, dn, dm);
889}
890
891
Ian Rogers2c8f6532011-09-02 17:16:34 -0700892void ArmAssembler::vabss(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700893 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
894}
895
896
Ian Rogers2c8f6532011-09-02 17:16:34 -0700897void ArmAssembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700898 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
899}
900
901
Ian Rogers2c8f6532011-09-02 17:16:34 -0700902void ArmAssembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700903 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
904}
905
906
Ian Rogers2c8f6532011-09-02 17:16:34 -0700907void ArmAssembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700908 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
909}
910
911
Ian Rogers2c8f6532011-09-02 17:16:34 -0700912void ArmAssembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700913 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
914}
915
Ian Rogers2c8f6532011-09-02 17:16:34 -0700916void ArmAssembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700917 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
918}
919
920
Ian Rogers2c8f6532011-09-02 17:16:34 -0700921void ArmAssembler::EmitVFPsd(Condition cond, int32_t opcode,
922 SRegister sd, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700923 CHECK_NE(sd, kNoSRegister);
924 CHECK_NE(dm, kNoDRegister);
925 CHECK_NE(cond, kNoCondition);
926 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
927 B27 | B26 | B25 | B11 | B9 | opcode |
928 ((static_cast<int32_t>(sd) & 1)*B22) |
929 ((static_cast<int32_t>(sd) >> 1)*B12) |
930 ((static_cast<int32_t>(dm) >> 4)*B5) |
931 (static_cast<int32_t>(dm) & 0xf);
932 Emit(encoding);
933}
934
935
Ian Rogers2c8f6532011-09-02 17:16:34 -0700936void ArmAssembler::EmitVFPds(Condition cond, int32_t opcode,
937 DRegister dd, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700938 CHECK_NE(dd, kNoDRegister);
939 CHECK_NE(sm, kNoSRegister);
940 CHECK_NE(cond, kNoCondition);
941 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
942 B27 | B26 | B25 | B11 | B9 | opcode |
943 ((static_cast<int32_t>(dd) >> 4)*B22) |
944 ((static_cast<int32_t>(dd) & 0xf)*B12) |
945 ((static_cast<int32_t>(sm) & 1)*B5) |
946 (static_cast<int32_t>(sm) >> 1);
947 Emit(encoding);
948}
949
950
Ian Rogers2c8f6532011-09-02 17:16:34 -0700951void ArmAssembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700952 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
953}
954
955
Ian Rogers2c8f6532011-09-02 17:16:34 -0700956void ArmAssembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700957 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
958}
959
960
Ian Rogers2c8f6532011-09-02 17:16:34 -0700961void ArmAssembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700962 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
963}
964
965
Ian Rogers2c8f6532011-09-02 17:16:34 -0700966void ArmAssembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700967 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
968}
969
970
Ian Rogers2c8f6532011-09-02 17:16:34 -0700971void ArmAssembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700972 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
973}
974
975
Ian Rogers2c8f6532011-09-02 17:16:34 -0700976void ArmAssembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700977 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
978}
979
980
Ian Rogers2c8f6532011-09-02 17:16:34 -0700981void ArmAssembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700982 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
983}
984
985
Ian Rogers2c8f6532011-09-02 17:16:34 -0700986void ArmAssembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700987 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
988}
989
990
Ian Rogers2c8f6532011-09-02 17:16:34 -0700991void ArmAssembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700992 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
993}
994
995
Ian Rogers2c8f6532011-09-02 17:16:34 -0700996void ArmAssembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700997 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
998}
999
1000
Ian Rogers2c8f6532011-09-02 17:16:34 -07001001void ArmAssembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001002 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
1003}
1004
1005
Ian Rogers2c8f6532011-09-02 17:16:34 -07001006void ArmAssembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001007 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
1008}
1009
1010
Ian Rogers2c8f6532011-09-02 17:16:34 -07001011void ArmAssembler::vcmpsz(SRegister sd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001012 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
1013}
1014
1015
Ian Rogers2c8f6532011-09-02 17:16:34 -07001016void ArmAssembler::vcmpdz(DRegister dd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001017 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
1018}
1019
1020
Ian Rogers2c8f6532011-09-02 17:16:34 -07001021void ArmAssembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001022 CHECK_NE(cond, kNoCondition);
1023 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1024 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1025 (static_cast<int32_t>(PC)*B12) |
1026 B11 | B9 | B4;
1027 Emit(encoding);
1028}
1029
1030
Ian Rogers2c8f6532011-09-02 17:16:34 -07001031void ArmAssembler::svc(uint32_t imm24) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001032 CHECK(IsUint(24, imm24)) << imm24;
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001033 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1034 Emit(encoding);
1035}
1036
1037
Ian Rogers2c8f6532011-09-02 17:16:34 -07001038void ArmAssembler::bkpt(uint16_t imm16) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001039 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1040 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1041 Emit(encoding);
1042}
1043
1044
Ian Rogers2c8f6532011-09-02 17:16:34 -07001045void ArmAssembler::b(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001046 EmitBranch(cond, label, false);
1047}
1048
1049
Ian Rogers2c8f6532011-09-02 17:16:34 -07001050void ArmAssembler::bl(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001051 EmitBranch(cond, label, true);
1052}
1053
1054
Ian Rogers2c8f6532011-09-02 17:16:34 -07001055void ArmAssembler::blx(Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001056 CHECK_NE(rm, kNoRegister);
1057 CHECK_NE(cond, kNoCondition);
1058 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1059 B24 | B21 | (0xfff << 8) | B5 | B4 |
1060 (static_cast<int32_t>(rm) << kRmShift);
1061 Emit(encoding);
1062}
1063
Ian Rogersae675992011-10-09 17:10:22 -07001064void ArmAssembler::bx(Register rm, Condition cond) {
1065 CHECK_NE(rm, kNoRegister);
1066 CHECK_NE(cond, kNoCondition);
1067 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1068 B24 | B21 | (0xfff << 8) | B4 |
1069 (static_cast<int32_t>(rm) << kRmShift);
1070 Emit(encoding);
1071}
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001072
Ian Rogers2c8f6532011-09-02 17:16:34 -07001073void ArmAssembler::MarkExceptionHandler(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001074 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
1075 Label l;
1076 b(&l);
1077 EmitBranch(AL, label, false);
1078 Bind(&l);
1079}
1080
1081
Ian Rogers2c8f6532011-09-02 17:16:34 -07001082void ArmAssembler::Bind(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001083 CHECK(!label->IsBound());
1084 int bound_pc = buffer_.Size();
1085 while (label->IsLinked()) {
1086 int32_t position = label->Position();
1087 int32_t next = buffer_.Load<int32_t>(position);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001088 int32_t encoded = ArmAssembler::EncodeBranchOffset(bound_pc - position, next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001089 buffer_.Store<int32_t>(position, encoded);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001090 label->position_ = ArmAssembler::DecodeBranchOffset(next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001091 }
1092 label->BindTo(bound_pc);
1093}
1094
1095
Ian Rogers2c8f6532011-09-02 17:16:34 -07001096void ArmAssembler::EncodeUint32InTstInstructions(uint32_t data) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001097 // TODO: Consider using movw ip, <16 bits>.
1098 while (!IsUint(8, data)) {
1099 tst(R0, ShifterOperand(data & 0xFF), VS);
1100 data >>= 8;
1101 }
1102 tst(R0, ShifterOperand(data), MI);
1103}
1104
Ian Rogersb033c752011-07-20 12:22:35 -07001105
Ian Rogers2c8f6532011-09-02 17:16:34 -07001106int32_t ArmAssembler::EncodeBranchOffset(int offset, int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001107 // The offset is off by 8 due to the way the ARM CPUs read PC.
1108 offset -= 8;
Elliott Hughes06b37d92011-10-16 11:51:29 -07001109 CHECK_ALIGNED(offset, 4);
Vladimir Marko81949632014-05-02 11:53:22 +01001110 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001111
1112 // Properly preserve only the bits supported in the instruction.
1113 offset >>= 2;
1114 offset &= kBranchOffsetMask;
1115 return (inst & ~kBranchOffsetMask) | offset;
1116}
1117
1118
Ian Rogers2c8f6532011-09-02 17:16:34 -07001119int ArmAssembler::DecodeBranchOffset(int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001120 // Sign-extend, left-shift by 2, then add 8.
1121 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1122}
1123
Ian Rogers2c8f6532011-09-02 17:16:34 -07001124void ArmAssembler::AddConstant(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001125 AddConstant(rd, rd, value, cond);
1126}
1127
1128
Ian Rogers2c8f6532011-09-02 17:16:34 -07001129void ArmAssembler::AddConstant(Register rd, Register rn, int32_t value,
1130 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001131 if (value == 0) {
1132 if (rd != rn) {
1133 mov(rd, ShifterOperand(rn), cond);
1134 }
1135 return;
1136 }
1137 // We prefer to select the shorter code sequence rather than selecting add for
1138 // positive values and sub for negatives ones, which would slightly improve
1139 // the readability of generated code for some constants.
1140 ShifterOperand shifter_op;
1141 if (ShifterOperand::CanHold(value, &shifter_op)) {
1142 add(rd, rn, shifter_op, cond);
1143 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1144 sub(rd, rn, shifter_op, cond);
1145 } else {
1146 CHECK(rn != IP);
1147 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1148 mvn(IP, shifter_op, cond);
1149 add(rd, rn, ShifterOperand(IP), cond);
1150 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1151 mvn(IP, shifter_op, cond);
1152 sub(rd, rn, ShifterOperand(IP), cond);
1153 } else {
1154 movw(IP, Low16Bits(value), cond);
1155 uint16_t value_high = High16Bits(value);
1156 if (value_high != 0) {
1157 movt(IP, value_high, cond);
1158 }
1159 add(rd, rn, ShifterOperand(IP), cond);
1160 }
1161 }
1162}
1163
1164
Ian Rogers2c8f6532011-09-02 17:16:34 -07001165void ArmAssembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1166 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001167 ShifterOperand shifter_op;
1168 if (ShifterOperand::CanHold(value, &shifter_op)) {
1169 adds(rd, rn, shifter_op, cond);
1170 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1171 subs(rd, rn, shifter_op, cond);
1172 } else {
1173 CHECK(rn != IP);
1174 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1175 mvn(IP, shifter_op, cond);
1176 adds(rd, rn, ShifterOperand(IP), cond);
1177 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1178 mvn(IP, shifter_op, cond);
1179 subs(rd, rn, ShifterOperand(IP), cond);
1180 } else {
1181 movw(IP, Low16Bits(value), cond);
1182 uint16_t value_high = High16Bits(value);
1183 if (value_high != 0) {
1184 movt(IP, value_high, cond);
1185 }
1186 adds(rd, rn, ShifterOperand(IP), cond);
1187 }
1188 }
1189}
1190
1191
Ian Rogers2c8f6532011-09-02 17:16:34 -07001192void ArmAssembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001193 ShifterOperand shifter_op;
1194 if (ShifterOperand::CanHold(value, &shifter_op)) {
1195 mov(rd, shifter_op, cond);
1196 } else if (ShifterOperand::CanHold(~value, &shifter_op)) {
1197 mvn(rd, shifter_op, cond);
1198 } else {
1199 movw(rd, Low16Bits(value), cond);
1200 uint16_t value_high = High16Bits(value);
1201 if (value_high != 0) {
1202 movt(rd, value_high, cond);
1203 }
1204 }
1205}
1206
1207
1208bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) {
1209 switch (type) {
1210 case kLoadSignedByte:
1211 case kLoadSignedHalfword:
1212 case kLoadUnsignedHalfword:
1213 case kLoadWordPair:
1214 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1215 case kLoadUnsignedByte:
1216 case kLoadWord:
1217 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1218 case kLoadSWord:
1219 case kLoadDWord:
1220 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1221 default:
1222 LOG(FATAL) << "UNREACHABLE";
1223 return false;
1224 }
1225}
1226
1227
1228bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) {
1229 switch (type) {
1230 case kStoreHalfword:
1231 case kStoreWordPair:
1232 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1233 case kStoreByte:
1234 case kStoreWord:
1235 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1236 case kStoreSWord:
1237 case kStoreDWord:
1238 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1239 default:
1240 LOG(FATAL) << "UNREACHABLE";
1241 return false;
1242 }
1243}
1244
1245
1246// Implementation note: this method must emit at most one instruction when
1247// Address::CanHoldLoadOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001248void ArmAssembler::LoadFromOffset(LoadOperandType type,
Ian Rogers468532e2013-08-05 10:56:33 -07001249 Register reg,
1250 Register base,
1251 int32_t offset,
1252 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001253 if (!Address::CanHoldLoadOffset(type, offset)) {
1254 CHECK(base != IP);
1255 LoadImmediate(IP, offset, cond);
1256 add(IP, IP, ShifterOperand(base), cond);
1257 base = IP;
1258 offset = 0;
1259 }
1260 CHECK(Address::CanHoldLoadOffset(type, offset));
1261 switch (type) {
1262 case kLoadSignedByte:
1263 ldrsb(reg, Address(base, offset), cond);
1264 break;
1265 case kLoadUnsignedByte:
1266 ldrb(reg, Address(base, offset), cond);
1267 break;
1268 case kLoadSignedHalfword:
1269 ldrsh(reg, Address(base, offset), cond);
1270 break;
1271 case kLoadUnsignedHalfword:
1272 ldrh(reg, Address(base, offset), cond);
1273 break;
1274 case kLoadWord:
1275 ldr(reg, Address(base, offset), cond);
1276 break;
1277 case kLoadWordPair:
1278 ldrd(reg, Address(base, offset), cond);
1279 break;
1280 default:
1281 LOG(FATAL) << "UNREACHABLE";
1282 }
1283}
1284
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001285// Implementation note: this method must emit at most one instruction when
1286// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001287void ArmAssembler::LoadSFromOffset(SRegister reg,
1288 Register base,
1289 int32_t offset,
1290 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001291 if (!Address::CanHoldLoadOffset(kLoadSWord, offset)) {
1292 CHECK_NE(base, IP);
1293 LoadImmediate(IP, offset, cond);
1294 add(IP, IP, ShifterOperand(base), cond);
1295 base = IP;
1296 offset = 0;
1297 }
1298 CHECK(Address::CanHoldLoadOffset(kLoadSWord, offset));
1299 vldrs(reg, Address(base, offset), cond);
1300}
1301
1302// Implementation note: this method must emit at most one instruction when
1303// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001304void ArmAssembler::LoadDFromOffset(DRegister reg,
1305 Register base,
1306 int32_t offset,
1307 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001308 if (!Address::CanHoldLoadOffset(kLoadDWord, offset)) {
1309 CHECK_NE(base, IP);
1310 LoadImmediate(IP, offset, cond);
1311 add(IP, IP, ShifterOperand(base), cond);
1312 base = IP;
1313 offset = 0;
1314 }
1315 CHECK(Address::CanHoldLoadOffset(kLoadDWord, offset));
1316 vldrd(reg, Address(base, offset), cond);
1317}
Ian Rogersb033c752011-07-20 12:22:35 -07001318
1319// Implementation note: this method must emit at most one instruction when
1320// Address::CanHoldStoreOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001321void ArmAssembler::StoreToOffset(StoreOperandType type,
1322 Register reg,
1323 Register base,
1324 int32_t offset,
1325 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001326 if (!Address::CanHoldStoreOffset(type, offset)) {
1327 CHECK(reg != IP);
1328 CHECK(base != IP);
1329 LoadImmediate(IP, offset, cond);
1330 add(IP, IP, ShifterOperand(base), cond);
1331 base = IP;
1332 offset = 0;
1333 }
1334 CHECK(Address::CanHoldStoreOffset(type, offset));
1335 switch (type) {
1336 case kStoreByte:
1337 strb(reg, Address(base, offset), cond);
1338 break;
1339 case kStoreHalfword:
1340 strh(reg, Address(base, offset), cond);
1341 break;
1342 case kStoreWord:
1343 str(reg, Address(base, offset), cond);
1344 break;
1345 case kStoreWordPair:
1346 strd(reg, Address(base, offset), cond);
1347 break;
1348 default:
1349 LOG(FATAL) << "UNREACHABLE";
1350 }
1351}
1352
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001353// Implementation note: this method must emit at most one instruction when
1354// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001355void ArmAssembler::StoreSToOffset(SRegister reg,
1356 Register base,
1357 int32_t offset,
1358 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001359 if (!Address::CanHoldStoreOffset(kStoreSWord, offset)) {
1360 CHECK_NE(base, IP);
1361 LoadImmediate(IP, offset, cond);
1362 add(IP, IP, ShifterOperand(base), cond);
1363 base = IP;
1364 offset = 0;
1365 }
1366 CHECK(Address::CanHoldStoreOffset(kStoreSWord, offset));
1367 vstrs(reg, Address(base, offset), cond);
1368}
1369
1370// Implementation note: this method must emit at most one instruction when
1371// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreSToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001372void ArmAssembler::StoreDToOffset(DRegister reg,
1373 Register base,
1374 int32_t offset,
1375 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001376 if (!Address::CanHoldStoreOffset(kStoreDWord, offset)) {
1377 CHECK_NE(base, IP);
1378 LoadImmediate(IP, offset, cond);
1379 add(IP, IP, ShifterOperand(base), cond);
1380 base = IP;
1381 offset = 0;
1382 }
1383 CHECK(Address::CanHoldStoreOffset(kStoreDWord, offset));
1384 vstrd(reg, Address(base, offset), cond);
1385}
1386
Ian Rogers2c8f6532011-09-02 17:16:34 -07001387void ArmAssembler::Push(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001388 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1389}
1390
Ian Rogers2c8f6532011-09-02 17:16:34 -07001391void ArmAssembler::Pop(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001392 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1393}
1394
Ian Rogers2c8f6532011-09-02 17:16:34 -07001395void ArmAssembler::PushList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001396 stm(DB_W, SP, regs, cond);
1397}
1398
Ian Rogers2c8f6532011-09-02 17:16:34 -07001399void ArmAssembler::PopList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001400 ldm(IA_W, SP, regs, cond);
1401}
1402
Ian Rogers2c8f6532011-09-02 17:16:34 -07001403void ArmAssembler::Mov(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001404 if (rd != rm) {
1405 mov(rd, ShifterOperand(rm), cond);
1406 }
1407}
1408
Ian Rogers2c8f6532011-09-02 17:16:34 -07001409void ArmAssembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
1410 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001411 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
1412 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1413}
1414
Ian Rogers2c8f6532011-09-02 17:16:34 -07001415void ArmAssembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
1416 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001417 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
1418 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1419 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1420}
1421
Ian Rogers2c8f6532011-09-02 17:16:34 -07001422void ArmAssembler::Asr(Register rd, Register rm, uint32_t shift_imm,
1423 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001424 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
1425 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1426 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1427}
1428
Ian Rogers2c8f6532011-09-02 17:16:34 -07001429void ArmAssembler::Ror(Register rd, Register rm, uint32_t shift_imm,
1430 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001431 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
1432 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1433}
1434
Ian Rogers2c8f6532011-09-02 17:16:34 -07001435void ArmAssembler::Rrx(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001436 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1437}
1438
Ian Rogers790a6b72014-04-01 10:36:00 -07001439constexpr size_t kFramePointerSize = 4;
1440
Ian Rogers2c8f6532011-09-02 17:16:34 -07001441void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersb5d09b22012-03-06 22:14:17 -08001442 const std::vector<ManagedRegister>& callee_save_regs,
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001443 const ManagedRegisterEntrySpills& entry_spills) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001444 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001445 CHECK_EQ(R0, method_reg.AsArm().AsCoreRegister());
Ian Rogersbdb03912011-09-14 00:55:44 -07001446
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001447 // Push callee saves and link register.
Ian Rogersbdb03912011-09-14 00:55:44 -07001448 RegList push_list = 1 << LR;
1449 size_t pushed_values = 1;
1450 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1451 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1452 push_list |= 1 << reg;
1453 pushed_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001454 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001455 PushList(push_list);
1456
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001457 // Increase frame to required size.
Ian Rogers790a6b72014-04-01 10:36:00 -07001458 CHECK_GT(frame_size, pushed_values * kFramePointerSize); // Must at least have space for Method*.
1459 size_t adjust = frame_size - (pushed_values * kFramePointerSize);
Ian Rogersbdb03912011-09-14 00:55:44 -07001460 IncreaseFrameSize(adjust);
1461
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001462 // Write out Method*.
Ian Rogersbdb03912011-09-14 00:55:44 -07001463 StoreToOffset(kStoreWord, R0, SP, 0);
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001464
1465 // Write out entry spills.
1466 for (size_t i = 0; i < entry_spills.size(); ++i) {
1467 Register reg = entry_spills.at(i).AsArm().AsCoreRegister();
Ian Rogers790a6b72014-04-01 10:36:00 -07001468 StoreToOffset(kStoreWord, reg, SP, frame_size + kFramePointerSize + (i * kFramePointerSize));
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001469 }
Ian Rogersb033c752011-07-20 12:22:35 -07001470}
1471
Ian Rogers2c8f6532011-09-02 17:16:34 -07001472void ArmAssembler::RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -07001473 const std::vector<ManagedRegister>& callee_save_regs) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001474 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogersbdb03912011-09-14 00:55:44 -07001475 // Compute callee saves to pop and PC
1476 RegList pop_list = 1 << PC;
1477 size_t pop_values = 1;
1478 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1479 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1480 pop_list |= 1 << reg;
1481 pop_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001482 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001483
1484 // Decrease frame to start of callee saves
Ian Rogers790a6b72014-04-01 10:36:00 -07001485 CHECK_GT(frame_size, pop_values * kFramePointerSize);
1486 size_t adjust = frame_size - (pop_values * kFramePointerSize);
Ian Rogersbdb03912011-09-14 00:55:44 -07001487 DecreaseFrameSize(adjust);
1488
1489 // Pop callee saves and PC
1490 PopList(pop_list);
Ian Rogers0d666d82011-08-14 16:03:46 -07001491}
1492
Ian Rogers2c8f6532011-09-02 17:16:34 -07001493void ArmAssembler::IncreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001494 AddConstant(SP, -adjust);
1495}
1496
Ian Rogers2c8f6532011-09-02 17:16:34 -07001497void ArmAssembler::DecreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001498 AddConstant(SP, adjust);
1499}
1500
Ian Rogers2c8f6532011-09-02 17:16:34 -07001501void ArmAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
1502 ArmManagedRegister src = msrc.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001503 if (src.IsNoRegister()) {
1504 CHECK_EQ(0u, size);
1505 } else if (src.IsCoreRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001506 CHECK_EQ(4u, size);
1507 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001508 } else if (src.IsRegisterPair()) {
1509 CHECK_EQ(8u, size);
1510 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
1511 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
1512 SP, dest.Int32Value() + 4);
1513 } else if (src.IsSRegister()) {
1514 StoreSToOffset(src.AsSRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001515 } else {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001516 CHECK(src.IsDRegister()) << src;
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001517 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001518 }
1519}
1520
Ian Rogers2c8f6532011-09-02 17:16:34 -07001521void ArmAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
1522 ArmManagedRegister src = msrc.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001523 CHECK(src.IsCoreRegister()) << src;
Ian Rogersb033c752011-07-20 12:22:35 -07001524 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1525}
1526
Ian Rogers2c8f6532011-09-02 17:16:34 -07001527void ArmAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
1528 ArmManagedRegister src = msrc.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001529 CHECK(src.IsCoreRegister()) << src;
Ian Rogersdf20fe02011-07-20 20:34:16 -07001530 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1531}
1532
Ian Rogers2c8f6532011-09-02 17:16:34 -07001533void ArmAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
1534 FrameOffset in_off, ManagedRegister mscratch) {
1535 ArmManagedRegister src = msrc.AsArm();
1536 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers7a99c112011-09-07 12:48:27 -07001537 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1538 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
1539 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
1540}
1541
Ian Rogers2c8f6532011-09-02 17:16:34 -07001542void ArmAssembler::CopyRef(FrameOffset dest, FrameOffset src,
1543 ManagedRegister mscratch) {
1544 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001545 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1546 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1547}
1548
Ian Rogers2c8f6532011-09-02 17:16:34 -07001549void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
1550 MemberOffset offs) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001551 ArmManagedRegister dst = mdest.AsArm();
1552 CHECK(dst.IsCoreRegister() && dst.IsCoreRegister()) << dst;
1553 LoadFromOffset(kLoadWord, dst.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001554 base.AsArm().AsCoreRegister(), offs.Int32Value());
Hiroshi Yamauchie63a7452014-02-27 14:44:36 -08001555 if (kPoisonHeapReferences) {
1556 rsb(dst.AsCoreRegister(), dst.AsCoreRegister(), ShifterOperand(0));
1557 }
Ian Rogersb033c752011-07-20 12:22:35 -07001558}
1559
Ian Rogers2c8f6532011-09-02 17:16:34 -07001560void ArmAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001561 ArmManagedRegister dst = mdest.AsArm();
1562 CHECK(dst.IsCoreRegister()) << dst;
1563 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), SP, src.Int32Value());
Elliott Hughes362f9bc2011-10-17 18:56:41 -07001564}
Ian Rogers2c8f6532011-09-02 17:16:34 -07001565
1566void ArmAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
Ian Rogersa04d3972011-08-17 11:33:44 -07001567 Offset offs) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001568 ArmManagedRegister dst = mdest.AsArm();
1569 CHECK(dst.IsCoreRegister() && dst.IsCoreRegister()) << dst;
1570 LoadFromOffset(kLoadWord, dst.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001571 base.AsArm().AsCoreRegister(), offs.Int32Value());
Ian Rogersa04d3972011-08-17 11:33:44 -07001572}
1573
Ian Rogers2c8f6532011-09-02 17:16:34 -07001574void ArmAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1575 ManagedRegister mscratch) {
1576 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001577 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001578 LoadImmediate(scratch.AsCoreRegister(), imm);
1579 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1580}
1581
Ian Rogersdd7624d2014-03-14 17:43:00 -07001582void ArmAssembler::StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm,
Ian Rogers2c8f6532011-09-02 17:16:34 -07001583 ManagedRegister mscratch) {
1584 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001585 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001586 LoadImmediate(scratch.AsCoreRegister(), imm);
1587 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), TR, dest.Int32Value());
1588}
1589
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001590static void EmitLoad(ArmAssembler* assembler, ManagedRegister m_dst,
1591 Register src_register, int32_t src_offset, size_t size) {
1592 ArmManagedRegister dst = m_dst.AsArm();
1593 if (dst.IsNoRegister()) {
1594 CHECK_EQ(0u, size) << dst;
1595 } else if (dst.IsCoreRegister()) {
1596 CHECK_EQ(4u, size) << dst;
1597 assembler->LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
1598 } else if (dst.IsRegisterPair()) {
1599 CHECK_EQ(8u, size) << dst;
1600 assembler->LoadFromOffset(kLoadWord, dst.AsRegisterPairLow(), src_register, src_offset);
1601 assembler->LoadFromOffset(kLoadWord, dst.AsRegisterPairHigh(), src_register, src_offset + 4);
1602 } else if (dst.IsSRegister()) {
1603 assembler->LoadSFromOffset(dst.AsSRegister(), src_register, src_offset);
Ian Rogersb033c752011-07-20 12:22:35 -07001604 } else {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001605 CHECK(dst.IsDRegister()) << dst;
1606 assembler->LoadDFromOffset(dst.AsDRegister(), src_register, src_offset);
Ian Rogersb033c752011-07-20 12:22:35 -07001607 }
1608}
1609
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001610void ArmAssembler::Load(ManagedRegister m_dst, FrameOffset src, size_t size) {
1611 return EmitLoad(this, m_dst, SP, src.Int32Value(), size);
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001612}
1613
Ian Rogersdd7624d2014-03-14 17:43:00 -07001614void ArmAssembler::LoadFromThread32(ManagedRegister m_dst, ThreadOffset<4> src, size_t size) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001615 return EmitLoad(this, m_dst, TR, src.Int32Value(), size);
1616}
1617
Ian Rogersdd7624d2014-03-14 17:43:00 -07001618void ArmAssembler::LoadRawPtrFromThread32(ManagedRegister m_dst, ThreadOffset<4> offs) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001619 ArmManagedRegister dst = m_dst.AsArm();
1620 CHECK(dst.IsCoreRegister()) << dst;
1621 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), TR, offs.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001622}
1623
Ian Rogersdd7624d2014-03-14 17:43:00 -07001624void ArmAssembler::CopyRawPtrFromThread32(FrameOffset fr_offs,
1625 ThreadOffset<4> thr_offs,
Ian Rogers2c8f6532011-09-02 17:16:34 -07001626 ManagedRegister mscratch) {
1627 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001628 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001629 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1630 TR, thr_offs.Int32Value());
1631 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1632 SP, fr_offs.Int32Value());
1633}
1634
Ian Rogersdd7624d2014-03-14 17:43:00 -07001635void ArmAssembler::CopyRawPtrToThread32(ThreadOffset<4> thr_offs,
Ian Rogers2c8f6532011-09-02 17:16:34 -07001636 FrameOffset fr_offs,
1637 ManagedRegister mscratch) {
1638 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001639 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001640 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1641 SP, fr_offs.Int32Value());
1642 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1643 TR, thr_offs.Int32Value());
1644}
1645
Ian Rogersdd7624d2014-03-14 17:43:00 -07001646void ArmAssembler::StoreStackOffsetToThread32(ThreadOffset<4> thr_offs,
Ian Rogers2c8f6532011-09-02 17:16:34 -07001647 FrameOffset fr_offs,
1648 ManagedRegister mscratch) {
1649 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001650 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001651 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value(), AL);
1652 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1653 TR, thr_offs.Int32Value());
1654}
1655
Ian Rogersdd7624d2014-03-14 17:43:00 -07001656void ArmAssembler::StoreStackPointerToThread32(ThreadOffset<4> thr_offs) {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001657 StoreToOffset(kStoreWord, SP, TR, thr_offs.Int32Value());
1658}
1659
jeffhao58136ca2012-05-24 13:40:11 -07001660void ArmAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
1661 UNIMPLEMENTED(FATAL) << "no sign extension necessary for arm";
1662}
1663
jeffhaocee4d0c2012-06-15 14:42:01 -07001664void ArmAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
1665 UNIMPLEMENTED(FATAL) << "no zero extension necessary for arm";
1666}
1667
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001668void ArmAssembler::Move(ManagedRegister m_dst, ManagedRegister m_src, size_t /*size*/) {
1669 ArmManagedRegister dst = m_dst.AsArm();
1670 ArmManagedRegister src = m_src.AsArm();
1671 if (!dst.Equals(src)) {
1672 if (dst.IsCoreRegister()) {
1673 CHECK(src.IsCoreRegister()) << src;
1674 mov(dst.AsCoreRegister(), ShifterOperand(src.AsCoreRegister()));
1675 } else if (dst.IsDRegister()) {
1676 CHECK(src.IsDRegister()) << src;
1677 vmovd(dst.AsDRegister(), src.AsDRegister());
1678 } else if (dst.IsSRegister()) {
1679 CHECK(src.IsSRegister()) << src;
1680 vmovs(dst.AsSRegister(), src.AsSRegister());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001681 } else {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001682 CHECK(dst.IsRegisterPair()) << dst;
1683 CHECK(src.IsRegisterPair()) << src;
Ian Rogers7a99c112011-09-07 12:48:27 -07001684 // Ensure that the first move doesn't clobber the input of the second
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001685 if (src.AsRegisterPairHigh() != dst.AsRegisterPairLow()) {
1686 mov(dst.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
1687 mov(dst.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
Ian Rogers7a99c112011-09-07 12:48:27 -07001688 } else {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001689 mov(dst.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
1690 mov(dst.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
Ian Rogers7a99c112011-09-07 12:48:27 -07001691 }
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001692 }
Ian Rogersb033c752011-07-20 12:22:35 -07001693 }
1694}
1695
Ian Rogersdc51b792011-09-22 20:41:37 -07001696void ArmAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001697 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001698 CHECK(scratch.IsCoreRegister()) << scratch;
1699 CHECK(size == 4 || size == 8) << size;
Ian Rogersb033c752011-07-20 12:22:35 -07001700 if (size == 4) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001701 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1702 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
Shih-wei Liao5381cf92011-07-27 00:28:04 -07001703 } else if (size == 8) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001704 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1705 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1706 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4);
1707 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
Ian Rogersb033c752011-07-20 12:22:35 -07001708 }
1709}
1710
Ian Rogersdc51b792011-09-22 20:41:37 -07001711void ArmAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
1712 ManagedRegister mscratch, size_t size) {
1713 Register scratch = mscratch.AsArm().AsCoreRegister();
1714 CHECK_EQ(size, 4u);
1715 LoadFromOffset(kLoadWord, scratch, src_base.AsArm().AsCoreRegister(), src_offset.Int32Value());
1716 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
1717}
1718
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001719void ArmAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
1720 ManagedRegister mscratch, size_t size) {
1721 Register scratch = mscratch.AsArm().AsCoreRegister();
1722 CHECK_EQ(size, 4u);
1723 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
1724 StoreToOffset(kStoreWord, scratch, dest_base.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1725}
1726
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001727void ArmAssembler::Copy(FrameOffset /*dst*/, FrameOffset /*src_base*/, Offset /*src_offset*/,
1728 ManagedRegister /*mscratch*/, size_t /*size*/) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001729 UNIMPLEMENTED(FATAL);
1730}
1731
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001732void ArmAssembler::Copy(ManagedRegister dest, Offset dest_offset,
1733 ManagedRegister src, Offset src_offset,
1734 ManagedRegister mscratch, size_t size) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001735 CHECK_EQ(size, 4u);
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001736 Register scratch = mscratch.AsArm().AsCoreRegister();
1737 LoadFromOffset(kLoadWord, scratch, src.AsArm().AsCoreRegister(), src_offset.Int32Value());
1738 StoreToOffset(kStoreWord, scratch, dest.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1739}
1740
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001741void ArmAssembler::Copy(FrameOffset /*dst*/, Offset /*dest_offset*/, FrameOffset /*src*/, Offset /*src_offset*/,
1742 ManagedRegister /*scratch*/, size_t /*size*/) {
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001743 UNIMPLEMENTED(FATAL);
Ian Rogersdc51b792011-09-22 20:41:37 -07001744}
1745
1746
Ian Rogerse5de95b2011-09-18 20:31:38 -07001747void ArmAssembler::MemoryBarrier(ManagedRegister mscratch) {
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001748 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001749#if ANDROID_SMP != 0
Ian Rogerse5de95b2011-09-18 20:31:38 -07001750 int32_t encoding = 0xf57ff05f; // dmb
1751 Emit(encoding);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001752#endif
1753}
1754
Ian Rogers2c8f6532011-09-02 17:16:34 -07001755void ArmAssembler::CreateSirtEntry(ManagedRegister mout_reg,
1756 FrameOffset sirt_offset,
1757 ManagedRegister min_reg, bool null_allowed) {
1758 ArmManagedRegister out_reg = mout_reg.AsArm();
1759 ArmManagedRegister in_reg = min_reg.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001760 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
1761 CHECK(out_reg.IsCoreRegister()) << out_reg;
Ian Rogersb033c752011-07-20 12:22:35 -07001762 if (null_allowed) {
Ian Rogers408f79a2011-08-23 18:22:33 -07001763 // Null values get a SIRT entry value of 0. Otherwise, the SIRT entry is
1764 // the address in the SIRT holding the reference.
Ian Rogersb033c752011-07-20 12:22:35 -07001765 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001766 if (in_reg.IsNoRegister()) {
1767 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
Ian Rogers408f79a2011-08-23 18:22:33 -07001768 SP, sirt_offset.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001769 in_reg = out_reg;
1770 }
Ian Rogersb033c752011-07-20 12:22:35 -07001771 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
1772 if (!out_reg.Equals(in_reg)) {
1773 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1774 }
Ian Rogers408f79a2011-08-23 18:22:33 -07001775 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001776 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001777 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001778 }
1779}
1780
Ian Rogers2c8f6532011-09-02 17:16:34 -07001781void ArmAssembler::CreateSirtEntry(FrameOffset out_off,
1782 FrameOffset sirt_offset,
1783 ManagedRegister mscratch,
1784 bool null_allowed) {
1785 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001786 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001787 if (null_allowed) {
1788 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
Ian Rogers408f79a2011-08-23 18:22:33 -07001789 sirt_offset.Int32Value());
1790 // Null values get a SIRT entry value of 0. Otherwise, the sirt entry is
1791 // the address in the SIRT holding the reference.
1792 // e.g. scratch = (scratch == 0) ? 0 : (SP+sirt_offset)
Ian Rogersb033c752011-07-20 12:22:35 -07001793 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
Ian Rogers408f79a2011-08-23 18:22:33 -07001794 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001795 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001796 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001797 }
1798 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
1799}
1800
Ian Rogers2c8f6532011-09-02 17:16:34 -07001801void ArmAssembler::LoadReferenceFromSirt(ManagedRegister mout_reg,
1802 ManagedRegister min_reg) {
1803 ArmManagedRegister out_reg = mout_reg.AsArm();
1804 ArmManagedRegister in_reg = min_reg.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001805 CHECK(out_reg.IsCoreRegister()) << out_reg;
1806 CHECK(in_reg.IsCoreRegister()) << in_reg;
Ian Rogersb033c752011-07-20 12:22:35 -07001807 Label null_arg;
1808 if (!out_reg.Equals(in_reg)) {
1809 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1810 }
1811 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
Ian Rogersdf20fe02011-07-20 20:34:16 -07001812 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
1813 in_reg.AsCoreRegister(), 0, NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001814}
1815
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001816void ArmAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
Ian Rogersb033c752011-07-20 12:22:35 -07001817 // TODO: not validating references
1818}
1819
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001820void ArmAssembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) {
Ian Rogersb033c752011-07-20 12:22:35 -07001821 // TODO: not validating references
1822}
1823
Ian Rogers2c8f6532011-09-02 17:16:34 -07001824void ArmAssembler::Call(ManagedRegister mbase, Offset offset,
1825 ManagedRegister mscratch) {
1826 ArmManagedRegister base = mbase.AsArm();
1827 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001828 CHECK(base.IsCoreRegister()) << base;
1829 CHECK(scratch.IsCoreRegister()) << scratch;
Ian Rogersb033c752011-07-20 12:22:35 -07001830 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1831 base.AsCoreRegister(), offset.Int32Value());
1832 blx(scratch.AsCoreRegister());
1833 // TODO: place reference map on call
1834}
1835
Ian Rogers2c8f6532011-09-02 17:16:34 -07001836void ArmAssembler::Call(FrameOffset base, Offset offset,
1837 ManagedRegister mscratch) {
1838 ArmManagedRegister scratch = mscratch.AsArm();
Elliott Hughesbf2739d2012-05-21 14:30:16 -07001839 CHECK(scratch.IsCoreRegister()) << scratch;
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001840 // Call *(*(SP + base) + offset)
1841 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1842 SP, base.Int32Value());
1843 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1844 scratch.AsCoreRegister(), offset.Int32Value());
1845 blx(scratch.AsCoreRegister());
1846 // TODO: place reference map on call
1847}
1848
Ian Rogersdd7624d2014-03-14 17:43:00 -07001849void ArmAssembler::CallFromThread32(ThreadOffset<4> /*offset*/, ManagedRegister /*scratch*/) {
Ian Rogersbdb03912011-09-14 00:55:44 -07001850 UNIMPLEMENTED(FATAL);
1851}
1852
Ian Rogers2c8f6532011-09-02 17:16:34 -07001853void ArmAssembler::GetCurrentThread(ManagedRegister tr) {
1854 mov(tr.AsArm().AsCoreRegister(), ShifterOperand(TR));
Shih-wei Liao668512a2011-09-01 14:18:34 -07001855}
1856
Ian Rogers2c8f6532011-09-02 17:16:34 -07001857void ArmAssembler::GetCurrentThread(FrameOffset offset,
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001858 ManagedRegister /*scratch*/) {
Shih-wei Liao668512a2011-09-01 14:18:34 -07001859 StoreToOffset(kStoreWord, TR, SP, offset.Int32Value(), AL);
1860}
1861
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001862void ArmAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001863 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001864 ArmExceptionSlowPath* slow = new ArmExceptionSlowPath(scratch, stack_adjust);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001865 buffer_.EnqueueSlowPath(slow);
1866 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
Ian Rogersdd7624d2014-03-14 17:43:00 -07001867 TR, Thread::ExceptionOffset<4>().Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001868 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1869 b(slow->Entry(), NE);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001870}
1871
Ian Rogers2c8f6532011-09-02 17:16:34 -07001872void ArmExceptionSlowPath::Emit(Assembler* sasm) {
1873 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm);
1874#define __ sp_asm->
1875 __ Bind(&entry_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001876 if (stack_adjust_ != 0) { // Fix up the frame.
1877 __ DecreaseFrameSize(stack_adjust_);
1878 }
Ian Rogers67375ac2011-09-14 00:55:44 -07001879 // Pass exception object as argument
1880 // Don't care about preserving R0 as this call won't return
1881 __ mov(R0, ShifterOperand(scratch_.AsCoreRegister()));
1882 // Set up call to Thread::Current()->pDeliverException
Ian Rogersdd7624d2014-03-14 17:43:00 -07001883 __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(4, pDeliverException).Int32Value());
Ian Rogers2c8f6532011-09-02 17:16:34 -07001884 __ blx(R12);
Ian Rogers67375ac2011-09-14 00:55:44 -07001885 // Call never returns
1886 __ bkpt(0);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001887#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001888}
1889
Ian Rogers2c8f6532011-09-02 17:16:34 -07001890} // namespace arm
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07001891} // namespace art