blob: ac39f2e1419d39094ca5b60cafd1f2835aafd36d [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Ian Rogers2c8f6532011-09-02 17:16:34 -07003#include "assembler_arm.h"
4
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07005#include "logging.h"
6#include "offsets.h"
Carl Shapiroe2d373e2011-07-25 15:20:06 -07007#include "thread.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07008#include "utils.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07009
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070010namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070011namespace arm {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070012
Carl Shapiroa2e18e12011-06-21 18:57:55 -070013// Instruction encoding bits.
14enum {
15 H = 1 << 5, // halfword (or byte)
16 L = 1 << 20, // load (or store)
17 S = 1 << 20, // set condition code (or leave unchanged)
18 W = 1 << 21, // writeback base register (or leave unchanged)
19 A = 1 << 21, // accumulate in multiply instruction (or not)
20 B = 1 << 22, // unsigned byte (or word)
21 N = 1 << 22, // long (or short)
22 U = 1 << 23, // positive (or negative) offset/index
23 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
24 I = 1 << 25, // immediate shifter operand (or not)
25
26 B0 = 1,
27 B1 = 1 << 1,
28 B2 = 1 << 2,
29 B3 = 1 << 3,
30 B4 = 1 << 4,
31 B5 = 1 << 5,
32 B6 = 1 << 6,
33 B7 = 1 << 7,
34 B8 = 1 << 8,
35 B9 = 1 << 9,
36 B10 = 1 << 10,
37 B11 = 1 << 11,
38 B12 = 1 << 12,
39 B16 = 1 << 16,
40 B17 = 1 << 17,
41 B18 = 1 << 18,
42 B19 = 1 << 19,
43 B20 = 1 << 20,
44 B21 = 1 << 21,
45 B22 = 1 << 22,
46 B23 = 1 << 23,
47 B24 = 1 << 24,
48 B25 = 1 << 25,
49 B26 = 1 << 26,
50 B27 = 1 << 27,
51
52 // Instruction bit masks.
53 RdMask = 15 << 12, // in str instruction
54 CondMask = 15 << 28,
55 CoprocessorMask = 15 << 8,
56 OpCodeMask = 15 << 21, // in data-processing instructions
57 Imm24Mask = (1 << 24) - 1,
58 Off12Mask = (1 << 12) - 1,
59
60 // ldrex/strex register field encodings.
61 kLdExRnShift = 16,
62 kLdExRtShift = 12,
63 kStrExRnShift = 16,
64 kStrExRdShift = 12,
65 kStrExRtShift = 0,
66};
67
68
Elliott Hughes1f359b02011-07-17 14:27:17 -070069static const char* kRegisterNames[] = {
70 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
71 "fp", "ip", "sp", "lr", "pc"
72};
73std::ostream& operator<<(std::ostream& os, const Register& rhs) {
74 if (rhs >= R0 && rhs <= PC) {
75 os << kRegisterNames[rhs];
76 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070077 os << "Register[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070078 }
79 return os;
80}
81
82
83std::ostream& operator<<(std::ostream& os, const SRegister& rhs) {
84 if (rhs >= S0 && rhs < kNumberOfSRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -070085 os << "s" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -070086 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070087 os << "SRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070088 }
89 return os;
90}
91
92
93std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
94 if (rhs >= D0 && rhs < kNumberOfDRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -070095 os << "d" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -070096 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070097 os << "DRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070098 }
99 return os;
100}
101
102
103static const char* kConditionNames[] = {
Ian Rogersb033c752011-07-20 12:22:35 -0700104 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT",
105 "LE", "AL",
Elliott Hughes1f359b02011-07-17 14:27:17 -0700106};
107std::ostream& operator<<(std::ostream& os, const Condition& rhs) {
108 if (rhs >= EQ && rhs <= AL) {
109 os << kConditionNames[rhs];
110 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700111 os << "Condition[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700112 }
113 return os;
114}
115
Ian Rogers2c8f6532011-09-02 17:16:34 -0700116void ArmAssembler::Emit(int32_t value) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700117 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
118 buffer_.Emit<int32_t>(value);
119}
120
121
Ian Rogers2c8f6532011-09-02 17:16:34 -0700122void ArmAssembler::EmitType01(Condition cond,
123 int type,
124 Opcode opcode,
125 int set_cc,
126 Register rn,
127 Register rd,
128 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700129 CHECK_NE(rd, kNoRegister);
130 CHECK_NE(cond, kNoCondition);
131 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
132 type << kTypeShift |
133 static_cast<int32_t>(opcode) << kOpcodeShift |
134 set_cc << kSShift |
135 static_cast<int32_t>(rn) << kRnShift |
136 static_cast<int32_t>(rd) << kRdShift |
137 so.encoding();
138 Emit(encoding);
139}
140
141
Ian Rogers2c8f6532011-09-02 17:16:34 -0700142void ArmAssembler::EmitType5(Condition cond, int offset, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700143 CHECK_NE(cond, kNoCondition);
144 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
145 5 << kTypeShift |
146 (link ? 1 : 0) << kLinkShift;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700147 Emit(ArmAssembler::EncodeBranchOffset(offset, encoding));
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700148}
149
150
Ian Rogers2c8f6532011-09-02 17:16:34 -0700151void ArmAssembler::EmitMemOp(Condition cond,
152 bool load,
153 bool byte,
154 Register rd,
155 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700156 CHECK_NE(rd, kNoRegister);
157 CHECK_NE(cond, kNoCondition);
158 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
159 B26 |
160 (load ? L : 0) |
161 (byte ? B : 0) |
162 (static_cast<int32_t>(rd) << kRdShift) |
163 ad.encoding();
164 Emit(encoding);
165}
166
167
Ian Rogers2c8f6532011-09-02 17:16:34 -0700168void ArmAssembler::EmitMemOpAddressMode3(Condition cond,
169 int32_t mode,
170 Register rd,
171 Address ad) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700172 CHECK_NE(rd, kNoRegister);
173 CHECK_NE(cond, kNoCondition);
174 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
175 B22 |
176 mode |
177 (static_cast<int32_t>(rd) << kRdShift) |
178 ad.encoding3();
179 Emit(encoding);
180}
181
182
Ian Rogers2c8f6532011-09-02 17:16:34 -0700183void ArmAssembler::EmitMultiMemOp(Condition cond,
184 BlockAddressMode am,
185 bool load,
186 Register base,
187 RegList regs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700188 CHECK_NE(base, kNoRegister);
189 CHECK_NE(cond, kNoCondition);
190 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
191 B27 |
192 am |
193 (load ? L : 0) |
194 (static_cast<int32_t>(base) << kRnShift) |
195 regs;
196 Emit(encoding);
197}
198
199
Ian Rogers2c8f6532011-09-02 17:16:34 -0700200void ArmAssembler::EmitShiftImmediate(Condition cond,
201 Shift opcode,
202 Register rd,
203 Register rm,
204 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700205 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700206 CHECK_EQ(so.type(), 1U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700207 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
208 static_cast<int32_t>(MOV) << kOpcodeShift |
209 static_cast<int32_t>(rd) << kRdShift |
210 so.encoding() << kShiftImmShift |
211 static_cast<int32_t>(opcode) << kShiftShift |
212 static_cast<int32_t>(rm);
213 Emit(encoding);
214}
215
216
Ian Rogers2c8f6532011-09-02 17:16:34 -0700217void ArmAssembler::EmitShiftRegister(Condition cond,
218 Shift opcode,
219 Register rd,
220 Register rm,
221 ShifterOperand so) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700222 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700223 CHECK_EQ(so.type(), 0U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700224 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
225 static_cast<int32_t>(MOV) << kOpcodeShift |
226 static_cast<int32_t>(rd) << kRdShift |
227 so.encoding() << kShiftRegisterShift |
228 static_cast<int32_t>(opcode) << kShiftShift |
229 B4 |
230 static_cast<int32_t>(rm);
231 Emit(encoding);
232}
233
234
Ian Rogers2c8f6532011-09-02 17:16:34 -0700235void ArmAssembler::EmitBranch(Condition cond, Label* label, bool link) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700236 if (label->IsBound()) {
237 EmitType5(cond, label->Position() - buffer_.Size(), link);
238 } else {
239 int position = buffer_.Size();
240 // Use the offset field of the branch instruction for linking the sites.
241 EmitType5(cond, label->position_, link);
242 label->LinkTo(position);
243 }
244}
245
Ian Rogers2c8f6532011-09-02 17:16:34 -0700246void ArmAssembler::and_(Register rd, Register rn, ShifterOperand so,
247 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700248 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
249}
250
251
Ian Rogers2c8f6532011-09-02 17:16:34 -0700252void ArmAssembler::eor(Register rd, Register rn, ShifterOperand so,
253 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700254 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
255}
256
257
Ian Rogers2c8f6532011-09-02 17:16:34 -0700258void ArmAssembler::sub(Register rd, Register rn, ShifterOperand so,
259 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700260 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
261}
262
Ian Rogers2c8f6532011-09-02 17:16:34 -0700263void ArmAssembler::rsb(Register rd, Register rn, ShifterOperand so,
264 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700265 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
266}
267
Ian Rogers2c8f6532011-09-02 17:16:34 -0700268void ArmAssembler::rsbs(Register rd, Register rn, ShifterOperand so,
269 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700270 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
271}
272
273
Ian Rogers2c8f6532011-09-02 17:16:34 -0700274void ArmAssembler::add(Register rd, Register rn, ShifterOperand so,
275 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700276 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
277}
278
279
Ian Rogers2c8f6532011-09-02 17:16:34 -0700280void ArmAssembler::adds(Register rd, Register rn, ShifterOperand so,
281 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700282 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
283}
284
285
Ian Rogers2c8f6532011-09-02 17:16:34 -0700286void ArmAssembler::subs(Register rd, Register rn, ShifterOperand so,
287 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700288 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
289}
290
291
Ian Rogers2c8f6532011-09-02 17:16:34 -0700292void ArmAssembler::adc(Register rd, Register rn, ShifterOperand so,
293 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700294 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
295}
296
297
Ian Rogers2c8f6532011-09-02 17:16:34 -0700298void ArmAssembler::sbc(Register rd, Register rn, ShifterOperand so,
299 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700300 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
301}
302
303
Ian Rogers2c8f6532011-09-02 17:16:34 -0700304void ArmAssembler::rsc(Register rd, Register rn, ShifterOperand so,
305 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700306 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
307}
308
309
Ian Rogers2c8f6532011-09-02 17:16:34 -0700310void ArmAssembler::tst(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700311 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
312 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
313}
314
315
Ian Rogers2c8f6532011-09-02 17:16:34 -0700316void ArmAssembler::teq(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700317 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
318 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
319}
320
321
Ian Rogers2c8f6532011-09-02 17:16:34 -0700322void ArmAssembler::cmp(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700323 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
324}
325
326
Ian Rogers2c8f6532011-09-02 17:16:34 -0700327void ArmAssembler::cmn(Register rn, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700328 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
329}
330
331
Ian Rogers2c8f6532011-09-02 17:16:34 -0700332void ArmAssembler::orr(Register rd, Register rn,
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700333 ShifterOperand so, Condition cond) {
334 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
335}
336
337
Ian Rogers2c8f6532011-09-02 17:16:34 -0700338void ArmAssembler::orrs(Register rd, Register rn,
339 ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700340 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
341}
342
343
Ian Rogers2c8f6532011-09-02 17:16:34 -0700344void ArmAssembler::mov(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700345 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
346}
347
348
Ian Rogers2c8f6532011-09-02 17:16:34 -0700349void ArmAssembler::movs(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700350 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
351}
352
353
Ian Rogers2c8f6532011-09-02 17:16:34 -0700354void ArmAssembler::bic(Register rd, Register rn, ShifterOperand so,
355 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700356 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
357}
358
359
Ian Rogers2c8f6532011-09-02 17:16:34 -0700360void ArmAssembler::mvn(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700361 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
362}
363
364
Ian Rogers2c8f6532011-09-02 17:16:34 -0700365void ArmAssembler::mvns(Register rd, ShifterOperand so, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700366 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
367}
368
369
Ian Rogers2c8f6532011-09-02 17:16:34 -0700370void ArmAssembler::clz(Register rd, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700371 CHECK_NE(rd, kNoRegister);
372 CHECK_NE(rm, kNoRegister);
373 CHECK_NE(cond, kNoCondition);
374 CHECK_NE(rd, PC);
375 CHECK_NE(rm, PC);
376 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
377 B24 | B22 | B21 | (0xf << 16) |
378 (static_cast<int32_t>(rd) << kRdShift) |
379 (0xf << 8) | B4 | static_cast<int32_t>(rm);
380 Emit(encoding);
381}
382
383
Ian Rogers2c8f6532011-09-02 17:16:34 -0700384void ArmAssembler::movw(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700385 CHECK_NE(cond, kNoCondition);
386 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
387 B25 | B24 | ((imm16 >> 12) << 16) |
388 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
389 Emit(encoding);
390}
391
392
Ian Rogers2c8f6532011-09-02 17:16:34 -0700393void ArmAssembler::movt(Register rd, uint16_t imm16, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700394 CHECK_NE(cond, kNoCondition);
395 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
396 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
397 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
398 Emit(encoding);
399}
400
401
Ian Rogers2c8f6532011-09-02 17:16:34 -0700402void ArmAssembler::EmitMulOp(Condition cond, int32_t opcode,
403 Register rd, Register rn,
404 Register rm, Register rs) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700405 CHECK_NE(rd, kNoRegister);
406 CHECK_NE(rn, kNoRegister);
407 CHECK_NE(rm, kNoRegister);
408 CHECK_NE(rs, kNoRegister);
409 CHECK_NE(cond, kNoCondition);
410 int32_t encoding = opcode |
411 (static_cast<int32_t>(cond) << kConditionShift) |
412 (static_cast<int32_t>(rn) << kRnShift) |
413 (static_cast<int32_t>(rd) << kRdShift) |
414 (static_cast<int32_t>(rs) << kRsShift) |
415 B7 | B4 |
416 (static_cast<int32_t>(rm) << kRmShift);
417 Emit(encoding);
418}
419
420
Ian Rogers2c8f6532011-09-02 17:16:34 -0700421void ArmAssembler::mul(Register rd, Register rn, Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700422 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
423 EmitMulOp(cond, 0, R0, rd, rn, rm);
424}
425
426
Ian Rogers2c8f6532011-09-02 17:16:34 -0700427void ArmAssembler::mla(Register rd, Register rn, Register rm, Register ra,
428 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700429 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
430 EmitMulOp(cond, B21, ra, rd, rn, rm);
431}
432
433
Ian Rogers2c8f6532011-09-02 17:16:34 -0700434void ArmAssembler::mls(Register rd, Register rn, Register rm, Register ra,
435 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700436 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
437 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
438}
439
440
Ian Rogers2c8f6532011-09-02 17:16:34 -0700441void ArmAssembler::umull(Register rd_lo, Register rd_hi, Register rn,
442 Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700443 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
444 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
445}
446
447
Ian Rogers2c8f6532011-09-02 17:16:34 -0700448void ArmAssembler::ldr(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700449 EmitMemOp(cond, true, false, rd, ad);
450}
451
452
Ian Rogers2c8f6532011-09-02 17:16:34 -0700453void ArmAssembler::str(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700454 EmitMemOp(cond, false, false, rd, ad);
455}
456
457
Ian Rogers2c8f6532011-09-02 17:16:34 -0700458void ArmAssembler::ldrb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700459 EmitMemOp(cond, true, true, rd, ad);
460}
461
462
Ian Rogers2c8f6532011-09-02 17:16:34 -0700463void ArmAssembler::strb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700464 EmitMemOp(cond, false, true, rd, ad);
465}
466
467
Ian Rogers2c8f6532011-09-02 17:16:34 -0700468void ArmAssembler::ldrh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700469 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
470}
471
472
Ian Rogers2c8f6532011-09-02 17:16:34 -0700473void ArmAssembler::strh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700474 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
475}
476
477
Ian Rogers2c8f6532011-09-02 17:16:34 -0700478void ArmAssembler::ldrsb(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700479 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
480}
481
482
Ian Rogers2c8f6532011-09-02 17:16:34 -0700483void ArmAssembler::ldrsh(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700484 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
485}
486
487
Ian Rogers2c8f6532011-09-02 17:16:34 -0700488void ArmAssembler::ldrd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700489 CHECK_EQ(rd % 2, 0);
490 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
491}
492
493
Ian Rogers2c8f6532011-09-02 17:16:34 -0700494void ArmAssembler::strd(Register rd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700495 CHECK_EQ(rd % 2, 0);
496 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
497}
498
499
Ian Rogers2c8f6532011-09-02 17:16:34 -0700500void ArmAssembler::ldm(BlockAddressMode am,
501 Register base,
502 RegList regs,
503 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700504 EmitMultiMemOp(cond, am, true, base, regs);
505}
506
507
Ian Rogers2c8f6532011-09-02 17:16:34 -0700508void ArmAssembler::stm(BlockAddressMode am,
509 Register base,
510 RegList regs,
511 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700512 EmitMultiMemOp(cond, am, false, base, regs);
513}
514
515
Ian Rogers2c8f6532011-09-02 17:16:34 -0700516void ArmAssembler::ldrex(Register rt, Register rn, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700517 CHECK_NE(rn, kNoRegister);
518 CHECK_NE(rt, kNoRegister);
519 CHECK_NE(cond, kNoCondition);
520 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
521 B24 |
522 B23 |
523 L |
524 (static_cast<int32_t>(rn) << kLdExRnShift) |
525 (static_cast<int32_t>(rt) << kLdExRtShift) |
526 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
527 Emit(encoding);
528}
529
530
Ian Rogers2c8f6532011-09-02 17:16:34 -0700531void ArmAssembler::strex(Register rd,
532 Register rt,
533 Register rn,
534 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700535 CHECK_NE(rn, kNoRegister);
536 CHECK_NE(rd, kNoRegister);
537 CHECK_NE(rt, kNoRegister);
538 CHECK_NE(cond, kNoCondition);
539 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
540 B24 |
541 B23 |
542 (static_cast<int32_t>(rn) << kStrExRnShift) |
543 (static_cast<int32_t>(rd) << kStrExRdShift) |
544 B11 | B10 | B9 | B8 | B7 | B4 |
545 (static_cast<int32_t>(rt) << kStrExRtShift);
546 Emit(encoding);
547}
548
549
Ian Rogers2c8f6532011-09-02 17:16:34 -0700550void ArmAssembler::clrex() {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700551 int32_t encoding = (kSpecialCondition << kConditionShift) |
552 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
553 Emit(encoding);
554}
555
556
Ian Rogers2c8f6532011-09-02 17:16:34 -0700557void ArmAssembler::nop(Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700558 CHECK_NE(cond, kNoCondition);
559 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
560 B25 | B24 | B21 | (0xf << 12);
561 Emit(encoding);
562}
563
564
Ian Rogers2c8f6532011-09-02 17:16:34 -0700565void ArmAssembler::vmovsr(SRegister sn, Register rt, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700566 CHECK_NE(sn, kNoSRegister);
567 CHECK_NE(rt, kNoRegister);
568 CHECK_NE(rt, SP);
569 CHECK_NE(rt, PC);
570 CHECK_NE(cond, kNoCondition);
571 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
572 B27 | B26 | B25 |
573 ((static_cast<int32_t>(sn) >> 1)*B16) |
574 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
575 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
576 Emit(encoding);
577}
578
579
Ian Rogers2c8f6532011-09-02 17:16:34 -0700580void ArmAssembler::vmovrs(Register rt, SRegister sn, 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 | B20 |
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::vmovsrr(SRegister sm, Register rt, Register rt2,
596 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700597 CHECK_NE(sm, kNoSRegister);
598 CHECK_NE(sm, S31);
599 CHECK_NE(rt, kNoRegister);
600 CHECK_NE(rt, SP);
601 CHECK_NE(rt, PC);
602 CHECK_NE(rt2, kNoRegister);
603 CHECK_NE(rt2, SP);
604 CHECK_NE(rt2, PC);
605 CHECK_NE(cond, kNoCondition);
606 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
607 B27 | B26 | B22 |
608 (static_cast<int32_t>(rt2)*B16) |
609 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
610 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
611 (static_cast<int32_t>(sm) >> 1);
612 Emit(encoding);
613}
614
615
Ian Rogers2c8f6532011-09-02 17:16:34 -0700616void ArmAssembler::vmovrrs(Register rt, Register rt2, SRegister sm,
617 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700618 CHECK_NE(sm, kNoSRegister);
619 CHECK_NE(sm, S31);
620 CHECK_NE(rt, kNoRegister);
621 CHECK_NE(rt, SP);
622 CHECK_NE(rt, PC);
623 CHECK_NE(rt2, kNoRegister);
624 CHECK_NE(rt2, SP);
625 CHECK_NE(rt2, PC);
626 CHECK_NE(rt, rt2);
627 CHECK_NE(cond, kNoCondition);
628 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
629 B27 | B26 | B22 | B20 |
630 (static_cast<int32_t>(rt2)*B16) |
631 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
632 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
633 (static_cast<int32_t>(sm) >> 1);
634 Emit(encoding);
635}
636
637
Ian Rogers2c8f6532011-09-02 17:16:34 -0700638void ArmAssembler::vmovdrr(DRegister dm, Register rt, Register rt2,
639 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700640 CHECK_NE(dm, kNoDRegister);
641 CHECK_NE(rt, kNoRegister);
642 CHECK_NE(rt, SP);
643 CHECK_NE(rt, PC);
644 CHECK_NE(rt2, kNoRegister);
645 CHECK_NE(rt2, SP);
646 CHECK_NE(rt2, PC);
647 CHECK_NE(cond, kNoCondition);
648 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
649 B27 | B26 | B22 |
650 (static_cast<int32_t>(rt2)*B16) |
651 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
652 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
653 (static_cast<int32_t>(dm) & 0xf);
654 Emit(encoding);
655}
656
657
Ian Rogers2c8f6532011-09-02 17:16:34 -0700658void ArmAssembler::vmovrrd(Register rt, Register rt2, DRegister dm,
659 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700660 CHECK_NE(dm, kNoDRegister);
661 CHECK_NE(rt, kNoRegister);
662 CHECK_NE(rt, SP);
663 CHECK_NE(rt, PC);
664 CHECK_NE(rt2, kNoRegister);
665 CHECK_NE(rt2, SP);
666 CHECK_NE(rt2, PC);
667 CHECK_NE(rt, rt2);
668 CHECK_NE(cond, kNoCondition);
669 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
670 B27 | B26 | B22 | B20 |
671 (static_cast<int32_t>(rt2)*B16) |
672 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
673 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
674 (static_cast<int32_t>(dm) & 0xf);
675 Emit(encoding);
676}
677
678
Ian Rogers2c8f6532011-09-02 17:16:34 -0700679void ArmAssembler::vldrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700680 CHECK_NE(sd, kNoSRegister);
681 CHECK_NE(cond, kNoCondition);
682 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
683 B27 | B26 | B24 | B20 |
684 ((static_cast<int32_t>(sd) & 1)*B22) |
685 ((static_cast<int32_t>(sd) >> 1)*B12) |
686 B11 | B9 | ad.vencoding();
687 Emit(encoding);
688}
689
690
Ian Rogers2c8f6532011-09-02 17:16:34 -0700691void ArmAssembler::vstrs(SRegister sd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700692 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
693 CHECK_NE(sd, kNoSRegister);
694 CHECK_NE(cond, kNoCondition);
695 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
696 B27 | B26 | B24 |
697 ((static_cast<int32_t>(sd) & 1)*B22) |
698 ((static_cast<int32_t>(sd) >> 1)*B12) |
699 B11 | B9 | ad.vencoding();
700 Emit(encoding);
701}
702
703
Ian Rogers2c8f6532011-09-02 17:16:34 -0700704void ArmAssembler::vldrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700705 CHECK_NE(dd, kNoDRegister);
706 CHECK_NE(cond, kNoCondition);
707 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
708 B27 | B26 | B24 | B20 |
709 ((static_cast<int32_t>(dd) >> 4)*B22) |
710 ((static_cast<int32_t>(dd) & 0xf)*B12) |
711 B11 | B9 | B8 | ad.vencoding();
712 Emit(encoding);
713}
714
715
Ian Rogers2c8f6532011-09-02 17:16:34 -0700716void ArmAssembler::vstrd(DRegister dd, Address ad, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700717 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
718 CHECK_NE(dd, kNoDRegister);
719 CHECK_NE(cond, kNoCondition);
720 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
721 B27 | B26 | B24 |
722 ((static_cast<int32_t>(dd) >> 4)*B22) |
723 ((static_cast<int32_t>(dd) & 0xf)*B12) |
724 B11 | B9 | B8 | ad.vencoding();
725 Emit(encoding);
726}
727
728
Ian Rogers2c8f6532011-09-02 17:16:34 -0700729void ArmAssembler::EmitVFPsss(Condition cond, int32_t opcode,
730 SRegister sd, SRegister sn, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700731 CHECK_NE(sd, kNoSRegister);
732 CHECK_NE(sn, kNoSRegister);
733 CHECK_NE(sm, kNoSRegister);
734 CHECK_NE(cond, kNoCondition);
735 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
736 B27 | B26 | B25 | B11 | B9 | opcode |
737 ((static_cast<int32_t>(sd) & 1)*B22) |
738 ((static_cast<int32_t>(sn) >> 1)*B16) |
739 ((static_cast<int32_t>(sd) >> 1)*B12) |
740 ((static_cast<int32_t>(sn) & 1)*B7) |
741 ((static_cast<int32_t>(sm) & 1)*B5) |
742 (static_cast<int32_t>(sm) >> 1);
743 Emit(encoding);
744}
745
746
Ian Rogers2c8f6532011-09-02 17:16:34 -0700747void ArmAssembler::EmitVFPddd(Condition cond, int32_t opcode,
748 DRegister dd, DRegister dn, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700749 CHECK_NE(dd, kNoDRegister);
750 CHECK_NE(dn, kNoDRegister);
751 CHECK_NE(dm, kNoDRegister);
752 CHECK_NE(cond, kNoCondition);
753 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
754 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
755 ((static_cast<int32_t>(dd) >> 4)*B22) |
756 ((static_cast<int32_t>(dn) & 0xf)*B16) |
757 ((static_cast<int32_t>(dd) & 0xf)*B12) |
758 ((static_cast<int32_t>(dn) >> 4)*B7) |
759 ((static_cast<int32_t>(dm) >> 4)*B5) |
760 (static_cast<int32_t>(dm) & 0xf);
761 Emit(encoding);
762}
763
764
Ian Rogers2c8f6532011-09-02 17:16:34 -0700765void ArmAssembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700766 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
767}
768
769
Ian Rogers2c8f6532011-09-02 17:16:34 -0700770void ArmAssembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700771 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
772}
773
774
Ian Rogers2c8f6532011-09-02 17:16:34 -0700775bool ArmAssembler::vmovs(SRegister sd, float s_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700776 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
777 if (((imm32 & ((1 << 19) - 1)) == 0) &&
778 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
779 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
780 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
781 ((imm32 >> 19) & ((1 << 6) -1));
782 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
783 sd, S0, S0);
784 return true;
785 }
786 return false;
787}
788
789
Ian Rogers2c8f6532011-09-02 17:16:34 -0700790bool ArmAssembler::vmovd(DRegister dd, double d_imm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700791 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
792 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
793 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
794 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
795 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
796 ((imm64 >> 48) & ((1 << 6) -1));
797 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
798 dd, D0, D0);
799 return true;
800 }
801 return false;
802}
803
804
Ian Rogers2c8f6532011-09-02 17:16:34 -0700805void ArmAssembler::vadds(SRegister sd, SRegister sn, SRegister sm,
806 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700807 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
808}
809
810
Ian Rogers2c8f6532011-09-02 17:16:34 -0700811void ArmAssembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
812 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700813 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
814}
815
816
Ian Rogers2c8f6532011-09-02 17:16:34 -0700817void ArmAssembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
818 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700819 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
820}
821
822
Ian Rogers2c8f6532011-09-02 17:16:34 -0700823void ArmAssembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
824 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700825 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
826}
827
828
Ian Rogers2c8f6532011-09-02 17:16:34 -0700829void ArmAssembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
830 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700831 EmitVFPsss(cond, B21, sd, sn, sm);
832}
833
834
Ian Rogers2c8f6532011-09-02 17:16:34 -0700835void ArmAssembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
836 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700837 EmitVFPddd(cond, B21, dd, dn, dm);
838}
839
840
Ian Rogers2c8f6532011-09-02 17:16:34 -0700841void ArmAssembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
842 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700843 EmitVFPsss(cond, 0, sd, sn, sm);
844}
845
846
Ian Rogers2c8f6532011-09-02 17:16:34 -0700847void ArmAssembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
848 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700849 EmitVFPddd(cond, 0, dd, dn, dm);
850}
851
852
Ian Rogers2c8f6532011-09-02 17:16:34 -0700853void ArmAssembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
854 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700855 EmitVFPsss(cond, B6, sd, sn, sm);
856}
857
858
Ian Rogers2c8f6532011-09-02 17:16:34 -0700859void ArmAssembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
860 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700861 EmitVFPddd(cond, B6, dd, dn, dm);
862}
863
864
Ian Rogers2c8f6532011-09-02 17:16:34 -0700865void ArmAssembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
866 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700867 EmitVFPsss(cond, B23, sd, sn, sm);
868}
869
870
Ian Rogers2c8f6532011-09-02 17:16:34 -0700871void ArmAssembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
872 Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700873 EmitVFPddd(cond, B23, dd, dn, dm);
874}
875
876
Ian Rogers2c8f6532011-09-02 17:16:34 -0700877void ArmAssembler::vabss(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700878 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
879}
880
881
Ian Rogers2c8f6532011-09-02 17:16:34 -0700882void ArmAssembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700883 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
884}
885
886
Ian Rogers2c8f6532011-09-02 17:16:34 -0700887void ArmAssembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700888 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
889}
890
891
Ian Rogers2c8f6532011-09-02 17:16:34 -0700892void ArmAssembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700893 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
894}
895
896
Ian Rogers2c8f6532011-09-02 17:16:34 -0700897void ArmAssembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700898 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
899}
900
Ian Rogers2c8f6532011-09-02 17:16:34 -0700901void ArmAssembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700902 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
903}
904
905
Ian Rogers2c8f6532011-09-02 17:16:34 -0700906void ArmAssembler::EmitVFPsd(Condition cond, int32_t opcode,
907 SRegister sd, DRegister dm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700908 CHECK_NE(sd, kNoSRegister);
909 CHECK_NE(dm, kNoDRegister);
910 CHECK_NE(cond, kNoCondition);
911 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
912 B27 | B26 | B25 | B11 | B9 | opcode |
913 ((static_cast<int32_t>(sd) & 1)*B22) |
914 ((static_cast<int32_t>(sd) >> 1)*B12) |
915 ((static_cast<int32_t>(dm) >> 4)*B5) |
916 (static_cast<int32_t>(dm) & 0xf);
917 Emit(encoding);
918}
919
920
Ian Rogers2c8f6532011-09-02 17:16:34 -0700921void ArmAssembler::EmitVFPds(Condition cond, int32_t opcode,
922 DRegister dd, SRegister sm) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700923 CHECK_NE(dd, kNoDRegister);
924 CHECK_NE(sm, kNoSRegister);
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>(dd) >> 4)*B22) |
929 ((static_cast<int32_t>(dd) & 0xf)*B12) |
930 ((static_cast<int32_t>(sm) & 1)*B5) |
931 (static_cast<int32_t>(sm) >> 1);
932 Emit(encoding);
933}
934
935
Ian Rogers2c8f6532011-09-02 17:16:34 -0700936void ArmAssembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700937 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
938}
939
940
Ian Rogers2c8f6532011-09-02 17:16:34 -0700941void ArmAssembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700942 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
943}
944
945
Ian Rogers2c8f6532011-09-02 17:16:34 -0700946void ArmAssembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700947 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
948}
949
950
Ian Rogers2c8f6532011-09-02 17:16:34 -0700951void ArmAssembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700952 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
953}
954
955
Ian Rogers2c8f6532011-09-02 17:16:34 -0700956void ArmAssembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700957 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
958}
959
960
Ian Rogers2c8f6532011-09-02 17:16:34 -0700961void ArmAssembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700962 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
963}
964
965
Ian Rogers2c8f6532011-09-02 17:16:34 -0700966void ArmAssembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700967 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
968}
969
970
Ian Rogers2c8f6532011-09-02 17:16:34 -0700971void ArmAssembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700972 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
973}
974
975
Ian Rogers2c8f6532011-09-02 17:16:34 -0700976void ArmAssembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700977 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
978}
979
980
Ian Rogers2c8f6532011-09-02 17:16:34 -0700981void ArmAssembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700982 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
983}
984
985
Ian Rogers2c8f6532011-09-02 17:16:34 -0700986void ArmAssembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700987 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
988}
989
990
Ian Rogers2c8f6532011-09-02 17:16:34 -0700991void ArmAssembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700992 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
993}
994
995
Ian Rogers2c8f6532011-09-02 17:16:34 -0700996void ArmAssembler::vcmpsz(SRegister sd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700997 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
998}
999
1000
Ian Rogers2c8f6532011-09-02 17:16:34 -07001001void ArmAssembler::vcmpdz(DRegister dd, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001002 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
1003}
1004
1005
Ian Rogers2c8f6532011-09-02 17:16:34 -07001006void ArmAssembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001007 CHECK_NE(cond, kNoCondition);
1008 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1009 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1010 (static_cast<int32_t>(PC)*B12) |
1011 B11 | B9 | B4;
1012 Emit(encoding);
1013}
1014
1015
Ian Rogers2c8f6532011-09-02 17:16:34 -07001016void ArmAssembler::svc(uint32_t imm24) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001017 CHECK(IsUint(24, imm24));
1018 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1019 Emit(encoding);
1020}
1021
1022
Ian Rogers2c8f6532011-09-02 17:16:34 -07001023void ArmAssembler::bkpt(uint16_t imm16) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001024 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1025 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1026 Emit(encoding);
1027}
1028
1029
Ian Rogers2c8f6532011-09-02 17:16:34 -07001030void ArmAssembler::b(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001031 EmitBranch(cond, label, false);
1032}
1033
1034
Ian Rogers2c8f6532011-09-02 17:16:34 -07001035void ArmAssembler::bl(Label* label, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001036 EmitBranch(cond, label, true);
1037}
1038
1039
Ian Rogers2c8f6532011-09-02 17:16:34 -07001040void ArmAssembler::blx(Register rm, Condition cond) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001041 CHECK_NE(rm, kNoRegister);
1042 CHECK_NE(cond, kNoCondition);
1043 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1044 B24 | B21 | (0xfff << 8) | B5 | B4 |
1045 (static_cast<int32_t>(rm) << kRmShift);
1046 Emit(encoding);
1047}
1048
Ian Rogersae675992011-10-09 17:10:22 -07001049void ArmAssembler::bx(Register rm, Condition cond) {
1050 CHECK_NE(rm, kNoRegister);
1051 CHECK_NE(cond, kNoCondition);
1052 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1053 B24 | B21 | (0xfff << 8) | B4 |
1054 (static_cast<int32_t>(rm) << kRmShift);
1055 Emit(encoding);
1056}
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001057
Ian Rogers2c8f6532011-09-02 17:16:34 -07001058void ArmAssembler::MarkExceptionHandler(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001059 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
1060 Label l;
1061 b(&l);
1062 EmitBranch(AL, label, false);
1063 Bind(&l);
1064}
1065
1066
Ian Rogers2c8f6532011-09-02 17:16:34 -07001067void ArmAssembler::Bind(Label* label) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001068 CHECK(!label->IsBound());
1069 int bound_pc = buffer_.Size();
1070 while (label->IsLinked()) {
1071 int32_t position = label->Position();
1072 int32_t next = buffer_.Load<int32_t>(position);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001073 int32_t encoded = ArmAssembler::EncodeBranchOffset(bound_pc - position, next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001074 buffer_.Store<int32_t>(position, encoded);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001075 label->position_ = ArmAssembler::DecodeBranchOffset(next);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001076 }
1077 label->BindTo(bound_pc);
1078}
1079
1080
Ian Rogers2c8f6532011-09-02 17:16:34 -07001081void ArmAssembler::EncodeUint32InTstInstructions(uint32_t data) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001082 // TODO: Consider using movw ip, <16 bits>.
1083 while (!IsUint(8, data)) {
1084 tst(R0, ShifterOperand(data & 0xFF), VS);
1085 data >>= 8;
1086 }
1087 tst(R0, ShifterOperand(data), MI);
1088}
1089
Ian Rogersb033c752011-07-20 12:22:35 -07001090
Ian Rogers2c8f6532011-09-02 17:16:34 -07001091int32_t ArmAssembler::EncodeBranchOffset(int offset, int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001092 // The offset is off by 8 due to the way the ARM CPUs read PC.
1093 offset -= 8;
Elliott Hughes06b37d92011-10-16 11:51:29 -07001094 CHECK_ALIGNED(offset, 4);
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001095 CHECK(IsInt(CountOneBits(kBranchOffsetMask), offset));
1096
1097 // Properly preserve only the bits supported in the instruction.
1098 offset >>= 2;
1099 offset &= kBranchOffsetMask;
1100 return (inst & ~kBranchOffsetMask) | offset;
1101}
1102
1103
Ian Rogers2c8f6532011-09-02 17:16:34 -07001104int ArmAssembler::DecodeBranchOffset(int32_t inst) {
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001105 // Sign-extend, left-shift by 2, then add 8.
1106 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1107}
1108
Ian Rogers2c8f6532011-09-02 17:16:34 -07001109void ArmAssembler::AddConstant(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001110 AddConstant(rd, rd, value, cond);
1111}
1112
1113
Ian Rogers2c8f6532011-09-02 17:16:34 -07001114void ArmAssembler::AddConstant(Register rd, Register rn, int32_t value,
1115 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001116 if (value == 0) {
1117 if (rd != rn) {
1118 mov(rd, ShifterOperand(rn), cond);
1119 }
1120 return;
1121 }
1122 // We prefer to select the shorter code sequence rather than selecting add for
1123 // positive values and sub for negatives ones, which would slightly improve
1124 // the readability of generated code for some constants.
1125 ShifterOperand shifter_op;
1126 if (ShifterOperand::CanHold(value, &shifter_op)) {
1127 add(rd, rn, shifter_op, cond);
1128 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1129 sub(rd, rn, shifter_op, cond);
1130 } else {
1131 CHECK(rn != IP);
1132 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1133 mvn(IP, shifter_op, cond);
1134 add(rd, rn, ShifterOperand(IP), cond);
1135 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1136 mvn(IP, shifter_op, cond);
1137 sub(rd, rn, ShifterOperand(IP), cond);
1138 } else {
1139 movw(IP, Low16Bits(value), cond);
1140 uint16_t value_high = High16Bits(value);
1141 if (value_high != 0) {
1142 movt(IP, value_high, cond);
1143 }
1144 add(rd, rn, ShifterOperand(IP), cond);
1145 }
1146 }
1147}
1148
1149
Ian Rogers2c8f6532011-09-02 17:16:34 -07001150void ArmAssembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1151 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001152 ShifterOperand shifter_op;
1153 if (ShifterOperand::CanHold(value, &shifter_op)) {
1154 adds(rd, rn, shifter_op, cond);
1155 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1156 subs(rd, rn, shifter_op, cond);
1157 } else {
1158 CHECK(rn != IP);
1159 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1160 mvn(IP, shifter_op, cond);
1161 adds(rd, rn, ShifterOperand(IP), cond);
1162 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1163 mvn(IP, shifter_op, cond);
1164 subs(rd, rn, ShifterOperand(IP), cond);
1165 } else {
1166 movw(IP, Low16Bits(value), cond);
1167 uint16_t value_high = High16Bits(value);
1168 if (value_high != 0) {
1169 movt(IP, value_high, cond);
1170 }
1171 adds(rd, rn, ShifterOperand(IP), cond);
1172 }
1173 }
1174}
1175
1176
Ian Rogers2c8f6532011-09-02 17:16:34 -07001177void ArmAssembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001178 ShifterOperand shifter_op;
1179 if (ShifterOperand::CanHold(value, &shifter_op)) {
1180 mov(rd, shifter_op, cond);
1181 } else if (ShifterOperand::CanHold(~value, &shifter_op)) {
1182 mvn(rd, shifter_op, cond);
1183 } else {
1184 movw(rd, Low16Bits(value), cond);
1185 uint16_t value_high = High16Bits(value);
1186 if (value_high != 0) {
1187 movt(rd, value_high, cond);
1188 }
1189 }
1190}
1191
1192
1193bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) {
1194 switch (type) {
1195 case kLoadSignedByte:
1196 case kLoadSignedHalfword:
1197 case kLoadUnsignedHalfword:
1198 case kLoadWordPair:
1199 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1200 case kLoadUnsignedByte:
1201 case kLoadWord:
1202 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1203 case kLoadSWord:
1204 case kLoadDWord:
1205 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1206 default:
1207 LOG(FATAL) << "UNREACHABLE";
1208 return false;
1209 }
1210}
1211
1212
1213bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) {
1214 switch (type) {
1215 case kStoreHalfword:
1216 case kStoreWordPair:
1217 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1218 case kStoreByte:
1219 case kStoreWord:
1220 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1221 case kStoreSWord:
1222 case kStoreDWord:
1223 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1224 default:
1225 LOG(FATAL) << "UNREACHABLE";
1226 return false;
1227 }
1228}
1229
1230
1231// Implementation note: this method must emit at most one instruction when
1232// Address::CanHoldLoadOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001233void ArmAssembler::LoadFromOffset(LoadOperandType type,
Ian Rogersb033c752011-07-20 12:22:35 -07001234 Register reg,
1235 Register base,
1236 int32_t offset,
1237 Condition cond) {
1238 if (!Address::CanHoldLoadOffset(type, offset)) {
1239 CHECK(base != IP);
1240 LoadImmediate(IP, offset, cond);
1241 add(IP, IP, ShifterOperand(base), cond);
1242 base = IP;
1243 offset = 0;
1244 }
1245 CHECK(Address::CanHoldLoadOffset(type, offset));
1246 switch (type) {
1247 case kLoadSignedByte:
1248 ldrsb(reg, Address(base, offset), cond);
1249 break;
1250 case kLoadUnsignedByte:
1251 ldrb(reg, Address(base, offset), cond);
1252 break;
1253 case kLoadSignedHalfword:
1254 ldrsh(reg, Address(base, offset), cond);
1255 break;
1256 case kLoadUnsignedHalfword:
1257 ldrh(reg, Address(base, offset), cond);
1258 break;
1259 case kLoadWord:
1260 ldr(reg, Address(base, offset), cond);
1261 break;
1262 case kLoadWordPair:
1263 ldrd(reg, Address(base, offset), cond);
1264 break;
1265 default:
1266 LOG(FATAL) << "UNREACHABLE";
1267 }
1268}
1269
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001270// Implementation note: this method must emit at most one instruction when
1271// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001272void ArmAssembler::LoadSFromOffset(SRegister reg,
1273 Register base,
1274 int32_t offset,
1275 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001276 if (!Address::CanHoldLoadOffset(kLoadSWord, offset)) {
1277 CHECK_NE(base, IP);
1278 LoadImmediate(IP, offset, cond);
1279 add(IP, IP, ShifterOperand(base), cond);
1280 base = IP;
1281 offset = 0;
1282 }
1283 CHECK(Address::CanHoldLoadOffset(kLoadSWord, offset));
1284 vldrs(reg, Address(base, offset), cond);
1285}
1286
1287// Implementation note: this method must emit at most one instruction when
1288// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001289void ArmAssembler::LoadDFromOffset(DRegister reg,
1290 Register base,
1291 int32_t offset,
1292 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001293 if (!Address::CanHoldLoadOffset(kLoadDWord, offset)) {
1294 CHECK_NE(base, IP);
1295 LoadImmediate(IP, offset, cond);
1296 add(IP, IP, ShifterOperand(base), cond);
1297 base = IP;
1298 offset = 0;
1299 }
1300 CHECK(Address::CanHoldLoadOffset(kLoadDWord, offset));
1301 vldrd(reg, Address(base, offset), cond);
1302}
Ian Rogersb033c752011-07-20 12:22:35 -07001303
1304// Implementation note: this method must emit at most one instruction when
1305// Address::CanHoldStoreOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001306void ArmAssembler::StoreToOffset(StoreOperandType type,
1307 Register reg,
1308 Register base,
1309 int32_t offset,
1310 Condition cond) {
Ian Rogersb033c752011-07-20 12:22:35 -07001311 if (!Address::CanHoldStoreOffset(type, offset)) {
1312 CHECK(reg != IP);
1313 CHECK(base != IP);
1314 LoadImmediate(IP, offset, cond);
1315 add(IP, IP, ShifterOperand(base), cond);
1316 base = IP;
1317 offset = 0;
1318 }
1319 CHECK(Address::CanHoldStoreOffset(type, offset));
1320 switch (type) {
1321 case kStoreByte:
1322 strb(reg, Address(base, offset), cond);
1323 break;
1324 case kStoreHalfword:
1325 strh(reg, Address(base, offset), cond);
1326 break;
1327 case kStoreWord:
1328 str(reg, Address(base, offset), cond);
1329 break;
1330 case kStoreWordPair:
1331 strd(reg, Address(base, offset), cond);
1332 break;
1333 default:
1334 LOG(FATAL) << "UNREACHABLE";
1335 }
1336}
1337
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001338// Implementation note: this method must emit at most one instruction when
1339// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001340void ArmAssembler::StoreSToOffset(SRegister reg,
1341 Register base,
1342 int32_t offset,
1343 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001344 if (!Address::CanHoldStoreOffset(kStoreSWord, offset)) {
1345 CHECK_NE(base, IP);
1346 LoadImmediate(IP, offset, cond);
1347 add(IP, IP, ShifterOperand(base), cond);
1348 base = IP;
1349 offset = 0;
1350 }
1351 CHECK(Address::CanHoldStoreOffset(kStoreSWord, offset));
1352 vstrs(reg, Address(base, offset), cond);
1353}
1354
1355// Implementation note: this method must emit at most one instruction when
1356// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreSToOffset.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001357void ArmAssembler::StoreDToOffset(DRegister reg,
1358 Register base,
1359 int32_t offset,
1360 Condition cond) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001361 if (!Address::CanHoldStoreOffset(kStoreDWord, offset)) {
1362 CHECK_NE(base, IP);
1363 LoadImmediate(IP, offset, cond);
1364 add(IP, IP, ShifterOperand(base), cond);
1365 base = IP;
1366 offset = 0;
1367 }
1368 CHECK(Address::CanHoldStoreOffset(kStoreDWord, offset));
1369 vstrd(reg, Address(base, offset), cond);
1370}
1371
Ian Rogers2c8f6532011-09-02 17:16:34 -07001372void ArmAssembler::Push(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001373 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1374}
1375
Ian Rogers2c8f6532011-09-02 17:16:34 -07001376void ArmAssembler::Pop(Register rd, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001377 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1378}
1379
Ian Rogers2c8f6532011-09-02 17:16:34 -07001380void ArmAssembler::PushList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001381 stm(DB_W, SP, regs, cond);
1382}
1383
Ian Rogers2c8f6532011-09-02 17:16:34 -07001384void ArmAssembler::PopList(RegList regs, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001385 ldm(IA_W, SP, regs, cond);
1386}
1387
Ian Rogers2c8f6532011-09-02 17:16:34 -07001388void ArmAssembler::Mov(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001389 if (rd != rm) {
1390 mov(rd, ShifterOperand(rm), cond);
1391 }
1392}
1393
Ian Rogers2c8f6532011-09-02 17:16:34 -07001394void ArmAssembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
1395 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001396 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
1397 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1398}
1399
Ian Rogers2c8f6532011-09-02 17:16:34 -07001400void ArmAssembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
1401 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001402 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
1403 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1404 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1405}
1406
Ian Rogers2c8f6532011-09-02 17:16:34 -07001407void ArmAssembler::Asr(Register rd, Register rm, uint32_t shift_imm,
1408 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001409 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
1410 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1411 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1412}
1413
Ian Rogers2c8f6532011-09-02 17:16:34 -07001414void ArmAssembler::Ror(Register rd, Register rm, uint32_t shift_imm,
1415 Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001416 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
1417 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1418}
1419
Ian Rogers2c8f6532011-09-02 17:16:34 -07001420void ArmAssembler::Rrx(Register rd, Register rm, Condition cond) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001421 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1422}
1423
Ian Rogers2c8f6532011-09-02 17:16:34 -07001424void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersbdb03912011-09-14 00:55:44 -07001425 const std::vector<ManagedRegister>& callee_save_regs) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001426 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001427 CHECK_EQ(R0, method_reg.AsArm().AsCoreRegister());
Ian Rogersbdb03912011-09-14 00:55:44 -07001428
1429 // Push callee saves and link register
1430 RegList push_list = 1 << LR;
1431 size_t pushed_values = 1;
1432 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1433 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1434 push_list |= 1 << reg;
1435 pushed_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001436 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001437 PushList(push_list);
1438
1439 // Increase frame to required size
1440 CHECK_GT(frame_size, pushed_values * kPointerSize); // Must be at least space to push Method*
1441 size_t adjust = frame_size - (pushed_values * kPointerSize);
1442 IncreaseFrameSize(adjust);
1443
1444 // Write out Method*
1445 StoreToOffset(kStoreWord, R0, SP, 0);
Ian Rogersb033c752011-07-20 12:22:35 -07001446}
1447
Ian Rogers2c8f6532011-09-02 17:16:34 -07001448void ArmAssembler::RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -07001449 const std::vector<ManagedRegister>& callee_save_regs) {
Elliott Hughes06b37d92011-10-16 11:51:29 -07001450 CHECK_ALIGNED(frame_size, kStackAlignment);
Ian Rogersbdb03912011-09-14 00:55:44 -07001451 // Compute callee saves to pop and PC
1452 RegList pop_list = 1 << PC;
1453 size_t pop_values = 1;
1454 for (size_t i = 0; i < callee_save_regs.size(); i++) {
1455 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
1456 pop_list |= 1 << reg;
1457 pop_values++;
Ian Rogers0d666d82011-08-14 16:03:46 -07001458 }
Ian Rogersbdb03912011-09-14 00:55:44 -07001459
1460 // Decrease frame to start of callee saves
1461 CHECK_GT(frame_size, pop_values * kPointerSize);
1462 size_t adjust = frame_size - (pop_values * kPointerSize);
1463 DecreaseFrameSize(adjust);
1464
1465 // Pop callee saves and PC
1466 PopList(pop_list);
Ian Rogers0d666d82011-08-14 16:03:46 -07001467}
1468
Ian Rogers2c8f6532011-09-02 17:16:34 -07001469void ArmAssembler::IncreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001470 AddConstant(SP, -adjust);
1471}
1472
Ian Rogers2c8f6532011-09-02 17:16:34 -07001473void ArmAssembler::DecreaseFrameSize(size_t adjust) {
Ian Rogersb033c752011-07-20 12:22:35 -07001474 AddConstant(SP, adjust);
1475}
1476
Ian Rogers2c8f6532011-09-02 17:16:34 -07001477void ArmAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
1478 ArmManagedRegister src = msrc.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001479 if (src.IsNoRegister()) {
1480 CHECK_EQ(0u, size);
1481 } else if (src.IsCoreRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001482 CHECK_EQ(4u, size);
1483 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001484 } else if (src.IsRegisterPair()) {
1485 CHECK_EQ(8u, size);
1486 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
1487 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
1488 SP, dest.Int32Value() + 4);
1489 } else if (src.IsSRegister()) {
1490 StoreSToOffset(src.AsSRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001491 } else {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001492 CHECK(src.IsDRegister());
1493 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001494 }
1495}
1496
Ian Rogers2c8f6532011-09-02 17:16:34 -07001497void ArmAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
1498 ArmManagedRegister src = msrc.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001499 CHECK(src.IsCoreRegister());
1500 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1501}
1502
Ian Rogers2c8f6532011-09-02 17:16:34 -07001503void ArmAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
1504 ArmManagedRegister src = msrc.AsArm();
Ian Rogersdf20fe02011-07-20 20:34:16 -07001505 CHECK(src.IsCoreRegister());
1506 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1507}
1508
Ian Rogers2c8f6532011-09-02 17:16:34 -07001509void ArmAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
1510 FrameOffset in_off, ManagedRegister mscratch) {
1511 ArmManagedRegister src = msrc.AsArm();
1512 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers7a99c112011-09-07 12:48:27 -07001513 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1514 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
1515 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
1516}
1517
Ian Rogers2c8f6532011-09-02 17:16:34 -07001518void ArmAssembler::CopyRef(FrameOffset dest, FrameOffset src,
1519 ManagedRegister mscratch) {
1520 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001521 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1522 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1523}
1524
Ian Rogers2c8f6532011-09-02 17:16:34 -07001525void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
1526 MemberOffset offs) {
1527 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001528 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
1529 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001530 base.AsArm().AsCoreRegister(), offs.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001531}
1532
Ian Rogers2c8f6532011-09-02 17:16:34 -07001533void ArmAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
1534 ArmManagedRegister dest = mdest.AsArm();
1535 CHECK(dest.IsCoreRegister());
1536 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
1537 SP, src.Int32Value());
1538 }
1539
1540void ArmAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
Ian Rogersa04d3972011-08-17 11:33:44 -07001541 Offset offs) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001542 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersa04d3972011-08-17 11:33:44 -07001543 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
1544 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
Ian Rogers2c8f6532011-09-02 17:16:34 -07001545 base.AsArm().AsCoreRegister(), offs.Int32Value());
Ian Rogersa04d3972011-08-17 11:33:44 -07001546}
1547
Ian Rogers2c8f6532011-09-02 17:16:34 -07001548void ArmAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1549 ManagedRegister mscratch) {
1550 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001551 CHECK(scratch.IsCoreRegister());
1552 LoadImmediate(scratch.AsCoreRegister(), imm);
1553 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1554}
1555
Ian Rogers2c8f6532011-09-02 17:16:34 -07001556void ArmAssembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
1557 ManagedRegister mscratch) {
1558 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001559 CHECK(scratch.IsCoreRegister());
1560 LoadImmediate(scratch.AsCoreRegister(), imm);
1561 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), TR, dest.Int32Value());
1562}
1563
Ian Rogers2c8f6532011-09-02 17:16:34 -07001564void ArmAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
1565 ArmManagedRegister dest = mdest.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001566 if (dest.IsNoRegister()) {
1567 CHECK_EQ(0u, size);
1568 } else if (dest.IsCoreRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001569 CHECK_EQ(4u, size);
1570 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001571 } else if (dest.IsRegisterPair()) {
1572 CHECK_EQ(8u, size);
1573 LoadFromOffset(kLoadWord, dest.AsRegisterPairLow(), SP, src.Int32Value());
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001574 LoadFromOffset(kLoadWord, dest.AsRegisterPairHigh(), SP, src.Int32Value() + 4);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001575 } else if (dest.IsSRegister()) {
1576 LoadSFromOffset(dest.AsSRegister(), SP, src.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001577 } else {
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001578 CHECK(dest.IsDRegister());
1579 LoadDFromOffset(dest.AsDRegister(), SP, src.Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -07001580 }
1581}
1582
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001583void ArmAssembler::Load(ManagedRegister mdest, ThreadOffset src, size_t size) {
1584 ArmManagedRegister dest = mdest.AsArm();
1585 if (dest.IsNoRegister()) {
1586 CHECK_EQ(0u, size);
1587 } else if (dest.IsCoreRegister()) {
1588 CHECK_EQ(4u, size);
1589 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), TR, src.Int32Value());
1590 } else if (dest.IsRegisterPair()) {
1591 CHECK_EQ(8u, size);
1592 LoadFromOffset(kLoadWord, dest.AsRegisterPairLow(), TR, src.Int32Value());
1593 LoadFromOffset(kLoadWord, dest.AsRegisterPairHigh(), TR, src.Int32Value() + 4);
1594 } else if (dest.IsSRegister()) {
1595 LoadSFromOffset(dest.AsSRegister(), TR, src.Int32Value());
1596 } else {
1597 CHECK(dest.IsDRegister());
1598 LoadDFromOffset(dest.AsDRegister(), TR, src.Int32Value());
1599 }
1600}
1601
Ian Rogers2c8f6532011-09-02 17:16:34 -07001602void ArmAssembler::LoadRawPtrFromThread(ManagedRegister mdest,
1603 ThreadOffset offs) {
1604 ArmManagedRegister dest = mdest.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001605 CHECK(dest.IsCoreRegister());
1606 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
1607 TR, offs.Int32Value());
1608}
1609
Ian Rogers2c8f6532011-09-02 17:16:34 -07001610void ArmAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
1611 ThreadOffset thr_offs,
1612 ManagedRegister mscratch) {
1613 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001614 CHECK(scratch.IsCoreRegister());
1615 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1616 TR, thr_offs.Int32Value());
1617 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1618 SP, fr_offs.Int32Value());
1619}
1620
Ian Rogers2c8f6532011-09-02 17:16:34 -07001621void ArmAssembler::CopyRawPtrToThread(ThreadOffset thr_offs,
1622 FrameOffset fr_offs,
1623 ManagedRegister mscratch) {
1624 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001625 CHECK(scratch.IsCoreRegister());
1626 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1627 SP, fr_offs.Int32Value());
1628 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1629 TR, thr_offs.Int32Value());
1630}
1631
Ian Rogers2c8f6532011-09-02 17:16:34 -07001632void ArmAssembler::StoreStackOffsetToThread(ThreadOffset thr_offs,
1633 FrameOffset fr_offs,
1634 ManagedRegister mscratch) {
1635 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001636 CHECK(scratch.IsCoreRegister());
1637 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value(), AL);
1638 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1639 TR, thr_offs.Int32Value());
1640}
1641
Ian Rogers2c8f6532011-09-02 17:16:34 -07001642void ArmAssembler::StoreStackPointerToThread(ThreadOffset thr_offs) {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001643 StoreToOffset(kStoreWord, SP, TR, thr_offs.Int32Value());
1644}
1645
Ian Rogers2c8f6532011-09-02 17:16:34 -07001646void ArmAssembler::Move(ManagedRegister mdest, ManagedRegister msrc) {
1647 ArmManagedRegister dest = mdest.AsArm();
1648 ArmManagedRegister src = msrc.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001649 if (!dest.Equals(src)) {
1650 if (dest.IsCoreRegister()) {
1651 CHECK(src.IsCoreRegister());
1652 mov(dest.AsCoreRegister(), ShifterOperand(src.AsCoreRegister()));
Ian Rogers7a99c112011-09-07 12:48:27 -07001653 } else if (dest.IsDRegister()) {
1654 CHECK(src.IsDRegister());
1655 vmovd(dest.AsDRegister(), src.AsDRegister());
1656 } else if (dest.IsSRegister()) {
1657 CHECK(src.IsSRegister());
1658 vmovs(dest.AsSRegister(), src.AsSRegister());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001659 } else {
Ian Rogers7a99c112011-09-07 12:48:27 -07001660 CHECK(dest.IsRegisterPair());
1661 CHECK(src.IsRegisterPair());
1662 // Ensure that the first move doesn't clobber the input of the second
1663 if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
1664 mov(dest.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
1665 mov(dest.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
1666 } else {
1667 mov(dest.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh()));
1668 mov(dest.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow()));
1669 }
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001670 }
Ian Rogersb033c752011-07-20 12:22:35 -07001671 }
1672}
1673
Ian Rogersdc51b792011-09-22 20:41:37 -07001674void ArmAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
Ian Rogers2c8f6532011-09-02 17:16:34 -07001675 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001676 CHECK(scratch.IsCoreRegister());
Shih-wei Liao5381cf92011-07-27 00:28:04 -07001677 CHECK(size == 4 || size == 8);
Ian Rogersb033c752011-07-20 12:22:35 -07001678 if (size == 4) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001679 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1680 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
Shih-wei Liao5381cf92011-07-27 00:28:04 -07001681 } else if (size == 8) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001682 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1683 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1684 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4);
1685 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
Ian Rogersb033c752011-07-20 12:22:35 -07001686 }
1687}
1688
Ian Rogersdc51b792011-09-22 20:41:37 -07001689void ArmAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
1690 ManagedRegister mscratch, size_t size) {
1691 Register scratch = mscratch.AsArm().AsCoreRegister();
1692 CHECK_EQ(size, 4u);
1693 LoadFromOffset(kLoadWord, scratch, src_base.AsArm().AsCoreRegister(), src_offset.Int32Value());
1694 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
1695}
1696
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001697void ArmAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
1698 ManagedRegister mscratch, size_t size) {
1699 Register scratch = mscratch.AsArm().AsCoreRegister();
1700 CHECK_EQ(size, 4u);
1701 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
1702 StoreToOffset(kStoreWord, scratch, dest_base.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1703}
1704
Ian Rogersdc51b792011-09-22 20:41:37 -07001705void ArmAssembler::Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
1706 ManagedRegister mscratch, size_t size) {
1707 UNIMPLEMENTED(FATAL);
1708}
1709
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001710void ArmAssembler::Copy(ManagedRegister dest, Offset dest_offset,
1711 ManagedRegister src, Offset src_offset,
1712 ManagedRegister mscratch, size_t size) {
Ian Rogersdc51b792011-09-22 20:41:37 -07001713 CHECK_EQ(size, 4u);
Ian Rogers5a7a74a2011-09-26 16:32:29 -07001714 Register scratch = mscratch.AsArm().AsCoreRegister();
1715 LoadFromOffset(kLoadWord, scratch, src.AsArm().AsCoreRegister(), src_offset.Int32Value());
1716 StoreToOffset(kStoreWord, scratch, dest.AsArm().AsCoreRegister(), dest_offset.Int32Value());
1717}
1718
1719void ArmAssembler::Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
1720 ManagedRegister scratch, size_t size) {
1721 UNIMPLEMENTED(FATAL);
Ian Rogersdc51b792011-09-22 20:41:37 -07001722}
1723
1724
Ian Rogerse5de95b2011-09-18 20:31:38 -07001725void ArmAssembler::MemoryBarrier(ManagedRegister mscratch) {
1726#if ANDROID_SMP != 0
1727#if defined(__ARM_HAVE_DMB)
1728 int32_t encoding = 0xf57ff05f; // dmb
1729 Emit(encoding);
1730#elif defined(__ARM_HAVE_LDREX_STREX)
1731 CHECK(mscratch.AsArm().AsCoreRegister() == R12);
1732 LoadImmediate(R12, 0);
1733 int32_t encoding = 0xee07cfba; // mcr p15, 0, r12, c7, c10, 5
1734 Emit(encoding);
1735#else
1736 CHECK(mscratch.AsArm().AsCoreRegister() == R12);
1737 LoadImmediate(R12, 0xffff0fa0); // kuser_memory_barrier
1738 blx(R12);
1739#endif
1740#endif
1741}
1742
Ian Rogers2c8f6532011-09-02 17:16:34 -07001743void ArmAssembler::CreateSirtEntry(ManagedRegister mout_reg,
1744 FrameOffset sirt_offset,
1745 ManagedRegister min_reg, bool null_allowed) {
1746 ArmManagedRegister out_reg = mout_reg.AsArm();
1747 ArmManagedRegister in_reg = min_reg.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001748 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister());
Ian Rogersb033c752011-07-20 12:22:35 -07001749 CHECK(out_reg.IsCoreRegister());
1750 if (null_allowed) {
Ian Rogers408f79a2011-08-23 18:22:33 -07001751 // Null values get a SIRT entry value of 0. Otherwise, the SIRT entry is
1752 // the address in the SIRT holding the reference.
Ian Rogersb033c752011-07-20 12:22:35 -07001753 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001754 if (in_reg.IsNoRegister()) {
1755 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
Ian Rogers408f79a2011-08-23 18:22:33 -07001756 SP, sirt_offset.Int32Value());
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001757 in_reg = out_reg;
1758 }
Ian Rogersb033c752011-07-20 12:22:35 -07001759 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
1760 if (!out_reg.Equals(in_reg)) {
1761 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1762 }
Ian Rogers408f79a2011-08-23 18:22:33 -07001763 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001764 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001765 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001766 }
1767}
1768
Ian Rogers2c8f6532011-09-02 17:16:34 -07001769void ArmAssembler::CreateSirtEntry(FrameOffset out_off,
1770 FrameOffset sirt_offset,
1771 ManagedRegister mscratch,
1772 bool null_allowed) {
1773 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001774 CHECK(scratch.IsCoreRegister());
1775 if (null_allowed) {
1776 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
Ian Rogers408f79a2011-08-23 18:22:33 -07001777 sirt_offset.Int32Value());
1778 // Null values get a SIRT entry value of 0. Otherwise, the sirt entry is
1779 // the address in the SIRT holding the reference.
1780 // e.g. scratch = (scratch == 0) ? 0 : (SP+sirt_offset)
Ian Rogersb033c752011-07-20 12:22:35 -07001781 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
Ian Rogers408f79a2011-08-23 18:22:33 -07001782 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001783 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001784 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL);
Ian Rogersb033c752011-07-20 12:22:35 -07001785 }
1786 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
1787}
1788
Ian Rogers2c8f6532011-09-02 17:16:34 -07001789void ArmAssembler::LoadReferenceFromSirt(ManagedRegister mout_reg,
1790 ManagedRegister min_reg) {
1791 ArmManagedRegister out_reg = mout_reg.AsArm();
1792 ArmManagedRegister in_reg = min_reg.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001793 CHECK(out_reg.IsCoreRegister());
1794 CHECK(in_reg.IsCoreRegister());
1795 Label null_arg;
1796 if (!out_reg.Equals(in_reg)) {
1797 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1798 }
1799 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
Ian Rogersdf20fe02011-07-20 20:34:16 -07001800 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
1801 in_reg.AsCoreRegister(), 0, NE);
Ian Rogersb033c752011-07-20 12:22:35 -07001802}
1803
Ian Rogers2c8f6532011-09-02 17:16:34 -07001804void ArmAssembler::VerifyObject(ManagedRegister src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001805 // TODO: not validating references
1806}
1807
Ian Rogers2c8f6532011-09-02 17:16:34 -07001808void ArmAssembler::VerifyObject(FrameOffset src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001809 // TODO: not validating references
1810}
1811
Ian Rogers2c8f6532011-09-02 17:16:34 -07001812void ArmAssembler::Call(ManagedRegister mbase, Offset offset,
1813 ManagedRegister mscratch) {
1814 ArmManagedRegister base = mbase.AsArm();
1815 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogersb033c752011-07-20 12:22:35 -07001816 CHECK(base.IsCoreRegister());
1817 CHECK(scratch.IsCoreRegister());
1818 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1819 base.AsCoreRegister(), offset.Int32Value());
1820 blx(scratch.AsCoreRegister());
1821 // TODO: place reference map on call
1822}
1823
Ian Rogers2c8f6532011-09-02 17:16:34 -07001824void ArmAssembler::Call(FrameOffset base, Offset offset,
1825 ManagedRegister mscratch) {
1826 ArmManagedRegister scratch = mscratch.AsArm();
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001827 CHECK(scratch.IsCoreRegister());
1828 // Call *(*(SP + base) + offset)
1829 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1830 SP, base.Int32Value());
1831 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1832 scratch.AsCoreRegister(), offset.Int32Value());
1833 blx(scratch.AsCoreRegister());
1834 // TODO: place reference map on call
1835}
1836
Ian Rogersbdb03912011-09-14 00:55:44 -07001837void ArmAssembler::Call(ThreadOffset offset, ManagedRegister scratch) {
1838 UNIMPLEMENTED(FATAL);
1839}
1840
Ian Rogers2c8f6532011-09-02 17:16:34 -07001841void ArmAssembler::GetCurrentThread(ManagedRegister tr) {
1842 mov(tr.AsArm().AsCoreRegister(), ShifterOperand(TR));
Shih-wei Liao668512a2011-09-01 14:18:34 -07001843}
1844
Ian Rogers2c8f6532011-09-02 17:16:34 -07001845void ArmAssembler::GetCurrentThread(FrameOffset offset,
1846 ManagedRegister scratch) {
Shih-wei Liao668512a2011-09-01 14:18:34 -07001847 StoreToOffset(kStoreWord, TR, SP, offset.Int32Value(), AL);
1848}
1849
Ian Rogers2c8f6532011-09-02 17:16:34 -07001850void ArmAssembler::SuspendPoll(ManagedRegister mscratch,
1851 ManagedRegister return_reg,
1852 FrameOffset return_save_location,
1853 size_t return_size) {
1854 ArmManagedRegister scratch = mscratch.AsArm();
1855 ArmSuspendCountSlowPath* slow =
1856 new ArmSuspendCountSlowPath(return_reg.AsArm(), return_save_location,
1857 return_size);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001858 buffer_.EnqueueSlowPath(slow);
1859 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1860 TR, Thread::SuspendCountOffset().Int32Value());
1861 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1862 b(slow->Entry(), NE);
1863 Bind(slow->Continuation());
1864}
1865
Ian Rogers2c8f6532011-09-02 17:16:34 -07001866void ArmSuspendCountSlowPath::Emit(Assembler* sasm) {
1867 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm);
1868#define __ sp_asm->
1869 __ Bind(&entry_);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001870 // Save return value
Ian Rogers2c8f6532011-09-02 17:16:34 -07001871 __ Store(return_save_location_, return_register_, return_size_);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001872 // Pass thread as argument
1873 __ mov(R0, ShifterOperand(TR));
1874 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode));
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001875 // Note: assume that link register will be spilled/filled on method entry/exit
Ian Rogers2c8f6532011-09-02 17:16:34 -07001876 __ blx(R12);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001877 // Reload return value
Ian Rogers2c8f6532011-09-02 17:16:34 -07001878 __ Load(return_register_, return_save_location_, return_size_);
1879 __ b(&continuation_);
1880#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001881}
1882
Ian Rogers2c8f6532011-09-02 17:16:34 -07001883void ArmAssembler::ExceptionPoll(ManagedRegister mscratch) {
1884 ArmManagedRegister scratch = mscratch.AsArm();
Ian Rogers67375ac2011-09-14 00:55:44 -07001885 ArmExceptionSlowPath* slow = new ArmExceptionSlowPath(scratch);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001886 buffer_.EnqueueSlowPath(slow);
1887 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1888 TR, Thread::ExceptionOffset().Int32Value());
1889 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1890 b(slow->Entry(), NE);
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001891}
1892
Ian Rogers2c8f6532011-09-02 17:16:34 -07001893void ArmExceptionSlowPath::Emit(Assembler* sasm) {
1894 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm);
1895#define __ sp_asm->
1896 __ Bind(&entry_);
Ian Rogers67375ac2011-09-14 00:55:44 -07001897
1898 // Pass exception object as argument
1899 // Don't care about preserving R0 as this call won't return
1900 __ mov(R0, ShifterOperand(scratch_.AsCoreRegister()));
1901 // Set up call to Thread::Current()->pDeliverException
1902 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pDeliverException));
Ian Rogers2c8f6532011-09-02 17:16:34 -07001903 __ blx(R12);
Ian Rogers67375ac2011-09-14 00:55:44 -07001904 // Call never returns
1905 __ bkpt(0);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001906#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001907}
1908
Ian Rogers2c8f6532011-09-02 17:16:34 -07001909} // namespace arm
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07001910} // namespace art