blob: b2bb20fa2d51f3064b526f839bc41460acd19f1f [file] [log] [blame]
Dave Allison65fcc2c2014-04-28 13:45:27 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "assembler_arm32.h"
18
19#include "base/logging.h"
20#include "entrypoints/quick/quick_entrypoints.h"
21#include "offsets.h"
22#include "thread.h"
23#include "utils.h"
24
25namespace art {
26namespace arm {
27
28void Arm32Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
29 Condition cond) {
30 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
31}
32
33
34void Arm32Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
35 Condition cond) {
36 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
37}
38
39
40void Arm32Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
41 Condition cond) {
42 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
43}
44
45void Arm32Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
46 Condition cond) {
47 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
48}
49
50void Arm32Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
51 Condition cond) {
52 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
53}
54
55
56void Arm32Assembler::add(Register rd, Register rn, const ShifterOperand& so,
57 Condition cond) {
58 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
59}
60
61
62void Arm32Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
63 Condition cond) {
64 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
65}
66
67
68void Arm32Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
69 Condition cond) {
70 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
71}
72
73
74void Arm32Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
75 Condition cond) {
76 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
77}
78
79
80void Arm32Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
81 Condition cond) {
82 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
83}
84
85
86void Arm32Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
87 Condition cond) {
88 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
89}
90
91
92void Arm32Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
93 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
94 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
95}
96
97
98void Arm32Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
99 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
100 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
101}
102
103
104void Arm32Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
105 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
106}
107
108
109void Arm32Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
110 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
111}
112
113
114void Arm32Assembler::orr(Register rd, Register rn,
115 const ShifterOperand& so, Condition cond) {
116 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
117}
118
119
120void Arm32Assembler::orrs(Register rd, Register rn,
121 const ShifterOperand& so, Condition cond) {
122 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
123}
124
125
126void Arm32Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
127 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
128}
129
130
131void Arm32Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
132 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
133}
134
135
136void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
137 Condition cond) {
138 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
139}
140
141
142void Arm32Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
143 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
144}
145
146
147void Arm32Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
148 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
149}
150
151
152void Arm32Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
153 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
154 EmitMulOp(cond, 0, R0, rd, rn, rm);
155}
156
157
158void Arm32Assembler::mla(Register rd, Register rn, Register rm, Register ra,
159 Condition cond) {
160 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
161 EmitMulOp(cond, B21, ra, rd, rn, rm);
162}
163
164
165void Arm32Assembler::mls(Register rd, Register rn, Register rm, Register ra,
166 Condition cond) {
167 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
168 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
169}
170
171
172void Arm32Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
173 Register rm, Condition cond) {
174 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
175 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
176}
177
178
179void Arm32Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
180 CHECK_NE(rd, kNoRegister);
181 CHECK_NE(rn, kNoRegister);
182 CHECK_NE(rm, kNoRegister);
183 CHECK_NE(cond, kNoCondition);
184 int32_t encoding = B26 | B25 | B24 | B20 |
185 B15 | B14 | B13 | B12 |
186 (static_cast<int32_t>(cond) << kConditionShift) |
187 (static_cast<int32_t>(rn) << 0) |
188 (static_cast<int32_t>(rd) << 16) |
189 (static_cast<int32_t>(rm) << 8) |
190 B4;
191 Emit(encoding);
192}
193
194
195void Arm32Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
196 CHECK_NE(rd, kNoRegister);
197 CHECK_NE(rn, kNoRegister);
198 CHECK_NE(rm, kNoRegister);
199 CHECK_NE(cond, kNoCondition);
200 int32_t encoding = B26 | B25 | B24 | B21 | B20 |
201 B15 | B14 | B13 | B12 |
202 (static_cast<int32_t>(cond) << kConditionShift) |
203 (static_cast<int32_t>(rn) << 0) |
204 (static_cast<int32_t>(rd) << 16) |
205 (static_cast<int32_t>(rm) << 8) |
206 B4;
207 Emit(encoding);
208}
209
210
211void Arm32Assembler::ldr(Register rd, const Address& ad, Condition cond) {
212 EmitMemOp(cond, true, false, rd, ad);
213}
214
215
216void Arm32Assembler::str(Register rd, const Address& ad, Condition cond) {
217 EmitMemOp(cond, false, false, rd, ad);
218}
219
220
221void Arm32Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
222 EmitMemOp(cond, true, true, rd, ad);
223}
224
225
226void Arm32Assembler::strb(Register rd, const Address& ad, Condition cond) {
227 EmitMemOp(cond, false, true, rd, ad);
228}
229
230
231void Arm32Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
232 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
233}
234
235
236void Arm32Assembler::strh(Register rd, const Address& ad, Condition cond) {
237 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
238}
239
240
241void Arm32Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
242 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
243}
244
245
246void Arm32Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
247 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
248}
249
250
251void Arm32Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
252 CHECK_EQ(rd % 2, 0);
253 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
254}
255
256
257void Arm32Assembler::strd(Register rd, const Address& ad, Condition cond) {
258 CHECK_EQ(rd % 2, 0);
259 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
260}
261
262
263void Arm32Assembler::ldm(BlockAddressMode am,
264 Register base,
265 RegList regs,
266 Condition cond) {
267 EmitMultiMemOp(cond, am, true, base, regs);
268}
269
270
271void Arm32Assembler::stm(BlockAddressMode am,
272 Register base,
273 RegList regs,
274 Condition cond) {
275 EmitMultiMemOp(cond, am, false, base, regs);
276}
277
278
279void Arm32Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
280 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
281}
282
283
284void Arm32Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
285 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
286}
287
288
289bool Arm32Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
290 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
291 if (((imm32 & ((1 << 19) - 1)) == 0) &&
292 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
293 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
294 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
295 ((imm32 >> 19) & ((1 << 6) -1));
296 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
297 sd, S0, S0);
298 return true;
299 }
300 return false;
301}
302
303
304bool Arm32Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
305 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
306 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
307 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
308 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
309 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
310 ((imm64 >> 48) & ((1 << 6) -1));
311 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
312 dd, D0, D0);
313 return true;
314 }
315 return false;
316}
317
318
319void Arm32Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
320 Condition cond) {
321 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
322}
323
324
325void Arm32Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
326 Condition cond) {
327 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
328}
329
330
331void Arm32Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
332 Condition cond) {
333 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
334}
335
336
337void Arm32Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
338 Condition cond) {
339 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
340}
341
342
343void Arm32Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
344 Condition cond) {
345 EmitVFPsss(cond, B21, sd, sn, sm);
346}
347
348
349void Arm32Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
350 Condition cond) {
351 EmitVFPddd(cond, B21, dd, dn, dm);
352}
353
354
355void Arm32Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
356 Condition cond) {
357 EmitVFPsss(cond, 0, sd, sn, sm);
358}
359
360
361void Arm32Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
362 Condition cond) {
363 EmitVFPddd(cond, 0, dd, dn, dm);
364}
365
366
367void Arm32Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
368 Condition cond) {
369 EmitVFPsss(cond, B6, sd, sn, sm);
370}
371
372
373void Arm32Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
374 Condition cond) {
375 EmitVFPddd(cond, B6, dd, dn, dm);
376}
377
378
379void Arm32Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
380 Condition cond) {
381 EmitVFPsss(cond, B23, sd, sn, sm);
382}
383
384
385void Arm32Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
386 Condition cond) {
387 EmitVFPddd(cond, B23, dd, dn, dm);
388}
389
390
391void Arm32Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
392 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
393}
394
395
396void Arm32Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
397 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
398}
399
400
401void Arm32Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
402 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
403}
404
405
406void Arm32Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
407 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
408}
409
410
411void Arm32Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
412 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
413}
414
415void Arm32Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
416 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
417}
418
419
420void Arm32Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
421 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
422}
423
424
425void Arm32Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
426 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
427}
428
429
430void Arm32Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
431 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
432}
433
434
435void Arm32Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
436 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
437}
438
439
440void Arm32Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
441 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
442}
443
444
445void Arm32Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
446 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
447}
448
449
450void Arm32Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
451 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
452}
453
454
455void Arm32Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
456 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
457}
458
459
460void Arm32Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
461 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
462}
463
464
465void Arm32Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
466 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
467}
468
469
470void Arm32Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
471 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
472}
473
474
475void Arm32Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
476 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
477}
478
479
480void Arm32Assembler::vcmpsz(SRegister sd, Condition cond) {
481 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
482}
483
484
485void Arm32Assembler::vcmpdz(DRegister dd, Condition cond) {
486 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
487}
488
489void Arm32Assembler::b(Label* label, Condition cond) {
490 EmitBranch(cond, label, false);
491}
492
493
494void Arm32Assembler::bl(Label* label, Condition cond) {
495 EmitBranch(cond, label, true);
496}
497
498
499void Arm32Assembler::MarkExceptionHandler(Label* label) {
500 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
501 Label l;
502 b(&l);
503 EmitBranch(AL, label, false);
504 Bind(&l);
505}
506
507
508void Arm32Assembler::Emit(int32_t value) {
509 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
510 buffer_.Emit<int32_t>(value);
511}
512
513
514void Arm32Assembler::EmitType01(Condition cond,
515 int type,
516 Opcode opcode,
517 int set_cc,
518 Register rn,
519 Register rd,
520 const ShifterOperand& so) {
521 CHECK_NE(rd, kNoRegister);
522 CHECK_NE(cond, kNoCondition);
523 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
524 type << kTypeShift |
525 static_cast<int32_t>(opcode) << kOpcodeShift |
526 set_cc << kSShift |
527 static_cast<int32_t>(rn) << kRnShift |
528 static_cast<int32_t>(rd) << kRdShift |
529 so.encodingArm();
530 Emit(encoding);
531}
532
533
534void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
535 CHECK_NE(cond, kNoCondition);
536 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
537 5 << kTypeShift |
538 (link ? 1 : 0) << kLinkShift;
539 Emit(Arm32Assembler::EncodeBranchOffset(offset, encoding));
540}
541
542
543void Arm32Assembler::EmitMemOp(Condition cond,
544 bool load,
545 bool byte,
546 Register rd,
547 const Address& ad) {
548 CHECK_NE(rd, kNoRegister);
549 CHECK_NE(cond, kNoCondition);
550 const Address& addr = static_cast<const Address&>(ad);
551
552 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
553 B26 |
554 (load ? L : 0) |
555 (byte ? B : 0) |
556 (static_cast<int32_t>(rd) << kRdShift) |
557 addr.encodingArm();
558 Emit(encoding);
559}
560
561
562void Arm32Assembler::EmitMemOpAddressMode3(Condition cond,
563 int32_t mode,
564 Register rd,
565 const Address& ad) {
566 CHECK_NE(rd, kNoRegister);
567 CHECK_NE(cond, kNoCondition);
568 const Address& addr = static_cast<const Address&>(ad);
569 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
570 B22 |
571 mode |
572 (static_cast<int32_t>(rd) << kRdShift) |
573 addr.encoding3();
574 Emit(encoding);
575}
576
577
578void Arm32Assembler::EmitMultiMemOp(Condition cond,
579 BlockAddressMode am,
580 bool load,
581 Register base,
582 RegList regs) {
583 CHECK_NE(base, kNoRegister);
584 CHECK_NE(cond, kNoCondition);
585 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
586 B27 |
587 am |
588 (load ? L : 0) |
589 (static_cast<int32_t>(base) << kRnShift) |
590 regs;
591 Emit(encoding);
592}
593
594
595void Arm32Assembler::EmitShiftImmediate(Condition cond,
596 Shift opcode,
597 Register rd,
598 Register rm,
599 const ShifterOperand& so) {
600 CHECK_NE(cond, kNoCondition);
601 CHECK(so.IsImmediate());
602 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
603 static_cast<int32_t>(MOV) << kOpcodeShift |
604 static_cast<int32_t>(rd) << kRdShift |
605 so.encodingArm() << kShiftImmShift |
606 static_cast<int32_t>(opcode) << kShiftShift |
607 static_cast<int32_t>(rm);
608 Emit(encoding);
609}
610
611
612void Arm32Assembler::EmitShiftRegister(Condition cond,
613 Shift opcode,
614 Register rd,
615 Register rm,
616 const ShifterOperand& so) {
617 CHECK_NE(cond, kNoCondition);
618 CHECK(so.IsRegister());
619 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
620 static_cast<int32_t>(MOV) << kOpcodeShift |
621 static_cast<int32_t>(rd) << kRdShift |
622 so.encodingArm() << kShiftRegisterShift |
623 static_cast<int32_t>(opcode) << kShiftShift |
624 B4 |
625 static_cast<int32_t>(rm);
626 Emit(encoding);
627}
628
629
630void Arm32Assembler::EmitBranch(Condition cond, Label* label, bool link) {
631 if (label->IsBound()) {
632 EmitType5(cond, label->Position() - buffer_.Size(), link);
633 } else {
634 int position = buffer_.Size();
635 // Use the offset field of the branch instruction for linking the sites.
636 EmitType5(cond, label->position_, link);
637 label->LinkTo(position);
638 }
639}
640
641
642void Arm32Assembler::clz(Register rd, Register rm, Condition cond) {
643 CHECK_NE(rd, kNoRegister);
644 CHECK_NE(rm, kNoRegister);
645 CHECK_NE(cond, kNoCondition);
646 CHECK_NE(rd, PC);
647 CHECK_NE(rm, PC);
648 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
649 B24 | B22 | B21 | (0xf << 16) |
650 (static_cast<int32_t>(rd) << kRdShift) |
651 (0xf << 8) | B4 | static_cast<int32_t>(rm);
652 Emit(encoding);
653}
654
655
656void Arm32Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
657 CHECK_NE(cond, kNoCondition);
658 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
659 B25 | B24 | ((imm16 >> 12) << 16) |
660 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
661 Emit(encoding);
662}
663
664
665void Arm32Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
666 CHECK_NE(cond, kNoCondition);
667 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
668 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
669 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
670 Emit(encoding);
671}
672
673
674void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
675 Register rd, Register rn,
676 Register rm, Register rs) {
677 CHECK_NE(rd, kNoRegister);
678 CHECK_NE(rn, kNoRegister);
679 CHECK_NE(rm, kNoRegister);
680 CHECK_NE(rs, kNoRegister);
681 CHECK_NE(cond, kNoCondition);
682 int32_t encoding = opcode |
683 (static_cast<int32_t>(cond) << kConditionShift) |
684 (static_cast<int32_t>(rn) << kRnShift) |
685 (static_cast<int32_t>(rd) << kRdShift) |
686 (static_cast<int32_t>(rs) << kRsShift) |
687 B7 | B4 |
688 (static_cast<int32_t>(rm) << kRmShift);
689 Emit(encoding);
690}
691
692void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) {
693 CHECK_NE(rn, kNoRegister);
694 CHECK_NE(rt, kNoRegister);
695 CHECK_NE(cond, kNoCondition);
696 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
697 B24 |
698 B23 |
699 L |
700 (static_cast<int32_t>(rn) << kLdExRnShift) |
701 (static_cast<int32_t>(rt) << kLdExRtShift) |
702 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
703 Emit(encoding);
704}
705
706
707void Arm32Assembler::strex(Register rd,
708 Register rt,
709 Register rn,
710 Condition cond) {
711 CHECK_NE(rn, kNoRegister);
712 CHECK_NE(rd, kNoRegister);
713 CHECK_NE(rt, kNoRegister);
714 CHECK_NE(cond, kNoCondition);
715 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
716 B24 |
717 B23 |
718 (static_cast<int32_t>(rn) << kStrExRnShift) |
719 (static_cast<int32_t>(rd) << kStrExRdShift) |
720 B11 | B10 | B9 | B8 | B7 | B4 |
721 (static_cast<int32_t>(rt) << kStrExRtShift);
722 Emit(encoding);
723}
724
725
726void Arm32Assembler::clrex(Condition cond) {
727 CHECK_EQ(cond, AL); // This cannot be conditional on ARM.
728 int32_t encoding = (kSpecialCondition << kConditionShift) |
729 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
730 Emit(encoding);
731}
732
733
734void Arm32Assembler::nop(Condition cond) {
735 CHECK_NE(cond, kNoCondition);
736 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
737 B25 | B24 | B21 | (0xf << 12);
738 Emit(encoding);
739}
740
741
742void Arm32Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
743 CHECK_NE(sn, kNoSRegister);
744 CHECK_NE(rt, kNoRegister);
745 CHECK_NE(rt, SP);
746 CHECK_NE(rt, PC);
747 CHECK_NE(cond, kNoCondition);
748 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
749 B27 | B26 | B25 |
750 ((static_cast<int32_t>(sn) >> 1)*B16) |
751 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
752 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
753 Emit(encoding);
754}
755
756
757void Arm32Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
758 CHECK_NE(sn, kNoSRegister);
759 CHECK_NE(rt, kNoRegister);
760 CHECK_NE(rt, SP);
761 CHECK_NE(rt, PC);
762 CHECK_NE(cond, kNoCondition);
763 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
764 B27 | B26 | B25 | B20 |
765 ((static_cast<int32_t>(sn) >> 1)*B16) |
766 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
767 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
768 Emit(encoding);
769}
770
771
772void Arm32Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
773 Condition cond) {
774 CHECK_NE(sm, kNoSRegister);
775 CHECK_NE(sm, S31);
776 CHECK_NE(rt, kNoRegister);
777 CHECK_NE(rt, SP);
778 CHECK_NE(rt, PC);
779 CHECK_NE(rt2, kNoRegister);
780 CHECK_NE(rt2, SP);
781 CHECK_NE(rt2, PC);
782 CHECK_NE(cond, kNoCondition);
783 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
784 B27 | B26 | B22 |
785 (static_cast<int32_t>(rt2)*B16) |
786 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
787 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
788 (static_cast<int32_t>(sm) >> 1);
789 Emit(encoding);
790}
791
792
793void Arm32Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
794 Condition cond) {
795 CHECK_NE(sm, kNoSRegister);
796 CHECK_NE(sm, S31);
797 CHECK_NE(rt, kNoRegister);
798 CHECK_NE(rt, SP);
799 CHECK_NE(rt, PC);
800 CHECK_NE(rt2, kNoRegister);
801 CHECK_NE(rt2, SP);
802 CHECK_NE(rt2, PC);
803 CHECK_NE(rt, rt2);
804 CHECK_NE(cond, kNoCondition);
805 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
806 B27 | B26 | B22 | B20 |
807 (static_cast<int32_t>(rt2)*B16) |
808 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
809 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
810 (static_cast<int32_t>(sm) >> 1);
811 Emit(encoding);
812}
813
814
815void Arm32Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
816 Condition cond) {
817 CHECK_NE(dm, kNoDRegister);
818 CHECK_NE(rt, kNoRegister);
819 CHECK_NE(rt, SP);
820 CHECK_NE(rt, PC);
821 CHECK_NE(rt2, kNoRegister);
822 CHECK_NE(rt2, SP);
823 CHECK_NE(rt2, PC);
824 CHECK_NE(cond, kNoCondition);
825 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
826 B27 | B26 | B22 |
827 (static_cast<int32_t>(rt2)*B16) |
828 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
829 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
830 (static_cast<int32_t>(dm) & 0xf);
831 Emit(encoding);
832}
833
834
835void Arm32Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
836 Condition cond) {
837 CHECK_NE(dm, kNoDRegister);
838 CHECK_NE(rt, kNoRegister);
839 CHECK_NE(rt, SP);
840 CHECK_NE(rt, PC);
841 CHECK_NE(rt2, kNoRegister);
842 CHECK_NE(rt2, SP);
843 CHECK_NE(rt2, PC);
844 CHECK_NE(rt, rt2);
845 CHECK_NE(cond, kNoCondition);
846 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
847 B27 | B26 | B22 | B20 |
848 (static_cast<int32_t>(rt2)*B16) |
849 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
850 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
851 (static_cast<int32_t>(dm) & 0xf);
852 Emit(encoding);
853}
854
855
856void Arm32Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
857 const Address& addr = static_cast<const Address&>(ad);
858 CHECK_NE(sd, kNoSRegister);
859 CHECK_NE(cond, kNoCondition);
860 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
861 B27 | B26 | B24 | B20 |
862 ((static_cast<int32_t>(sd) & 1)*B22) |
863 ((static_cast<int32_t>(sd) >> 1)*B12) |
864 B11 | B9 | addr.vencoding();
865 Emit(encoding);
866}
867
868
869void Arm32Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
870 const Address& addr = static_cast<const Address&>(ad);
871 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
872 CHECK_NE(sd, kNoSRegister);
873 CHECK_NE(cond, kNoCondition);
874 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
875 B27 | B26 | B24 |
876 ((static_cast<int32_t>(sd) & 1)*B22) |
877 ((static_cast<int32_t>(sd) >> 1)*B12) |
878 B11 | B9 | addr.vencoding();
879 Emit(encoding);
880}
881
882
883void Arm32Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
884 const Address& addr = static_cast<const Address&>(ad);
885 CHECK_NE(dd, kNoDRegister);
886 CHECK_NE(cond, kNoCondition);
887 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
888 B27 | B26 | B24 | B20 |
889 ((static_cast<int32_t>(dd) >> 4)*B22) |
890 ((static_cast<int32_t>(dd) & 0xf)*B12) |
891 B11 | B9 | B8 | addr.vencoding();
892 Emit(encoding);
893}
894
895
896void Arm32Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
897 const Address& addr = static_cast<const Address&>(ad);
898 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
899 CHECK_NE(dd, kNoDRegister);
900 CHECK_NE(cond, kNoCondition);
901 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
902 B27 | B26 | B24 |
903 ((static_cast<int32_t>(dd) >> 4)*B22) |
904 ((static_cast<int32_t>(dd) & 0xf)*B12) |
905 B11 | B9 | B8 | addr.vencoding();
906 Emit(encoding);
907}
908
909
910void Arm32Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
911 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
912}
913
914
915void Arm32Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
916 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
917}
918
919
920void Arm32Assembler::vpops(SRegister reg, int nregs, Condition cond) {
921 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
922}
923
924
925void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
926 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
927}
928
929
930void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
931 CHECK_NE(cond, kNoCondition);
932 CHECK_GT(nregs, 0);
933 uint32_t D;
934 uint32_t Vd;
935 if (dbl) {
936 // Encoded as D:Vd.
937 D = (reg >> 4) & 1;
938 Vd = reg & 0b1111;
939 } else {
940 // Encoded as Vd:D.
941 D = reg & 1;
942 Vd = (reg >> 1) & 0b1111;
943 }
944 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
945 B11 | B9 |
946 (dbl ? B8 : 0) |
947 (push ? B24 : (B23 | B20)) |
948 static_cast<int32_t>(cond) << kConditionShift |
949 nregs << (dbl ? 1 : 0) |
950 D << 22 |
951 Vd << 12;
952 Emit(encoding);
953}
954
955
956void Arm32Assembler::EmitVFPsss(Condition cond, int32_t opcode,
957 SRegister sd, SRegister sn, SRegister sm) {
958 CHECK_NE(sd, kNoSRegister);
959 CHECK_NE(sn, kNoSRegister);
960 CHECK_NE(sm, kNoSRegister);
961 CHECK_NE(cond, kNoCondition);
962 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
963 B27 | B26 | B25 | B11 | B9 | opcode |
964 ((static_cast<int32_t>(sd) & 1)*B22) |
965 ((static_cast<int32_t>(sn) >> 1)*B16) |
966 ((static_cast<int32_t>(sd) >> 1)*B12) |
967 ((static_cast<int32_t>(sn) & 1)*B7) |
968 ((static_cast<int32_t>(sm) & 1)*B5) |
969 (static_cast<int32_t>(sm) >> 1);
970 Emit(encoding);
971}
972
973
974void Arm32Assembler::EmitVFPddd(Condition cond, int32_t opcode,
975 DRegister dd, DRegister dn, DRegister dm) {
976 CHECK_NE(dd, kNoDRegister);
977 CHECK_NE(dn, kNoDRegister);
978 CHECK_NE(dm, kNoDRegister);
979 CHECK_NE(cond, kNoCondition);
980 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
981 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
982 ((static_cast<int32_t>(dd) >> 4)*B22) |
983 ((static_cast<int32_t>(dn) & 0xf)*B16) |
984 ((static_cast<int32_t>(dd) & 0xf)*B12) |
985 ((static_cast<int32_t>(dn) >> 4)*B7) |
986 ((static_cast<int32_t>(dm) >> 4)*B5) |
987 (static_cast<int32_t>(dm) & 0xf);
988 Emit(encoding);
989}
990
991
992void Arm32Assembler::EmitVFPsd(Condition cond, int32_t opcode,
993 SRegister sd, DRegister dm) {
994 CHECK_NE(sd, kNoSRegister);
995 CHECK_NE(dm, kNoDRegister);
996 CHECK_NE(cond, kNoCondition);
997 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
998 B27 | B26 | B25 | B11 | B9 | opcode |
999 ((static_cast<int32_t>(sd) & 1)*B22) |
1000 ((static_cast<int32_t>(sd) >> 1)*B12) |
1001 ((static_cast<int32_t>(dm) >> 4)*B5) |
1002 (static_cast<int32_t>(dm) & 0xf);
1003 Emit(encoding);
1004}
1005
1006
1007void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
1008 DRegister dd, SRegister sm) {
1009 CHECK_NE(dd, kNoDRegister);
1010 CHECK_NE(sm, kNoSRegister);
1011 CHECK_NE(cond, kNoCondition);
1012 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1013 B27 | B26 | B25 | B11 | B9 | opcode |
1014 ((static_cast<int32_t>(dd) >> 4)*B22) |
1015 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1016 ((static_cast<int32_t>(sm) & 1)*B5) |
1017 (static_cast<int32_t>(sm) >> 1);
1018 Emit(encoding);
1019}
1020
1021
1022void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
1023 Condition cond) {
1024 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
1025 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1026}
1027
1028
1029void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
1030 Condition cond) {
1031 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
1032 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1033 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1034}
1035
1036
1037void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
1038 Condition cond) {
1039 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
1040 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
1041 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1042}
1043
1044
1045void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
1046 Condition cond) {
1047 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
1048 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1049}
1050
1051void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond) {
1052 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1053}
1054
1055
1056void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1057 CHECK_NE(cond, kNoCondition);
1058 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1059 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1060 (static_cast<int32_t>(PC)*B12) |
1061 B11 | B9 | B4;
1062 Emit(encoding);
1063}
1064
1065
1066void Arm32Assembler::svc(uint32_t imm24) {
1067 CHECK(IsUint(24, imm24)) << imm24;
1068 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1069 Emit(encoding);
1070}
1071
1072
1073void Arm32Assembler::bkpt(uint16_t imm16) {
1074 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1075 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1076 Emit(encoding);
1077}
1078
1079
1080void Arm32Assembler::blx(Register rm, Condition cond) {
1081 CHECK_NE(rm, kNoRegister);
1082 CHECK_NE(cond, kNoCondition);
1083 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1084 B24 | B21 | (0xfff << 8) | B5 | B4 |
1085 (static_cast<int32_t>(rm) << kRmShift);
1086 Emit(encoding);
1087}
1088
1089
1090void Arm32Assembler::bx(Register rm, Condition cond) {
1091 CHECK_NE(rm, kNoRegister);
1092 CHECK_NE(cond, kNoCondition);
1093 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1094 B24 | B21 | (0xfff << 8) | B4 |
1095 (static_cast<int32_t>(rm) << kRmShift);
1096 Emit(encoding);
1097}
1098
1099
1100void Arm32Assembler::Push(Register rd, Condition cond) {
1101 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1102}
1103
1104
1105void Arm32Assembler::Pop(Register rd, Condition cond) {
1106 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1107}
1108
1109
1110void Arm32Assembler::PushList(RegList regs, Condition cond) {
1111 stm(DB_W, SP, regs, cond);
1112}
1113
1114
1115void Arm32Assembler::PopList(RegList regs, Condition cond) {
1116 ldm(IA_W, SP, regs, cond);
1117}
1118
1119
1120void Arm32Assembler::Mov(Register rd, Register rm, Condition cond) {
1121 if (rd != rm) {
1122 mov(rd, ShifterOperand(rm), cond);
1123 }
1124}
1125
1126
1127void Arm32Assembler::Bind(Label* label) {
1128 CHECK(!label->IsBound());
1129 int bound_pc = buffer_.Size();
1130 while (label->IsLinked()) {
1131 int32_t position = label->Position();
1132 int32_t next = buffer_.Load<int32_t>(position);
1133 int32_t encoded = Arm32Assembler::EncodeBranchOffset(bound_pc - position, next);
1134 buffer_.Store<int32_t>(position, encoded);
1135 label->position_ = Arm32Assembler::DecodeBranchOffset(next);
1136 }
1137 label->BindTo(bound_pc);
1138}
1139
1140
1141int32_t Arm32Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1142 // The offset is off by 8 due to the way the ARM CPUs read PC.
1143 offset -= 8;
1144 CHECK_ALIGNED(offset, 4);
1145 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
1146
1147 // Properly preserve only the bits supported in the instruction.
1148 offset >>= 2;
1149 offset &= kBranchOffsetMask;
1150 return (inst & ~kBranchOffsetMask) | offset;
1151}
1152
1153
1154int Arm32Assembler::DecodeBranchOffset(int32_t inst) {
1155 // Sign-extend, left-shift by 2, then add 8.
1156 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1157}
1158
1159
1160void Arm32Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
1161 AddConstant(rd, rd, value, cond);
1162}
1163
1164
1165void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
1166 Condition cond) {
1167 if (value == 0) {
1168 if (rd != rn) {
1169 mov(rd, ShifterOperand(rn), cond);
1170 }
1171 return;
1172 }
1173 // We prefer to select the shorter code sequence rather than selecting add for
1174 // positive values and sub for negatives ones, which would slightly improve
1175 // the readability of generated code for some constants.
1176 ShifterOperand shifter_op;
1177 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1178 add(rd, rn, shifter_op, cond);
1179 } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
1180 sub(rd, rn, shifter_op, cond);
1181 } else {
1182 CHECK(rn != IP);
1183 if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1184 mvn(IP, shifter_op, cond);
1185 add(rd, rn, ShifterOperand(IP), cond);
1186 } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
1187 mvn(IP, shifter_op, cond);
1188 sub(rd, rn, ShifterOperand(IP), cond);
1189 } else {
1190 movw(IP, Low16Bits(value), cond);
1191 uint16_t value_high = High16Bits(value);
1192 if (value_high != 0) {
1193 movt(IP, value_high, cond);
1194 }
1195 add(rd, rn, ShifterOperand(IP), cond);
1196 }
1197 }
1198}
1199
1200
1201void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1202 Condition cond) {
1203 ShifterOperand shifter_op;
1204 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1205 adds(rd, rn, shifter_op, cond);
1206 } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
1207 subs(rd, rn, shifter_op, cond);
1208 } else {
1209 CHECK(rn != IP);
1210 if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1211 mvn(IP, shifter_op, cond);
1212 adds(rd, rn, ShifterOperand(IP), cond);
1213 } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
1214 mvn(IP, shifter_op, cond);
1215 subs(rd, rn, ShifterOperand(IP), cond);
1216 } else {
1217 movw(IP, Low16Bits(value), cond);
1218 uint16_t value_high = High16Bits(value);
1219 if (value_high != 0) {
1220 movt(IP, value_high, cond);
1221 }
1222 adds(rd, rn, ShifterOperand(IP), cond);
1223 }
1224 }
1225}
1226
1227
1228void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1229 ShifterOperand shifter_op;
1230 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1231 mov(rd, shifter_op, cond);
1232 } else if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1233 mvn(rd, shifter_op, cond);
1234 } else {
1235 movw(rd, Low16Bits(value), cond);
1236 uint16_t value_high = High16Bits(value);
1237 if (value_high != 0) {
1238 movt(rd, value_high, cond);
1239 }
1240 }
1241}
1242
1243
1244// Implementation note: this method must emit at most one instruction when
1245// Address::CanHoldLoadOffsetArm.
1246void Arm32Assembler::LoadFromOffset(LoadOperandType type,
1247 Register reg,
1248 Register base,
1249 int32_t offset,
1250 Condition cond) {
1251 if (!Address::CanHoldLoadOffsetArm(type, offset)) {
1252 CHECK(base != IP);
1253 LoadImmediate(IP, offset, cond);
1254 add(IP, IP, ShifterOperand(base), cond);
1255 base = IP;
1256 offset = 0;
1257 }
1258 CHECK(Address::CanHoldLoadOffsetArm(type, offset));
1259 switch (type) {
1260 case kLoadSignedByte:
1261 ldrsb(reg, Address(base, offset), cond);
1262 break;
1263 case kLoadUnsignedByte:
1264 ldrb(reg, Address(base, offset), cond);
1265 break;
1266 case kLoadSignedHalfword:
1267 ldrsh(reg, Address(base, offset), cond);
1268 break;
1269 case kLoadUnsignedHalfword:
1270 ldrh(reg, Address(base, offset), cond);
1271 break;
1272 case kLoadWord:
1273 ldr(reg, Address(base, offset), cond);
1274 break;
1275 case kLoadWordPair:
1276 ldrd(reg, Address(base, offset), cond);
1277 break;
1278 default:
1279 LOG(FATAL) << "UNREACHABLE";
1280 }
1281}
1282
1283
1284// Implementation note: this method must emit at most one instruction when
1285// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1286void Arm32Assembler::LoadSFromOffset(SRegister reg,
1287 Register base,
1288 int32_t offset,
1289 Condition cond) {
1290 if (!Address::CanHoldLoadOffsetArm(kLoadSWord, offset)) {
1291 CHECK_NE(base, IP);
1292 LoadImmediate(IP, offset, cond);
1293 add(IP, IP, ShifterOperand(base), cond);
1294 base = IP;
1295 offset = 0;
1296 }
1297 CHECK(Address::CanHoldLoadOffsetArm(kLoadSWord, offset));
1298 vldrs(reg, Address(base, offset), cond);
1299}
1300
1301
1302// Implementation note: this method must emit at most one instruction when
1303// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1304void Arm32Assembler::LoadDFromOffset(DRegister reg,
1305 Register base,
1306 int32_t offset,
1307 Condition cond) {
1308 if (!Address::CanHoldLoadOffsetArm(kLoadDWord, offset)) {
1309 CHECK_NE(base, IP);
1310 LoadImmediate(IP, offset, cond);
1311 add(IP, IP, ShifterOperand(base), cond);
1312 base = IP;
1313 offset = 0;
1314 }
1315 CHECK(Address::CanHoldLoadOffsetArm(kLoadDWord, offset));
1316 vldrd(reg, Address(base, offset), cond);
1317}
1318
1319
1320// Implementation note: this method must emit at most one instruction when
1321// Address::CanHoldStoreOffsetArm.
1322void Arm32Assembler::StoreToOffset(StoreOperandType type,
1323 Register reg,
1324 Register base,
1325 int32_t offset,
1326 Condition cond) {
1327 if (!Address::CanHoldStoreOffsetArm(type, offset)) {
1328 CHECK(reg != IP);
1329 CHECK(base != IP);
1330 LoadImmediate(IP, offset, cond);
1331 add(IP, IP, ShifterOperand(base), cond);
1332 base = IP;
1333 offset = 0;
1334 }
1335 CHECK(Address::CanHoldStoreOffsetArm(type, offset));
1336 switch (type) {
1337 case kStoreByte:
1338 strb(reg, Address(base, offset), cond);
1339 break;
1340 case kStoreHalfword:
1341 strh(reg, Address(base, offset), cond);
1342 break;
1343 case kStoreWord:
1344 str(reg, Address(base, offset), cond);
1345 break;
1346 case kStoreWordPair:
1347 strd(reg, Address(base, offset), cond);
1348 break;
1349 default:
1350 LOG(FATAL) << "UNREACHABLE";
1351 }
1352}
1353
1354
1355// Implementation note: this method must emit at most one instruction when
1356// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreToOffset.
1357void Arm32Assembler::StoreSToOffset(SRegister reg,
1358 Register base,
1359 int32_t offset,
1360 Condition cond) {
1361 if (!Address::CanHoldStoreOffsetArm(kStoreSWord, 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::CanHoldStoreOffsetArm(kStoreSWord, offset));
1369 vstrs(reg, Address(base, offset), cond);
1370}
1371
1372
1373// Implementation note: this method must emit at most one instruction when
1374// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreSToOffset.
1375void Arm32Assembler::StoreDToOffset(DRegister reg,
1376 Register base,
1377 int32_t offset,
1378 Condition cond) {
1379 if (!Address::CanHoldStoreOffsetArm(kStoreDWord, offset)) {
1380 CHECK_NE(base, IP);
1381 LoadImmediate(IP, offset, cond);
1382 add(IP, IP, ShifterOperand(base), cond);
1383 base = IP;
1384 offset = 0;
1385 }
1386 CHECK(Address::CanHoldStoreOffsetArm(kStoreDWord, offset));
1387 vstrd(reg, Address(base, offset), cond);
1388}
1389
1390
1391void Arm32Assembler::MemoryBarrier(ManagedRegister mscratch) {
1392 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
1393#if ANDROID_SMP != 0
1394 int32_t encoding = 0xf57ff05f; // dmb
1395 Emit(encoding);
1396#endif
1397}
1398
1399
1400void Arm32Assembler::cbz(Register rn, Label* target) {
1401 LOG(FATAL) << "cbz is not supported on ARM32";
1402}
1403
1404
1405void Arm32Assembler::cbnz(Register rn, Label* target) {
1406 LOG(FATAL) << "cbnz is not supported on ARM32";
1407}
1408
1409
1410void Arm32Assembler::CompareAndBranchIfZero(Register r, Label* label) {
1411 cmp(r, ShifterOperand(0));
1412 b(label, EQ);
1413}
1414
1415
1416void Arm32Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
1417 cmp(r, ShifterOperand(0));
1418 b(label, NE);
1419}
1420
1421
1422} // namespace arm
1423} // namespace art