blob: 91c259ef029090c84a958c9c3d6ec3b51c120163 [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "src/assembler.h"
Carl Shapiroa2e18e12011-06-21 18:57:55 -07004#include "src/logging.h"
Ian Rogersb033c752011-07-20 12:22:35 -07005#include "src/utils.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07006
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07007namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07008
Carl Shapiroa2e18e12011-06-21 18:57:55 -07009// Instruction encoding bits.
10enum {
11 H = 1 << 5, // halfword (or byte)
12 L = 1 << 20, // load (or store)
13 S = 1 << 20, // set condition code (or leave unchanged)
14 W = 1 << 21, // writeback base register (or leave unchanged)
15 A = 1 << 21, // accumulate in multiply instruction (or not)
16 B = 1 << 22, // unsigned byte (or word)
17 N = 1 << 22, // long (or short)
18 U = 1 << 23, // positive (or negative) offset/index
19 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
20 I = 1 << 25, // immediate shifter operand (or not)
21
22 B0 = 1,
23 B1 = 1 << 1,
24 B2 = 1 << 2,
25 B3 = 1 << 3,
26 B4 = 1 << 4,
27 B5 = 1 << 5,
28 B6 = 1 << 6,
29 B7 = 1 << 7,
30 B8 = 1 << 8,
31 B9 = 1 << 9,
32 B10 = 1 << 10,
33 B11 = 1 << 11,
34 B12 = 1 << 12,
35 B16 = 1 << 16,
36 B17 = 1 << 17,
37 B18 = 1 << 18,
38 B19 = 1 << 19,
39 B20 = 1 << 20,
40 B21 = 1 << 21,
41 B22 = 1 << 22,
42 B23 = 1 << 23,
43 B24 = 1 << 24,
44 B25 = 1 << 25,
45 B26 = 1 << 26,
46 B27 = 1 << 27,
47
48 // Instruction bit masks.
49 RdMask = 15 << 12, // in str instruction
50 CondMask = 15 << 28,
51 CoprocessorMask = 15 << 8,
52 OpCodeMask = 15 << 21, // in data-processing instructions
53 Imm24Mask = (1 << 24) - 1,
54 Off12Mask = (1 << 12) - 1,
55
56 // ldrex/strex register field encodings.
57 kLdExRnShift = 16,
58 kLdExRtShift = 12,
59 kStrExRnShift = 16,
60 kStrExRdShift = 12,
61 kStrExRtShift = 0,
62};
63
64
Elliott Hughes1f359b02011-07-17 14:27:17 -070065static const char* kRegisterNames[] = {
66 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
67 "fp", "ip", "sp", "lr", "pc"
68};
69std::ostream& operator<<(std::ostream& os, const Register& rhs) {
70 if (rhs >= R0 && rhs <= PC) {
71 os << kRegisterNames[rhs];
72 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070073 os << "Register[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070074 }
75 return os;
76}
77
78
79std::ostream& operator<<(std::ostream& os, const SRegister& rhs) {
80 if (rhs >= S0 && rhs < kNumberOfSRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -070081 os << "s" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -070082 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070083 os << "SRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070084 }
85 return os;
86}
87
88
89std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
90 if (rhs >= D0 && rhs < kNumberOfDRegisters) {
Ian Rogersb033c752011-07-20 12:22:35 -070091 os << "d" << static_cast<int>(rhs);
Elliott Hughes1f359b02011-07-17 14:27:17 -070092 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070093 os << "DRegister[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070094 }
95 return os;
96}
97
98
99static const char* kConditionNames[] = {
Ian Rogersb033c752011-07-20 12:22:35 -0700100 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT",
101 "LE", "AL",
Elliott Hughes1f359b02011-07-17 14:27:17 -0700102};
103std::ostream& operator<<(std::ostream& os, const Condition& rhs) {
104 if (rhs >= EQ && rhs <= AL) {
105 os << kConditionNames[rhs];
106 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700107 os << "Condition[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700108 }
109 return os;
110}
111
112
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700113void Assembler::Emit(int32_t value) {
114 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
115 buffer_.Emit<int32_t>(value);
116}
117
118
119void Assembler::EmitType01(Condition cond,
120 int type,
121 Opcode opcode,
122 int set_cc,
123 Register rn,
124 Register rd,
125 ShifterOperand so) {
126 CHECK_NE(rd, kNoRegister);
127 CHECK_NE(cond, kNoCondition);
128 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
129 type << kTypeShift |
130 static_cast<int32_t>(opcode) << kOpcodeShift |
131 set_cc << kSShift |
132 static_cast<int32_t>(rn) << kRnShift |
133 static_cast<int32_t>(rd) << kRdShift |
134 so.encoding();
135 Emit(encoding);
136}
137
138
139void Assembler::EmitType5(Condition cond, int offset, bool link) {
140 CHECK_NE(cond, kNoCondition);
141 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
142 5 << kTypeShift |
143 (link ? 1 : 0) << kLinkShift;
144 Emit(Assembler::EncodeBranchOffset(offset, encoding));
145}
146
147
148void Assembler::EmitMemOp(Condition cond,
149 bool load,
150 bool byte,
151 Register rd,
152 Address ad) {
153 CHECK_NE(rd, kNoRegister);
154 CHECK_NE(cond, kNoCondition);
155 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
156 B26 |
157 (load ? L : 0) |
158 (byte ? B : 0) |
159 (static_cast<int32_t>(rd) << kRdShift) |
160 ad.encoding();
161 Emit(encoding);
162}
163
164
165void Assembler::EmitMemOpAddressMode3(Condition cond,
166 int32_t mode,
167 Register rd,
168 Address ad) {
169 CHECK_NE(rd, kNoRegister);
170 CHECK_NE(cond, kNoCondition);
171 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
172 B22 |
173 mode |
174 (static_cast<int32_t>(rd) << kRdShift) |
175 ad.encoding3();
176 Emit(encoding);
177}
178
179
180void Assembler::EmitMultiMemOp(Condition cond,
181 BlockAddressMode am,
182 bool load,
183 Register base,
184 RegList regs) {
185 CHECK_NE(base, kNoRegister);
186 CHECK_NE(cond, kNoCondition);
187 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
188 B27 |
189 am |
190 (load ? L : 0) |
191 (static_cast<int32_t>(base) << kRnShift) |
192 regs;
193 Emit(encoding);
194}
195
196
197void Assembler::EmitShiftImmediate(Condition cond,
198 Shift opcode,
199 Register rd,
200 Register rm,
201 ShifterOperand so) {
202 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700203 CHECK_EQ(so.type(), 1U);
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700204 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
205 static_cast<int32_t>(MOV) << kOpcodeShift |
206 static_cast<int32_t>(rd) << kRdShift |
207 so.encoding() << kShiftImmShift |
208 static_cast<int32_t>(opcode) << kShiftShift |
209 static_cast<int32_t>(rm);
210 Emit(encoding);
211}
212
213
214void Assembler::EmitShiftRegister(Condition cond,
215 Shift opcode,
216 Register rd,
217 Register rm,
218 ShifterOperand so) {
219 CHECK_NE(cond, kNoCondition);
Elliott Hughes1f359b02011-07-17 14:27:17 -0700220 CHECK_EQ(so.type(), 0U);
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() << kShiftRegisterShift |
225 static_cast<int32_t>(opcode) << kShiftShift |
226 B4 |
227 static_cast<int32_t>(rm);
228 Emit(encoding);
229}
230
231
232void Assembler::EmitBranch(Condition cond, Label* label, bool link) {
233 if (label->IsBound()) {
234 EmitType5(cond, label->Position() - buffer_.Size(), link);
235 } else {
236 int position = buffer_.Size();
237 // Use the offset field of the branch instruction for linking the sites.
238 EmitType5(cond, label->position_, link);
239 label->LinkTo(position);
240 }
241}
242
243
244void Assembler::and_(Register rd, Register rn, ShifterOperand so,
245 Condition cond) {
246 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
247}
248
249
250void Assembler::eor(Register rd, Register rn, ShifterOperand so,
251 Condition cond) {
252 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
253}
254
255
256void Assembler::sub(Register rd, Register rn, ShifterOperand so,
257 Condition cond) {
258 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
259}
260
261void Assembler::rsb(Register rd, Register rn, ShifterOperand so,
262 Condition cond) {
263 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
264}
265
266void Assembler::rsbs(Register rd, Register rn, ShifterOperand so,
267 Condition cond) {
268 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
269}
270
271
272void Assembler::add(Register rd, Register rn, ShifterOperand so,
273 Condition cond) {
274 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
275}
276
277
278void Assembler::adds(Register rd, Register rn, ShifterOperand so,
279 Condition cond) {
280 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
281}
282
283
284void Assembler::subs(Register rd, Register rn, ShifterOperand so,
285 Condition cond) {
286 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
287}
288
289
290void Assembler::adc(Register rd, Register rn, ShifterOperand so,
291 Condition cond) {
292 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
293}
294
295
296void Assembler::sbc(Register rd, Register rn, ShifterOperand so,
297 Condition cond) {
298 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
299}
300
301
302void Assembler::rsc(Register rd, Register rn, ShifterOperand so,
303 Condition cond) {
304 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
305}
306
307
308void Assembler::tst(Register rn, ShifterOperand so, Condition cond) {
309 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
310 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
311}
312
313
314void Assembler::teq(Register rn, ShifterOperand so, Condition cond) {
315 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
316 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
317}
318
319
320void Assembler::cmp(Register rn, ShifterOperand so, Condition cond) {
321 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
322}
323
324
325void Assembler::cmn(Register rn, ShifterOperand so, Condition cond) {
326 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
327}
328
329
330void Assembler::orr(Register rd, Register rn,
331 ShifterOperand so, Condition cond) {
332 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
333}
334
335
336void Assembler::orrs(Register rd, Register rn,
337 ShifterOperand so, Condition cond) {
338 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
339}
340
341
342void Assembler::mov(Register rd, ShifterOperand so, Condition cond) {
343 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
344}
345
346
347void Assembler::movs(Register rd, ShifterOperand so, Condition cond) {
348 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
349}
350
351
352void Assembler::bic(Register rd, Register rn, ShifterOperand so,
353 Condition cond) {
354 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
355}
356
357
358void Assembler::mvn(Register rd, ShifterOperand so, Condition cond) {
359 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
360}
361
362
363void Assembler::mvns(Register rd, ShifterOperand so, Condition cond) {
364 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
365}
366
367
368void Assembler::clz(Register rd, Register rm, Condition cond) {
369 CHECK_NE(rd, kNoRegister);
370 CHECK_NE(rm, kNoRegister);
371 CHECK_NE(cond, kNoCondition);
372 CHECK_NE(rd, PC);
373 CHECK_NE(rm, PC);
374 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
375 B24 | B22 | B21 | (0xf << 16) |
376 (static_cast<int32_t>(rd) << kRdShift) |
377 (0xf << 8) | B4 | static_cast<int32_t>(rm);
378 Emit(encoding);
379}
380
381
382void Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
383 CHECK_NE(cond, kNoCondition);
384 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
385 B25 | B24 | ((imm16 >> 12) << 16) |
386 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
387 Emit(encoding);
388}
389
390
391void Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
392 CHECK_NE(cond, kNoCondition);
393 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
394 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
395 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
396 Emit(encoding);
397}
398
399
400void Assembler::EmitMulOp(Condition cond, int32_t opcode,
401 Register rd, Register rn,
402 Register rm, Register rs) {
403 CHECK_NE(rd, kNoRegister);
404 CHECK_NE(rn, kNoRegister);
405 CHECK_NE(rm, kNoRegister);
406 CHECK_NE(rs, kNoRegister);
407 CHECK_NE(cond, kNoCondition);
408 int32_t encoding = opcode |
409 (static_cast<int32_t>(cond) << kConditionShift) |
410 (static_cast<int32_t>(rn) << kRnShift) |
411 (static_cast<int32_t>(rd) << kRdShift) |
412 (static_cast<int32_t>(rs) << kRsShift) |
413 B7 | B4 |
414 (static_cast<int32_t>(rm) << kRmShift);
415 Emit(encoding);
416}
417
418
419void Assembler::mul(Register rd, Register rn,
420 Register rm, Condition cond) {
421 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
422 EmitMulOp(cond, 0, R0, rd, rn, rm);
423}
424
425
426void Assembler::mla(Register rd, Register rn,
427 Register rm, Register ra, Condition cond) {
428 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
429 EmitMulOp(cond, B21, ra, rd, rn, rm);
430}
431
432
433void Assembler::mls(Register rd, Register rn,
434 Register rm, Register ra, Condition cond) {
435 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
436 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
437}
438
439
440void Assembler::umull(Register rd_lo, Register rd_hi,
441 Register rn, Register rm, Condition cond) {
442 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
443 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
444}
445
446
447void Assembler::ldr(Register rd, Address ad, Condition cond) {
448 EmitMemOp(cond, true, false, rd, ad);
449}
450
451
452void Assembler::str(Register rd, Address ad, Condition cond) {
453 EmitMemOp(cond, false, false, rd, ad);
454}
455
456
457void Assembler::ldrb(Register rd, Address ad, Condition cond) {
458 EmitMemOp(cond, true, true, rd, ad);
459}
460
461
462void Assembler::strb(Register rd, Address ad, Condition cond) {
463 EmitMemOp(cond, false, true, rd, ad);
464}
465
466
467void Assembler::ldrh(Register rd, Address ad, Condition cond) {
468 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
469}
470
471
472void Assembler::strh(Register rd, Address ad, Condition cond) {
473 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
474}
475
476
477void Assembler::ldrsb(Register rd, Address ad, Condition cond) {
478 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
479}
480
481
482void Assembler::ldrsh(Register rd, Address ad, Condition cond) {
483 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
484}
485
486
487void Assembler::ldrd(Register rd, Address ad, Condition cond) {
488 CHECK_EQ(rd % 2, 0);
489 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
490}
491
492
493void Assembler::strd(Register rd, Address ad, Condition cond) {
494 CHECK_EQ(rd % 2, 0);
495 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
496}
497
498
499void Assembler::ldm(BlockAddressMode am,
500 Register base,
501 RegList regs,
502 Condition cond) {
503 EmitMultiMemOp(cond, am, true, base, regs);
504}
505
506
507void Assembler::stm(BlockAddressMode am,
508 Register base,
509 RegList regs,
510 Condition cond) {
511 EmitMultiMemOp(cond, am, false, base, regs);
512}
513
514
515void Assembler::ldrex(Register rt, Register rn, Condition cond) {
516 CHECK_NE(rn, kNoRegister);
517 CHECK_NE(rt, kNoRegister);
518 CHECK_NE(cond, kNoCondition);
519 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
520 B24 |
521 B23 |
522 L |
523 (static_cast<int32_t>(rn) << kLdExRnShift) |
524 (static_cast<int32_t>(rt) << kLdExRtShift) |
525 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
526 Emit(encoding);
527}
528
529
530void Assembler::strex(Register rd,
531 Register rt,
532 Register rn,
533 Condition cond) {
534 CHECK_NE(rn, kNoRegister);
535 CHECK_NE(rd, kNoRegister);
536 CHECK_NE(rt, kNoRegister);
537 CHECK_NE(cond, kNoCondition);
538 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
539 B24 |
540 B23 |
541 (static_cast<int32_t>(rn) << kStrExRnShift) |
542 (static_cast<int32_t>(rd) << kStrExRdShift) |
543 B11 | B10 | B9 | B8 | B7 | B4 |
544 (static_cast<int32_t>(rt) << kStrExRtShift);
545 Emit(encoding);
546}
547
548
549void Assembler::clrex() {
550 int32_t encoding = (kSpecialCondition << kConditionShift) |
551 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
552 Emit(encoding);
553}
554
555
556void Assembler::nop(Condition cond) {
557 CHECK_NE(cond, kNoCondition);
558 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
559 B25 | B24 | B21 | (0xf << 12);
560 Emit(encoding);
561}
562
563
564void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
565 CHECK_NE(sn, kNoSRegister);
566 CHECK_NE(rt, kNoRegister);
567 CHECK_NE(rt, SP);
568 CHECK_NE(rt, PC);
569 CHECK_NE(cond, kNoCondition);
570 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
571 B27 | B26 | B25 |
572 ((static_cast<int32_t>(sn) >> 1)*B16) |
573 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
574 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
575 Emit(encoding);
576}
577
578
579void Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
580 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 | B20 |
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
594void Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
595 Condition cond) {
596 CHECK_NE(sm, kNoSRegister);
597 CHECK_NE(sm, S31);
598 CHECK_NE(rt, kNoRegister);
599 CHECK_NE(rt, SP);
600 CHECK_NE(rt, PC);
601 CHECK_NE(rt2, kNoRegister);
602 CHECK_NE(rt2, SP);
603 CHECK_NE(rt2, PC);
604 CHECK_NE(cond, kNoCondition);
605 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
606 B27 | B26 | B22 |
607 (static_cast<int32_t>(rt2)*B16) |
608 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
609 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
610 (static_cast<int32_t>(sm) >> 1);
611 Emit(encoding);
612}
613
614
615void Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
616 Condition cond) {
617 CHECK_NE(sm, kNoSRegister);
618 CHECK_NE(sm, S31);
619 CHECK_NE(rt, kNoRegister);
620 CHECK_NE(rt, SP);
621 CHECK_NE(rt, PC);
622 CHECK_NE(rt2, kNoRegister);
623 CHECK_NE(rt2, SP);
624 CHECK_NE(rt2, PC);
625 CHECK_NE(rt, rt2);
626 CHECK_NE(cond, kNoCondition);
627 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
628 B27 | B26 | B22 | B20 |
629 (static_cast<int32_t>(rt2)*B16) |
630 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
631 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
632 (static_cast<int32_t>(sm) >> 1);
633 Emit(encoding);
634}
635
636
637void Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
638 Condition cond) {
639 CHECK_NE(dm, kNoDRegister);
640 CHECK_NE(rt, kNoRegister);
641 CHECK_NE(rt, SP);
642 CHECK_NE(rt, PC);
643 CHECK_NE(rt2, kNoRegister);
644 CHECK_NE(rt2, SP);
645 CHECK_NE(rt2, PC);
646 CHECK_NE(cond, kNoCondition);
647 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
648 B27 | B26 | B22 |
649 (static_cast<int32_t>(rt2)*B16) |
650 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
651 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
652 (static_cast<int32_t>(dm) & 0xf);
653 Emit(encoding);
654}
655
656
657void Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
658 Condition cond) {
659 CHECK_NE(dm, kNoDRegister);
660 CHECK_NE(rt, kNoRegister);
661 CHECK_NE(rt, SP);
662 CHECK_NE(rt, PC);
663 CHECK_NE(rt2, kNoRegister);
664 CHECK_NE(rt2, SP);
665 CHECK_NE(rt2, PC);
666 CHECK_NE(rt, rt2);
667 CHECK_NE(cond, kNoCondition);
668 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
669 B27 | B26 | B22 | B20 |
670 (static_cast<int32_t>(rt2)*B16) |
671 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
672 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
673 (static_cast<int32_t>(dm) & 0xf);
674 Emit(encoding);
675}
676
677
678void Assembler::vldrs(SRegister sd, Address ad, Condition cond) {
679 CHECK_NE(sd, kNoSRegister);
680 CHECK_NE(cond, kNoCondition);
681 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
682 B27 | B26 | B24 | B20 |
683 ((static_cast<int32_t>(sd) & 1)*B22) |
684 ((static_cast<int32_t>(sd) >> 1)*B12) |
685 B11 | B9 | ad.vencoding();
686 Emit(encoding);
687}
688
689
690void Assembler::vstrs(SRegister sd, Address ad, Condition cond) {
691 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
692 CHECK_NE(sd, kNoSRegister);
693 CHECK_NE(cond, kNoCondition);
694 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
695 B27 | B26 | B24 |
696 ((static_cast<int32_t>(sd) & 1)*B22) |
697 ((static_cast<int32_t>(sd) >> 1)*B12) |
698 B11 | B9 | ad.vencoding();
699 Emit(encoding);
700}
701
702
703void Assembler::vldrd(DRegister dd, Address ad, Condition cond) {
704 CHECK_NE(dd, kNoDRegister);
705 CHECK_NE(cond, kNoCondition);
706 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
707 B27 | B26 | B24 | B20 |
708 ((static_cast<int32_t>(dd) >> 4)*B22) |
709 ((static_cast<int32_t>(dd) & 0xf)*B12) |
710 B11 | B9 | B8 | ad.vencoding();
711 Emit(encoding);
712}
713
714
715void Assembler::vstrd(DRegister dd, Address ad, Condition cond) {
716 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC);
717 CHECK_NE(dd, kNoDRegister);
718 CHECK_NE(cond, kNoCondition);
719 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
720 B27 | B26 | B24 |
721 ((static_cast<int32_t>(dd) >> 4)*B22) |
722 ((static_cast<int32_t>(dd) & 0xf)*B12) |
723 B11 | B9 | B8 | ad.vencoding();
724 Emit(encoding);
725}
726
727
728void Assembler::EmitVFPsss(Condition cond, int32_t opcode,
729 SRegister sd, SRegister sn, SRegister sm) {
730 CHECK_NE(sd, kNoSRegister);
731 CHECK_NE(sn, kNoSRegister);
732 CHECK_NE(sm, kNoSRegister);
733 CHECK_NE(cond, kNoCondition);
734 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
735 B27 | B26 | B25 | B11 | B9 | opcode |
736 ((static_cast<int32_t>(sd) & 1)*B22) |
737 ((static_cast<int32_t>(sn) >> 1)*B16) |
738 ((static_cast<int32_t>(sd) >> 1)*B12) |
739 ((static_cast<int32_t>(sn) & 1)*B7) |
740 ((static_cast<int32_t>(sm) & 1)*B5) |
741 (static_cast<int32_t>(sm) >> 1);
742 Emit(encoding);
743}
744
745
746void Assembler::EmitVFPddd(Condition cond, int32_t opcode,
747 DRegister dd, DRegister dn, DRegister dm) {
748 CHECK_NE(dd, kNoDRegister);
749 CHECK_NE(dn, kNoDRegister);
750 CHECK_NE(dm, kNoDRegister);
751 CHECK_NE(cond, kNoCondition);
752 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
753 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
754 ((static_cast<int32_t>(dd) >> 4)*B22) |
755 ((static_cast<int32_t>(dn) & 0xf)*B16) |
756 ((static_cast<int32_t>(dd) & 0xf)*B12) |
757 ((static_cast<int32_t>(dn) >> 4)*B7) |
758 ((static_cast<int32_t>(dm) >> 4)*B5) |
759 (static_cast<int32_t>(dm) & 0xf);
760 Emit(encoding);
761}
762
763
764void Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
765 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
766}
767
768
769void Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
770 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
771}
772
773
774bool Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
775 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
776 if (((imm32 & ((1 << 19) - 1)) == 0) &&
777 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
778 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
779 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
780 ((imm32 >> 19) & ((1 << 6) -1));
781 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
782 sd, S0, S0);
783 return true;
784 }
785 return false;
786}
787
788
789bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
790 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
791 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
792 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
793 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
794 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
795 ((imm64 >> 48) & ((1 << 6) -1));
796 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
797 dd, D0, D0);
798 return true;
799 }
800 return false;
801}
802
803
804void Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
805 Condition cond) {
806 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
807}
808
809
810void Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
811 Condition cond) {
812 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
813}
814
815
816void Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
817 Condition cond) {
818 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
819}
820
821
822void Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
823 Condition cond) {
824 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
825}
826
827
828void Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
829 Condition cond) {
830 EmitVFPsss(cond, B21, sd, sn, sm);
831}
832
833
834void Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
835 Condition cond) {
836 EmitVFPddd(cond, B21, dd, dn, dm);
837}
838
839
840void Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
841 Condition cond) {
842 EmitVFPsss(cond, 0, sd, sn, sm);
843}
844
845
846void Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
847 Condition cond) {
848 EmitVFPddd(cond, 0, dd, dn, dm);
849}
850
851
852void Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
853 Condition cond) {
854 EmitVFPsss(cond, B6, sd, sn, sm);
855}
856
857
858void Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
859 Condition cond) {
860 EmitVFPddd(cond, B6, dd, dn, dm);
861}
862
863
864void Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
865 Condition cond) {
866 EmitVFPsss(cond, B23, sd, sn, sm);
867}
868
869
870void Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
871 Condition cond) {
872 EmitVFPddd(cond, B23, dd, dn, dm);
873}
874
875
876void Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
877 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
878}
879
880
881void Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
882 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
883}
884
885
886void Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
887 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
888}
889
890
891void Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
892 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
893}
894
895
896void Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
897 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
898}
899
900void Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
901 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
902}
903
904
905void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
906 SRegister sd, DRegister dm) {
907 CHECK_NE(sd, kNoSRegister);
908 CHECK_NE(dm, kNoDRegister);
909 CHECK_NE(cond, kNoCondition);
910 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
911 B27 | B26 | B25 | B11 | B9 | opcode |
912 ((static_cast<int32_t>(sd) & 1)*B22) |
913 ((static_cast<int32_t>(sd) >> 1)*B12) |
914 ((static_cast<int32_t>(dm) >> 4)*B5) |
915 (static_cast<int32_t>(dm) & 0xf);
916 Emit(encoding);
917}
918
919
920void Assembler::EmitVFPds(Condition cond, int32_t opcode,
921 DRegister dd, SRegister sm) {
922 CHECK_NE(dd, kNoDRegister);
923 CHECK_NE(sm, kNoSRegister);
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>(dd) >> 4)*B22) |
928 ((static_cast<int32_t>(dd) & 0xf)*B12) |
929 ((static_cast<int32_t>(sm) & 1)*B5) |
930 (static_cast<int32_t>(sm) >> 1);
931 Emit(encoding);
932}
933
934
935void Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
936 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
937}
938
939
940void Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
941 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
942}
943
944
945void Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
946 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
947}
948
949
950void Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
951 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
952}
953
954
955void Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
956 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
957}
958
959
960void Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
961 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
962}
963
964
965void Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
966 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
967}
968
969
970void Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
971 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
972}
973
974
975void Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
976 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
977}
978
979
980void Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
981 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
982}
983
984
985void Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
986 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
987}
988
989
990void Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
991 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
992}
993
994
995void Assembler::vcmpsz(SRegister sd, Condition cond) {
996 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
997}
998
999
1000void Assembler::vcmpdz(DRegister dd, Condition cond) {
1001 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
1002}
1003
1004
1005void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1006 CHECK_NE(cond, kNoCondition);
1007 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1008 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1009 (static_cast<int32_t>(PC)*B12) |
1010 B11 | B9 | B4;
1011 Emit(encoding);
1012}
1013
1014
1015void Assembler::svc(uint32_t imm24) {
1016 CHECK(IsUint(24, imm24));
1017 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1018 Emit(encoding);
1019}
1020
1021
1022void Assembler::bkpt(uint16_t imm16) {
1023 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1024 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1025 Emit(encoding);
1026}
1027
1028
1029void Assembler::b(Label* label, Condition cond) {
1030 EmitBranch(cond, label, false);
1031}
1032
1033
1034void Assembler::bl(Label* label, Condition cond) {
1035 EmitBranch(cond, label, true);
1036}
1037
1038
1039void Assembler::blx(Register rm, Condition cond) {
1040 CHECK_NE(rm, kNoRegister);
1041 CHECK_NE(cond, kNoCondition);
1042 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1043 B24 | B21 | (0xfff << 8) | B5 | B4 |
1044 (static_cast<int32_t>(rm) << kRmShift);
1045 Emit(encoding);
1046}
1047
1048
1049void Assembler::MarkExceptionHandler(Label* label) {
1050 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
1051 Label l;
1052 b(&l);
1053 EmitBranch(AL, label, false);
1054 Bind(&l);
1055}
1056
1057
1058void Assembler::Bind(Label* label) {
1059 CHECK(!label->IsBound());
1060 int bound_pc = buffer_.Size();
1061 while (label->IsLinked()) {
1062 int32_t position = label->Position();
1063 int32_t next = buffer_.Load<int32_t>(position);
1064 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next);
1065 buffer_.Store<int32_t>(position, encoded);
1066 label->position_ = Assembler::DecodeBranchOffset(next);
1067 }
1068 label->BindTo(bound_pc);
1069}
1070
1071
1072void Assembler::EncodeUint32InTstInstructions(uint32_t data) {
1073 // TODO: Consider using movw ip, <16 bits>.
1074 while (!IsUint(8, data)) {
1075 tst(R0, ShifterOperand(data & 0xFF), VS);
1076 data >>= 8;
1077 }
1078 tst(R0, ShifterOperand(data), MI);
1079}
1080
Ian Rogersb033c752011-07-20 12:22:35 -07001081
Carl Shapiroa2e18e12011-06-21 18:57:55 -07001082int32_t Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1083 // The offset is off by 8 due to the way the ARM CPUs read PC.
1084 offset -= 8;
1085 CHECK(IsAligned(offset, 4));
1086 CHECK(IsInt(CountOneBits(kBranchOffsetMask), offset));
1087
1088 // Properly preserve only the bits supported in the instruction.
1089 offset >>= 2;
1090 offset &= kBranchOffsetMask;
1091 return (inst & ~kBranchOffsetMask) | offset;
1092}
1093
1094
1095int Assembler::DecodeBranchOffset(int32_t inst) {
1096 // Sign-extend, left-shift by 2, then add 8.
1097 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1098}
1099
Ian Rogersb033c752011-07-20 12:22:35 -07001100void Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
1101 AddConstant(rd, rd, value, cond);
1102}
1103
1104
1105void Assembler::AddConstant(Register rd, Register rn, int32_t value,
1106 Condition cond) {
1107 if (value == 0) {
1108 if (rd != rn) {
1109 mov(rd, ShifterOperand(rn), cond);
1110 }
1111 return;
1112 }
1113 // We prefer to select the shorter code sequence rather than selecting add for
1114 // positive values and sub for negatives ones, which would slightly improve
1115 // the readability of generated code for some constants.
1116 ShifterOperand shifter_op;
1117 if (ShifterOperand::CanHold(value, &shifter_op)) {
1118 add(rd, rn, shifter_op, cond);
1119 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1120 sub(rd, rn, shifter_op, cond);
1121 } else {
1122 CHECK(rn != IP);
1123 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1124 mvn(IP, shifter_op, cond);
1125 add(rd, rn, ShifterOperand(IP), cond);
1126 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1127 mvn(IP, shifter_op, cond);
1128 sub(rd, rn, ShifterOperand(IP), cond);
1129 } else {
1130 movw(IP, Low16Bits(value), cond);
1131 uint16_t value_high = High16Bits(value);
1132 if (value_high != 0) {
1133 movt(IP, value_high, cond);
1134 }
1135 add(rd, rn, ShifterOperand(IP), cond);
1136 }
1137 }
1138}
1139
1140
1141void Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1142 Condition cond) {
1143 ShifterOperand shifter_op;
1144 if (ShifterOperand::CanHold(value, &shifter_op)) {
1145 adds(rd, rn, shifter_op, cond);
1146 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1147 subs(rd, rn, shifter_op, cond);
1148 } else {
1149 CHECK(rn != IP);
1150 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1151 mvn(IP, shifter_op, cond);
1152 adds(rd, rn, ShifterOperand(IP), cond);
1153 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1154 mvn(IP, shifter_op, cond);
1155 subs(rd, rn, ShifterOperand(IP), cond);
1156 } else {
1157 movw(IP, Low16Bits(value), cond);
1158 uint16_t value_high = High16Bits(value);
1159 if (value_high != 0) {
1160 movt(IP, value_high, cond);
1161 }
1162 adds(rd, rn, ShifterOperand(IP), cond);
1163 }
1164 }
1165}
1166
1167
1168void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1169 ShifterOperand shifter_op;
1170 if (ShifterOperand::CanHold(value, &shifter_op)) {
1171 mov(rd, shifter_op, cond);
1172 } else if (ShifterOperand::CanHold(~value, &shifter_op)) {
1173 mvn(rd, shifter_op, cond);
1174 } else {
1175 movw(rd, Low16Bits(value), cond);
1176 uint16_t value_high = High16Bits(value);
1177 if (value_high != 0) {
1178 movt(rd, value_high, cond);
1179 }
1180 }
1181}
1182
1183
1184bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) {
1185 switch (type) {
1186 case kLoadSignedByte:
1187 case kLoadSignedHalfword:
1188 case kLoadUnsignedHalfword:
1189 case kLoadWordPair:
1190 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1191 case kLoadUnsignedByte:
1192 case kLoadWord:
1193 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1194 case kLoadSWord:
1195 case kLoadDWord:
1196 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1197 default:
1198 LOG(FATAL) << "UNREACHABLE";
1199 return false;
1200 }
1201}
1202
1203
1204bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) {
1205 switch (type) {
1206 case kStoreHalfword:
1207 case kStoreWordPair:
1208 return IsAbsoluteUint(8, offset); // Addressing mode 3.
1209 case kStoreByte:
1210 case kStoreWord:
1211 return IsAbsoluteUint(12, offset); // Addressing mode 2.
1212 case kStoreSWord:
1213 case kStoreDWord:
1214 return IsAbsoluteUint(10, offset); // VFP addressing mode.
1215 default:
1216 LOG(FATAL) << "UNREACHABLE";
1217 return false;
1218 }
1219}
1220
1221
1222// Implementation note: this method must emit at most one instruction when
1223// Address::CanHoldLoadOffset.
1224void Assembler::LoadFromOffset(LoadOperandType type,
1225 Register reg,
1226 Register base,
1227 int32_t offset,
1228 Condition cond) {
1229 if (!Address::CanHoldLoadOffset(type, offset)) {
1230 CHECK(base != IP);
1231 LoadImmediate(IP, offset, cond);
1232 add(IP, IP, ShifterOperand(base), cond);
1233 base = IP;
1234 offset = 0;
1235 }
1236 CHECK(Address::CanHoldLoadOffset(type, offset));
1237 switch (type) {
1238 case kLoadSignedByte:
1239 ldrsb(reg, Address(base, offset), cond);
1240 break;
1241 case kLoadUnsignedByte:
1242 ldrb(reg, Address(base, offset), cond);
1243 break;
1244 case kLoadSignedHalfword:
1245 ldrsh(reg, Address(base, offset), cond);
1246 break;
1247 case kLoadUnsignedHalfword:
1248 ldrh(reg, Address(base, offset), cond);
1249 break;
1250 case kLoadWord:
1251 ldr(reg, Address(base, offset), cond);
1252 break;
1253 case kLoadWordPair:
1254 ldrd(reg, Address(base, offset), cond);
1255 break;
1256 default:
1257 LOG(FATAL) << "UNREACHABLE";
1258 }
1259}
1260
1261
1262// Implementation note: this method must emit at most one instruction when
1263// Address::CanHoldStoreOffset.
1264void Assembler::StoreToOffset(StoreOperandType type,
1265 Register reg,
1266 Register base,
1267 int32_t offset,
1268 Condition cond) {
1269 if (!Address::CanHoldStoreOffset(type, offset)) {
1270 CHECK(reg != IP);
1271 CHECK(base != IP);
1272 LoadImmediate(IP, offset, cond);
1273 add(IP, IP, ShifterOperand(base), cond);
1274 base = IP;
1275 offset = 0;
1276 }
1277 CHECK(Address::CanHoldStoreOffset(type, offset));
1278 switch (type) {
1279 case kStoreByte:
1280 strb(reg, Address(base, offset), cond);
1281 break;
1282 case kStoreHalfword:
1283 strh(reg, Address(base, offset), cond);
1284 break;
1285 case kStoreWord:
1286 str(reg, Address(base, offset), cond);
1287 break;
1288 case kStoreWordPair:
1289 strd(reg, Address(base, offset), cond);
1290 break;
1291 default:
1292 LOG(FATAL) << "UNREACHABLE";
1293 }
1294}
1295
1296// Emit code that will create an activation on the stack
1297void Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg) {
1298 CHECK(IsAligned(frame_size, 16));
1299 // TODO: use stm/ldm
1300 StoreToOffset(kStoreWord, LR, SP, 0);
1301 StoreToOffset(kStoreWord, method_reg.AsCoreRegister(), SP, -4);
1302 AddConstant(SP, -frame_size);
1303}
1304
1305// Emit code that will remove an activation from the stack
1306void Assembler::RemoveFrame(size_t frame_size) {
1307 CHECK(IsAligned(frame_size, 16));
1308 LoadFromOffset(kLoadWord, LR, SP, 0);
1309 AddConstant(SP, frame_size);
1310 mov(PC, ShifterOperand(LR));
1311}
1312
1313void Assembler::IncreaseFrameSize(size_t adjust) {
1314 CHECK(IsAligned(adjust, 16));
1315 AddConstant(SP, -adjust);
1316}
1317
1318void Assembler::DecreaseFrameSize(size_t adjust) {
1319 CHECK(IsAligned(adjust, 16));
1320 AddConstant(SP, adjust);
1321}
1322
1323// Store bytes from the given register onto the stack
1324void Assembler::Store(FrameOffset dest, ManagedRegister src, size_t size) {
1325 if (src.IsCoreRegister()) {
1326 CHECK_EQ(4u, size);
1327 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1328 } else {
1329 // VFP
1330 LOG(FATAL) << "TODO";
1331 }
1332}
1333
1334void Assembler::StoreRef(FrameOffset dest, ManagedRegister src) {
1335 CHECK(src.IsCoreRegister());
1336 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
1337}
1338
1339void Assembler::CopyRef(FrameOffset dest, FrameOffset src,
1340 ManagedRegister scratch) {
1341 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
1342 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1343}
1344
1345void Assembler::LoadRef(ManagedRegister dest, ManagedRegister base,
1346 MemberOffset offs) {
1347 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
1348 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
1349 base.AsCoreRegister(), offs.Int32Value());
1350}
1351
1352void Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1353 ManagedRegister scratch) {
1354 CHECK(scratch.IsCoreRegister());
1355 LoadImmediate(scratch.AsCoreRegister(), imm);
1356 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
1357}
1358
1359void Assembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
1360 ManagedRegister scratch) {
1361 CHECK(scratch.IsCoreRegister());
1362 LoadImmediate(scratch.AsCoreRegister(), imm);
1363 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), TR, dest.Int32Value());
1364}
1365
1366void Assembler::Load(ManagedRegister dest, FrameOffset src, size_t size) {
1367 if (dest.IsCoreRegister()) {
1368 CHECK_EQ(4u, size);
1369 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
1370 } else {
1371 // TODO: VFP
1372 LOG(FATAL) << "Unimplemented";
1373 }
1374}
1375
1376void Assembler::LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset offs) {
1377 CHECK(dest.IsCoreRegister());
1378 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
1379 TR, offs.Int32Value());
1380}
1381
1382void Assembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
1383 ManagedRegister scratch) {
1384 CHECK(scratch.IsCoreRegister());
1385 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1386 TR, thr_offs.Int32Value());
1387 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1388 SP, fr_offs.Int32Value());
1389}
1390
1391void Assembler::CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
1392 ManagedRegister scratch) {
1393 CHECK(scratch.IsCoreRegister());
1394 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1395 SP, fr_offs.Int32Value());
1396 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1397 TR, thr_offs.Int32Value());
1398}
1399
1400void Assembler::StoreStackOffsetToThread(ThreadOffset thr_offs,
1401 FrameOffset fr_offs,
1402 ManagedRegister scratch) {
1403 CHECK(scratch.IsCoreRegister());
1404 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value(), AL);
1405 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1406 TR, thr_offs.Int32Value());
1407}
1408
1409void Assembler::Move(ManagedRegister dest, ManagedRegister src) {
1410 if (dest.IsCoreRegister()) {
1411 CHECK(src.IsCoreRegister());
1412 mov(dest.AsCoreRegister(), ShifterOperand(src.AsCoreRegister()));
1413 } else {
1414 // TODO: VFP
1415 LOG(FATAL) << "Unimplemented";
1416 }
1417}
1418
1419void Assembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
1420 size_t size) {
1421 CHECK(scratch.IsCoreRegister());
1422 if (size == 4) {
1423 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1424 SP, src.Int32Value());
1425 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
1426 SP, dest.Int32Value());
1427 } else {
1428 // TODO: size != 4
1429 LOG(FATAL) << "Unimplemented";
1430 }
1431}
1432
1433void Assembler::CreateStackHandle(ManagedRegister out_reg,
1434 FrameOffset handle_offset,
1435 ManagedRegister in_reg, bool null_allowed) {
1436 CHECK(in_reg.IsCoreRegister());
1437 CHECK(out_reg.IsCoreRegister());
1438 if (null_allowed) {
1439 // Null values get a handle value of 0. Otherwise, the handle value is
1440 // the address in the stack handle block holding the reference.
1441 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
1442 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
1443 if (!out_reg.Equals(in_reg)) {
1444 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1445 }
1446 AddConstant(out_reg.AsCoreRegister(), SP, handle_offset.Int32Value(), NE);
1447 } else {
1448 AddConstant(out_reg.AsCoreRegister(), SP, handle_offset.Int32Value(), AL);
1449 }
1450}
1451
1452void Assembler::CreateStackHandle(FrameOffset out_off,
1453 FrameOffset handle_offset,
1454 ManagedRegister scratch, bool null_allowed) {
1455 CHECK(scratch.IsCoreRegister());
1456 if (null_allowed) {
1457 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
1458 handle_offset.Int32Value());
1459 // Null values get a handle value of 0. Otherwise, the handle value is
1460 // the address in the stack handle block holding the reference.
1461 // e.g. scratch = (handle == 0) ? 0 : (SP+handle_offset)
1462 cmp(scratch.AsCoreRegister(), ShifterOperand(0));
1463 AddConstant(scratch.AsCoreRegister(), SP, handle_offset.Int32Value(), NE);
1464 } else {
1465 AddConstant(scratch.AsCoreRegister(), SP, handle_offset.Int32Value(), AL);
1466 }
1467 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
1468}
1469
1470void Assembler::LoadReferenceFromStackHandle(ManagedRegister out_reg,
1471 ManagedRegister in_reg,
1472 FrameOffset shb_offset) {
1473 CHECK(out_reg.IsCoreRegister());
1474 CHECK(in_reg.IsCoreRegister());
1475 Label null_arg;
1476 if (!out_reg.Equals(in_reg)) {
1477 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ);
1478 }
1479 cmp(in_reg.AsCoreRegister(), ShifterOperand(0));
1480 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(), in_reg.AsCoreRegister(),
1481 shb_offset.Int32Value(), NE);
1482}
1483
1484void Assembler::ValidateRef(ManagedRegister src, bool could_be_null) {
1485 // TODO: not validating references
1486}
1487
1488void Assembler::ValidateRef(FrameOffset src, bool could_be_null) {
1489 // TODO: not validating references
1490}
1491
1492void Assembler::Call(ManagedRegister base, MemberOffset offset,
1493 ManagedRegister scratch) {
1494 CHECK(base.IsCoreRegister());
1495 CHECK(scratch.IsCoreRegister());
1496 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
1497 base.AsCoreRegister(), offset.Int32Value());
1498 blx(scratch.AsCoreRegister());
1499 // TODO: place reference map on call
1500}
1501
1502// Emit code that will lock the reference in the given register
1503void Assembler::LockReferenceOnStack(FrameOffset fr_offs) {
1504 LOG(FATAL) << "TODO";
1505}
1506// Emit code that will unlock the reference in the given register
1507void Assembler::UnLockReferenceOnStack(FrameOffset fr_offs) {
1508 LOG(FATAL) << "TODO";
1509}
1510
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07001511} // namespace art