blob: e25e65680aa1ddcbb05f90bb8db35deaea7f641e [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
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070019#include "logging.h"
20#include "offsets.h"
Carl Shapiroe2d373e2011-07-25 15:20:06 -070021#include "thread.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070022#include "utils.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070023
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070024namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070025namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070026
Carl Shapiroa2e18e12011-06-21 18:57:55 -070027// Instruction encoding bits.
28enum {
29 H = 1 << 5, // halfword (or byte)
30 L = 1 << 20, // load (or store)
31 S = 1 << 20, // set condition code (or leave unchanged)
32 W = 1 << 21, // writeback base register (or leave unchanged)
33 A = 1 << 21, // accumulate in multiply instruction (or not)
34 B = 1 << 22, // unsigned byte (or word)
35 N = 1 << 22, // long (or short)
36 U = 1 << 23, // positive (or negative) offset/index
37 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
38 I = 1 << 25, // immediate shifter operand (or not)
39
40 B0 = 1,
41 B1 = 1 << 1,
42 B2 = 1 << 2,
43 B3 = 1 << 3,
44 B4 = 1 << 4,
45 B5 = 1 << 5,
46 B6 = 1 << 6,
47 B7 = 1 << 7,
48 B8 = 1 << 8,
49 B9 = 1 << 9,
50 B10 = 1 << 10,
51 B11 = 1 << 11,
52 B12 = 1 << 12,
53 B16 = 1 << 16,
54 B17 = 1 << 17,
55 B18 = 1 << 18,
56 B19 = 1 << 19,
57 B20 = 1 << 20,
58 B21 = 1 << 21,
59 B22 = 1 << 22,
60 B23 = 1 << 23,
61 B24 = 1 << 24,
62 B25 = 1 << 25,
63 B26 = 1 << 26,
64 B27 = 1 << 27,
65
66 // Instruction bit masks.
67 RdMask = 15 << 12, // in str instruction
68 CondMask = 15 << 28,
69 CoprocessorMask = 15 << 8,
70 OpCodeMask = 15 << 21, // in data-processing instructions
71 Imm24Mask = (1 << 24) - 1,
72 Off12Mask = (1 << 12) - 1,
73
74 // ldrex/strex register field encodings.
75 kLdExRnShift = 16,
76 kLdExRtShift = 12,
77 kStrExRnShift = 16,
78 kStrExRdShift = 12,
79 kStrExRtShift = 0,
80};
81
82
Elliott Hughes1f359b02011-07-17 14:27:17 -070083static const char* kRegisterNames[] = {
84 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
85 "fp", "ip", "sp", "lr", "pc"
86};
87std::ostream& operator<<(std::ostream& os, const Register& rhs) {
88 if (rhs >= R0 && rhs <= PC) {
89 os << kRegisterNames[rhs];
90 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070091 os << "Register[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070092 }
93 return os;
94}
95
96
97std::ostream& operator<<(std::ostream& os, const SRegister& rhs) {
98 if (rhs >= S0 && rhs < kNumberOfSRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -070099 os << "s" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700100 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700101 os << "SRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700102 }
103 return os;
104}
105
106
107std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
108 if (rhs >= D0 && rhs < kNumberOfDRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -0700109 os << "d" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700110 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700111 os << "DRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700112 }
113 return os;
114}
115
116
117static const char* kConditionNames[] = {
Ian Rogersb033c752011-07-20 12:22:35 -0700118 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT",
119 "LE", "AL",
Elliott Hughes1f359b02011-07-17 14:27:17 -0700120};
121std::ostream& operator<<(std::ostream& os, const Condition& rhs) {
122 if (rhs >= EQ && rhs <= AL) {
123 os << kConditionNames[rhs];
124 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700125 os << "Condition[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700126 }
127 return os;
128}
129
Ian Rogers2c8f6532011-09-02 17:16:34 -0700130void ArmAssembler::Emit(int32_t value) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700131 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
132 buffer_.Emit<int32_t>(value);
133}
134
135
Ian Rogers2c8f6532011-09-02 17:16:34 -0700136void ArmAssembler::EmitType01(Condition cond,
137 int type,
138 Opcode opcode,
139 int set_cc,
140 Register rn,
141 Register rd,
142 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700143 CHECK_NE(rd, kNoRegister);
144 CHECK_NE(cond, kNoCondition);
145 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
146 type << kTypeShift |
147 static_cast<int32_t>(opcode) << kOpcodeShift |
148 set_cc << kSShift |
149 static_cast<int32_t>(rn) << kRnShift |
150 static_cast<int32_t>(rd) << kRdShift |
151 so.encoding();
152 Emit(encoding);
153}
154
155
Ian Rogers2c8f6532011-09-02 17:16:34 -0700156void ArmAssembler::EmitType5(Condition cond, int offset, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700157 CHECK_NE(cond, kNoCondition);
158 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
159 5 << kTypeShift |
160 (link ? 1 : 0) << kLinkShift;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700161 Emit(ArmAssembler::EncodeBranchOffset(offset, encoding));
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700162}
163
164
Ian Rogers2c8f6532011-09-02 17:16:34 -0700165void ArmAssembler::EmitMemOp(Condition cond,
166 bool load,
167 bool byte,
168 Register rd,
169 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700170 CHECK_NE(rd, kNoRegister);
171 CHECK_NE(cond, kNoCondition);
172 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
173 B26 |
174 (load ? L : 0) |
175 (byte ? B : 0) |
176 (static_cast<int32_t>(rd) << kRdShift) |
177 ad.encoding();
178 Emit(encoding);
179}
180
181
Ian Rogers2c8f6532011-09-02 17:16:34 -0700182void ArmAssembler::EmitMemOpAddressMode3(Condition cond,
183 int32_t mode,
184 Register rd,
185 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700186 CHECK_NE(rd, kNoRegister);
187 CHECK_NE(cond, kNoCondition);
188 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
189 B22 |
190 mode |
191 (static_cast<int32_t>(rd) << kRdShift) |
192 ad.encoding3();
193 Emit(encoding);
194}
195
196
Ian Rogers2c8f6532011-09-02 17:16:34 -0700197void ArmAssembler::EmitMultiMemOp(Condition cond,
198 BlockAddressMode am,
199 bool load,
200 Register base,
201 RegList regs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700202 CHECK_NE(base, kNoRegister);
203 CHECK_NE(cond, kNoCondition);
204 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
205 B27 |
206 am |
207 (load ? L : 0) |
208 (static_cast<int32_t>(base) << kRnShift) |
209 regs;
210 Emit(encoding);
211}
212
213
Ian Rogers2c8f6532011-09-02 17:16:34 -0700214void ArmAssembler::EmitShiftImmediate(Condition cond,
215 Shift opcode,
216 Register rd,
217 Register rm,
218 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700219 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700220 CHECK_EQ(so.type(), 1U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700221 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
222 static_cast<int32_t>(MOV) << kOpcodeShift |
223 static_cast<int32_t>(rd) << kRdShift |
224 so.encoding() << kShiftImmShift |
225 static_cast<int32_t>(opcode) << kShiftShift |
226 static_cast<int32_t>(rm);
227 Emit(encoding);
228}
229
230
Ian Rogers2c8f6532011-09-02 17:16:34 -0700231void ArmAssembler::EmitShiftRegister(Condition cond,
232 Shift opcode,
233 Register rd,
234 Register rm,
235 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700236 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700237 CHECK_EQ(so.type(), 0U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700238 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
239 static_cast<int32_t>(MOV) << kOpcodeShift |
240 static_cast<int32_t>(rd) << kRdShift |
241 so.encoding() << kShiftRegisterShift |
242 static_cast<int32_t>(opcode) << kShiftShift |
243 B4 |
244 static_cast<int32_t>(rm);
245 Emit(encoding);
246}
247
248
Ian Rogers2c8f6532011-09-02 17:16:34 -0700249void ArmAssembler::EmitBranch(Condition cond, Label* label, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700250 if (label->IsBound()) {
251 EmitType5(cond, label->Position() - buffer_.Size(), link);
252 } else {
253 int position = buffer_.Size();
254 // Use the offset field of the branch instruction for linking the sites.
255 EmitType5(cond, label->position_, link);
256 label->LinkTo(position);
257 }
258}
259
Ian Rogers2c8f6532011-09-02 17:16:34 -0700260void ArmAssembler::and_(Register rd, Register rn, ShifterOperand so,
261 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700262 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
263}
264
265
Ian Rogers2c8f6532011-09-02 17:16:34 -0700266void ArmAssembler::eor(Register rd, Register rn, ShifterOperand so,
267 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700268 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
269}
270
271
Ian Rogers2c8f6532011-09-02 17:16:34 -0700272void ArmAssembler::sub(Register rd, Register rn, ShifterOperand so,
273 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700274 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
275}
276
Ian Rogers2c8f6532011-09-02 17:16:34 -0700277void ArmAssembler::rsb(Register rd, Register rn, ShifterOperand so,
278 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700279 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
280}
281
Ian Rogers2c8f6532011-09-02 17:16:34 -0700282void ArmAssembler::rsbs(Register rd, Register rn, ShifterOperand so,
283 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700284 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
285}
286
287
Ian Rogers2c8f6532011-09-02 17:16:34 -0700288void ArmAssembler::add(Register rd, Register rn, ShifterOperand so,
289 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700290 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
291}
292
293
Ian Rogers2c8f6532011-09-02 17:16:34 -0700294void ArmAssembler::adds(Register rd, Register rn, ShifterOperand so,
295 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700296 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
297}
298
299
Ian Rogers2c8f6532011-09-02 17:16:34 -0700300void ArmAssembler::subs(Register rd, Register rn, ShifterOperand so,
301 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700302 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
303}
304
305
Ian Rogers2c8f6532011-09-02 17:16:34 -0700306void ArmAssembler::adc(Register rd, Register rn, ShifterOperand so,
307 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700308 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
309}
310
311
Ian Rogers2c8f6532011-09-02 17:16:34 -0700312void ArmAssembler::sbc(Register rd, Register rn, ShifterOperand so,
313 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700314 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
315}
316
317
Ian Rogers2c8f6532011-09-02 17:16:34 -0700318void ArmAssembler::rsc(Register rd, Register rn, ShifterOperand so,
319 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700320 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
321}
322
323
Ian Rogers2c8f6532011-09-02 17:16:34 -0700324void ArmAssembler::tst(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700325 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
326 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
327}
328
329
Ian Rogers2c8f6532011-09-02 17:16:34 -0700330void ArmAssembler::teq(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700331 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
332 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
333}
334
335
Ian Rogers2c8f6532011-09-02 17:16:34 -0700336void ArmAssembler::cmp(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700337 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
338}
339
340
Ian Rogers2c8f6532011-09-02 17:16:34 -0700341void ArmAssembler::cmn(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700342 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
343}
344
345
Ian Rogers2c8f6532011-09-02 17:16:34 -0700346void ArmAssembler::orr(Register rd, Register rn,
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700347 ShifterOperand so, Condition cond) {
348 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
349}
350
351
Ian Rogers2c8f6532011-09-02 17:16:34 -0700352void ArmAssembler::orrs(Register rd, Register rn,
353 ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700354 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
355}
356
357
Ian Rogers2c8f6532011-09-02 17:16:34 -0700358void ArmAssembler::mov(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700359 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
360}
361
362
Ian Rogers2c8f6532011-09-02 17:16:34 -0700363void ArmAssembler::movs(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700364 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
365}
366
367
Ian Rogers2c8f6532011-09-02 17:16:34 -0700368void ArmAssembler::bic(Register rd, Register rn, ShifterOperand so,
369 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700370 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
371}
372
373
Ian Rogers2c8f6532011-09-02 17:16:34 -0700374void ArmAssembler::mvn(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700375 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
376}
377
378
Ian Rogers2c8f6532011-09-02 17:16:34 -0700379void ArmAssembler::mvns(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700380 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
381}
382
383
Ian Rogers2c8f6532011-09-02 17:16:34 -0700384void ArmAssembler::clz(Register rd, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700385 CHECK_NE(rd, kNoRegister);
386 CHECK_NE(rm, kNoRegister);
387 CHECK_NE(cond, kNoCondition);
388 CHECK_NE(rd, PC);
389 CHECK_NE(rm, PC);
390 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
391 B24 | B22 | B21 | (0xf << 16) |
392 (static_cast<int32_t>(rd) << kRdShift) |
393 (0xf << 8) | B4 | static_cast<int32_t>(rm);
394 Emit(encoding);
395}
396
397
Ian Rogers2c8f6532011-09-02 17:16:34 -0700398void ArmAssembler::movw(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700399 CHECK_NE(cond, kNoCondition);
400 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
401 B25 | B24 | ((imm16 >> 12) << 16) |
402 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
403 Emit(encoding);
404}
405
406
Ian Rogers2c8f6532011-09-02 17:16:34 -0700407void ArmAssembler::movt(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700408 CHECK_NE(cond, kNoCondition);
409 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
410 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
411 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
412 Emit(encoding);
413}
414
415
Ian Rogers2c8f6532011-09-02 17:16:34 -0700416void ArmAssembler::EmitMulOp(Condition cond, int32_t opcode,
417 Register rd, Register rn,
418 Register rm, Register rs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700419 CHECK_NE(rd, kNoRegister);
420 CHECK_NE(rn, kNoRegister);
421 CHECK_NE(rm, kNoRegister);
422 CHECK_NE(rs, kNoRegister);
423 CHECK_NE(cond, kNoCondition);
424 int32_t encoding = opcode |
425 (static_cast<int32_t>(cond) << kConditionShift) |
426 (static_cast<int32_t>(rn) << kRnShift) |
427 (static_cast<int32_t>(rd) << kRdShift) |
428 (static_cast<int32_t>(rs) << kRsShift) |
429 B7 | B4 |
430 (static_cast<int32_t>(rm) << kRmShift);
431 Emit(encoding);
432}
433
434
Ian Rogers2c8f6532011-09-02 17:16:34 -0700435void ArmAssembler::mul(Register rd, Register rn, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700436 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
437 EmitMulOp(cond, 0, R0, rd, rn, rm);
438}
439
440
Ian Rogers2c8f6532011-09-02 17:16:34 -0700441void ArmAssembler::mla(Register rd, Register rn, Register rm, Register ra,
442 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700443 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
444 EmitMulOp(cond, B21, ra, rd, rn, rm);
445}
446
447
Ian Rogers2c8f6532011-09-02 17:16:34 -0700448void ArmAssembler::mls(Register rd, Register rn, Register rm, Register ra,
449 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700450 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
451 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
452}
453
454
Ian Rogers2c8f6532011-09-02 17:16:34 -0700455void ArmAssembler::umull(Register rd_lo, Register rd_hi, Register rn,
456 Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700457 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
458 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
459}
460
461
Ian Rogers2c8f6532011-09-02 17:16:34 -0700462void ArmAssembler::ldr(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700463 EmitMemOp(cond, true, false, rd, ad);
464}
465
466
Ian Rogers2c8f6532011-09-02 17:16:34 -0700467void ArmAssembler::str(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700468 EmitMemOp(cond, false, false, rd, ad);
469}
470
471
Ian Rogers2c8f6532011-09-02 17:16:34 -0700472void ArmAssembler::ldrb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700473 EmitMemOp(cond, true, true, rd, ad);
474}
475
476
Ian Rogers2c8f6532011-09-02 17:16:34 -0700477void ArmAssembler::strb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700478 EmitMemOp(cond, false, true, rd, ad);
479}
480
481
Ian Rogers2c8f6532011-09-02 17:16:34 -0700482void ArmAssembler::ldrh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700483 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
484}
485
486
Ian Rogers2c8f6532011-09-02 17:16:34 -0700487void ArmAssembler::strh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700488 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
489}
490
491
Ian Rogers2c8f6532011-09-02 17:16:34 -0700492void ArmAssembler::ldrsb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700493 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
494}
495
496
Ian Rogers2c8f6532011-09-02 17:16:34 -0700497void ArmAssembler::ldrsh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700498 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
499}
500
501
Ian Rogers2c8f6532011-09-02 17:16:34 -0700502void ArmAssembler::ldrd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700503 CHECK_EQ(rd % 2, 0);
504 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
505}
506
507
Ian Rogers2c8f6532011-09-02 17:16:34 -0700508void ArmAssembler::strd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700509 CHECK_EQ(rd % 2, 0);
510 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
511}
512
513
Ian Rogers2c8f6532011-09-02 17:16:34 -0700514void ArmAssembler::ldm(BlockAddressMode am,
515 Register base,
516 RegList regs,
517 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700518 EmitMultiMemOp(cond, am, true, base, regs);
519}
520
521
Ian Rogers2c8f6532011-09-02 17:16:34 -0700522void ArmAssembler::stm(BlockAddressMode am,
523 Register base,
524 RegList regs,
525 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700526 EmitMultiMemOp(cond, am, false, base, regs);
527}
528
529
Ian Rogers2c8f6532011-09-02 17:16:34 -0700530void ArmAssembler::ldrex(Register rt, Register rn, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700531 CHECK_NE(rn, kNoRegister);
532 CHECK_NE(rt, kNoRegister);
533 CHECK_NE(cond, kNoCondition);
534 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
535 B24 |
536 B23 |
537 L |
538 (static_cast<int32_t>(rn) << kLdExRnShift) |
539 (static_cast<int32_t>(rt) << kLdExRtShift) |
540 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
541 Emit(encoding);
542}
543
544
Ian Rogers2c8f6532011-09-02 17:16:34 -0700545void ArmAssembler::strex(Register rd,
546 Register rt,
547 Register rn,
548 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700549 CHECK_NE(rn, kNoRegister);
550 CHECK_NE(rd, kNoRegister);
551 CHECK_NE(rt, kNoRegister);
552 CHECK_NE(cond, kNoCondition);
553 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
554 B24 |
555 B23 |
556 (static_cast<int32_t>(rn) << kStrExRnShift) |
557 (static_cast<int32_t>(rd) << kStrExRdShift) |
558 B11 | B10 | B9 | B8 | B7 | B4 |
559 (static_cast<int32_t>(rt) << kStrExRtShift);
560 Emit(encoding);
561}
562
563
Ian Rogers2c8f6532011-09-02 17:16:34 -0700564void ArmAssembler::clrex() {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700565 int32_t encoding = (kSpecialCondition << kConditionShift) |
566 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
567 Emit(encoding);
568}
569
570
Ian Rogers2c8f6532011-09-02 17:16:34 -0700571void ArmAssembler::nop(Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700572 CHECK_NE(cond, kNoCondition);
573 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
574 B25 | B24 | B21 | (0xf << 12);
575 Emit(encoding);
576}
577
578
Ian Rogers2c8f6532011-09-02 17:16:34 -0700579void ArmAssembler::vmovsr(SRegister sn, Register rt, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700580 CHECK_NE(sn, kNoSRegister);
581 CHECK_NE(rt, kNoRegister);
582 CHECK_NE(rt, SP);
583 CHECK_NE(rt, PC);
584 CHECK_NE(cond, kNoCondition);
585 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
586 B27 | B26 | B25 |
587 ((static_cast<int32_t>(sn) >> 1)*B16) |
588 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
589 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
590 Emit(encoding);
591}
592
593
Ian Rogers2c8f6532011-09-02 17:16:34 -0700594void ArmAssembler::vmovrs(Register rt, SRegister sn, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700595 CHECK_NE(sn, kNoSRegister);
596 CHECK_NE(rt, kNoRegister);
597 CHECK_NE(rt, SP);
598 CHECK_NE(rt, PC);
599 CHECK_NE(cond, kNoCondition);
600 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
601 B27 | B26 | B25 | B20 |
602 ((static_cast<int32_t>(sn) >> 1)*B16) |
603 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
604 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
605 Emit(encoding);
606}
607
608
Ian Rogers2c8f6532011-09-02 17:16:34 -0700609void ArmAssembler::vmovsrr(SRegister sm, Register rt, Register rt2,
610 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700611 CHECK_NE(sm, kNoSRegister);
612 CHECK_NE(sm, S31);
613 CHECK_NE(rt, kNoRegister);
614 CHECK_NE(rt, SP);
615 CHECK_NE(rt, PC);
616 CHECK_NE(rt2, kNoRegister);
617 CHECK_NE(rt2, SP);
618 CHECK_NE(rt2, PC);
619 CHECK_NE(cond, kNoCondition);
620 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
621 B27 | B26 | B22 |
622 (static_cast<int32_t>(rt2)*B16) |
623 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
624 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
625 (static_cast<int32_t>(sm) >> 1);
626 Emit(encoding);
627}
628
629
Ian Rogers2c8f6532011-09-02 17:16:34 -0700630void ArmAssembler::vmovrrs(Register rt, Register rt2, SRegister sm,
631 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700632 CHECK_NE(sm, kNoSRegister);
633 CHECK_NE(sm, S31);
634 CHECK_NE(rt, kNoRegister);
635 CHECK_NE(rt, SP);
636 CHECK_NE(rt, PC);
637 CHECK_NE(rt2, kNoRegister);
638 CHECK_NE(rt2, SP);
639 CHECK_NE(rt2, PC);
640 CHECK_NE(rt, rt2);
641 CHECK_NE(cond, kNoCondition);
642 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
643 B27 | B26 | B22 | B20 |
644 (static_cast<int32_t>(rt2)*B16) |
645 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
646 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
647 (static_cast<int32_t>(sm) >> 1);
648 Emit(encoding);
649}
650
651
Ian Rogers2c8f6532011-09-02 17:16:34 -0700652void ArmAssembler::vmovdrr(DRegister dm, Register rt, Register rt2,
653 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700654 CHECK_NE(dm, kNoDRegister);
655 CHECK_NE(rt, kNoRegister);
656 CHECK_NE(rt, SP);
657 CHECK_NE(rt, PC);
658 CHECK_NE(rt2, kNoRegister);
659 CHECK_NE(rt2, SP);
660 CHECK_NE(rt2, PC);
661 CHECK_NE(cond, kNoCondition);
662 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
663 B27 | B26 | B22 |
664 (static_cast<int32_t>(rt2)*B16) |
665 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
666 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
667 (static_cast<int32_t>(dm) & 0xf);
668 Emit(encoding);
669}
670
671
Ian Rogers2c8f6532011-09-02 17:16:34 -0700672void ArmAssembler::vmovrrd(Register rt, Register rt2, DRegister dm,
673 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700674 CHECK_NE(dm, kNoDRegister);
675 CHECK_NE(rt, kNoRegister);
676 CHECK_NE(rt, SP);
677 CHECK_NE(rt, PC);
678 CHECK_NE(rt2, kNoRegister);
679 CHECK_NE(rt2, SP);
680 CHECK_NE(rt2, PC);
681 CHECK_NE(rt, rt2);
682 CHECK_NE(cond, kNoCondition);
683 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
684 B27 | B26 | B22 | B20 |
685 (static_cast<int32_t>(rt2)*B16) |
686 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
687 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
688 (static_cast<int32_t>(dm) & 0xf);
689 Emit(encoding);
690}
691
692
Ian Rogers2c8f6532011-09-02 17:16:34 -0700693void ArmAssembler::vldrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700694 CHECK_NE(sd, kNoSRegister);
695 CHECK_NE(cond, kNoCondition);
696 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
697 B27 | B26 | B24 | B20 |
698 ((static_cast<int32_t>(sd) & 1)*B22) |
699 ((static_cast<int32_t>(sd) >> 1)*B12) |
700 B11 | B9 | ad.vencoding();
701 Emit(encoding);
702}
703
704
Ian Rogers2c8f6532011-09-02 17:16:34 -0700705void ArmAssembler::vstrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700706 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
707 CHECK_NE(sd, kNoSRegister);
708 CHECK_NE(cond, kNoCondition);
709 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
710 B27 | B26 | B24 |
711 ((static_cast<int32_t>(sd) & 1)*B22) |
712 ((static_cast<int32_t>(sd) >> 1)*B12) |
713 B11 | B9 | ad.vencoding();
714 Emit(encoding);
715}
716
717
Ian Rogers2c8f6532011-09-02 17:16:34 -0700718void ArmAssembler::vldrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700719 CHECK_NE(dd, kNoDRegister);
720 CHECK_NE(cond, kNoCondition);
721 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
722 B27 | B26 | B24 | B20 |
723 ((static_cast<int32_t>(dd) >> 4)*B22) |
724 ((static_cast<int32_t>(dd) & 0xf)*B12) |
725 B11 | B9 | B8 | ad.vencoding();
726 Emit(encoding);
727}
728
729
Ian Rogers2c8f6532011-09-02 17:16:34 -0700730void ArmAssembler::vstrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700731 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
732 CHECK_NE(dd, kNoDRegister);
733 CHECK_NE(cond, kNoCondition);
734 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
735 B27 | B26 | B24 |
736 ((static_cast<int32_t>(dd) >> 4)*B22) |
737 ((static_cast<int32_t>(dd) & 0xf)*B12) |
738 B11 | B9 | B8 | ad.vencoding();
739 Emit(encoding);
740}
741
742
Ian Rogers2c8f6532011-09-02 17:16:34 -0700743void ArmAssembler::EmitVFPsss(Condition cond, int32_t opcode,
744 SRegister sd, SRegister sn, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700745 CHECK_NE(sd, kNoSRegister);
746 CHECK_NE(sn, kNoSRegister);
747 CHECK_NE(sm, kNoSRegister);
748 CHECK_NE(cond, kNoCondition);
749 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
750 B27 | B26 | B25 | B11 | B9 | opcode |
751 ((static_cast<int32_t>(sd) & 1)*B22) |
752 ((static_cast<int32_t>(sn) >> 1)*B16) |
753 ((static_cast<int32_t>(sd) >> 1)*B12) |
754 ((static_cast<int32_t>(sn) & 1)*B7) |
755 ((static_cast<int32_t>(sm) & 1)*B5) |
756 (static_cast<int32_t>(sm) >> 1);
757 Emit(encoding);
758}
759
760
Ian Rogers2c8f6532011-09-02 17:16:34 -0700761void ArmAssembler::EmitVFPddd(Condition cond, int32_t opcode,
762 DRegister dd, DRegister dn, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700763 CHECK_NE(dd, kNoDRegister);
764 CHECK_NE(dn, kNoDRegister);
765 CHECK_NE(dm, kNoDRegister);
766 CHECK_NE(cond, kNoCondition);
767 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
768 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
769 ((static_cast<int32_t>(dd) >> 4)*B22) |
770 ((static_cast<int32_t>(dn) & 0xf)*B16) |
771 ((static_cast<int32_t>(dd) & 0xf)*B12) |
772 ((static_cast<int32_t>(dn) >> 4)*B7) |
773 ((static_cast<int32_t>(dm) >> 4)*B5) |
774 (static_cast<int32_t>(dm) & 0xf);
775 Emit(encoding);
776}
777
778
Ian Rogers2c8f6532011-09-02 17:16:34 -0700779void ArmAssembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700780 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
781}
782
783
Ian Rogers2c8f6532011-09-02 17:16:34 -0700784void ArmAssembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700785 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
786}
787
788
Ian Rogers2c8f6532011-09-02 17:16:34 -0700789bool ArmAssembler::vmovs(SRegister sd, float s_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700790 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
791 if (((imm32 & ((1 << 19) - 1)) == 0) &&
792 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
793 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
794 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
795 ((imm32 >> 19) & ((1 << 6) -1));
796 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
797 sd, S0, S0);
798 return true;
799 }
800 return false;
801}
802
803
Ian Rogers2c8f6532011-09-02 17:16:34 -0700804bool ArmAssembler::vmovd(DRegister dd, double d_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700805 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
806 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
807 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
808 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
809 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
810 ((imm64 >> 48) & ((1 << 6) -1));
811 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
812 dd, D0, D0);
813 return true;
814 }
815 return false;
816}
817
818
Ian Rogers2c8f6532011-09-02 17:16:34 -0700819void ArmAssembler::vadds(SRegister sd, SRegister sn, SRegister sm,
820 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700821 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
822}
823
824
Ian Rogers2c8f6532011-09-02 17:16:34 -0700825void ArmAssembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
826 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700827 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
828}
829
830
Ian Rogers2c8f6532011-09-02 17:16:34 -0700831void ArmAssembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
832 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700833 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
834}
835
836
Ian Rogers2c8f6532011-09-02 17:16:34 -0700837void ArmAssembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
838 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700839 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
840}
841
842
Ian Rogers2c8f6532011-09-02 17:16:34 -0700843void ArmAssembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
844 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700845 EmitVFPsss(cond, B21, sd, sn, sm);
846}
847
848
Ian Rogers2c8f6532011-09-02 17:16:34 -0700849void ArmAssembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
850 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700851 EmitVFPddd(cond, B21, dd, dn, dm);
852}
853
854
Ian Rogers2c8f6532011-09-02 17:16:34 -0700855void ArmAssembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
856 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700857 EmitVFPsss(cond, 0, sd, sn, sm);
858}
859
860
Ian Rogers2c8f6532011-09-02 17:16:34 -0700861void ArmAssembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
862 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700863 EmitVFPddd(cond, 0, dd, dn, dm);
864}
865
866
Ian Rogers2c8f6532011-09-02 17:16:34 -0700867void ArmAssembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
868 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700869 EmitVFPsss(cond, B6, sd, sn, sm);
870}
871
872
Ian Rogers2c8f6532011-09-02 17:16:34 -0700873void ArmAssembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
874 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700875 EmitVFPddd(cond, B6, dd, dn, dm);
876}
877
878
Ian Rogers2c8f6532011-09-02 17:16:34 -0700879void ArmAssembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
880 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700881 EmitVFPsss(cond, B23, sd, sn, sm);
882}
883
884
Ian Rogers2c8f6532011-09-02 17:16:34 -0700885void ArmAssembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
886 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700887 EmitVFPddd(cond, B23, dd, dn, dm);
888}
889
890
Ian Rogers2c8f6532011-09-02 17:16:34 -0700891void ArmAssembler::vabss(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700892 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
893}
894
895
Ian Rogers2c8f6532011-09-02 17:16:34 -0700896void ArmAssembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700897 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
898}
899
900
Ian Rogers2c8f6532011-09-02 17:16:34 -0700901void ArmAssembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700902 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
903}
904
905
Ian Rogers2c8f6532011-09-02 17:16:34 -0700906void ArmAssembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700907 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
908}
909
910
Ian Rogers2c8f6532011-09-02 17:16:34 -0700911void ArmAssembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700912 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
913}
914
Ian Rogers2c8f6532011-09-02 17:16:34 -0700915void ArmAssembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700916 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
917}
918
919
Ian Rogers2c8f6532011-09-02 17:16:34 -0700920void ArmAssembler::EmitVFPsd(Condition cond, int32_t opcode,
921 SRegister sd, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700922 CHECK_NE(sd, kNoSRegister);
923 CHECK_NE(dm, kNoDRegister);
924 CHECK_NE(cond, kNoCondition);
925 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
926 B27 | B26 | B25 | B11 | B9 | opcode |
927 ((static_cast<int32_t>(sd) & 1)*B22) |
928 ((static_cast<int32_t>(sd) >> 1)*B12) |
929 ((static_cast<int32_t>(dm) >> 4)*B5) |
930 (static_cast<int32_t>(dm) & 0xf);
931 Emit(encoding);
932}
933
934
Ian Rogers2c8f6532011-09-02 17:16:34 -0700935void ArmAssembler::EmitVFPds(Condition cond, int32_t opcode,
936 DRegister dd, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700937 CHECK_NE(dd, kNoDRegister);
938 CHECK_NE(sm, kNoSRegister);
939 CHECK_NE(cond, kNoCondition);
940 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
941 B27 | B26 | B25 | B11 | B9 | opcode |
942 ((static_cast<int32_t>(dd) >> 4)*B22) |
943 ((static_cast<int32_t>(dd) & 0xf)*B12) |
944 ((static_cast<int32_t>(sm) & 1)*B5) |
945 (static_cast<int32_t>(sm) >> 1);
946 Emit(encoding);
947}
948
949
Ian Rogers2c8f6532011-09-02 17:16:34 -0700950void ArmAssembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700951 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
952}
953
954
Ian Rogers2c8f6532011-09-02 17:16:34 -0700955void ArmAssembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700956 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
957}
958
959
Ian Rogers2c8f6532011-09-02 17:16:34 -0700960void ArmAssembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700961 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
962}
963
964
Ian Rogers2c8f6532011-09-02 17:16:34 -0700965void ArmAssembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700966 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
967}
968
969
Ian Rogers2c8f6532011-09-02 17:16:34 -0700970void ArmAssembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700971 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
972}
973
974
Ian Rogers2c8f6532011-09-02 17:16:34 -0700975void ArmAssembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700976 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
977}
978
979
Ian Rogers2c8f6532011-09-02 17:16:34 -0700980void ArmAssembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700981 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
982}
983
984
Ian Rogers2c8f6532011-09-02 17:16:34 -0700985void ArmAssembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700986 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
987}
988
989
Ian Rogers2c8f6532011-09-02 17:16:34 -0700990void ArmAssembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700991 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
992}
993
994
Ian Rogers2c8f6532011-09-02 17:16:34 -0700995void ArmAssembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700996 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
997}
998
999
Ian Rogers2c8f6532011-09-02 17:16:34 -07001000void ArmAssembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001001 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
1002}
1003
1004
Ian Rogers2c8f6532011-09-02 17:16:34 -07001005void ArmAssembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001006 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
1007}
1008
1009
Ian Rogers2c8f6532011-09-02 17:16:34 -07001010void ArmAssembler::vcmpsz(SRegister sd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001011 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
1012}
1013
1014
Ian Rogers2c8f6532011-09-02 17:16:34 -07001015void ArmAssembler::vcmpdz(DRegister dd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001016 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
1017}
1018
1019
Ian Rogers2c8f6532011-09-02 17:16:34 -07001020void ArmAssembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001021 CHECK_NE(cond, kNoCondition);
1022 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1023 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1024 (static_cast<int32_t>(PC)*B12) |
1025 B11 | B9 | B4;
1026 Emit(encoding);
1027}
1028
1029
Ian Rogers2c8f6532011-09-02 17:16:34 -07001030void ArmAssembler::svc(uint32_t imm24) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001031 CHECK(IsUint(24, imm24));
1032 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1033 Emit(encoding);
1034}
1035
1036
Ian Rogers2c8f6532011-09-02 17:16:34 -07001037void ArmAssembler::bkpt(uint16_t imm16) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001038 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1039 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1040 Emit(encoding);
1041}
1042
1043
Ian Rogers2c8f6532011-09-02 17:16:34 -07001044void ArmAssembler::b(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001045 EmitBranch(cond, label, false);
1046}
1047
1048
Ian Rogers2c8f6532011-09-02 17:16:34 -07001049void ArmAssembler::bl(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001050 EmitBranch(cond, label, true);
1051}
1052
1053
Ian Rogers2c8f6532011-09-02 17:16:34 -07001054void ArmAssembler::blx(Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001055 CHECK_NE(rm, kNoRegister);
1056 CHECK_NE(cond, kNoCondition);
1057 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1058 B24 | B21 | (0xfff << 8) | B5 | B4 |
1059 (static_cast<int32_t>(rm) << kRmShift);
1060 Emit(encoding);
1061}
1062
Ian Rogersae675992011-10-09 17:10:22 -07001063void ArmAssembler::bx(Register rm, Condition cond) {
1064 CHECK_NE(rm, kNoRegister);
1065 CHECK_NE(cond, kNoCondition);
1066 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1067 B24 | B21 | (0xfff << 8) | B4 |
1068 (static_cast<int32_t>(rm) << kRmShift);
1069 Emit(encoding);
1070}
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001071
Ian Rogers2c8f6532011-09-02 17:16:34 -07001072void ArmAssembler::MarkExceptionHandler(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001073 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
1074 Label l;
1075 b(&l);
1076 EmitBranch(AL, label, false);
1077 Bind(&l);
1078}
1079
1080
Ian Rogers2c8f6532011-09-02 17:16:34 -07001081void ArmAssembler::Bind(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001082 CHECK(!label->IsBound());
1083 int bound_pc = buffer_.Size();
1084 while (label->IsLinked()) {
1085 int32_t position = label->Position();
1086 int32_t next = buffer_.Load<int32_t>(position);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001087 int32_t encoded = ArmAssembler::EncodeBranchOffset(bound_pc - position, next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001088 buffer_.Store<int32_t>(position, encoded);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001089 label->position_ = ArmAssembler::DecodeBranchOffset(next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001090 }
1091 label->BindTo(bound_pc);
1092}
1093
1094
Ian Rogers2c8f6532011-09-02 17:16:34 -07001095void ArmAssembler::EncodeUint32InTstInstructions(uint32_t data) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001096 // TODO: Consider using movw ip, <16 bits>.
1097 while (!IsUint(8, data)) {
1098 tst(R0, ShifterOperand(data & 0xFF), VS);
1099 data >>= 8;
1100 }
1101 tst(R0, ShifterOperand(data), MI);
1102}
1103
Ian Rogersb033c752011-07-20 12:22:35 -07001104
Ian Rogers2c8f6532011-09-02 17:16:34 -07001105int32_t ArmAssembler::EncodeBranchOffset(int offset, int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001106 // The offset is off by 8 due to the way the ARM CPUs read PC.
1107 offset -= 8;
Elliott Hughes06b37d92011-10-16 11:51:29 -07001108 CHECK_ALIGNED(offset, 4);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001109 CHECK(IsInt(CountOneBits(kBranchOffsetMask), offset));
1110
1111 // Properly preserve only the bits supported in the instruction.
1112 offset >>= 2;
1113 offset &= kBranchOffsetMask;
1114 return (inst & ~kBranchOffsetMask) | offset;
1115}
1116
1117
Ian Rogers2c8f6532011-09-02 17:16:34 -07001118int ArmAssembler::DecodeBranchOffset(int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001119 // Sign-extend, left-shift by 2, then add 8.
1120 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1121}
1122
Ian Rogers2c8f6532011-09-02 17:16:34 -07001123void ArmAssembler::AddConstant(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001124 AddConstant(rd, rd, value, cond);
1125}
1126
1127
Ian Rogers2c8f6532011-09-02 17:16:34 -07001128void ArmAssembler::AddConstant(Register rd, Register rn, int32_t value,
1129 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001130 if (value == 0) {
1131 if (rd != rn) {
1132 mov(rd, ShifterOperand(rn), cond);
1133 }
1134 return;
1135 }
1136 // We prefer to select the shorter code sequence rather than selecting add for
1137 // positive values and sub for negatives ones, which would slightly improve
1138 // the readability of generated code for some constants.
1139 ShifterOperand shifter_op;
1140 if (ShifterOperand::CanHold(value, &shifter_op)) {
1141 add(rd, rn, shifter_op, cond);
1142 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1143 sub(rd, rn, shifter_op, cond);
1144 } else {
1145 CHECK(rn != IP);
1146 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1147 mvn(IP, shifter_op, cond);
1148 add(rd, rn, ShifterOperand(IP), cond);
1149 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1150 mvn(IP, shifter_op, cond);
1151 sub(rd, rn, ShifterOperand(IP), cond);
1152 } else {
1153 movw(IP, Low16Bits(value), cond);
1154 uint16_t value_high = High16Bits(value);
1155 if (value_high != 0) {
1156 movt(IP, value_high, cond);
1157 }
1158 add(rd, rn, ShifterOperand(IP), cond);
1159 }
1160 }
1161}
1162
1163
Ian Rogers2c8f6532011-09-02 17:16:34 -07001164void ArmAssembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1165 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001166 ShifterOperand shifter_op;
1167 if (ShifterOperand::CanHold(value, &shifter_op)) {
1168 adds(rd, rn, shifter_op, cond);
1169 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1170 subs(rd, rn, shifter_op, cond);
1171 } else {
1172 CHECK(rn != IP);
1173 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1174 mvn(IP, shifter_op, cond);
1175 adds(rd, rn, ShifterOperand(IP), cond);
1176 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1177 mvn(IP, shifter_op, cond);
1178 subs(rd, rn, ShifterOperand(IP), cond);
1179 } else {
1180 movw(IP, Low16Bits(value), cond);
1181 uint16_t value_high = High16Bits(value);
1182 if (value_high != 0) {
1183 movt(IP, value_high, cond);
1184 }
1185 adds(rd, rn, ShifterOperand(IP), cond);
1186 }
1187 }
1188}
1189
1190
Ian Rogers2c8f6532011-09-02 17:16:34 -07001191void ArmAssembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001192 ShifterOperand shifter_op;
1193 if (ShifterOperand::CanHold(value, &shifter_op)) {
1194 mov(rd, shifter_op, cond);
1195 } else if (ShifterOperand::CanHold(~value, &shifter_op)) {
1196 mvn(rd, shifter_op, cond);
1197 } else {
1198 movw(rd, Low16Bits(value), cond);
1199 uint16_t value_high = High16Bits(value);
1200 if (value_high != 0) {
1201 movt(rd, value_high, cond);
1202 }
1203 }
1204}
1205
1206
1207bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) {
1208 switch (type) {
1209 case kLoadSignedByte:
1210 case kLoadSignedHalfword:
1211 case kLoadUnsignedHalfword:
1212 case kLoadWordPair:
1213 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1214 case kLoadUnsignedByte:
1215 case kLoadWord:
1216 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1217 case kLoadSWord:
1218 case kLoadDWord:
1219 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1220 default:
1221 LOG(FATAL) << "UNREACHABLE";
1222 return false;
1223 }
1224}
1225
1226
1227bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) {
1228 switch (type) {
1229 case kStoreHalfword:
1230 case kStoreWordPair:
1231 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1232 case kStoreByte:
1233 case kStoreWord:
1234 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1235 case kStoreSWord:
1236 case kStoreDWord:
1237 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1238 default:
1239 LOG(FATAL) << "UNREACHABLE";
1240 return false;
1241 }
1242}
1243
1244
1245// Implementation note: this method must emit at most one instruction when
1246// Address::CanHoldLoadOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001247void ArmAssembler::LoadFromOffset(LoadOperandType type,
Ian Rogersb033c752011-07-20 12:22:35 -07001248 Register reg,
1249 Register base,
1250 int32_t offset,
1251 Condition cond) {
1252 if (!Address::CanHoldLoadOffset(type, offset)) {
1253 CHECK(base != IP);
1254 LoadImmediate(IP, offset, cond);
1255 add(IP, IP, ShifterOperand(base), cond);
1256 base = IP;
1257 offset = 0;
1258 }
1259 CHECK(Address::CanHoldLoadOffset(type, offset));
1260 switch (type) {
1261 case kLoadSignedByte:
1262 ldrsb(reg, Address(base, offset), cond);
1263 break;
1264 case kLoadUnsignedByte:
1265 ldrb(reg, Address(base, offset), cond);
1266 break;
1267 case kLoadSignedHalfword:
1268 ldrsh(reg, Address(base, offset), cond);
1269 break;
1270 case kLoadUnsignedHalfword:
1271 ldrh(reg, Address(base, offset), cond);
1272 break;
1273 case kLoadWord:
1274 ldr(reg, Address(base, offset), cond);
1275 break;
1276 case kLoadWordPair:
1277 ldrd(reg, Address(base, offset), cond);
1278 break;
1279 default:
1280 LOG(FATAL) << "UNREACHABLE";
1281 }
1282}
1283
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001284// Implementation note: this method must emit at most one instruction when
1285// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001286void ArmAssembler::LoadSFromOffset(SRegister reg,
1287 Register base,
1288 int32_t offset,
1289 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001290 if (!Address::CanHoldLoadOffset(kLoadSWord, offset)) {
1291 CHECK_NE(base, IP);
1292 LoadImmediate(IP, offset, cond);
1293 add(IP, IP, ShifterOperand(base), cond);
1294 base = IP;
1295 offset = 0;
1296 }
1297 CHECK(Address::CanHoldLoadOffset(kLoadSWord, offset));
1298 vldrs(reg, Address(base, offset), cond);
1299}
1300
1301// Implementation note: this method must emit at most one instruction when
1302// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001303void ArmAssembler::LoadDFromOffset(DRegister reg,
1304 Register base,
1305 int32_t offset,
1306 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001307 if (!Address::CanHoldLoadOffset(kLoadDWord, offset)) {
1308 CHECK_NE(base, IP);
1309 LoadImmediate(IP, offset, cond);
1310 add(IP, IP, ShifterOperand(base), cond);
1311 base = IP;
1312 offset = 0;
1313 }
1314 CHECK(Address::CanHoldLoadOffset(kLoadDWord, offset));
1315 vldrd(reg, Address(base, offset), cond);
1316}
Ian Rogersb033c752011-07-20 12:22:35 -07001317
1318// Implementation note: this method must emit at most one instruction when
1319// Address::CanHoldStoreOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001320void ArmAssembler::StoreToOffset(StoreOperandType type,
1321 Register reg,
1322 Register base,
1323 int32_t offset,
1324 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001325 if (!Address::CanHoldStoreOffset(type, offset)) {
1326 CHECK(reg != IP);
1327 CHECK(base != IP);
1328 LoadImmediate(IP, offset, cond);
1329 add(IP, IP, ShifterOperand(base), cond);
1330 base = IP;
1331 offset = 0;
1332 }
1333 CHECK(Address::CanHoldStoreOffset(type, offset));
1334 switch (type) {
1335 case kStoreByte:
1336 strb(reg, Address(base, offset), cond);
1337 break;
1338 case kStoreHalfword:
1339 strh(reg, Address(base, offset), cond);
1340 break;
1341 case kStoreWord:
1342 str(reg, Address(base, offset), cond);
1343 break;
1344 case kStoreWordPair:
1345 strd(reg, Address(base, offset), cond);
1346 break;
1347 default:
1348 LOG(FATAL) << "UNREACHABLE";
1349 }
1350}
1351
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001352// Implementation note: this method must emit at most one instruction when
1353// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001354void ArmAssembler::StoreSToOffset(SRegister reg,
1355 Register base,
1356 int32_t offset,
1357 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001358 if (!Address::CanHoldStoreOffset(kStoreSWord, offset)) {
1359 CHECK_NE(base, IP);
1360 LoadImmediate(IP, offset, cond);
1361 add(IP, IP, ShifterOperand(base), cond);
1362 base = IP;
1363 offset = 0;
1364 }
1365 CHECK(Address::CanHoldStoreOffset(kStoreSWord, offset));
1366 vstrs(reg, Address(base, offset), cond);
1367}
1368
1369// Implementation note: this method must emit at most one instruction when
1370// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreSToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001371void ArmAssembler::StoreDToOffset(DRegister reg,
1372 Register base,
1373 int32_t offset,
1374 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001375 if (!Address::CanHoldStoreOffset(kStoreDWord, offset)) {
1376 CHECK_NE(base, IP);
1377 LoadImmediate(IP, offset, cond);
1378 add(IP, IP, ShifterOperand(base), cond);
1379 base = IP;
1380 offset = 0;
1381 }
1382 CHECK(Address::CanHoldStoreOffset(kStoreDWord, offset));
1383 vstrd(reg, Address(base, offset), cond);
1384}
1385
Ian Rogers2c8f6532011-09-02 17:16:34 -07001386void ArmAssembler::Push(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001387 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1388}
1389
Ian Rogers2c8f6532011-09-02 17:16:34 -07001390void ArmAssembler::Pop(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001391 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1392}
1393
Ian Rogers2c8f6532011-09-02 17:16:34 -07001394void ArmAssembler::PushList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001395 stm(DB_W, SP, regs, cond);
1396}
1397
Ian Rogers2c8f6532011-09-02 17:16:34 -07001398void ArmAssembler::PopList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001399 ldm(IA_W, SP, regs, cond);
1400}
1401
Ian Rogers2c8f6532011-09-02 17:16:34 -07001402void ArmAssembler::Mov(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001403 if (rd != rm) {
1404 mov(rd, ShifterOperand(rm), cond);
1405 }
1406}
1407
Ian Rogers2c8f6532011-09-02 17:16:34 -07001408void ArmAssembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
1409 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001410 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
1411 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1412}
1413
Ian Rogers2c8f6532011-09-02 17:16:34 -07001414void ArmAssembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
1415 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001416 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
1417 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1418 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1419}
1420
Ian Rogers2c8f6532011-09-02 17:16:34 -07001421void ArmAssembler::Asr(Register rd, Register rm, uint32_t shift_imm,
1422 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001423 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
1424 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1425 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1426}
1427
Ian Rogers2c8f6532011-09-02 17:16:34 -07001428void ArmAssembler::Ror(Register rd, Register rm, uint32_t shift_imm,
1429 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001430 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
1431 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1432}
1433
Ian Rogers2c8f6532011-09-02 17:16:34 -07001434void ArmAssembler::Rrx(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001435 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1436}
1437
Ian Rogers2c8f6532011-09-02 17:16:34 -07001438void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersb5d09b22012-03-06 22:14:17 -08001439 const std::vector<ManagedRegister>& callee_save_regs,
1440 const std::vector<ManagedRegister>& entry_spills) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001441 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogersb5d09b22012-03-06 22:14:17 -08001442 DCHECK_EQ(entry_spills.size(), 0u);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001443 CHECK_EQ(R0, method_reg.AsArm().AsCoreRegister());
Ian Rogersbdb03912011-09-14 00:55:44 -07001444
1445 // Push callee saves and link register
1446 RegList push_list = 1 << LR;
1447 size_t pushed_values = 1;
1448 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1449 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1450 push_list |= 1 << reg;
1451 pushed_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001452 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001453 PushList(push_list);
1454
1455 // Increase frame to required size
1456 CHECK_GT(frame_size, pushed_values * kPointerSize); // Must be at least space to push Method*
1457 size_t adjust = frame_size - (pushed_values * kPointerSize);
1458 IncreaseFrameSize(adjust);
1459
1460 // Write out Method*
1461 StoreToOffset(kStoreWord, R0, SP, 0);
Ian Rogersb033c752011-07-20 12:22:35 -07001462}
1463
Ian Rogers2c8f6532011-09-02 17:16:34 -07001464void ArmAssembler::RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -07001465 const std::vector<ManagedRegister>& callee_save_regs) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001466 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogersbdb03912011-09-14 00:55:44 -07001467 // Compute callee saves to pop and PC
1468 RegList pop_list = 1 << PC;
1469 size_t pop_values = 1;
1470 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1471 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1472 pop_list |= 1 << reg;
1473 pop_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001474 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001475
1476 // Decrease frame to start of callee saves
1477 CHECK_GT(frame_size, pop_values * kPointerSize);
1478 size_t adjust = frame_size - (pop_values * kPointerSize);
1479 DecreaseFrameSize(adjust);
1480
1481 // Pop callee saves and PC
1482 PopList(pop_list);
Ian Rogers0d666d82011-08-14 16:03:46 -07001483}
1484
Ian Rogers2c8f6532011-09-02 17:16:34 -07001485void ArmAssembler::IncreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001486 AddConstant(SP, -adjust);
1487}
1488
Ian Rogers2c8f6532011-09-02 17:16:34 -07001489void ArmAssembler::DecreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001490 AddConstant(SP, adjust);
1491}
1492
Ian Rogers2c8f6532011-09-02 17:16:34 -07001493void ArmAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
1494 ArmManagedRegister src = msrc.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001495 if (src.IsNoRegister()) {
1496 CHECK_EQ(0u, size);
1497 } else if (src.IsCoreRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001498 CHECK_EQ(4u, size);
1499 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001500 } else if (src.IsRegisterPair()) {
1501 CHECK_EQ(8u, size);
1502 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
1503 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
1504 SP, dest.Int32Value() + 4);
1505 } else if (src.IsSRegister()) {
1506 StoreSToOffset(src.AsSRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001507 } else {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001508 CHECK(src.IsDRegister());
1509 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001510 }
1511}
1512
Ian Rogers2c8f6532011-09-02 17:16:34 -07001513void ArmAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
1514 ArmManagedRegister src = msrc.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001515 CHECK(src.IsCoreRegister());
1516 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1517}
1518
Ian Rogers2c8f6532011-09-02 17:16:34 -07001519void ArmAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
1520 ArmManagedRegister src = msrc.AsArm();
Ian Rogersdf20fe02011-07-20 20:34:16 -07001521 CHECK(src.IsCoreRegister());
1522 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1523}
1524
Ian Rogers2c8f6532011-09-02 17:16:34 -07001525void ArmAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
1526 FrameOffset in_off, ManagedRegister mscratch) {
1527 ArmManagedRegister src = msrc.AsArm();
1528 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers7a99c112011-09-07 12:48:27 -07001529 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1530 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
1531 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
1532}
1533
Ian Rogers2c8f6532011-09-02 17:16:34 -07001534void ArmAssembler::CopyRef(FrameOffset dest, FrameOffset src,
1535 ManagedRegister mscratch) {
1536 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001537 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1538 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1539}
1540
Ian Rogers2c8f6532011-09-02 17:16:34 -07001541void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
1542 MemberOffset offs) {
1543 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001544 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
1545 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001546 base.AsArm().AsCoreRegister(), offs.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001547}
1548
Ian Rogers2c8f6532011-09-02 17:16:34 -07001549void ArmAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
1550 ArmManagedRegister dest = mdest.AsArm();
Elliott Hughes362f9bc2011-10-17 18:56:41 -07001551 CHECK(dest.IsCoreRegister());
1552 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
1553}
Ian Rogers2c8f6532011-09-02 17:16:34 -07001554
1555void ArmAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
Ian Rogersa04d3972011-08-17 11:33:44 -07001556 Offset offs) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001557 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersa04d3972011-08-17 11:33:44 -07001558 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
1559 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001560 base.AsArm().AsCoreRegister(), offs.Int32Value());
Ian Rogersa04d3972011-08-17 11:33:44 -07001561}
1562
Ian Rogers2c8f6532011-09-02 17:16:34 -07001563void ArmAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1564 ManagedRegister mscratch) {
1565 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001566 CHECK(scratch.IsCoreRegister());
1567 LoadImmediate(scratch.AsCoreRegister(), imm);
1568 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1569}
1570
Ian Rogers2c8f6532011-09-02 17:16:34 -07001571void ArmAssembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
1572 ManagedRegister mscratch) {
1573 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001574 CHECK(scratch.IsCoreRegister());
1575 LoadImmediate(scratch.AsCoreRegister(), imm);
1576 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), TR, dest.Int32Value());
1577}
1578
Ian Rogers2c8f6532011-09-02 17:16:34 -07001579void ArmAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
1580 ArmManagedRegister dest = mdest.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001581 if (dest.IsNoRegister()) {
1582 CHECK_EQ(0u, size);
1583 } else if (dest.IsCoreRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001584 CHECK_EQ(4u, size);
1585 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001586 } else if (dest.IsRegisterPair()) {
1587 CHECK_EQ(8u, size);
1588 LoadFromOffset(kLoadWord, dest.AsRegisterPairLow(), SP, src.Int32Value());
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001589 LoadFromOffset(kLoadWord, dest.AsRegisterPairHigh(), SP, src.Int32Value() + 4);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001590 } else if (dest.IsSRegister()) {
1591 LoadSFromOffset(dest.AsSRegister(), SP, src.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001592 } else {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001593 CHECK(dest.IsDRegister());
1594 LoadDFromOffset(dest.AsDRegister(), SP, src.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001595 }
1596}
1597
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001598void ArmAssembler::Load(ManagedRegister mdest, ThreadOffset src, size_t size) {
1599 ArmManagedRegister dest = mdest.AsArm();
1600 if (dest.IsNoRegister()) {
1601 CHECK_EQ(0u, size);
1602 } else if (dest.IsCoreRegister()) {
1603 CHECK_EQ(4u, size);
1604 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), TR, src.Int32Value());
1605 } else if (dest.IsRegisterPair()) {
1606 CHECK_EQ(8u, size);
1607 LoadFromOffset(kLoadWord, dest.AsRegisterPairLow(), TR, src.Int32Value());
1608 LoadFromOffset(kLoadWord, dest.AsRegisterPairHigh(), TR, src.Int32Value() + 4);
1609 } else if (dest.IsSRegister()) {
1610 LoadSFromOffset(dest.AsSRegister(), TR, src.Int32Value());
1611 } else {
1612 CHECK(dest.IsDRegister());
1613 LoadDFromOffset(dest.AsDRegister(), TR, src.Int32Value());
1614 }
1615}
1616
Ian Rogers2c8f6532011-09-02 17:16:34 -07001617void ArmAssembler::LoadRawPtrFromThread(ManagedRegister mdest,
1618 ThreadOffset offs) {
1619 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001620 CHECK(dest.IsCoreRegister());
1621 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
1622 TR, offs.Int32Value());
1623}
1624
Ian Rogers2c8f6532011-09-02 17:16:34 -07001625void ArmAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
1626 ThreadOffset thr_offs,
1627 ManagedRegister mscratch) {
1628 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001629 CHECK(scratch.IsCoreRegister());
1630 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1631 TR, thr_offs.Int32Value());
1632 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1633 SP, fr_offs.Int32Value());
1634}
1635
Ian Rogers2c8f6532011-09-02 17:16:34 -07001636void ArmAssembler::CopyRawPtrToThread(ThreadOffset thr_offs,
1637 FrameOffset fr_offs,
1638 ManagedRegister mscratch) {
1639 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001640 CHECK(scratch.IsCoreRegister());
1641 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1642 SP, fr_offs.Int32Value());
1643 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1644 TR, thr_offs.Int32Value());
1645}
1646
Ian Rogers2c8f6532011-09-02 17:16:34 -07001647void ArmAssembler::StoreStackOffsetToThread(ThreadOffset thr_offs,
1648 FrameOffset fr_offs,
1649 ManagedRegister mscratch) {
1650 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001651 CHECK(scratch.IsCoreRegister());
1652 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value(), AL);
1653 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1654 TR, thr_offs.Int32Value());
1655}
1656
Ian Rogers2c8f6532011-09-02 17:16:34 -07001657void ArmAssembler::StoreStackPointerToThread(ThreadOffset thr_offs) {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001658 StoreToOffset(kStoreWord, SP, TR, thr_offs.Int32Value());
1659}
1660
Ian Rogersb5d09b22012-03-06 22:14:17 -08001661void ArmAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001662 ArmManagedRegister dest = mdest.AsArm();
1663 ArmManagedRegister src = msrc.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001664 if (!dest.Equals(src)) {
1665 if (dest.IsCoreRegister()) {
1666 CHECK(src.IsCoreRegister());
1667 mov(dest.AsCoreRegister(), ShifterOperand(src.AsCoreRegister()));
Ian Rogers7a99c112011-09-07 12:48:27 -07001668 } else if (dest.IsDRegister()) {
1669 CHECK(src.IsDRegister());
1670 vmovd(dest.AsDRegister(), src.AsDRegister());
1671 } else if (dest.IsSRegister()) {
1672 CHECK(src.IsSRegister());
1673 vmovs(dest.AsSRegister(), src.AsSRegister());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001674 } else {
Ian Rogers7a99c112011-09-07 12:48:27 -07001675 CHECK(dest.IsRegisterPair());
1676 CHECK(src.IsRegisterPair());
1677 // Ensure that the first move doesn't clobber the input of the second
1678 if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
1679 mov(dest.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
1680 mov(dest.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
1681 } else {
1682 mov(dest.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
1683 mov(dest.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
1684 }
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001685 }
Ian Rogersb033c752011-07-20 12:22:35 -07001686 }
1687}
1688
Ian Rogersdc51b792011-09-22 20:41:37 -07001689void ArmAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001690 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001691 CHECK(scratch.IsCoreRegister());
Shih-wei Liao5381cf92011-07-27 00:28:04 -07001692 CHECK(size == 4 || size == 8);
Ian Rogersb033c752011-07-20 12:22:35 -07001693 if (size == 4) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001694 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1695 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
Shih-wei Liao5381cf92011-07-27 00:28:04 -07001696 } else if (size == 8) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001697 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1698 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1699 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4);
1700 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
Ian Rogersb033c752011-07-20 12:22:35 -07001701 }
1702}
1703
Ian Rogersdc51b792011-09-22 20:41:37 -07001704void ArmAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
1705 ManagedRegister mscratch, size_t size) {
1706 Register scratch = mscratch.AsArm().AsCoreRegister();
1707 CHECK_EQ(size, 4u);
1708 LoadFromOffset(kLoadWord, scratch, src_base.AsArm().AsCoreRegister(), src_offset.Int32Value());
1709 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
1710}
1711
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001712void ArmAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
1713 ManagedRegister mscratch, size_t size) {
1714 Register scratch = mscratch.AsArm().AsCoreRegister();
1715 CHECK_EQ(size, 4u);
1716 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
1717 StoreToOffset(kStoreWord, scratch, dest_base.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1718}
1719
Ian Rogersdc51b792011-09-22 20:41:37 -07001720void ArmAssembler::Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
1721 ManagedRegister mscratch, size_t size) {
1722 UNIMPLEMENTED(FATAL);
1723}
1724
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001725void ArmAssembler::Copy(ManagedRegister dest, Offset dest_offset,
1726 ManagedRegister src, Offset src_offset,
1727 ManagedRegister mscratch, size_t size) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001728 CHECK_EQ(size, 4u);
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001729 Register scratch = mscratch.AsArm().AsCoreRegister();
1730 LoadFromOffset(kLoadWord, scratch, src.AsArm().AsCoreRegister(), src_offset.Int32Value());
1731 StoreToOffset(kStoreWord, scratch, dest.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1732}
1733
1734void ArmAssembler::Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
1735 ManagedRegister scratch, size_t size) {
1736 UNIMPLEMENTED(FATAL);
Ian Rogersdc51b792011-09-22 20:41:37 -07001737}
1738
1739
Ian Rogerse5de95b2011-09-18 20:31:38 -07001740void ArmAssembler::MemoryBarrier(ManagedRegister mscratch) {
1741#if ANDROID_SMP != 0
1742#if defined(__ARM_HAVE_DMB)
1743 int32_t encoding = 0xf57ff05f; // dmb
1744 Emit(encoding);
1745#elif defined(__ARM_HAVE_LDREX_STREX)
1746 CHECK(mscratch.AsArm().AsCoreRegister() == R12);
1747 LoadImmediate(R12, 0);
1748 int32_t encoding = 0xee07cfba; // mcr p15, 0, r12, c7, c10, 5
1749 Emit(encoding);
1750#else
1751 CHECK(mscratch.AsArm().AsCoreRegister() == R12);
1752 LoadImmediate(R12, 0xffff0fa0); // kuser_memory_barrier
1753 blx(R12);
1754#endif
1755#endif
1756}
1757
Ian Rogers2c8f6532011-09-02 17:16:34 -07001758void ArmAssembler::CreateSirtEntry(ManagedRegister mout_reg,
1759 FrameOffset sirt_offset,
1760 ManagedRegister min_reg, bool null_allowed) {
1761 ArmManagedRegister out_reg = mout_reg.AsArm();
1762 ArmManagedRegister in_reg = min_reg.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001763 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister());
Ian Rogersb033c752011-07-20 12:22:35 -07001764 CHECK(out_reg.IsCoreRegister());
1765 if (null_allowed) {
Ian Rogers408f79a2011-08-23 18:22:33 -07001766 // Null values get a SIRT entry value of 0. Otherwise, the SIRT entry is
1767 // the address in the SIRT holding the reference.
Ian Rogersb033c752011-07-20 12:22:35 -07001768 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001769 if (in_reg.IsNoRegister()) {
1770 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
Ian Rogers408f79a2011-08-23 18:22:33 -07001771 SP, sirt_offset.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001772 in_reg = out_reg;
1773 }
Ian Rogersb033c752011-07-20 12:22:35 -07001774 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
1775 if (!out_reg.Equals(in_reg)) {
1776 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1777 }
Ian Rogers408f79a2011-08-23 18:22:33 -07001778 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001779 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001780 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001781 }
1782}
1783
Ian Rogers2c8f6532011-09-02 17:16:34 -07001784void ArmAssembler::CreateSirtEntry(FrameOffset out_off,
1785 FrameOffset sirt_offset,
1786 ManagedRegister mscratch,
1787 bool null_allowed) {
1788 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001789 CHECK(scratch.IsCoreRegister());
1790 if (null_allowed) {
1791 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
Ian Rogers408f79a2011-08-23 18:22:33 -07001792 sirt_offset.Int32Value());
1793 // Null values get a SIRT entry value of 0. Otherwise, the sirt entry is
1794 // the address in the SIRT holding the reference.
1795 // e.g. scratch = (scratch == 0) ? 0 : (SP+sirt_offset)
Ian Rogersb033c752011-07-20 12:22:35 -07001796 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
Ian Rogers408f79a2011-08-23 18:22:33 -07001797 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001798 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001799 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001800 }
1801 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
1802}
1803
Ian Rogers2c8f6532011-09-02 17:16:34 -07001804void ArmAssembler::LoadReferenceFromSirt(ManagedRegister mout_reg,
1805 ManagedRegister min_reg) {
1806 ArmManagedRegister out_reg = mout_reg.AsArm();
1807 ArmManagedRegister in_reg = min_reg.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001808 CHECK(out_reg.IsCoreRegister());
1809 CHECK(in_reg.IsCoreRegister());
1810 Label null_arg;
1811 if (!out_reg.Equals(in_reg)) {
1812 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1813 }
1814 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
Ian Rogersdf20fe02011-07-20 20:34:16 -07001815 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
1816 in_reg.AsCoreRegister(), 0, NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001817}
1818
Ian Rogers2c8f6532011-09-02 17:16:34 -07001819void ArmAssembler::VerifyObject(ManagedRegister src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001820 // TODO: not validating references
1821}
1822
Ian Rogers2c8f6532011-09-02 17:16:34 -07001823void ArmAssembler::VerifyObject(FrameOffset src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001824 // TODO: not validating references
1825}
1826
Ian Rogers2c8f6532011-09-02 17:16:34 -07001827void ArmAssembler::Call(ManagedRegister mbase, Offset offset,
1828 ManagedRegister mscratch) {
1829 ArmManagedRegister base = mbase.AsArm();
1830 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001831 CHECK(base.IsCoreRegister());
1832 CHECK(scratch.IsCoreRegister());
1833 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1834 base.AsCoreRegister(), offset.Int32Value());
1835 blx(scratch.AsCoreRegister());
1836 // TODO: place reference map on call
1837}
1838
Ian Rogers2c8f6532011-09-02 17:16:34 -07001839void ArmAssembler::Call(FrameOffset base, Offset offset,
1840 ManagedRegister mscratch) {
1841 ArmManagedRegister scratch = mscratch.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001842 CHECK(scratch.IsCoreRegister());
1843 // Call *(*(SP + base) + offset)
1844 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1845 SP, base.Int32Value());
1846 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1847 scratch.AsCoreRegister(), offset.Int32Value());
1848 blx(scratch.AsCoreRegister());
1849 // TODO: place reference map on call
1850}
1851
Ian Rogersbdb03912011-09-14 00:55:44 -07001852void ArmAssembler::Call(ThreadOffset offset, ManagedRegister scratch) {
1853 UNIMPLEMENTED(FATAL);
1854}
1855
Ian Rogers2c8f6532011-09-02 17:16:34 -07001856void ArmAssembler::GetCurrentThread(ManagedRegister tr) {
1857 mov(tr.AsArm().AsCoreRegister(), ShifterOperand(TR));
Shih-wei Liao668512a2011-09-01 14:18:34 -07001858}
1859
Ian Rogers2c8f6532011-09-02 17:16:34 -07001860void ArmAssembler::GetCurrentThread(FrameOffset offset,
1861 ManagedRegister scratch) {
Shih-wei Liao668512a2011-09-01 14:18:34 -07001862 StoreToOffset(kStoreWord, TR, SP, offset.Int32Value(), AL);
1863}
1864
Ian Rogers2c8f6532011-09-02 17:16:34 -07001865void ArmAssembler::SuspendPoll(ManagedRegister mscratch,
1866 ManagedRegister return_reg,
1867 FrameOffset return_save_location,
1868 size_t return_size) {
1869 ArmManagedRegister scratch = mscratch.AsArm();
1870 ArmSuspendCountSlowPath* slow =
1871 new ArmSuspendCountSlowPath(return_reg.AsArm(), return_save_location,
1872 return_size);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001873 buffer_.EnqueueSlowPath(slow);
1874 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1875 TR, Thread::SuspendCountOffset().Int32Value());
1876 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1877 b(slow->Entry(), NE);
1878 Bind(slow->Continuation());
1879}
1880
Ian Rogers2c8f6532011-09-02 17:16:34 -07001881void ArmSuspendCountSlowPath::Emit(Assembler* sasm) {
1882 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm);
1883#define __ sp_asm->
1884 __ Bind(&entry_);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001885 // Save return value
Ian Rogers2c8f6532011-09-02 17:16:34 -07001886 __ Store(return_save_location_, return_register_, return_size_);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001887 // Pass thread as argument
1888 __ mov(R0, ShifterOperand(TR));
1889 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode));
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001890 // Note: assume that link register will be spilled/filled on method entry/exit
Ian Rogers2c8f6532011-09-02 17:16:34 -07001891 __ blx(R12);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001892 // Reload return value
Ian Rogers2c8f6532011-09-02 17:16:34 -07001893 __ Load(return_register_, return_save_location_, return_size_);
1894 __ b(&continuation_);
1895#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001896}
1897
Ian Rogers2c8f6532011-09-02 17:16:34 -07001898void ArmAssembler::ExceptionPoll(ManagedRegister mscratch) {
1899 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers67375ac2011-09-14 00:55:44 -07001900 ArmExceptionSlowPath* slow = new ArmExceptionSlowPath(scratch);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001901 buffer_.EnqueueSlowPath(slow);
1902 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1903 TR, Thread::ExceptionOffset().Int32Value());
1904 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1905 b(slow->Entry(), NE);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001906}
1907
Ian Rogers2c8f6532011-09-02 17:16:34 -07001908void ArmExceptionSlowPath::Emit(Assembler* sasm) {
1909 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm);
1910#define __ sp_asm->
1911 __ Bind(&entry_);
Ian Rogers67375ac2011-09-14 00:55:44 -07001912
1913 // Pass exception object as argument
1914 // Don't care about preserving R0 as this call won't return
1915 __ mov(R0, ShifterOperand(scratch_.AsCoreRegister()));
1916 // Set up call to Thread::Current()->pDeliverException
1917 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pDeliverException));
Ian Rogers2c8f6532011-09-02 17:16:34 -07001918 __ blx(R12);
Ian Rogers67375ac2011-09-14 00:55:44 -07001919 // Call never returns
1920 __ bkpt(0);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001921#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001922}
1923
Ian Rogers2c8f6532011-09-02 17:16:34 -07001924} // namespace arm
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07001925} // namespace art