blob: 29cbf5851f2fddb5f4ab1fc928986458ba39ef67 [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
Roland Levillain51d3fc42014-11-13 14:11:42 +0000211void Arm32Assembler::sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
212 CHECK_NE(rd, kNoRegister);
213 CHECK_NE(rn, kNoRegister);
214 CHECK_NE(cond, kNoCondition);
215 CHECK_LE(lsb, 31U);
216 CHECK(1U <= width && width <= 32U) << width;
217 uint32_t widthminus1 = width - 1;
218
219 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
220 B26 | B25 | B24 | B23 | B21 |
221 (widthminus1 << 16) |
222 (static_cast<uint32_t>(rd) << 12) |
223 (lsb << 7) |
224 B6 | B4 |
225 static_cast<uint32_t>(rn);
226 Emit(encoding);
227}
228
229
Dave Allison65fcc2c2014-04-28 13:45:27 -0700230void Arm32Assembler::ldr(Register rd, const Address& ad, Condition cond) {
231 EmitMemOp(cond, true, false, rd, ad);
232}
233
234
235void Arm32Assembler::str(Register rd, const Address& ad, Condition cond) {
236 EmitMemOp(cond, false, false, rd, ad);
237}
238
239
240void Arm32Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
241 EmitMemOp(cond, true, true, rd, ad);
242}
243
244
245void Arm32Assembler::strb(Register rd, const Address& ad, Condition cond) {
246 EmitMemOp(cond, false, true, rd, ad);
247}
248
249
250void Arm32Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
251 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
252}
253
254
255void Arm32Assembler::strh(Register rd, const Address& ad, Condition cond) {
256 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
257}
258
259
260void Arm32Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
261 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
262}
263
264
265void Arm32Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
266 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
267}
268
269
270void Arm32Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
271 CHECK_EQ(rd % 2, 0);
272 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
273}
274
275
276void Arm32Assembler::strd(Register rd, const Address& ad, Condition cond) {
277 CHECK_EQ(rd % 2, 0);
278 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
279}
280
281
282void Arm32Assembler::ldm(BlockAddressMode am,
283 Register base,
284 RegList regs,
285 Condition cond) {
286 EmitMultiMemOp(cond, am, true, base, regs);
287}
288
289
290void Arm32Assembler::stm(BlockAddressMode am,
291 Register base,
292 RegList regs,
293 Condition cond) {
294 EmitMultiMemOp(cond, am, false, base, regs);
295}
296
297
298void Arm32Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
299 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
300}
301
302
303void Arm32Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
304 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
305}
306
307
308bool Arm32Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
309 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
310 if (((imm32 & ((1 << 19) - 1)) == 0) &&
311 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
312 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
313 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
314 ((imm32 >> 19) & ((1 << 6) -1));
315 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
316 sd, S0, S0);
317 return true;
318 }
319 return false;
320}
321
322
323bool Arm32Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
324 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
325 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
326 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
327 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
328 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
329 ((imm64 >> 48) & ((1 << 6) -1));
330 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
331 dd, D0, D0);
332 return true;
333 }
334 return false;
335}
336
337
338void Arm32Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
339 Condition cond) {
340 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
341}
342
343
344void Arm32Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
345 Condition cond) {
346 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
347}
348
349
350void Arm32Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
351 Condition cond) {
352 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
353}
354
355
356void Arm32Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
357 Condition cond) {
358 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
359}
360
361
362void Arm32Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
363 Condition cond) {
364 EmitVFPsss(cond, B21, sd, sn, sm);
365}
366
367
368void Arm32Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
369 Condition cond) {
370 EmitVFPddd(cond, B21, dd, dn, dm);
371}
372
373
374void Arm32Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
375 Condition cond) {
376 EmitVFPsss(cond, 0, sd, sn, sm);
377}
378
379
380void Arm32Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
381 Condition cond) {
382 EmitVFPddd(cond, 0, dd, dn, dm);
383}
384
385
386void Arm32Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
387 Condition cond) {
388 EmitVFPsss(cond, B6, sd, sn, sm);
389}
390
391
392void Arm32Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
393 Condition cond) {
394 EmitVFPddd(cond, B6, dd, dn, dm);
395}
396
397
398void Arm32Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
399 Condition cond) {
400 EmitVFPsss(cond, B23, sd, sn, sm);
401}
402
403
404void Arm32Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
405 Condition cond) {
406 EmitVFPddd(cond, B23, dd, dn, dm);
407}
408
409
410void Arm32Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
411 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
412}
413
414
415void Arm32Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
416 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
417}
418
419
420void Arm32Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
421 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
422}
423
424
425void Arm32Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
426 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
427}
428
429
430void Arm32Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
431 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
432}
433
434void Arm32Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
435 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
436}
437
438
439void Arm32Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
440 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
441}
442
443
444void Arm32Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
445 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
446}
447
448
449void Arm32Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
450 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
451}
452
453
454void Arm32Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
455 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
456}
457
458
459void Arm32Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
460 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
461}
462
463
464void Arm32Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
465 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
466}
467
468
469void Arm32Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
470 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
471}
472
473
474void Arm32Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
475 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
476}
477
478
479void Arm32Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
480 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
481}
482
483
484void Arm32Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
485 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
486}
487
488
489void Arm32Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
490 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
491}
492
493
494void Arm32Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
495 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
496}
497
498
499void Arm32Assembler::vcmpsz(SRegister sd, Condition cond) {
500 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
501}
502
503
504void Arm32Assembler::vcmpdz(DRegister dd, Condition cond) {
505 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
506}
507
508void Arm32Assembler::b(Label* label, Condition cond) {
509 EmitBranch(cond, label, false);
510}
511
512
513void Arm32Assembler::bl(Label* label, Condition cond) {
514 EmitBranch(cond, label, true);
515}
516
517
518void Arm32Assembler::MarkExceptionHandler(Label* label) {
519 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
520 Label l;
521 b(&l);
522 EmitBranch(AL, label, false);
523 Bind(&l);
524}
525
526
527void Arm32Assembler::Emit(int32_t value) {
528 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
529 buffer_.Emit<int32_t>(value);
530}
531
532
533void Arm32Assembler::EmitType01(Condition cond,
534 int type,
535 Opcode opcode,
536 int set_cc,
537 Register rn,
538 Register rd,
539 const ShifterOperand& so) {
540 CHECK_NE(rd, kNoRegister);
541 CHECK_NE(cond, kNoCondition);
542 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
543 type << kTypeShift |
544 static_cast<int32_t>(opcode) << kOpcodeShift |
545 set_cc << kSShift |
546 static_cast<int32_t>(rn) << kRnShift |
547 static_cast<int32_t>(rd) << kRdShift |
548 so.encodingArm();
549 Emit(encoding);
550}
551
552
553void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
554 CHECK_NE(cond, kNoCondition);
555 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
556 5 << kTypeShift |
557 (link ? 1 : 0) << kLinkShift;
558 Emit(Arm32Assembler::EncodeBranchOffset(offset, encoding));
559}
560
561
562void Arm32Assembler::EmitMemOp(Condition cond,
Dave Allison45fdb932014-06-25 12:37:10 -0700563 bool load,
564 bool byte,
565 Register rd,
566 const Address& ad) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700567 CHECK_NE(rd, kNoRegister);
568 CHECK_NE(cond, kNoCondition);
569 const Address& addr = static_cast<const Address&>(ad);
570
Dave Allison45fdb932014-06-25 12:37:10 -0700571 int32_t encoding = 0;
572 if (!ad.IsImmediate() && ad.GetRegisterOffset() == PC) {
573 // PC relative LDR(literal)
574 int32_t offset = ad.GetOffset();
575 int32_t u = B23;
576 if (offset < 0) {
577 offset = -offset;
578 u = 0;
579 }
580 CHECK_LT(offset, (1 << 12));
581 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
582 B26 | B24 | u | B20 |
583 (load ? L : 0) |
584 (byte ? B : 0) |
585 (static_cast<int32_t>(rd) << kRdShift) |
586 0xf << 16 |
587 (offset & 0xfff);
588
589 } else {
590 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
591 B26 |
592 (load ? L : 0) |
593 (byte ? B : 0) |
594 (static_cast<int32_t>(rd) << kRdShift) |
595 addr.encodingArm();
596 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700597 Emit(encoding);
598}
599
600
601void Arm32Assembler::EmitMemOpAddressMode3(Condition cond,
602 int32_t mode,
603 Register rd,
604 const Address& ad) {
605 CHECK_NE(rd, kNoRegister);
606 CHECK_NE(cond, kNoCondition);
607 const Address& addr = static_cast<const Address&>(ad);
608 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
609 B22 |
610 mode |
611 (static_cast<int32_t>(rd) << kRdShift) |
612 addr.encoding3();
613 Emit(encoding);
614}
615
616
617void Arm32Assembler::EmitMultiMemOp(Condition cond,
618 BlockAddressMode am,
619 bool load,
620 Register base,
621 RegList regs) {
622 CHECK_NE(base, kNoRegister);
623 CHECK_NE(cond, kNoCondition);
624 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
625 B27 |
626 am |
627 (load ? L : 0) |
628 (static_cast<int32_t>(base) << kRnShift) |
629 regs;
630 Emit(encoding);
631}
632
633
634void Arm32Assembler::EmitShiftImmediate(Condition cond,
635 Shift opcode,
636 Register rd,
637 Register rm,
638 const ShifterOperand& so) {
639 CHECK_NE(cond, kNoCondition);
640 CHECK(so.IsImmediate());
641 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
642 static_cast<int32_t>(MOV) << kOpcodeShift |
643 static_cast<int32_t>(rd) << kRdShift |
644 so.encodingArm() << kShiftImmShift |
645 static_cast<int32_t>(opcode) << kShiftShift |
646 static_cast<int32_t>(rm);
647 Emit(encoding);
648}
649
650
651void Arm32Assembler::EmitShiftRegister(Condition cond,
652 Shift opcode,
653 Register rd,
654 Register rm,
655 const ShifterOperand& so) {
656 CHECK_NE(cond, kNoCondition);
657 CHECK(so.IsRegister());
658 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
659 static_cast<int32_t>(MOV) << kOpcodeShift |
660 static_cast<int32_t>(rd) << kRdShift |
661 so.encodingArm() << kShiftRegisterShift |
662 static_cast<int32_t>(opcode) << kShiftShift |
663 B4 |
664 static_cast<int32_t>(rm);
665 Emit(encoding);
666}
667
668
669void Arm32Assembler::EmitBranch(Condition cond, Label* label, bool link) {
670 if (label->IsBound()) {
671 EmitType5(cond, label->Position() - buffer_.Size(), link);
672 } else {
673 int position = buffer_.Size();
674 // Use the offset field of the branch instruction for linking the sites.
675 EmitType5(cond, label->position_, link);
676 label->LinkTo(position);
677 }
678}
679
680
681void Arm32Assembler::clz(Register rd, Register rm, Condition cond) {
682 CHECK_NE(rd, kNoRegister);
683 CHECK_NE(rm, kNoRegister);
684 CHECK_NE(cond, kNoCondition);
685 CHECK_NE(rd, PC);
686 CHECK_NE(rm, PC);
687 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
688 B24 | B22 | B21 | (0xf << 16) |
689 (static_cast<int32_t>(rd) << kRdShift) |
690 (0xf << 8) | B4 | static_cast<int32_t>(rm);
691 Emit(encoding);
692}
693
694
695void Arm32Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
696 CHECK_NE(cond, kNoCondition);
697 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
698 B25 | B24 | ((imm16 >> 12) << 16) |
699 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
700 Emit(encoding);
701}
702
703
704void Arm32Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
705 CHECK_NE(cond, kNoCondition);
706 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
707 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
708 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
709 Emit(encoding);
710}
711
712
713void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
714 Register rd, Register rn,
715 Register rm, Register rs) {
716 CHECK_NE(rd, kNoRegister);
717 CHECK_NE(rn, kNoRegister);
718 CHECK_NE(rm, kNoRegister);
719 CHECK_NE(rs, kNoRegister);
720 CHECK_NE(cond, kNoCondition);
721 int32_t encoding = opcode |
722 (static_cast<int32_t>(cond) << kConditionShift) |
723 (static_cast<int32_t>(rn) << kRnShift) |
724 (static_cast<int32_t>(rd) << kRdShift) |
725 (static_cast<int32_t>(rs) << kRsShift) |
726 B7 | B4 |
727 (static_cast<int32_t>(rm) << kRmShift);
728 Emit(encoding);
729}
730
731void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) {
732 CHECK_NE(rn, kNoRegister);
733 CHECK_NE(rt, kNoRegister);
734 CHECK_NE(cond, kNoCondition);
735 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
736 B24 |
737 B23 |
738 L |
739 (static_cast<int32_t>(rn) << kLdExRnShift) |
740 (static_cast<int32_t>(rt) << kLdExRtShift) |
741 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
742 Emit(encoding);
743}
744
745
746void Arm32Assembler::strex(Register rd,
747 Register rt,
748 Register rn,
749 Condition cond) {
750 CHECK_NE(rn, kNoRegister);
751 CHECK_NE(rd, kNoRegister);
752 CHECK_NE(rt, kNoRegister);
753 CHECK_NE(cond, kNoCondition);
754 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
755 B24 |
756 B23 |
757 (static_cast<int32_t>(rn) << kStrExRnShift) |
758 (static_cast<int32_t>(rd) << kStrExRdShift) |
759 B11 | B10 | B9 | B8 | B7 | B4 |
760 (static_cast<int32_t>(rt) << kStrExRtShift);
761 Emit(encoding);
762}
763
764
765void Arm32Assembler::clrex(Condition cond) {
766 CHECK_EQ(cond, AL); // This cannot be conditional on ARM.
767 int32_t encoding = (kSpecialCondition << kConditionShift) |
768 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
769 Emit(encoding);
770}
771
772
773void Arm32Assembler::nop(Condition cond) {
774 CHECK_NE(cond, kNoCondition);
775 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
776 B25 | B24 | B21 | (0xf << 12);
777 Emit(encoding);
778}
779
780
781void Arm32Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
782 CHECK_NE(sn, kNoSRegister);
783 CHECK_NE(rt, kNoRegister);
784 CHECK_NE(rt, SP);
785 CHECK_NE(rt, PC);
786 CHECK_NE(cond, kNoCondition);
787 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
788 B27 | B26 | B25 |
789 ((static_cast<int32_t>(sn) >> 1)*B16) |
790 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
791 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
792 Emit(encoding);
793}
794
795
796void Arm32Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
797 CHECK_NE(sn, kNoSRegister);
798 CHECK_NE(rt, kNoRegister);
799 CHECK_NE(rt, SP);
800 CHECK_NE(rt, PC);
801 CHECK_NE(cond, kNoCondition);
802 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
803 B27 | B26 | B25 | B20 |
804 ((static_cast<int32_t>(sn) >> 1)*B16) |
805 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
806 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
807 Emit(encoding);
808}
809
810
811void Arm32Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
812 Condition cond) {
813 CHECK_NE(sm, kNoSRegister);
814 CHECK_NE(sm, S31);
815 CHECK_NE(rt, kNoRegister);
816 CHECK_NE(rt, SP);
817 CHECK_NE(rt, PC);
818 CHECK_NE(rt2, kNoRegister);
819 CHECK_NE(rt2, SP);
820 CHECK_NE(rt2, PC);
821 CHECK_NE(cond, kNoCondition);
822 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
823 B27 | B26 | B22 |
824 (static_cast<int32_t>(rt2)*B16) |
825 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
826 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
827 (static_cast<int32_t>(sm) >> 1);
828 Emit(encoding);
829}
830
831
832void Arm32Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
833 Condition cond) {
834 CHECK_NE(sm, kNoSRegister);
835 CHECK_NE(sm, S31);
836 CHECK_NE(rt, kNoRegister);
837 CHECK_NE(rt, SP);
838 CHECK_NE(rt, PC);
839 CHECK_NE(rt2, kNoRegister);
840 CHECK_NE(rt2, SP);
841 CHECK_NE(rt2, PC);
842 CHECK_NE(rt, rt2);
843 CHECK_NE(cond, kNoCondition);
844 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
845 B27 | B26 | B22 | B20 |
846 (static_cast<int32_t>(rt2)*B16) |
847 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
848 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
849 (static_cast<int32_t>(sm) >> 1);
850 Emit(encoding);
851}
852
853
854void Arm32Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
855 Condition cond) {
856 CHECK_NE(dm, kNoDRegister);
857 CHECK_NE(rt, kNoRegister);
858 CHECK_NE(rt, SP);
859 CHECK_NE(rt, PC);
860 CHECK_NE(rt2, kNoRegister);
861 CHECK_NE(rt2, SP);
862 CHECK_NE(rt2, PC);
863 CHECK_NE(cond, kNoCondition);
864 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
865 B27 | B26 | B22 |
866 (static_cast<int32_t>(rt2)*B16) |
867 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
868 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
869 (static_cast<int32_t>(dm) & 0xf);
870 Emit(encoding);
871}
872
873
874void Arm32Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
875 Condition cond) {
876 CHECK_NE(dm, kNoDRegister);
877 CHECK_NE(rt, kNoRegister);
878 CHECK_NE(rt, SP);
879 CHECK_NE(rt, PC);
880 CHECK_NE(rt2, kNoRegister);
881 CHECK_NE(rt2, SP);
882 CHECK_NE(rt2, PC);
883 CHECK_NE(rt, rt2);
884 CHECK_NE(cond, kNoCondition);
885 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
886 B27 | B26 | B22 | B20 |
887 (static_cast<int32_t>(rt2)*B16) |
888 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
889 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
890 (static_cast<int32_t>(dm) & 0xf);
891 Emit(encoding);
892}
893
894
895void Arm32Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
896 const Address& addr = static_cast<const Address&>(ad);
897 CHECK_NE(sd, kNoSRegister);
898 CHECK_NE(cond, kNoCondition);
899 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
900 B27 | B26 | B24 | B20 |
901 ((static_cast<int32_t>(sd) & 1)*B22) |
902 ((static_cast<int32_t>(sd) >> 1)*B12) |
903 B11 | B9 | addr.vencoding();
904 Emit(encoding);
905}
906
907
908void Arm32Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
909 const Address& addr = static_cast<const Address&>(ad);
910 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
911 CHECK_NE(sd, kNoSRegister);
912 CHECK_NE(cond, kNoCondition);
913 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
914 B27 | B26 | B24 |
915 ((static_cast<int32_t>(sd) & 1)*B22) |
916 ((static_cast<int32_t>(sd) >> 1)*B12) |
917 B11 | B9 | addr.vencoding();
918 Emit(encoding);
919}
920
921
922void Arm32Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
923 const Address& addr = static_cast<const Address&>(ad);
924 CHECK_NE(dd, kNoDRegister);
925 CHECK_NE(cond, kNoCondition);
926 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
927 B27 | B26 | B24 | B20 |
928 ((static_cast<int32_t>(dd) >> 4)*B22) |
929 ((static_cast<int32_t>(dd) & 0xf)*B12) |
930 B11 | B9 | B8 | addr.vencoding();
931 Emit(encoding);
932}
933
934
935void Arm32Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
936 const Address& addr = static_cast<const Address&>(ad);
937 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
938 CHECK_NE(dd, kNoDRegister);
939 CHECK_NE(cond, kNoCondition);
940 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
941 B27 | B26 | B24 |
942 ((static_cast<int32_t>(dd) >> 4)*B22) |
943 ((static_cast<int32_t>(dd) & 0xf)*B12) |
944 B11 | B9 | B8 | addr.vencoding();
945 Emit(encoding);
946}
947
948
949void Arm32Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
950 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
951}
952
953
954void Arm32Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
955 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
956}
957
958
959void Arm32Assembler::vpops(SRegister reg, int nregs, Condition cond) {
960 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
961}
962
963
964void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
965 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
966}
967
968
969void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
970 CHECK_NE(cond, kNoCondition);
971 CHECK_GT(nregs, 0);
972 uint32_t D;
973 uint32_t Vd;
974 if (dbl) {
975 // Encoded as D:Vd.
976 D = (reg >> 4) & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700977 Vd = reg & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700978 } else {
979 // Encoded as Vd:D.
980 D = reg & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700981 Vd = (reg >> 1) & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700982 }
983 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
984 B11 | B9 |
985 (dbl ? B8 : 0) |
986 (push ? B24 : (B23 | B20)) |
987 static_cast<int32_t>(cond) << kConditionShift |
988 nregs << (dbl ? 1 : 0) |
989 D << 22 |
990 Vd << 12;
991 Emit(encoding);
992}
993
994
995void Arm32Assembler::EmitVFPsss(Condition cond, int32_t opcode,
996 SRegister sd, SRegister sn, SRegister sm) {
997 CHECK_NE(sd, kNoSRegister);
998 CHECK_NE(sn, kNoSRegister);
999 CHECK_NE(sm, kNoSRegister);
1000 CHECK_NE(cond, kNoCondition);
1001 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1002 B27 | B26 | B25 | B11 | B9 | opcode |
1003 ((static_cast<int32_t>(sd) & 1)*B22) |
1004 ((static_cast<int32_t>(sn) >> 1)*B16) |
1005 ((static_cast<int32_t>(sd) >> 1)*B12) |
1006 ((static_cast<int32_t>(sn) & 1)*B7) |
1007 ((static_cast<int32_t>(sm) & 1)*B5) |
1008 (static_cast<int32_t>(sm) >> 1);
1009 Emit(encoding);
1010}
1011
1012
1013void Arm32Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1014 DRegister dd, DRegister dn, DRegister dm) {
1015 CHECK_NE(dd, kNoDRegister);
1016 CHECK_NE(dn, kNoDRegister);
1017 CHECK_NE(dm, kNoDRegister);
1018 CHECK_NE(cond, kNoCondition);
1019 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1020 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1021 ((static_cast<int32_t>(dd) >> 4)*B22) |
1022 ((static_cast<int32_t>(dn) & 0xf)*B16) |
1023 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1024 ((static_cast<int32_t>(dn) >> 4)*B7) |
1025 ((static_cast<int32_t>(dm) >> 4)*B5) |
1026 (static_cast<int32_t>(dm) & 0xf);
1027 Emit(encoding);
1028}
1029
1030
1031void Arm32Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1032 SRegister sd, DRegister dm) {
1033 CHECK_NE(sd, kNoSRegister);
1034 CHECK_NE(dm, kNoDRegister);
1035 CHECK_NE(cond, kNoCondition);
1036 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1037 B27 | B26 | B25 | B11 | B9 | opcode |
1038 ((static_cast<int32_t>(sd) & 1)*B22) |
1039 ((static_cast<int32_t>(sd) >> 1)*B12) |
1040 ((static_cast<int32_t>(dm) >> 4)*B5) |
1041 (static_cast<int32_t>(dm) & 0xf);
1042 Emit(encoding);
1043}
1044
1045
1046void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
1047 DRegister dd, SRegister sm) {
1048 CHECK_NE(dd, kNoDRegister);
1049 CHECK_NE(sm, kNoSRegister);
1050 CHECK_NE(cond, kNoCondition);
1051 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1052 B27 | B26 | B25 | B11 | B9 | opcode |
1053 ((static_cast<int32_t>(dd) >> 4)*B22) |
1054 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1055 ((static_cast<int32_t>(sm) & 1)*B5) |
1056 (static_cast<int32_t>(sm) >> 1);
1057 Emit(encoding);
1058}
1059
1060
1061void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001062 bool setcc, Condition cond) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001063 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
Dave Allison45fdb932014-06-25 12:37:10 -07001064 if (setcc) {
1065 movs(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1066 } else {
1067 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1068 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001069}
1070
1071
1072void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001073 bool setcc, Condition cond) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001074 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
1075 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Dave Allison45fdb932014-06-25 12:37:10 -07001076 if (setcc) {
1077 movs(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1078 } else {
1079 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1080 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001081}
1082
1083
1084void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001085 bool setcc, Condition cond) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001086 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
1087 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Dave Allison45fdb932014-06-25 12:37:10 -07001088 if (setcc) {
1089 movs(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1090 } else {
1091 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1092 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001093}
1094
1095
1096void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001097 bool setcc, Condition cond) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001098 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
Dave Allison45fdb932014-06-25 12:37:10 -07001099 if (setcc) {
1100 movs(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1101 } else {
1102 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1103 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001104}
1105
Dave Allison45fdb932014-06-25 12:37:10 -07001106void Arm32Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
1107 if (setcc) {
1108 movs(rd, ShifterOperand(rm, ROR, 0), cond);
1109 } else {
1110 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1111 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001112}
1113
1114
Dave Allison45fdb932014-06-25 12:37:10 -07001115void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
1116 bool setcc, Condition cond) {
1117 if (setcc) {
1118 movs(rd, ShifterOperand(rm, LSL, rn), cond);
1119 } else {
1120 mov(rd, ShifterOperand(rm, LSL, rn), cond);
1121 }
1122}
1123
1124
1125void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
1126 bool setcc, Condition cond) {
1127 if (setcc) {
1128 movs(rd, ShifterOperand(rm, LSR, rn), cond);
1129 } else {
1130 mov(rd, ShifterOperand(rm, LSR, rn), cond);
1131 }
1132}
1133
1134
1135void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
1136 bool setcc, Condition cond) {
1137 if (setcc) {
1138 movs(rd, ShifterOperand(rm, ASR, rn), cond);
1139 } else {
1140 mov(rd, ShifterOperand(rm, ASR, rn), cond);
1141 }
1142}
1143
1144
1145void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
1146 bool setcc, Condition cond) {
1147 if (setcc) {
1148 movs(rd, ShifterOperand(rm, ROR, rn), cond);
1149 } else {
1150 mov(rd, ShifterOperand(rm, ROR, rn), cond);
1151 }
1152}
1153
Dave Allison65fcc2c2014-04-28 13:45:27 -07001154void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1155 CHECK_NE(cond, kNoCondition);
1156 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1157 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1158 (static_cast<int32_t>(PC)*B12) |
1159 B11 | B9 | B4;
1160 Emit(encoding);
1161}
1162
1163
1164void Arm32Assembler::svc(uint32_t imm24) {
1165 CHECK(IsUint(24, imm24)) << imm24;
1166 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1167 Emit(encoding);
1168}
1169
1170
1171void Arm32Assembler::bkpt(uint16_t imm16) {
1172 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1173 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1174 Emit(encoding);
1175}
1176
1177
1178void Arm32Assembler::blx(Register rm, Condition cond) {
1179 CHECK_NE(rm, kNoRegister);
1180 CHECK_NE(cond, kNoCondition);
1181 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1182 B24 | B21 | (0xfff << 8) | B5 | B4 |
1183 (static_cast<int32_t>(rm) << kRmShift);
1184 Emit(encoding);
1185}
1186
1187
1188void Arm32Assembler::bx(Register rm, Condition cond) {
1189 CHECK_NE(rm, kNoRegister);
1190 CHECK_NE(cond, kNoCondition);
1191 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1192 B24 | B21 | (0xfff << 8) | B4 |
1193 (static_cast<int32_t>(rm) << kRmShift);
1194 Emit(encoding);
1195}
1196
1197
1198void Arm32Assembler::Push(Register rd, Condition cond) {
1199 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1200}
1201
1202
1203void Arm32Assembler::Pop(Register rd, Condition cond) {
1204 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1205}
1206
1207
1208void Arm32Assembler::PushList(RegList regs, Condition cond) {
1209 stm(DB_W, SP, regs, cond);
1210}
1211
1212
1213void Arm32Assembler::PopList(RegList regs, Condition cond) {
1214 ldm(IA_W, SP, regs, cond);
1215}
1216
1217
1218void Arm32Assembler::Mov(Register rd, Register rm, Condition cond) {
1219 if (rd != rm) {
1220 mov(rd, ShifterOperand(rm), cond);
1221 }
1222}
1223
1224
1225void Arm32Assembler::Bind(Label* label) {
1226 CHECK(!label->IsBound());
1227 int bound_pc = buffer_.Size();
1228 while (label->IsLinked()) {
1229 int32_t position = label->Position();
1230 int32_t next = buffer_.Load<int32_t>(position);
1231 int32_t encoded = Arm32Assembler::EncodeBranchOffset(bound_pc - position, next);
1232 buffer_.Store<int32_t>(position, encoded);
1233 label->position_ = Arm32Assembler::DecodeBranchOffset(next);
1234 }
1235 label->BindTo(bound_pc);
1236}
1237
1238
1239int32_t Arm32Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1240 // The offset is off by 8 due to the way the ARM CPUs read PC.
1241 offset -= 8;
1242 CHECK_ALIGNED(offset, 4);
1243 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
1244
1245 // Properly preserve only the bits supported in the instruction.
1246 offset >>= 2;
1247 offset &= kBranchOffsetMask;
1248 return (inst & ~kBranchOffsetMask) | offset;
1249}
1250
1251
1252int Arm32Assembler::DecodeBranchOffset(int32_t inst) {
1253 // Sign-extend, left-shift by 2, then add 8.
1254 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1255}
1256
1257
1258void Arm32Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
1259 AddConstant(rd, rd, value, cond);
1260}
1261
1262
1263void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
1264 Condition cond) {
1265 if (value == 0) {
1266 if (rd != rn) {
1267 mov(rd, ShifterOperand(rn), cond);
1268 }
1269 return;
1270 }
1271 // We prefer to select the shorter code sequence rather than selecting add for
1272 // positive values and sub for negatives ones, which would slightly improve
1273 // the readability of generated code for some constants.
1274 ShifterOperand shifter_op;
1275 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1276 add(rd, rn, shifter_op, cond);
1277 } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
1278 sub(rd, rn, shifter_op, cond);
1279 } else {
1280 CHECK(rn != IP);
1281 if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1282 mvn(IP, shifter_op, cond);
1283 add(rd, rn, ShifterOperand(IP), cond);
1284 } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
1285 mvn(IP, shifter_op, cond);
1286 sub(rd, rn, ShifterOperand(IP), cond);
1287 } else {
1288 movw(IP, Low16Bits(value), cond);
1289 uint16_t value_high = High16Bits(value);
1290 if (value_high != 0) {
1291 movt(IP, value_high, cond);
1292 }
1293 add(rd, rn, ShifterOperand(IP), cond);
1294 }
1295 }
1296}
1297
1298
1299void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1300 Condition cond) {
1301 ShifterOperand shifter_op;
1302 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1303 adds(rd, rn, shifter_op, cond);
1304 } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
1305 subs(rd, rn, shifter_op, cond);
1306 } else {
1307 CHECK(rn != IP);
1308 if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1309 mvn(IP, shifter_op, cond);
1310 adds(rd, rn, ShifterOperand(IP), cond);
1311 } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
1312 mvn(IP, shifter_op, cond);
1313 subs(rd, rn, ShifterOperand(IP), cond);
1314 } else {
1315 movw(IP, Low16Bits(value), cond);
1316 uint16_t value_high = High16Bits(value);
1317 if (value_high != 0) {
1318 movt(IP, value_high, cond);
1319 }
1320 adds(rd, rn, ShifterOperand(IP), cond);
1321 }
1322 }
1323}
1324
Dave Allison65fcc2c2014-04-28 13:45:27 -07001325void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1326 ShifterOperand shifter_op;
1327 if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
1328 mov(rd, shifter_op, cond);
1329 } else if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
1330 mvn(rd, shifter_op, cond);
1331 } else {
1332 movw(rd, Low16Bits(value), cond);
1333 uint16_t value_high = High16Bits(value);
1334 if (value_high != 0) {
1335 movt(rd, value_high, cond);
1336 }
1337 }
1338}
1339
1340
1341// Implementation note: this method must emit at most one instruction when
1342// Address::CanHoldLoadOffsetArm.
1343void Arm32Assembler::LoadFromOffset(LoadOperandType type,
1344 Register reg,
1345 Register base,
1346 int32_t offset,
1347 Condition cond) {
1348 if (!Address::CanHoldLoadOffsetArm(type, offset)) {
1349 CHECK(base != IP);
1350 LoadImmediate(IP, offset, cond);
1351 add(IP, IP, ShifterOperand(base), cond);
1352 base = IP;
1353 offset = 0;
1354 }
1355 CHECK(Address::CanHoldLoadOffsetArm(type, offset));
1356 switch (type) {
1357 case kLoadSignedByte:
1358 ldrsb(reg, Address(base, offset), cond);
1359 break;
1360 case kLoadUnsignedByte:
1361 ldrb(reg, Address(base, offset), cond);
1362 break;
1363 case kLoadSignedHalfword:
1364 ldrsh(reg, Address(base, offset), cond);
1365 break;
1366 case kLoadUnsignedHalfword:
1367 ldrh(reg, Address(base, offset), cond);
1368 break;
1369 case kLoadWord:
1370 ldr(reg, Address(base, offset), cond);
1371 break;
1372 case kLoadWordPair:
1373 ldrd(reg, Address(base, offset), cond);
1374 break;
1375 default:
1376 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001377 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001378 }
1379}
1380
1381
1382// Implementation note: this method must emit at most one instruction when
1383// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1384void Arm32Assembler::LoadSFromOffset(SRegister reg,
1385 Register base,
1386 int32_t offset,
1387 Condition cond) {
1388 if (!Address::CanHoldLoadOffsetArm(kLoadSWord, offset)) {
1389 CHECK_NE(base, IP);
1390 LoadImmediate(IP, offset, cond);
1391 add(IP, IP, ShifterOperand(base), cond);
1392 base = IP;
1393 offset = 0;
1394 }
1395 CHECK(Address::CanHoldLoadOffsetArm(kLoadSWord, offset));
1396 vldrs(reg, Address(base, offset), cond);
1397}
1398
1399
1400// Implementation note: this method must emit at most one instruction when
1401// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1402void Arm32Assembler::LoadDFromOffset(DRegister reg,
1403 Register base,
1404 int32_t offset,
1405 Condition cond) {
1406 if (!Address::CanHoldLoadOffsetArm(kLoadDWord, offset)) {
1407 CHECK_NE(base, IP);
1408 LoadImmediate(IP, offset, cond);
1409 add(IP, IP, ShifterOperand(base), cond);
1410 base = IP;
1411 offset = 0;
1412 }
1413 CHECK(Address::CanHoldLoadOffsetArm(kLoadDWord, offset));
1414 vldrd(reg, Address(base, offset), cond);
1415}
1416
1417
1418// Implementation note: this method must emit at most one instruction when
1419// Address::CanHoldStoreOffsetArm.
1420void Arm32Assembler::StoreToOffset(StoreOperandType type,
1421 Register reg,
1422 Register base,
1423 int32_t offset,
1424 Condition cond) {
1425 if (!Address::CanHoldStoreOffsetArm(type, offset)) {
1426 CHECK(reg != IP);
1427 CHECK(base != IP);
1428 LoadImmediate(IP, offset, cond);
1429 add(IP, IP, ShifterOperand(base), cond);
1430 base = IP;
1431 offset = 0;
1432 }
1433 CHECK(Address::CanHoldStoreOffsetArm(type, offset));
1434 switch (type) {
1435 case kStoreByte:
1436 strb(reg, Address(base, offset), cond);
1437 break;
1438 case kStoreHalfword:
1439 strh(reg, Address(base, offset), cond);
1440 break;
1441 case kStoreWord:
1442 str(reg, Address(base, offset), cond);
1443 break;
1444 case kStoreWordPair:
1445 strd(reg, Address(base, offset), cond);
1446 break;
1447 default:
1448 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001449 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001450 }
1451}
1452
1453
1454// Implementation note: this method must emit at most one instruction when
1455// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreToOffset.
1456void Arm32Assembler::StoreSToOffset(SRegister reg,
1457 Register base,
1458 int32_t offset,
1459 Condition cond) {
1460 if (!Address::CanHoldStoreOffsetArm(kStoreSWord, offset)) {
1461 CHECK_NE(base, IP);
1462 LoadImmediate(IP, offset, cond);
1463 add(IP, IP, ShifterOperand(base), cond);
1464 base = IP;
1465 offset = 0;
1466 }
1467 CHECK(Address::CanHoldStoreOffsetArm(kStoreSWord, offset));
1468 vstrs(reg, Address(base, offset), cond);
1469}
1470
1471
1472// Implementation note: this method must emit at most one instruction when
1473// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreSToOffset.
1474void Arm32Assembler::StoreDToOffset(DRegister reg,
1475 Register base,
1476 int32_t offset,
1477 Condition cond) {
1478 if (!Address::CanHoldStoreOffsetArm(kStoreDWord, offset)) {
1479 CHECK_NE(base, IP);
1480 LoadImmediate(IP, offset, cond);
1481 add(IP, IP, ShifterOperand(base), cond);
1482 base = IP;
1483 offset = 0;
1484 }
1485 CHECK(Address::CanHoldStoreOffsetArm(kStoreDWord, offset));
1486 vstrd(reg, Address(base, offset), cond);
1487}
1488
1489
1490void Arm32Assembler::MemoryBarrier(ManagedRegister mscratch) {
1491 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001492 dmb(SY);
1493}
1494
1495
1496void Arm32Assembler::dmb(DmbOptions flavor) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001497#if ANDROID_SMP != 0
1498 int32_t encoding = 0xf57ff05f; // dmb
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001499 Emit(encoding | flavor);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001500#endif
1501}
1502
1503
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001504void Arm32Assembler::cbz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001505 LOG(FATAL) << "cbz is not supported on ARM32";
1506}
1507
1508
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001509void Arm32Assembler::cbnz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001510 LOG(FATAL) << "cbnz is not supported on ARM32";
1511}
1512
1513
1514void Arm32Assembler::CompareAndBranchIfZero(Register r, Label* label) {
1515 cmp(r, ShifterOperand(0));
1516 b(label, EQ);
1517}
1518
1519
1520void Arm32Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
1521 cmp(r, ShifterOperand(0));
1522 b(label, NE);
1523}
1524
1525
1526} // namespace arm
1527} // namespace art