blob: cdf62bf8853804421b391bde96a28260c6536132 [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
Vladimir Marko80afd022015-05-19 18:08:00 +010019#include "base/bit_utils.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070020#include "base/logging.h"
21#include "entrypoints/quick/quick_entrypoints.h"
22#include "offsets.h"
23#include "thread.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070024
25namespace art {
26namespace arm {
27
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +000028bool Arm32Assembler::ShifterOperandCanHoldArm32(uint32_t immediate, ShifterOperand* shifter_op) {
29 // Avoid the more expensive test for frequent small immediate values.
30 if (immediate < (1 << kImmed8Bits)) {
31 shifter_op->type_ = ShifterOperand::kImmediate;
32 shifter_op->is_rotate_ = true;
33 shifter_op->rotate_ = 0;
34 shifter_op->immed_ = immediate;
35 return true;
36 }
37 // Note that immediate must be unsigned for the test to work correctly.
38 for (int rot = 0; rot < 16; rot++) {
39 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
40 if (imm8 < (1 << kImmed8Bits)) {
41 shifter_op->type_ = ShifterOperand::kImmediate;
42 shifter_op->is_rotate_ = true;
43 shifter_op->rotate_ = rot;
44 shifter_op->immed_ = imm8;
45 return true;
46 }
47 }
48 return false;
49}
50
51bool Arm32Assembler::ShifterOperandCanHold(Register rd ATTRIBUTE_UNUSED,
52 Register rn ATTRIBUTE_UNUSED,
53 Opcode opcode ATTRIBUTE_UNUSED,
54 uint32_t immediate,
55 ShifterOperand* shifter_op) {
56 return ShifterOperandCanHoldArm32(immediate, shifter_op);
57}
58
Dave Allison65fcc2c2014-04-28 13:45:27 -070059void Arm32Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
60 Condition cond) {
61 EmitType01(cond, so.type(), AND, 0, rn, rd, so);
62}
63
64
65void Arm32Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
66 Condition cond) {
67 EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
68}
69
70
71void Arm32Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
72 Condition cond) {
73 EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
74}
75
76void Arm32Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
77 Condition cond) {
78 EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
79}
80
81void Arm32Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
82 Condition cond) {
83 EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
84}
85
86
87void Arm32Assembler::add(Register rd, Register rn, const ShifterOperand& so,
88 Condition cond) {
89 EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
90}
91
92
93void Arm32Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
94 Condition cond) {
95 EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
96}
97
98
99void Arm32Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
100 Condition cond) {
101 EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
102}
103
104
105void Arm32Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
106 Condition cond) {
107 EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
108}
109
110
111void Arm32Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
112 Condition cond) {
113 EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
114}
115
116
117void Arm32Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
118 Condition cond) {
119 EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
120}
121
122
123void Arm32Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
124 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
125 EmitType01(cond, so.type(), TST, 1, rn, R0, so);
126}
127
128
129void Arm32Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
130 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
131 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
132}
133
134
135void Arm32Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
136 EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
137}
138
139
140void Arm32Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
141 EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
142}
143
144
145void Arm32Assembler::orr(Register rd, Register rn,
146 const ShifterOperand& so, Condition cond) {
147 EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
148}
149
150
151void Arm32Assembler::orrs(Register rd, Register rn,
152 const ShifterOperand& so, Condition cond) {
153 EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
154}
155
156
157void Arm32Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
158 EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
159}
160
161
162void Arm32Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
163 EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
164}
165
166
167void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
168 Condition cond) {
169 EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
170}
171
172
173void Arm32Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
174 EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
175}
176
177
178void Arm32Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
179 EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
180}
181
182
183void Arm32Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
184 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
185 EmitMulOp(cond, 0, R0, rd, rn, rm);
186}
187
188
189void Arm32Assembler::mla(Register rd, Register rn, Register rm, Register ra,
190 Condition cond) {
191 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
192 EmitMulOp(cond, B21, ra, rd, rn, rm);
193}
194
195
196void Arm32Assembler::mls(Register rd, Register rn, Register rm, Register ra,
197 Condition cond) {
198 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
199 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
200}
201
202
Zheng Xuc6667102015-05-15 16:08:45 +0800203void Arm32Assembler::smull(Register rd_lo, Register rd_hi, Register rn,
204 Register rm, Condition cond) {
205 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
206 EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
207}
208
209
Dave Allison65fcc2c2014-04-28 13:45:27 -0700210void Arm32Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
211 Register rm, Condition cond) {
212 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
213 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
214}
215
216
217void Arm32Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
218 CHECK_NE(rd, kNoRegister);
219 CHECK_NE(rn, kNoRegister);
220 CHECK_NE(rm, kNoRegister);
221 CHECK_NE(cond, kNoCondition);
222 int32_t encoding = B26 | B25 | B24 | B20 |
223 B15 | B14 | B13 | B12 |
224 (static_cast<int32_t>(cond) << kConditionShift) |
225 (static_cast<int32_t>(rn) << 0) |
226 (static_cast<int32_t>(rd) << 16) |
227 (static_cast<int32_t>(rm) << 8) |
228 B4;
229 Emit(encoding);
230}
231
232
233void Arm32Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
234 CHECK_NE(rd, kNoRegister);
235 CHECK_NE(rn, kNoRegister);
236 CHECK_NE(rm, kNoRegister);
237 CHECK_NE(cond, kNoCondition);
238 int32_t encoding = B26 | B25 | B24 | B21 | B20 |
239 B15 | B14 | B13 | B12 |
240 (static_cast<int32_t>(cond) << kConditionShift) |
241 (static_cast<int32_t>(rn) << 0) |
242 (static_cast<int32_t>(rd) << 16) |
243 (static_cast<int32_t>(rm) << 8) |
244 B4;
245 Emit(encoding);
246}
247
248
Roland Levillain51d3fc42014-11-13 14:11:42 +0000249void Arm32Assembler::sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
250 CHECK_NE(rd, kNoRegister);
251 CHECK_NE(rn, kNoRegister);
252 CHECK_NE(cond, kNoCondition);
253 CHECK_LE(lsb, 31U);
254 CHECK(1U <= width && width <= 32U) << width;
255 uint32_t widthminus1 = width - 1;
256
257 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
258 B26 | B25 | B24 | B23 | B21 |
259 (widthminus1 << 16) |
260 (static_cast<uint32_t>(rd) << 12) |
261 (lsb << 7) |
262 B6 | B4 |
263 static_cast<uint32_t>(rn);
264 Emit(encoding);
265}
266
267
Roland Levillain981e4542014-11-14 11:47:14 +0000268void Arm32Assembler::ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
269 CHECK_NE(rd, kNoRegister);
270 CHECK_NE(rn, kNoRegister);
271 CHECK_NE(cond, kNoCondition);
272 CHECK_LE(lsb, 31U);
273 CHECK(1U <= width && width <= 32U) << width;
274 uint32_t widthminus1 = width - 1;
275
276 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
277 B26 | B25 | B24 | B23 | B22 | B21 |
278 (widthminus1 << 16) |
279 (static_cast<uint32_t>(rd) << 12) |
280 (lsb << 7) |
281 B6 | B4 |
282 static_cast<uint32_t>(rn);
283 Emit(encoding);
284}
285
286
Dave Allison65fcc2c2014-04-28 13:45:27 -0700287void Arm32Assembler::ldr(Register rd, const Address& ad, Condition cond) {
288 EmitMemOp(cond, true, false, rd, ad);
289}
290
291
292void Arm32Assembler::str(Register rd, const Address& ad, Condition cond) {
293 EmitMemOp(cond, false, false, rd, ad);
294}
295
296
297void Arm32Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
298 EmitMemOp(cond, true, true, rd, ad);
299}
300
301
302void Arm32Assembler::strb(Register rd, const Address& ad, Condition cond) {
303 EmitMemOp(cond, false, true, rd, ad);
304}
305
306
307void Arm32Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
308 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
309}
310
311
312void Arm32Assembler::strh(Register rd, const Address& ad, Condition cond) {
313 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
314}
315
316
317void Arm32Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
318 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
319}
320
321
322void Arm32Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
323 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
324}
325
326
327void Arm32Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
328 CHECK_EQ(rd % 2, 0);
329 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
330}
331
332
333void Arm32Assembler::strd(Register rd, const Address& ad, Condition cond) {
334 CHECK_EQ(rd % 2, 0);
335 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
336}
337
338
339void Arm32Assembler::ldm(BlockAddressMode am,
340 Register base,
341 RegList regs,
342 Condition cond) {
343 EmitMultiMemOp(cond, am, true, base, regs);
344}
345
346
347void Arm32Assembler::stm(BlockAddressMode am,
348 Register base,
349 RegList regs,
350 Condition cond) {
351 EmitMultiMemOp(cond, am, false, base, regs);
352}
353
354
355void Arm32Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
356 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
357}
358
359
360void Arm32Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
361 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
362}
363
364
365bool Arm32Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
366 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
367 if (((imm32 & ((1 << 19) - 1)) == 0) &&
368 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
369 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
370 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
371 ((imm32 >> 19) & ((1 << 6) -1));
372 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
373 sd, S0, S0);
374 return true;
375 }
376 return false;
377}
378
379
380bool Arm32Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
381 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
382 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
383 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
384 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
385 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
386 ((imm64 >> 48) & ((1 << 6) -1));
387 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
388 dd, D0, D0);
389 return true;
390 }
391 return false;
392}
393
394
395void Arm32Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
396 Condition cond) {
397 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
398}
399
400
401void Arm32Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
402 Condition cond) {
403 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
404}
405
406
407void Arm32Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
408 Condition cond) {
409 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
410}
411
412
413void Arm32Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
414 Condition cond) {
415 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
416}
417
418
419void Arm32Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
420 Condition cond) {
421 EmitVFPsss(cond, B21, sd, sn, sm);
422}
423
424
425void Arm32Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
426 Condition cond) {
427 EmitVFPddd(cond, B21, dd, dn, dm);
428}
429
430
431void Arm32Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
432 Condition cond) {
433 EmitVFPsss(cond, 0, sd, sn, sm);
434}
435
436
437void Arm32Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
438 Condition cond) {
439 EmitVFPddd(cond, 0, dd, dn, dm);
440}
441
442
443void Arm32Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
444 Condition cond) {
445 EmitVFPsss(cond, B6, sd, sn, sm);
446}
447
448
449void Arm32Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
450 Condition cond) {
451 EmitVFPddd(cond, B6, dd, dn, dm);
452}
453
454
455void Arm32Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
456 Condition cond) {
457 EmitVFPsss(cond, B23, sd, sn, sm);
458}
459
460
461void Arm32Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
462 Condition cond) {
463 EmitVFPddd(cond, B23, dd, dn, dm);
464}
465
466
467void Arm32Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
468 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
469}
470
471
472void Arm32Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
473 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
474}
475
476
477void Arm32Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
478 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
479}
480
481
482void Arm32Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
483 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
484}
485
486
487void Arm32Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
488 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
489}
490
491void Arm32Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
492 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
493}
494
495
496void Arm32Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
497 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
498}
499
500
501void Arm32Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
502 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
503}
504
505
506void Arm32Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
507 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
508}
509
510
511void Arm32Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
512 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
513}
514
515
516void Arm32Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
517 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
518}
519
520
521void Arm32Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
522 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
523}
524
525
526void Arm32Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
527 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
528}
529
530
531void Arm32Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
532 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
533}
534
535
536void Arm32Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
537 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
538}
539
540
541void Arm32Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
542 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
543}
544
545
546void Arm32Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
547 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
548}
549
550
551void Arm32Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
552 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
553}
554
555
556void Arm32Assembler::vcmpsz(SRegister sd, Condition cond) {
557 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
558}
559
560
561void Arm32Assembler::vcmpdz(DRegister dd, Condition cond) {
562 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
563}
564
565void Arm32Assembler::b(Label* label, Condition cond) {
566 EmitBranch(cond, label, false);
567}
568
569
570void Arm32Assembler::bl(Label* label, Condition cond) {
571 EmitBranch(cond, label, true);
572}
573
574
575void Arm32Assembler::MarkExceptionHandler(Label* label) {
576 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
577 Label l;
578 b(&l);
579 EmitBranch(AL, label, false);
580 Bind(&l);
581}
582
583
584void Arm32Assembler::Emit(int32_t value) {
585 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
586 buffer_.Emit<int32_t>(value);
587}
588
589
590void Arm32Assembler::EmitType01(Condition cond,
591 int type,
592 Opcode opcode,
593 int set_cc,
594 Register rn,
595 Register rd,
596 const ShifterOperand& so) {
597 CHECK_NE(rd, kNoRegister);
598 CHECK_NE(cond, kNoCondition);
599 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
600 type << kTypeShift |
601 static_cast<int32_t>(opcode) << kOpcodeShift |
602 set_cc << kSShift |
603 static_cast<int32_t>(rn) << kRnShift |
604 static_cast<int32_t>(rd) << kRdShift |
605 so.encodingArm();
606 Emit(encoding);
607}
608
609
610void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
611 CHECK_NE(cond, kNoCondition);
612 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
613 5 << kTypeShift |
614 (link ? 1 : 0) << kLinkShift;
615 Emit(Arm32Assembler::EncodeBranchOffset(offset, encoding));
616}
617
618
619void Arm32Assembler::EmitMemOp(Condition cond,
Dave Allison45fdb932014-06-25 12:37:10 -0700620 bool load,
621 bool byte,
622 Register rd,
623 const Address& ad) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700624 CHECK_NE(rd, kNoRegister);
625 CHECK_NE(cond, kNoCondition);
626 const Address& addr = static_cast<const Address&>(ad);
627
Dave Allison45fdb932014-06-25 12:37:10 -0700628 int32_t encoding = 0;
629 if (!ad.IsImmediate() && ad.GetRegisterOffset() == PC) {
630 // PC relative LDR(literal)
631 int32_t offset = ad.GetOffset();
632 int32_t u = B23;
633 if (offset < 0) {
634 offset = -offset;
635 u = 0;
636 }
637 CHECK_LT(offset, (1 << 12));
638 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
639 B26 | B24 | u | B20 |
640 (load ? L : 0) |
641 (byte ? B : 0) |
642 (static_cast<int32_t>(rd) << kRdShift) |
643 0xf << 16 |
644 (offset & 0xfff);
645
646 } else {
647 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
648 B26 |
649 (load ? L : 0) |
650 (byte ? B : 0) |
651 (static_cast<int32_t>(rd) << kRdShift) |
652 addr.encodingArm();
653 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700654 Emit(encoding);
655}
656
657
658void Arm32Assembler::EmitMemOpAddressMode3(Condition cond,
659 int32_t mode,
660 Register rd,
661 const Address& ad) {
662 CHECK_NE(rd, kNoRegister);
663 CHECK_NE(cond, kNoCondition);
664 const Address& addr = static_cast<const Address&>(ad);
665 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
666 B22 |
667 mode |
668 (static_cast<int32_t>(rd) << kRdShift) |
669 addr.encoding3();
670 Emit(encoding);
671}
672
673
674void Arm32Assembler::EmitMultiMemOp(Condition cond,
675 BlockAddressMode am,
676 bool load,
677 Register base,
678 RegList regs) {
679 CHECK_NE(base, kNoRegister);
680 CHECK_NE(cond, kNoCondition);
681 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
682 B27 |
683 am |
684 (load ? L : 0) |
685 (static_cast<int32_t>(base) << kRnShift) |
686 regs;
687 Emit(encoding);
688}
689
690
691void Arm32Assembler::EmitShiftImmediate(Condition cond,
692 Shift opcode,
693 Register rd,
694 Register rm,
695 const ShifterOperand& so) {
696 CHECK_NE(cond, kNoCondition);
697 CHECK(so.IsImmediate());
698 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
699 static_cast<int32_t>(MOV) << kOpcodeShift |
700 static_cast<int32_t>(rd) << kRdShift |
701 so.encodingArm() << kShiftImmShift |
702 static_cast<int32_t>(opcode) << kShiftShift |
703 static_cast<int32_t>(rm);
704 Emit(encoding);
705}
706
707
708void Arm32Assembler::EmitShiftRegister(Condition cond,
709 Shift opcode,
710 Register rd,
711 Register rm,
712 const ShifterOperand& so) {
713 CHECK_NE(cond, kNoCondition);
714 CHECK(so.IsRegister());
715 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
716 static_cast<int32_t>(MOV) << kOpcodeShift |
717 static_cast<int32_t>(rd) << kRdShift |
718 so.encodingArm() << kShiftRegisterShift |
719 static_cast<int32_t>(opcode) << kShiftShift |
720 B4 |
721 static_cast<int32_t>(rm);
722 Emit(encoding);
723}
724
725
726void Arm32Assembler::EmitBranch(Condition cond, Label* label, bool link) {
727 if (label->IsBound()) {
728 EmitType5(cond, label->Position() - buffer_.Size(), link);
729 } else {
730 int position = buffer_.Size();
731 // Use the offset field of the branch instruction for linking the sites.
732 EmitType5(cond, label->position_, link);
733 label->LinkTo(position);
734 }
735}
736
737
738void Arm32Assembler::clz(Register rd, Register rm, Condition cond) {
739 CHECK_NE(rd, kNoRegister);
740 CHECK_NE(rm, kNoRegister);
741 CHECK_NE(cond, kNoCondition);
742 CHECK_NE(rd, PC);
743 CHECK_NE(rm, PC);
744 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
745 B24 | B22 | B21 | (0xf << 16) |
746 (static_cast<int32_t>(rd) << kRdShift) |
747 (0xf << 8) | B4 | static_cast<int32_t>(rm);
748 Emit(encoding);
749}
750
751
752void Arm32Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
753 CHECK_NE(cond, kNoCondition);
754 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
755 B25 | B24 | ((imm16 >> 12) << 16) |
756 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
757 Emit(encoding);
758}
759
760
761void Arm32Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
762 CHECK_NE(cond, kNoCondition);
763 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
764 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
765 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
766 Emit(encoding);
767}
768
769
770void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
771 Register rd, Register rn,
772 Register rm, Register rs) {
773 CHECK_NE(rd, kNoRegister);
774 CHECK_NE(rn, kNoRegister);
775 CHECK_NE(rm, kNoRegister);
776 CHECK_NE(rs, kNoRegister);
777 CHECK_NE(cond, kNoCondition);
778 int32_t encoding = opcode |
779 (static_cast<int32_t>(cond) << kConditionShift) |
780 (static_cast<int32_t>(rn) << kRnShift) |
781 (static_cast<int32_t>(rd) << kRdShift) |
782 (static_cast<int32_t>(rs) << kRsShift) |
783 B7 | B4 |
784 (static_cast<int32_t>(rm) << kRmShift);
785 Emit(encoding);
786}
787
Calin Juravle52c48962014-12-16 17:02:57 +0000788
Dave Allison65fcc2c2014-04-28 13:45:27 -0700789void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) {
790 CHECK_NE(rn, kNoRegister);
791 CHECK_NE(rt, kNoRegister);
792 CHECK_NE(cond, kNoCondition);
793 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
794 B24 |
795 B23 |
796 L |
797 (static_cast<int32_t>(rn) << kLdExRnShift) |
798 (static_cast<int32_t>(rt) << kLdExRtShift) |
799 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
800 Emit(encoding);
801}
802
803
Calin Juravle52c48962014-12-16 17:02:57 +0000804void Arm32Assembler::ldrexd(Register rt, Register rt2, Register rn, Condition cond) {
805 CHECK_NE(rn, kNoRegister);
806 CHECK_NE(rt, kNoRegister);
807 CHECK_NE(rt2, kNoRegister);
808 CHECK_NE(rt, R14);
809 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
810 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
811 CHECK_NE(cond, kNoCondition);
812
813 int32_t encoding =
814 (static_cast<uint32_t>(cond) << kConditionShift) |
815 B24 | B23 | B21 | B20 |
816 static_cast<uint32_t>(rn) << 16 |
817 static_cast<uint32_t>(rt) << 12 |
818 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
819 Emit(encoding);
820}
821
822
Dave Allison65fcc2c2014-04-28 13:45:27 -0700823void Arm32Assembler::strex(Register rd,
824 Register rt,
825 Register rn,
826 Condition cond) {
827 CHECK_NE(rn, kNoRegister);
828 CHECK_NE(rd, kNoRegister);
829 CHECK_NE(rt, kNoRegister);
830 CHECK_NE(cond, kNoCondition);
831 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
832 B24 |
833 B23 |
834 (static_cast<int32_t>(rn) << kStrExRnShift) |
835 (static_cast<int32_t>(rd) << kStrExRdShift) |
836 B11 | B10 | B9 | B8 | B7 | B4 |
837 (static_cast<int32_t>(rt) << kStrExRtShift);
838 Emit(encoding);
839}
840
Calin Juravle52c48962014-12-16 17:02:57 +0000841void Arm32Assembler::strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond) {
842 CHECK_NE(rd, kNoRegister);
843 CHECK_NE(rn, kNoRegister);
844 CHECK_NE(rt, kNoRegister);
845 CHECK_NE(rt2, kNoRegister);
846 CHECK_NE(rt, R14);
847 CHECK_NE(rd, rt);
848 CHECK_NE(rd, rt2);
849 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
850 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
851 CHECK_NE(cond, kNoCondition);
852
853 int32_t encoding =
854 (static_cast<uint32_t>(cond) << kConditionShift) |
855 B24 | B23 | B21 |
856 static_cast<uint32_t>(rn) << 16 |
857 static_cast<uint32_t>(rd) << 12 |
858 B11 | B10 | B9 | B8 | B7 | B4 |
859 static_cast<uint32_t>(rt);
860 Emit(encoding);
861}
862
Dave Allison65fcc2c2014-04-28 13:45:27 -0700863
864void Arm32Assembler::clrex(Condition cond) {
865 CHECK_EQ(cond, AL); // This cannot be conditional on ARM.
866 int32_t encoding = (kSpecialCondition << kConditionShift) |
867 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
868 Emit(encoding);
869}
870
871
872void Arm32Assembler::nop(Condition cond) {
873 CHECK_NE(cond, kNoCondition);
874 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
875 B25 | B24 | B21 | (0xf << 12);
876 Emit(encoding);
877}
878
879
880void Arm32Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
881 CHECK_NE(sn, kNoSRegister);
882 CHECK_NE(rt, kNoRegister);
883 CHECK_NE(rt, SP);
884 CHECK_NE(rt, PC);
885 CHECK_NE(cond, kNoCondition);
886 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
887 B27 | B26 | B25 |
888 ((static_cast<int32_t>(sn) >> 1)*B16) |
889 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
890 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
891 Emit(encoding);
892}
893
894
895void Arm32Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
896 CHECK_NE(sn, kNoSRegister);
897 CHECK_NE(rt, kNoRegister);
898 CHECK_NE(rt, SP);
899 CHECK_NE(rt, PC);
900 CHECK_NE(cond, kNoCondition);
901 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
902 B27 | B26 | B25 | B20 |
903 ((static_cast<int32_t>(sn) >> 1)*B16) |
904 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
905 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
906 Emit(encoding);
907}
908
909
910void Arm32Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
911 Condition cond) {
912 CHECK_NE(sm, kNoSRegister);
913 CHECK_NE(sm, S31);
914 CHECK_NE(rt, kNoRegister);
915 CHECK_NE(rt, SP);
916 CHECK_NE(rt, PC);
917 CHECK_NE(rt2, kNoRegister);
918 CHECK_NE(rt2, SP);
919 CHECK_NE(rt2, PC);
920 CHECK_NE(cond, kNoCondition);
921 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
922 B27 | B26 | B22 |
923 (static_cast<int32_t>(rt2)*B16) |
924 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
925 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
926 (static_cast<int32_t>(sm) >> 1);
927 Emit(encoding);
928}
929
930
931void Arm32Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
932 Condition cond) {
933 CHECK_NE(sm, kNoSRegister);
934 CHECK_NE(sm, S31);
935 CHECK_NE(rt, kNoRegister);
936 CHECK_NE(rt, SP);
937 CHECK_NE(rt, PC);
938 CHECK_NE(rt2, kNoRegister);
939 CHECK_NE(rt2, SP);
940 CHECK_NE(rt2, PC);
941 CHECK_NE(rt, rt2);
942 CHECK_NE(cond, kNoCondition);
943 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
944 B27 | B26 | B22 | B20 |
945 (static_cast<int32_t>(rt2)*B16) |
946 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
947 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
948 (static_cast<int32_t>(sm) >> 1);
949 Emit(encoding);
950}
951
952
953void Arm32Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
954 Condition cond) {
955 CHECK_NE(dm, kNoDRegister);
956 CHECK_NE(rt, kNoRegister);
957 CHECK_NE(rt, SP);
958 CHECK_NE(rt, PC);
959 CHECK_NE(rt2, kNoRegister);
960 CHECK_NE(rt2, SP);
961 CHECK_NE(rt2, PC);
962 CHECK_NE(cond, kNoCondition);
963 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
964 B27 | B26 | B22 |
965 (static_cast<int32_t>(rt2)*B16) |
966 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
967 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
968 (static_cast<int32_t>(dm) & 0xf);
969 Emit(encoding);
970}
971
972
973void Arm32Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
974 Condition cond) {
975 CHECK_NE(dm, kNoDRegister);
976 CHECK_NE(rt, kNoRegister);
977 CHECK_NE(rt, SP);
978 CHECK_NE(rt, PC);
979 CHECK_NE(rt2, kNoRegister);
980 CHECK_NE(rt2, SP);
981 CHECK_NE(rt2, PC);
982 CHECK_NE(rt, rt2);
983 CHECK_NE(cond, kNoCondition);
984 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
985 B27 | B26 | B22 | B20 |
986 (static_cast<int32_t>(rt2)*B16) |
987 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
988 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
989 (static_cast<int32_t>(dm) & 0xf);
990 Emit(encoding);
991}
992
993
994void Arm32Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
995 const Address& addr = static_cast<const Address&>(ad);
996 CHECK_NE(sd, kNoSRegister);
997 CHECK_NE(cond, kNoCondition);
998 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
999 B27 | B26 | B24 | B20 |
1000 ((static_cast<int32_t>(sd) & 1)*B22) |
1001 ((static_cast<int32_t>(sd) >> 1)*B12) |
1002 B11 | B9 | addr.vencoding();
1003 Emit(encoding);
1004}
1005
1006
1007void Arm32Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
1008 const Address& addr = static_cast<const Address&>(ad);
1009 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1010 CHECK_NE(sd, kNoSRegister);
1011 CHECK_NE(cond, kNoCondition);
1012 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1013 B27 | B26 | B24 |
1014 ((static_cast<int32_t>(sd) & 1)*B22) |
1015 ((static_cast<int32_t>(sd) >> 1)*B12) |
1016 B11 | B9 | addr.vencoding();
1017 Emit(encoding);
1018}
1019
1020
1021void Arm32Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
1022 const Address& addr = static_cast<const Address&>(ad);
1023 CHECK_NE(dd, kNoDRegister);
1024 CHECK_NE(cond, kNoCondition);
1025 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1026 B27 | B26 | B24 | B20 |
1027 ((static_cast<int32_t>(dd) >> 4)*B22) |
1028 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1029 B11 | B9 | B8 | addr.vencoding();
1030 Emit(encoding);
1031}
1032
1033
1034void Arm32Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
1035 const Address& addr = static_cast<const Address&>(ad);
1036 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1037 CHECK_NE(dd, kNoDRegister);
1038 CHECK_NE(cond, kNoCondition);
1039 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1040 B27 | B26 | B24 |
1041 ((static_cast<int32_t>(dd) >> 4)*B22) |
1042 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1043 B11 | B9 | B8 | addr.vencoding();
1044 Emit(encoding);
1045}
1046
1047
1048void Arm32Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
1049 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
1050}
1051
1052
1053void Arm32Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
1054 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
1055}
1056
1057
1058void Arm32Assembler::vpops(SRegister reg, int nregs, Condition cond) {
1059 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
1060}
1061
1062
1063void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
1064 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
1065}
1066
1067
1068void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
1069 CHECK_NE(cond, kNoCondition);
1070 CHECK_GT(nregs, 0);
1071 uint32_t D;
1072 uint32_t Vd;
1073 if (dbl) {
1074 // Encoded as D:Vd.
1075 D = (reg >> 4) & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001076 Vd = reg & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001077 } else {
1078 // Encoded as Vd:D.
1079 D = reg & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001080 Vd = (reg >> 1) & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001081 }
1082 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
1083 B11 | B9 |
1084 (dbl ? B8 : 0) |
1085 (push ? B24 : (B23 | B20)) |
1086 static_cast<int32_t>(cond) << kConditionShift |
1087 nregs << (dbl ? 1 : 0) |
1088 D << 22 |
1089 Vd << 12;
1090 Emit(encoding);
1091}
1092
1093
1094void Arm32Assembler::EmitVFPsss(Condition cond, int32_t opcode,
1095 SRegister sd, SRegister sn, SRegister sm) {
1096 CHECK_NE(sd, kNoSRegister);
1097 CHECK_NE(sn, kNoSRegister);
1098 CHECK_NE(sm, kNoSRegister);
1099 CHECK_NE(cond, kNoCondition);
1100 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1101 B27 | B26 | B25 | B11 | B9 | opcode |
1102 ((static_cast<int32_t>(sd) & 1)*B22) |
1103 ((static_cast<int32_t>(sn) >> 1)*B16) |
1104 ((static_cast<int32_t>(sd) >> 1)*B12) |
1105 ((static_cast<int32_t>(sn) & 1)*B7) |
1106 ((static_cast<int32_t>(sm) & 1)*B5) |
1107 (static_cast<int32_t>(sm) >> 1);
1108 Emit(encoding);
1109}
1110
1111
1112void Arm32Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1113 DRegister dd, DRegister dn, DRegister dm) {
1114 CHECK_NE(dd, kNoDRegister);
1115 CHECK_NE(dn, kNoDRegister);
1116 CHECK_NE(dm, kNoDRegister);
1117 CHECK_NE(cond, kNoCondition);
1118 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1119 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1120 ((static_cast<int32_t>(dd) >> 4)*B22) |
1121 ((static_cast<int32_t>(dn) & 0xf)*B16) |
1122 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1123 ((static_cast<int32_t>(dn) >> 4)*B7) |
1124 ((static_cast<int32_t>(dm) >> 4)*B5) |
1125 (static_cast<int32_t>(dm) & 0xf);
1126 Emit(encoding);
1127}
1128
1129
1130void Arm32Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1131 SRegister sd, DRegister dm) {
1132 CHECK_NE(sd, kNoSRegister);
1133 CHECK_NE(dm, kNoDRegister);
1134 CHECK_NE(cond, kNoCondition);
1135 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1136 B27 | B26 | B25 | B11 | B9 | opcode |
1137 ((static_cast<int32_t>(sd) & 1)*B22) |
1138 ((static_cast<int32_t>(sd) >> 1)*B12) |
1139 ((static_cast<int32_t>(dm) >> 4)*B5) |
1140 (static_cast<int32_t>(dm) & 0xf);
1141 Emit(encoding);
1142}
1143
1144
1145void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
1146 DRegister dd, SRegister sm) {
1147 CHECK_NE(dd, kNoDRegister);
1148 CHECK_NE(sm, kNoSRegister);
1149 CHECK_NE(cond, kNoCondition);
1150 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1151 B27 | B26 | B25 | B11 | B9 | opcode |
1152 ((static_cast<int32_t>(dd) >> 4)*B22) |
1153 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1154 ((static_cast<int32_t>(sm) & 1)*B5) |
1155 (static_cast<int32_t>(sm) >> 1);
1156 Emit(encoding);
1157}
1158
1159
1160void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001161 bool setcc, Condition cond) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001162 CHECK_LE(shift_imm, 31u);
Dave Allison45fdb932014-06-25 12:37:10 -07001163 if (setcc) {
1164 movs(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1165 } else {
1166 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
1167 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001168}
1169
1170
1171void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001172 bool setcc, Condition cond) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001173 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001174 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Dave Allison45fdb932014-06-25 12:37:10 -07001175 if (setcc) {
1176 movs(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1177 } else {
1178 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
1179 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001180}
1181
1182
1183void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001184 bool setcc, Condition cond) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001185 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001186 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Dave Allison45fdb932014-06-25 12:37:10 -07001187 if (setcc) {
1188 movs(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1189 } else {
1190 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
1191 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001192}
1193
1194
1195void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
Dave Allison45fdb932014-06-25 12:37:10 -07001196 bool setcc, Condition cond) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001197 CHECK(1u <= shift_imm && shift_imm <= 31u);
Dave Allison45fdb932014-06-25 12:37:10 -07001198 if (setcc) {
1199 movs(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1200 } else {
1201 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1202 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001203}
1204
Dave Allison45fdb932014-06-25 12:37:10 -07001205void Arm32Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
1206 if (setcc) {
1207 movs(rd, ShifterOperand(rm, ROR, 0), cond);
1208 } else {
1209 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1210 }
Dave Allison65fcc2c2014-04-28 13:45:27 -07001211}
1212
1213
Dave Allison45fdb932014-06-25 12:37:10 -07001214void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
1215 bool setcc, Condition cond) {
1216 if (setcc) {
1217 movs(rd, ShifterOperand(rm, LSL, rn), cond);
1218 } else {
1219 mov(rd, ShifterOperand(rm, LSL, rn), cond);
1220 }
1221}
1222
1223
1224void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
1225 bool setcc, Condition cond) {
1226 if (setcc) {
1227 movs(rd, ShifterOperand(rm, LSR, rn), cond);
1228 } else {
1229 mov(rd, ShifterOperand(rm, LSR, rn), cond);
1230 }
1231}
1232
1233
1234void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
1235 bool setcc, Condition cond) {
1236 if (setcc) {
1237 movs(rd, ShifterOperand(rm, ASR, rn), cond);
1238 } else {
1239 mov(rd, ShifterOperand(rm, ASR, rn), cond);
1240 }
1241}
1242
1243
1244void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
1245 bool setcc, Condition cond) {
1246 if (setcc) {
1247 movs(rd, ShifterOperand(rm, ROR, rn), cond);
1248 } else {
1249 mov(rd, ShifterOperand(rm, ROR, rn), cond);
1250 }
1251}
1252
Dave Allison65fcc2c2014-04-28 13:45:27 -07001253void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1254 CHECK_NE(cond, kNoCondition);
1255 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1256 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1257 (static_cast<int32_t>(PC)*B12) |
1258 B11 | B9 | B4;
1259 Emit(encoding);
1260}
1261
1262
1263void Arm32Assembler::svc(uint32_t imm24) {
Andreas Gampeab1eb0d2015-02-13 19:23:55 -08001264 CHECK(IsUint<24>(imm24)) << imm24;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001265 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1266 Emit(encoding);
1267}
1268
1269
1270void Arm32Assembler::bkpt(uint16_t imm16) {
1271 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1272 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1273 Emit(encoding);
1274}
1275
1276
1277void Arm32Assembler::blx(Register rm, Condition cond) {
1278 CHECK_NE(rm, kNoRegister);
1279 CHECK_NE(cond, kNoCondition);
1280 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1281 B24 | B21 | (0xfff << 8) | B5 | B4 |
1282 (static_cast<int32_t>(rm) << kRmShift);
1283 Emit(encoding);
1284}
1285
1286
1287void Arm32Assembler::bx(Register rm, Condition cond) {
1288 CHECK_NE(rm, kNoRegister);
1289 CHECK_NE(cond, kNoCondition);
1290 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1291 B24 | B21 | (0xfff << 8) | B4 |
1292 (static_cast<int32_t>(rm) << kRmShift);
1293 Emit(encoding);
1294}
1295
1296
1297void Arm32Assembler::Push(Register rd, Condition cond) {
1298 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1299}
1300
1301
1302void Arm32Assembler::Pop(Register rd, Condition cond) {
1303 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1304}
1305
1306
1307void Arm32Assembler::PushList(RegList regs, Condition cond) {
1308 stm(DB_W, SP, regs, cond);
1309}
1310
1311
1312void Arm32Assembler::PopList(RegList regs, Condition cond) {
1313 ldm(IA_W, SP, regs, cond);
1314}
1315
1316
1317void Arm32Assembler::Mov(Register rd, Register rm, Condition cond) {
1318 if (rd != rm) {
1319 mov(rd, ShifterOperand(rm), cond);
1320 }
1321}
1322
1323
1324void Arm32Assembler::Bind(Label* label) {
1325 CHECK(!label->IsBound());
1326 int bound_pc = buffer_.Size();
1327 while (label->IsLinked()) {
1328 int32_t position = label->Position();
1329 int32_t next = buffer_.Load<int32_t>(position);
1330 int32_t encoded = Arm32Assembler::EncodeBranchOffset(bound_pc - position, next);
1331 buffer_.Store<int32_t>(position, encoded);
1332 label->position_ = Arm32Assembler::DecodeBranchOffset(next);
1333 }
1334 label->BindTo(bound_pc);
1335}
1336
1337
1338int32_t Arm32Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1339 // The offset is off by 8 due to the way the ARM CPUs read PC.
1340 offset -= 8;
1341 CHECK_ALIGNED(offset, 4);
1342 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
1343
1344 // Properly preserve only the bits supported in the instruction.
1345 offset >>= 2;
1346 offset &= kBranchOffsetMask;
1347 return (inst & ~kBranchOffsetMask) | offset;
1348}
1349
1350
1351int Arm32Assembler::DecodeBranchOffset(int32_t inst) {
1352 // Sign-extend, left-shift by 2, then add 8.
1353 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1354}
1355
1356
1357void Arm32Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
1358 AddConstant(rd, rd, value, cond);
1359}
1360
1361
1362void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
1363 Condition cond) {
1364 if (value == 0) {
1365 if (rd != rn) {
1366 mov(rd, ShifterOperand(rn), cond);
1367 }
1368 return;
1369 }
1370 // We prefer to select the shorter code sequence rather than selecting add for
1371 // positive values and sub for negatives ones, which would slightly improve
1372 // the readability of generated code for some constants.
1373 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001374 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001375 add(rd, rn, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001376 } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001377 sub(rd, rn, shifter_op, cond);
1378 } else {
1379 CHECK(rn != IP);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001380 if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001381 mvn(IP, shifter_op, cond);
1382 add(rd, rn, ShifterOperand(IP), cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001383 } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001384 mvn(IP, shifter_op, cond);
1385 sub(rd, rn, ShifterOperand(IP), cond);
1386 } else {
1387 movw(IP, Low16Bits(value), cond);
1388 uint16_t value_high = High16Bits(value);
1389 if (value_high != 0) {
1390 movt(IP, value_high, cond);
1391 }
1392 add(rd, rn, ShifterOperand(IP), cond);
1393 }
1394 }
1395}
1396
1397
1398void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1399 Condition cond) {
1400 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001401 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001402 adds(rd, rn, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001403 } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001404 subs(rd, rn, shifter_op, cond);
1405 } else {
1406 CHECK(rn != IP);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001407 if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001408 mvn(IP, shifter_op, cond);
1409 adds(rd, rn, ShifterOperand(IP), cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001410 } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001411 mvn(IP, shifter_op, cond);
1412 subs(rd, rn, ShifterOperand(IP), cond);
1413 } else {
1414 movw(IP, Low16Bits(value), cond);
1415 uint16_t value_high = High16Bits(value);
1416 if (value_high != 0) {
1417 movt(IP, value_high, cond);
1418 }
1419 adds(rd, rn, ShifterOperand(IP), cond);
1420 }
1421 }
1422}
1423
Dave Allison65fcc2c2014-04-28 13:45:27 -07001424void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1425 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001426 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001427 mov(rd, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001428 } else if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001429 mvn(rd, shifter_op, cond);
1430 } else {
1431 movw(rd, Low16Bits(value), cond);
1432 uint16_t value_high = High16Bits(value);
1433 if (value_high != 0) {
1434 movt(rd, value_high, cond);
1435 }
1436 }
1437}
1438
1439
1440// Implementation note: this method must emit at most one instruction when
1441// Address::CanHoldLoadOffsetArm.
1442void Arm32Assembler::LoadFromOffset(LoadOperandType type,
1443 Register reg,
1444 Register base,
1445 int32_t offset,
1446 Condition cond) {
1447 if (!Address::CanHoldLoadOffsetArm(type, offset)) {
1448 CHECK(base != IP);
1449 LoadImmediate(IP, offset, cond);
1450 add(IP, IP, ShifterOperand(base), cond);
1451 base = IP;
1452 offset = 0;
1453 }
1454 CHECK(Address::CanHoldLoadOffsetArm(type, offset));
1455 switch (type) {
1456 case kLoadSignedByte:
1457 ldrsb(reg, Address(base, offset), cond);
1458 break;
1459 case kLoadUnsignedByte:
1460 ldrb(reg, Address(base, offset), cond);
1461 break;
1462 case kLoadSignedHalfword:
1463 ldrsh(reg, Address(base, offset), cond);
1464 break;
1465 case kLoadUnsignedHalfword:
1466 ldrh(reg, Address(base, offset), cond);
1467 break;
1468 case kLoadWord:
1469 ldr(reg, Address(base, offset), cond);
1470 break;
1471 case kLoadWordPair:
1472 ldrd(reg, Address(base, offset), cond);
1473 break;
1474 default:
1475 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001476 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001477 }
1478}
1479
1480
1481// Implementation note: this method must emit at most one instruction when
1482// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1483void Arm32Assembler::LoadSFromOffset(SRegister reg,
1484 Register base,
1485 int32_t offset,
1486 Condition cond) {
1487 if (!Address::CanHoldLoadOffsetArm(kLoadSWord, offset)) {
1488 CHECK_NE(base, IP);
1489 LoadImmediate(IP, offset, cond);
1490 add(IP, IP, ShifterOperand(base), cond);
1491 base = IP;
1492 offset = 0;
1493 }
1494 CHECK(Address::CanHoldLoadOffsetArm(kLoadSWord, offset));
1495 vldrs(reg, Address(base, offset), cond);
1496}
1497
1498
1499// Implementation note: this method must emit at most one instruction when
1500// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1501void Arm32Assembler::LoadDFromOffset(DRegister reg,
1502 Register base,
1503 int32_t offset,
1504 Condition cond) {
1505 if (!Address::CanHoldLoadOffsetArm(kLoadDWord, offset)) {
1506 CHECK_NE(base, IP);
1507 LoadImmediate(IP, offset, cond);
1508 add(IP, IP, ShifterOperand(base), cond);
1509 base = IP;
1510 offset = 0;
1511 }
1512 CHECK(Address::CanHoldLoadOffsetArm(kLoadDWord, offset));
1513 vldrd(reg, Address(base, offset), cond);
1514}
1515
1516
1517// Implementation note: this method must emit at most one instruction when
1518// Address::CanHoldStoreOffsetArm.
1519void Arm32Assembler::StoreToOffset(StoreOperandType type,
1520 Register reg,
1521 Register base,
1522 int32_t offset,
1523 Condition cond) {
1524 if (!Address::CanHoldStoreOffsetArm(type, offset)) {
1525 CHECK(reg != IP);
1526 CHECK(base != IP);
1527 LoadImmediate(IP, offset, cond);
1528 add(IP, IP, ShifterOperand(base), cond);
1529 base = IP;
1530 offset = 0;
1531 }
1532 CHECK(Address::CanHoldStoreOffsetArm(type, offset));
1533 switch (type) {
1534 case kStoreByte:
1535 strb(reg, Address(base, offset), cond);
1536 break;
1537 case kStoreHalfword:
1538 strh(reg, Address(base, offset), cond);
1539 break;
1540 case kStoreWord:
1541 str(reg, Address(base, offset), cond);
1542 break;
1543 case kStoreWordPair:
1544 strd(reg, Address(base, offset), cond);
1545 break;
1546 default:
1547 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001548 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001549 }
1550}
1551
1552
1553// Implementation note: this method must emit at most one instruction when
1554// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreToOffset.
1555void Arm32Assembler::StoreSToOffset(SRegister reg,
1556 Register base,
1557 int32_t offset,
1558 Condition cond) {
1559 if (!Address::CanHoldStoreOffsetArm(kStoreSWord, offset)) {
1560 CHECK_NE(base, IP);
1561 LoadImmediate(IP, offset, cond);
1562 add(IP, IP, ShifterOperand(base), cond);
1563 base = IP;
1564 offset = 0;
1565 }
1566 CHECK(Address::CanHoldStoreOffsetArm(kStoreSWord, offset));
1567 vstrs(reg, Address(base, offset), cond);
1568}
1569
1570
1571// Implementation note: this method must emit at most one instruction when
1572// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreSToOffset.
1573void Arm32Assembler::StoreDToOffset(DRegister reg,
1574 Register base,
1575 int32_t offset,
1576 Condition cond) {
1577 if (!Address::CanHoldStoreOffsetArm(kStoreDWord, offset)) {
1578 CHECK_NE(base, IP);
1579 LoadImmediate(IP, offset, cond);
1580 add(IP, IP, ShifterOperand(base), cond);
1581 base = IP;
1582 offset = 0;
1583 }
1584 CHECK(Address::CanHoldStoreOffsetArm(kStoreDWord, offset));
1585 vstrd(reg, Address(base, offset), cond);
1586}
1587
1588
1589void Arm32Assembler::MemoryBarrier(ManagedRegister mscratch) {
1590 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001591 dmb(SY);
1592}
1593
1594
1595void Arm32Assembler::dmb(DmbOptions flavor) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001596 int32_t encoding = 0xf57ff05f; // dmb
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001597 Emit(encoding | flavor);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001598}
1599
1600
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001601void Arm32Assembler::cbz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001602 LOG(FATAL) << "cbz is not supported on ARM32";
1603}
1604
1605
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001606void Arm32Assembler::cbnz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001607 LOG(FATAL) << "cbnz is not supported on ARM32";
1608}
1609
1610
1611void Arm32Assembler::CompareAndBranchIfZero(Register r, Label* label) {
1612 cmp(r, ShifterOperand(0));
1613 b(label, EQ);
1614}
1615
1616
1617void Arm32Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
1618 cmp(r, ShifterOperand(0));
1619 b(label, NE);
1620}
1621
1622
1623} // namespace arm
1624} // namespace art