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