blob: c6af28337083b8f66cb08bbda63603aab68111e0 [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,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010060 Condition cond, SetCc set_cc) {
61 EmitType01(cond, so.type(), AND, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070062}
63
64
65void Arm32Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010066 Condition cond, SetCc set_cc) {
67 EmitType01(cond, so.type(), EOR, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070068}
69
70
71void Arm32Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010072 Condition cond, SetCc set_cc) {
73 EmitType01(cond, so.type(), SUB, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070074}
75
76void Arm32Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010077 Condition cond, SetCc set_cc) {
78 EmitType01(cond, so.type(), RSB, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070079}
80
Dave Allison65fcc2c2014-04-28 13:45:27 -070081void Arm32Assembler::add(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010082 Condition cond, SetCc set_cc) {
83 EmitType01(cond, so.type(), ADD, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070084}
85
86
87void Arm32Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010088 Condition cond, SetCc set_cc) {
89 EmitType01(cond, so.type(), ADC, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070090}
91
92
93void Arm32Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +010094 Condition cond, SetCc set_cc) {
95 EmitType01(cond, so.type(), SBC, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -070096}
97
98
99void Arm32Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100100 Condition cond, SetCc set_cc) {
101 EmitType01(cond, so.type(), RSC, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700102}
103
104
105void Arm32Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
106 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100107 EmitType01(cond, so.type(), TST, kCcSet, rn, R0, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700108}
109
110
111void Arm32Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
112 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100113 EmitType01(cond, so.type(), TEQ, kCcSet, rn, R0, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700114}
115
116
117void Arm32Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100118 EmitType01(cond, so.type(), CMP, kCcSet, rn, R0, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700119}
120
121
122void Arm32Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100123 EmitType01(cond, so.type(), CMN, kCcSet, rn, R0, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700124}
125
126
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100127void Arm32Assembler::orr(Register rd, Register rn, const ShifterOperand& so,
128 Condition cond, SetCc set_cc) {
129 EmitType01(cond, so.type(), ORR, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700130}
131
132
Vladimir Markod2b4ca22015-09-14 15:13:26 +0100133void Arm32Assembler::orn(Register rd ATTRIBUTE_UNUSED,
134 Register rn ATTRIBUTE_UNUSED,
135 const ShifterOperand& so ATTRIBUTE_UNUSED,
136 Condition cond ATTRIBUTE_UNUSED,
137 SetCc set_cc ATTRIBUTE_UNUSED) {
138 LOG(FATAL) << "orn is not supported on ARM32";
139}
140
141
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100142void Arm32Assembler::mov(Register rd, const ShifterOperand& so,
143 Condition cond, SetCc set_cc) {
144 EmitType01(cond, so.type(), MOV, set_cc, R0, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700145}
146
147
148void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100149 Condition cond, SetCc set_cc) {
150 EmitType01(cond, so.type(), BIC, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700151}
152
153
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100154void Arm32Assembler::mvn(Register rd, const ShifterOperand& so,
155 Condition cond, SetCc set_cc) {
156 EmitType01(cond, so.type(), MVN, set_cc, R0, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700157}
158
159
160void Arm32Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
161 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
162 EmitMulOp(cond, 0, R0, rd, rn, rm);
163}
164
165
166void Arm32Assembler::mla(Register rd, Register rn, Register rm, Register ra,
167 Condition cond) {
168 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
169 EmitMulOp(cond, B21, ra, rd, rn, rm);
170}
171
172
173void Arm32Assembler::mls(Register rd, Register rn, Register rm, Register ra,
174 Condition cond) {
175 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
176 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
177}
178
179
Zheng Xuc6667102015-05-15 16:08:45 +0800180void Arm32Assembler::smull(Register rd_lo, Register rd_hi, Register rn,
181 Register rm, Condition cond) {
182 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
183 EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
184}
185
186
Dave Allison65fcc2c2014-04-28 13:45:27 -0700187void Arm32Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
188 Register rm, Condition cond) {
189 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
190 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
191}
192
193
194void Arm32Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
195 CHECK_NE(rd, kNoRegister);
196 CHECK_NE(rn, kNoRegister);
197 CHECK_NE(rm, kNoRegister);
198 CHECK_NE(cond, kNoCondition);
199 int32_t encoding = B26 | B25 | B24 | B20 |
200 B15 | B14 | B13 | B12 |
201 (static_cast<int32_t>(cond) << kConditionShift) |
202 (static_cast<int32_t>(rn) << 0) |
203 (static_cast<int32_t>(rd) << 16) |
204 (static_cast<int32_t>(rm) << 8) |
205 B4;
206 Emit(encoding);
207}
208
209
210void Arm32Assembler::udiv(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 | B21 | 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
Roland Levillain51d3fc42014-11-13 14:11:42 +0000226void Arm32Assembler::sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
227 CHECK_NE(rd, kNoRegister);
228 CHECK_NE(rn, kNoRegister);
229 CHECK_NE(cond, kNoCondition);
230 CHECK_LE(lsb, 31U);
231 CHECK(1U <= width && width <= 32U) << width;
232 uint32_t widthminus1 = width - 1;
233
234 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
235 B26 | B25 | B24 | B23 | B21 |
236 (widthminus1 << 16) |
237 (static_cast<uint32_t>(rd) << 12) |
238 (lsb << 7) |
239 B6 | B4 |
240 static_cast<uint32_t>(rn);
241 Emit(encoding);
242}
243
244
Roland Levillain981e4542014-11-14 11:47:14 +0000245void Arm32Assembler::ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
246 CHECK_NE(rd, kNoRegister);
247 CHECK_NE(rn, kNoRegister);
248 CHECK_NE(cond, kNoCondition);
249 CHECK_LE(lsb, 31U);
250 CHECK(1U <= width && width <= 32U) << width;
251 uint32_t widthminus1 = width - 1;
252
253 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
254 B26 | B25 | B24 | B23 | B22 | B21 |
255 (widthminus1 << 16) |
256 (static_cast<uint32_t>(rd) << 12) |
257 (lsb << 7) |
258 B6 | B4 |
259 static_cast<uint32_t>(rn);
260 Emit(encoding);
261}
262
263
Dave Allison65fcc2c2014-04-28 13:45:27 -0700264void Arm32Assembler::ldr(Register rd, const Address& ad, Condition cond) {
265 EmitMemOp(cond, true, false, rd, ad);
266}
267
268
269void Arm32Assembler::str(Register rd, const Address& ad, Condition cond) {
270 EmitMemOp(cond, false, false, rd, ad);
271}
272
273
274void Arm32Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
275 EmitMemOp(cond, true, true, rd, ad);
276}
277
278
279void Arm32Assembler::strb(Register rd, const Address& ad, Condition cond) {
280 EmitMemOp(cond, false, true, rd, ad);
281}
282
283
284void Arm32Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
285 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
286}
287
288
289void Arm32Assembler::strh(Register rd, const Address& ad, Condition cond) {
290 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
291}
292
293
294void Arm32Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
295 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
296}
297
298
299void Arm32Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
300 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
301}
302
303
304void Arm32Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
305 CHECK_EQ(rd % 2, 0);
306 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
307}
308
309
310void Arm32Assembler::strd(Register rd, const Address& ad, Condition cond) {
311 CHECK_EQ(rd % 2, 0);
312 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
313}
314
315
316void Arm32Assembler::ldm(BlockAddressMode am,
317 Register base,
318 RegList regs,
319 Condition cond) {
320 EmitMultiMemOp(cond, am, true, base, regs);
321}
322
323
324void Arm32Assembler::stm(BlockAddressMode am,
325 Register base,
326 RegList regs,
327 Condition cond) {
328 EmitMultiMemOp(cond, am, false, base, regs);
329}
330
331
332void Arm32Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
333 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
334}
335
336
337void Arm32Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
338 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
339}
340
341
342bool Arm32Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
343 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
344 if (((imm32 & ((1 << 19) - 1)) == 0) &&
345 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
346 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
347 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
348 ((imm32 >> 19) & ((1 << 6) -1));
349 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
350 sd, S0, S0);
351 return true;
352 }
353 return false;
354}
355
356
357bool Arm32Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
358 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
359 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
360 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
361 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
362 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
363 ((imm64 >> 48) & ((1 << 6) -1));
364 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
365 dd, D0, D0);
366 return true;
367 }
368 return false;
369}
370
371
372void Arm32Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
373 Condition cond) {
374 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
375}
376
377
378void Arm32Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
379 Condition cond) {
380 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
381}
382
383
384void Arm32Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
385 Condition cond) {
386 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
387}
388
389
390void Arm32Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
391 Condition cond) {
392 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
393}
394
395
396void Arm32Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
397 Condition cond) {
398 EmitVFPsss(cond, B21, sd, sn, sm);
399}
400
401
402void Arm32Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
403 Condition cond) {
404 EmitVFPddd(cond, B21, dd, dn, dm);
405}
406
407
408void Arm32Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
409 Condition cond) {
410 EmitVFPsss(cond, 0, sd, sn, sm);
411}
412
413
414void Arm32Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
415 Condition cond) {
416 EmitVFPddd(cond, 0, dd, dn, dm);
417}
418
419
420void Arm32Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
421 Condition cond) {
422 EmitVFPsss(cond, B6, sd, sn, sm);
423}
424
425
426void Arm32Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
427 Condition cond) {
428 EmitVFPddd(cond, B6, dd, dn, dm);
429}
430
431
432void Arm32Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
433 Condition cond) {
434 EmitVFPsss(cond, B23, sd, sn, sm);
435}
436
437
438void Arm32Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
439 Condition cond) {
440 EmitVFPddd(cond, B23, dd, dn, dm);
441}
442
443
444void Arm32Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
445 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
446}
447
448
449void Arm32Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
450 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
451}
452
453
454void Arm32Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
455 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
456}
457
458
459void Arm32Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
460 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
461}
462
463
464void Arm32Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
465 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
466}
467
468void Arm32Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
469 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
470}
471
472
473void Arm32Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
474 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
475}
476
477
478void Arm32Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
479 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
480}
481
482
483void Arm32Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
484 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
485}
486
487
488void Arm32Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
489 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
490}
491
492
493void Arm32Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
494 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
495}
496
497
498void Arm32Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
499 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
500}
501
502
503void Arm32Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
504 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
505}
506
507
508void Arm32Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
509 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
510}
511
512
513void Arm32Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
514 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
515}
516
517
518void Arm32Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
519 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
520}
521
522
523void Arm32Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
524 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
525}
526
527
528void Arm32Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
529 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
530}
531
532
533void Arm32Assembler::vcmpsz(SRegister sd, Condition cond) {
534 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
535}
536
537
538void Arm32Assembler::vcmpdz(DRegister dd, Condition cond) {
539 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
540}
541
542void Arm32Assembler::b(Label* label, Condition cond) {
543 EmitBranch(cond, label, false);
544}
545
546
547void Arm32Assembler::bl(Label* label, Condition cond) {
548 EmitBranch(cond, label, true);
549}
550
551
552void Arm32Assembler::MarkExceptionHandler(Label* label) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100553 EmitType01(AL, 1, TST, kCcSet, PC, R0, ShifterOperand(0));
Dave Allison65fcc2c2014-04-28 13:45:27 -0700554 Label l;
555 b(&l);
556 EmitBranch(AL, label, false);
557 Bind(&l);
558}
559
560
561void Arm32Assembler::Emit(int32_t value) {
562 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
563 buffer_.Emit<int32_t>(value);
564}
565
566
567void Arm32Assembler::EmitType01(Condition cond,
568 int type,
569 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100570 SetCc set_cc,
Dave Allison65fcc2c2014-04-28 13:45:27 -0700571 Register rn,
572 Register rd,
573 const ShifterOperand& so) {
574 CHECK_NE(rd, kNoRegister);
575 CHECK_NE(cond, kNoCondition);
576 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
577 type << kTypeShift |
578 static_cast<int32_t>(opcode) << kOpcodeShift |
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100579 (set_cc == kCcSet ? 1 : 0) << kSShift |
Dave Allison65fcc2c2014-04-28 13:45:27 -0700580 static_cast<int32_t>(rn) << kRnShift |
581 static_cast<int32_t>(rd) << kRdShift |
582 so.encodingArm();
583 Emit(encoding);
584}
585
586
587void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
588 CHECK_NE(cond, kNoCondition);
589 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
590 5 << kTypeShift |
591 (link ? 1 : 0) << kLinkShift;
592 Emit(Arm32Assembler::EncodeBranchOffset(offset, encoding));
593}
594
595
596void Arm32Assembler::EmitMemOp(Condition cond,
Dave Allison45fdb932014-06-25 12:37:10 -0700597 bool load,
598 bool byte,
599 Register rd,
600 const Address& ad) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700601 CHECK_NE(rd, kNoRegister);
602 CHECK_NE(cond, kNoCondition);
603 const Address& addr = static_cast<const Address&>(ad);
604
Dave Allison45fdb932014-06-25 12:37:10 -0700605 int32_t encoding = 0;
606 if (!ad.IsImmediate() && ad.GetRegisterOffset() == PC) {
607 // PC relative LDR(literal)
608 int32_t offset = ad.GetOffset();
609 int32_t u = B23;
610 if (offset < 0) {
611 offset = -offset;
612 u = 0;
613 }
614 CHECK_LT(offset, (1 << 12));
615 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
616 B26 | B24 | u | B20 |
617 (load ? L : 0) |
618 (byte ? B : 0) |
619 (static_cast<int32_t>(rd) << kRdShift) |
620 0xf << 16 |
621 (offset & 0xfff);
622
623 } else {
624 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
625 B26 |
626 (load ? L : 0) |
627 (byte ? B : 0) |
628 (static_cast<int32_t>(rd) << kRdShift) |
629 addr.encodingArm();
630 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700631 Emit(encoding);
632}
633
634
635void Arm32Assembler::EmitMemOpAddressMode3(Condition cond,
636 int32_t mode,
637 Register rd,
638 const Address& ad) {
639 CHECK_NE(rd, kNoRegister);
640 CHECK_NE(cond, kNoCondition);
641 const Address& addr = static_cast<const Address&>(ad);
642 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
643 B22 |
644 mode |
645 (static_cast<int32_t>(rd) << kRdShift) |
646 addr.encoding3();
647 Emit(encoding);
648}
649
650
651void Arm32Assembler::EmitMultiMemOp(Condition cond,
652 BlockAddressMode am,
653 bool load,
654 Register base,
655 RegList regs) {
656 CHECK_NE(base, kNoRegister);
657 CHECK_NE(cond, kNoCondition);
658 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
659 B27 |
660 am |
661 (load ? L : 0) |
662 (static_cast<int32_t>(base) << kRnShift) |
663 regs;
664 Emit(encoding);
665}
666
667
668void Arm32Assembler::EmitShiftImmediate(Condition cond,
669 Shift opcode,
670 Register rd,
671 Register rm,
672 const ShifterOperand& so) {
673 CHECK_NE(cond, kNoCondition);
674 CHECK(so.IsImmediate());
675 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
676 static_cast<int32_t>(MOV) << kOpcodeShift |
677 static_cast<int32_t>(rd) << kRdShift |
678 so.encodingArm() << kShiftImmShift |
679 static_cast<int32_t>(opcode) << kShiftShift |
680 static_cast<int32_t>(rm);
681 Emit(encoding);
682}
683
684
685void Arm32Assembler::EmitShiftRegister(Condition cond,
686 Shift opcode,
687 Register rd,
688 Register rm,
689 const ShifterOperand& so) {
690 CHECK_NE(cond, kNoCondition);
691 CHECK(so.IsRegister());
692 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
693 static_cast<int32_t>(MOV) << kOpcodeShift |
694 static_cast<int32_t>(rd) << kRdShift |
695 so.encodingArm() << kShiftRegisterShift |
696 static_cast<int32_t>(opcode) << kShiftShift |
697 B4 |
698 static_cast<int32_t>(rm);
699 Emit(encoding);
700}
701
702
703void Arm32Assembler::EmitBranch(Condition cond, Label* label, bool link) {
704 if (label->IsBound()) {
705 EmitType5(cond, label->Position() - buffer_.Size(), link);
706 } else {
707 int position = buffer_.Size();
708 // Use the offset field of the branch instruction for linking the sites.
709 EmitType5(cond, label->position_, link);
710 label->LinkTo(position);
711 }
712}
713
714
715void Arm32Assembler::clz(Register rd, Register rm, Condition cond) {
716 CHECK_NE(rd, kNoRegister);
717 CHECK_NE(rm, kNoRegister);
718 CHECK_NE(cond, kNoCondition);
719 CHECK_NE(rd, PC);
720 CHECK_NE(rm, PC);
721 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
722 B24 | B22 | B21 | (0xf << 16) |
723 (static_cast<int32_t>(rd) << kRdShift) |
724 (0xf << 8) | B4 | static_cast<int32_t>(rm);
725 Emit(encoding);
726}
727
728
729void Arm32Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
730 CHECK_NE(cond, kNoCondition);
731 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
732 B25 | B24 | ((imm16 >> 12) << 16) |
733 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
734 Emit(encoding);
735}
736
737
738void Arm32Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
739 CHECK_NE(cond, kNoCondition);
740 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
741 B25 | B24 | B22 | ((imm16 >> 12) << 16) |
742 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
743 Emit(encoding);
744}
745
746
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100747void Arm32Assembler::rbit(Register rd, Register rm, Condition cond) {
748 CHECK_NE(rd, kNoRegister);
749 CHECK_NE(rm, kNoRegister);
750 CHECK_NE(cond, kNoCondition);
751 CHECK_NE(rd, PC);
752 CHECK_NE(rm, PC);
753 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
754 B26 | B25 | B23 | B22 | B21 | B20 | (0xf << 16) |
755 (static_cast<int32_t>(rd) << kRdShift) |
756 (0xf << 8) | B5 | B4 | static_cast<int32_t>(rm);
757 Emit(encoding);
758}
759
760
Dave Allison65fcc2c2014-04-28 13:45:27 -0700761void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
762 Register rd, Register rn,
763 Register rm, Register rs) {
764 CHECK_NE(rd, kNoRegister);
765 CHECK_NE(rn, kNoRegister);
766 CHECK_NE(rm, kNoRegister);
767 CHECK_NE(rs, kNoRegister);
768 CHECK_NE(cond, kNoCondition);
769 int32_t encoding = opcode |
770 (static_cast<int32_t>(cond) << kConditionShift) |
771 (static_cast<int32_t>(rn) << kRnShift) |
772 (static_cast<int32_t>(rd) << kRdShift) |
773 (static_cast<int32_t>(rs) << kRsShift) |
774 B7 | B4 |
775 (static_cast<int32_t>(rm) << kRmShift);
776 Emit(encoding);
777}
778
Calin Juravle52c48962014-12-16 17:02:57 +0000779
Dave Allison65fcc2c2014-04-28 13:45:27 -0700780void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) {
781 CHECK_NE(rn, kNoRegister);
782 CHECK_NE(rt, kNoRegister);
783 CHECK_NE(cond, kNoCondition);
784 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
785 B24 |
786 B23 |
787 L |
788 (static_cast<int32_t>(rn) << kLdExRnShift) |
789 (static_cast<int32_t>(rt) << kLdExRtShift) |
790 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
791 Emit(encoding);
792}
793
794
Calin Juravle52c48962014-12-16 17:02:57 +0000795void Arm32Assembler::ldrexd(Register rt, Register rt2, Register rn, Condition cond) {
796 CHECK_NE(rn, kNoRegister);
797 CHECK_NE(rt, kNoRegister);
798 CHECK_NE(rt2, kNoRegister);
799 CHECK_NE(rt, R14);
800 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
801 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
802 CHECK_NE(cond, kNoCondition);
803
804 int32_t encoding =
805 (static_cast<uint32_t>(cond) << kConditionShift) |
806 B24 | B23 | B21 | B20 |
807 static_cast<uint32_t>(rn) << 16 |
808 static_cast<uint32_t>(rt) << 12 |
809 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
810 Emit(encoding);
811}
812
813
Dave Allison65fcc2c2014-04-28 13:45:27 -0700814void Arm32Assembler::strex(Register rd,
815 Register rt,
816 Register rn,
817 Condition cond) {
818 CHECK_NE(rn, kNoRegister);
819 CHECK_NE(rd, kNoRegister);
820 CHECK_NE(rt, kNoRegister);
821 CHECK_NE(cond, kNoCondition);
822 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
823 B24 |
824 B23 |
825 (static_cast<int32_t>(rn) << kStrExRnShift) |
826 (static_cast<int32_t>(rd) << kStrExRdShift) |
827 B11 | B10 | B9 | B8 | B7 | B4 |
828 (static_cast<int32_t>(rt) << kStrExRtShift);
829 Emit(encoding);
830}
831
Calin Juravle52c48962014-12-16 17:02:57 +0000832void Arm32Assembler::strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond) {
833 CHECK_NE(rd, kNoRegister);
834 CHECK_NE(rn, kNoRegister);
835 CHECK_NE(rt, kNoRegister);
836 CHECK_NE(rt2, kNoRegister);
837 CHECK_NE(rt, R14);
838 CHECK_NE(rd, rt);
839 CHECK_NE(rd, rt2);
840 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
841 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
842 CHECK_NE(cond, kNoCondition);
843
844 int32_t encoding =
845 (static_cast<uint32_t>(cond) << kConditionShift) |
846 B24 | B23 | B21 |
847 static_cast<uint32_t>(rn) << 16 |
848 static_cast<uint32_t>(rd) << 12 |
849 B11 | B10 | B9 | B8 | B7 | B4 |
850 static_cast<uint32_t>(rt);
851 Emit(encoding);
852}
853
Dave Allison65fcc2c2014-04-28 13:45:27 -0700854
855void Arm32Assembler::clrex(Condition cond) {
856 CHECK_EQ(cond, AL); // This cannot be conditional on ARM.
857 int32_t encoding = (kSpecialCondition << kConditionShift) |
858 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
859 Emit(encoding);
860}
861
862
863void Arm32Assembler::nop(Condition cond) {
864 CHECK_NE(cond, kNoCondition);
865 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
866 B25 | B24 | B21 | (0xf << 12);
867 Emit(encoding);
868}
869
870
871void Arm32Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
872 CHECK_NE(sn, kNoSRegister);
873 CHECK_NE(rt, kNoRegister);
874 CHECK_NE(rt, SP);
875 CHECK_NE(rt, PC);
876 CHECK_NE(cond, kNoCondition);
877 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
878 B27 | B26 | B25 |
879 ((static_cast<int32_t>(sn) >> 1)*B16) |
880 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
881 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
882 Emit(encoding);
883}
884
885
886void Arm32Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
887 CHECK_NE(sn, kNoSRegister);
888 CHECK_NE(rt, kNoRegister);
889 CHECK_NE(rt, SP);
890 CHECK_NE(rt, PC);
891 CHECK_NE(cond, kNoCondition);
892 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
893 B27 | B26 | B25 | B20 |
894 ((static_cast<int32_t>(sn) >> 1)*B16) |
895 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
896 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
897 Emit(encoding);
898}
899
900
901void Arm32Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
902 Condition cond) {
903 CHECK_NE(sm, kNoSRegister);
904 CHECK_NE(sm, S31);
905 CHECK_NE(rt, kNoRegister);
906 CHECK_NE(rt, SP);
907 CHECK_NE(rt, PC);
908 CHECK_NE(rt2, kNoRegister);
909 CHECK_NE(rt2, SP);
910 CHECK_NE(rt2, PC);
911 CHECK_NE(cond, kNoCondition);
912 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
913 B27 | B26 | B22 |
914 (static_cast<int32_t>(rt2)*B16) |
915 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
916 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
917 (static_cast<int32_t>(sm) >> 1);
918 Emit(encoding);
919}
920
921
922void Arm32Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
923 Condition cond) {
924 CHECK_NE(sm, kNoSRegister);
925 CHECK_NE(sm, S31);
926 CHECK_NE(rt, kNoRegister);
927 CHECK_NE(rt, SP);
928 CHECK_NE(rt, PC);
929 CHECK_NE(rt2, kNoRegister);
930 CHECK_NE(rt2, SP);
931 CHECK_NE(rt2, PC);
932 CHECK_NE(rt, rt2);
933 CHECK_NE(cond, kNoCondition);
934 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
935 B27 | B26 | B22 | B20 |
936 (static_cast<int32_t>(rt2)*B16) |
937 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
938 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
939 (static_cast<int32_t>(sm) >> 1);
940 Emit(encoding);
941}
942
943
944void Arm32Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
945 Condition cond) {
946 CHECK_NE(dm, kNoDRegister);
947 CHECK_NE(rt, kNoRegister);
948 CHECK_NE(rt, SP);
949 CHECK_NE(rt, PC);
950 CHECK_NE(rt2, kNoRegister);
951 CHECK_NE(rt2, SP);
952 CHECK_NE(rt2, PC);
953 CHECK_NE(cond, kNoCondition);
954 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
955 B27 | B26 | B22 |
956 (static_cast<int32_t>(rt2)*B16) |
957 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
958 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
959 (static_cast<int32_t>(dm) & 0xf);
960 Emit(encoding);
961}
962
963
964void Arm32Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
965 Condition cond) {
966 CHECK_NE(dm, kNoDRegister);
967 CHECK_NE(rt, kNoRegister);
968 CHECK_NE(rt, SP);
969 CHECK_NE(rt, PC);
970 CHECK_NE(rt2, kNoRegister);
971 CHECK_NE(rt2, SP);
972 CHECK_NE(rt2, PC);
973 CHECK_NE(rt, rt2);
974 CHECK_NE(cond, kNoCondition);
975 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
976 B27 | B26 | B22 | B20 |
977 (static_cast<int32_t>(rt2)*B16) |
978 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
979 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
980 (static_cast<int32_t>(dm) & 0xf);
981 Emit(encoding);
982}
983
984
985void Arm32Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
986 const Address& addr = static_cast<const Address&>(ad);
987 CHECK_NE(sd, kNoSRegister);
988 CHECK_NE(cond, kNoCondition);
989 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
990 B27 | B26 | B24 | B20 |
991 ((static_cast<int32_t>(sd) & 1)*B22) |
992 ((static_cast<int32_t>(sd) >> 1)*B12) |
993 B11 | B9 | addr.vencoding();
994 Emit(encoding);
995}
996
997
998void Arm32Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
999 const Address& addr = static_cast<const Address&>(ad);
1000 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1001 CHECK_NE(sd, kNoSRegister);
1002 CHECK_NE(cond, kNoCondition);
1003 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1004 B27 | B26 | B24 |
1005 ((static_cast<int32_t>(sd) & 1)*B22) |
1006 ((static_cast<int32_t>(sd) >> 1)*B12) |
1007 B11 | B9 | addr.vencoding();
1008 Emit(encoding);
1009}
1010
1011
1012void Arm32Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
1013 const Address& addr = static_cast<const Address&>(ad);
1014 CHECK_NE(dd, kNoDRegister);
1015 CHECK_NE(cond, kNoCondition);
1016 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1017 B27 | B26 | B24 | B20 |
1018 ((static_cast<int32_t>(dd) >> 4)*B22) |
1019 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1020 B11 | B9 | B8 | addr.vencoding();
1021 Emit(encoding);
1022}
1023
1024
1025void Arm32Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
1026 const Address& addr = static_cast<const Address&>(ad);
1027 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1028 CHECK_NE(dd, kNoDRegister);
1029 CHECK_NE(cond, kNoCondition);
1030 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1031 B27 | B26 | B24 |
1032 ((static_cast<int32_t>(dd) >> 4)*B22) |
1033 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1034 B11 | B9 | B8 | addr.vencoding();
1035 Emit(encoding);
1036}
1037
1038
1039void Arm32Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
1040 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
1041}
1042
1043
1044void Arm32Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
1045 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
1046}
1047
1048
1049void Arm32Assembler::vpops(SRegister reg, int nregs, Condition cond) {
1050 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
1051}
1052
1053
1054void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
1055 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
1056}
1057
1058
1059void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
1060 CHECK_NE(cond, kNoCondition);
1061 CHECK_GT(nregs, 0);
1062 uint32_t D;
1063 uint32_t Vd;
1064 if (dbl) {
1065 // Encoded as D:Vd.
1066 D = (reg >> 4) & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001067 Vd = reg & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001068 } else {
1069 // Encoded as Vd:D.
1070 D = reg & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001071 Vd = (reg >> 1) & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001072 }
1073 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
1074 B11 | B9 |
1075 (dbl ? B8 : 0) |
1076 (push ? B24 : (B23 | B20)) |
1077 static_cast<int32_t>(cond) << kConditionShift |
1078 nregs << (dbl ? 1 : 0) |
1079 D << 22 |
1080 Vd << 12;
1081 Emit(encoding);
1082}
1083
1084
1085void Arm32Assembler::EmitVFPsss(Condition cond, int32_t opcode,
1086 SRegister sd, SRegister sn, SRegister sm) {
1087 CHECK_NE(sd, kNoSRegister);
1088 CHECK_NE(sn, kNoSRegister);
1089 CHECK_NE(sm, kNoSRegister);
1090 CHECK_NE(cond, kNoCondition);
1091 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1092 B27 | B26 | B25 | B11 | B9 | opcode |
1093 ((static_cast<int32_t>(sd) & 1)*B22) |
1094 ((static_cast<int32_t>(sn) >> 1)*B16) |
1095 ((static_cast<int32_t>(sd) >> 1)*B12) |
1096 ((static_cast<int32_t>(sn) & 1)*B7) |
1097 ((static_cast<int32_t>(sm) & 1)*B5) |
1098 (static_cast<int32_t>(sm) >> 1);
1099 Emit(encoding);
1100}
1101
1102
1103void Arm32Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1104 DRegister dd, DRegister dn, DRegister dm) {
1105 CHECK_NE(dd, kNoDRegister);
1106 CHECK_NE(dn, kNoDRegister);
1107 CHECK_NE(dm, kNoDRegister);
1108 CHECK_NE(cond, kNoCondition);
1109 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1110 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1111 ((static_cast<int32_t>(dd) >> 4)*B22) |
1112 ((static_cast<int32_t>(dn) & 0xf)*B16) |
1113 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1114 ((static_cast<int32_t>(dn) >> 4)*B7) |
1115 ((static_cast<int32_t>(dm) >> 4)*B5) |
1116 (static_cast<int32_t>(dm) & 0xf);
1117 Emit(encoding);
1118}
1119
1120
1121void Arm32Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1122 SRegister sd, DRegister dm) {
1123 CHECK_NE(sd, kNoSRegister);
1124 CHECK_NE(dm, kNoDRegister);
1125 CHECK_NE(cond, kNoCondition);
1126 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1127 B27 | B26 | B25 | B11 | B9 | opcode |
1128 ((static_cast<int32_t>(sd) & 1)*B22) |
1129 ((static_cast<int32_t>(sd) >> 1)*B12) |
1130 ((static_cast<int32_t>(dm) >> 4)*B5) |
1131 (static_cast<int32_t>(dm) & 0xf);
1132 Emit(encoding);
1133}
1134
1135
1136void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
1137 DRegister dd, SRegister sm) {
1138 CHECK_NE(dd, kNoDRegister);
1139 CHECK_NE(sm, kNoSRegister);
1140 CHECK_NE(cond, kNoCondition);
1141 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1142 B27 | B26 | B25 | B11 | B9 | opcode |
1143 ((static_cast<int32_t>(dd) >> 4)*B22) |
1144 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1145 ((static_cast<int32_t>(sm) & 1)*B5) |
1146 (static_cast<int32_t>(sm) >> 1);
1147 Emit(encoding);
1148}
1149
1150
1151void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001152 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001153 CHECK_LE(shift_imm, 31u);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001154 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001155}
1156
1157
1158void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001159 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001160 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001161 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001162 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001163}
1164
1165
1166void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001167 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001168 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001169 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001170 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001171}
1172
1173
1174void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001175 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001176 CHECK(1u <= shift_imm && shift_imm <= 31u);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001177 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001178}
1179
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001180void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
1181 mov(rd, ShifterOperand(rm, ROR, 0), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001182}
1183
1184
Dave Allison45fdb932014-06-25 12:37:10 -07001185void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001186 Condition cond, SetCc set_cc) {
1187 mov(rd, ShifterOperand(rm, LSL, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001188}
1189
1190
1191void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001192 Condition cond, SetCc set_cc) {
1193 mov(rd, ShifterOperand(rm, LSR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001194}
1195
1196
1197void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001198 Condition cond, SetCc set_cc) {
1199 mov(rd, ShifterOperand(rm, ASR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001200}
1201
1202
1203void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001204 Condition cond, SetCc set_cc) {
1205 mov(rd, ShifterOperand(rm, ROR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001206}
1207
Dave Allison65fcc2c2014-04-28 13:45:27 -07001208void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1209 CHECK_NE(cond, kNoCondition);
1210 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1211 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1212 (static_cast<int32_t>(PC)*B12) |
1213 B11 | B9 | B4;
1214 Emit(encoding);
1215}
1216
1217
1218void Arm32Assembler::svc(uint32_t imm24) {
Andreas Gampeab1eb0d2015-02-13 19:23:55 -08001219 CHECK(IsUint<24>(imm24)) << imm24;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001220 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1221 Emit(encoding);
1222}
1223
1224
1225void Arm32Assembler::bkpt(uint16_t imm16) {
1226 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1227 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1228 Emit(encoding);
1229}
1230
1231
1232void Arm32Assembler::blx(Register rm, Condition cond) {
1233 CHECK_NE(rm, kNoRegister);
1234 CHECK_NE(cond, kNoCondition);
1235 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1236 B24 | B21 | (0xfff << 8) | B5 | B4 |
1237 (static_cast<int32_t>(rm) << kRmShift);
1238 Emit(encoding);
1239}
1240
1241
1242void Arm32Assembler::bx(Register rm, Condition cond) {
1243 CHECK_NE(rm, kNoRegister);
1244 CHECK_NE(cond, kNoCondition);
1245 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1246 B24 | B21 | (0xfff << 8) | B4 |
1247 (static_cast<int32_t>(rm) << kRmShift);
1248 Emit(encoding);
1249}
1250
1251
1252void Arm32Assembler::Push(Register rd, Condition cond) {
1253 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1254}
1255
1256
1257void Arm32Assembler::Pop(Register rd, Condition cond) {
1258 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1259}
1260
1261
1262void Arm32Assembler::PushList(RegList regs, Condition cond) {
1263 stm(DB_W, SP, regs, cond);
1264}
1265
1266
1267void Arm32Assembler::PopList(RegList regs, Condition cond) {
1268 ldm(IA_W, SP, regs, cond);
1269}
1270
1271
1272void Arm32Assembler::Mov(Register rd, Register rm, Condition cond) {
1273 if (rd != rm) {
1274 mov(rd, ShifterOperand(rm), cond);
1275 }
1276}
1277
1278
1279void Arm32Assembler::Bind(Label* label) {
1280 CHECK(!label->IsBound());
1281 int bound_pc = buffer_.Size();
1282 while (label->IsLinked()) {
1283 int32_t position = label->Position();
1284 int32_t next = buffer_.Load<int32_t>(position);
1285 int32_t encoded = Arm32Assembler::EncodeBranchOffset(bound_pc - position, next);
1286 buffer_.Store<int32_t>(position, encoded);
1287 label->position_ = Arm32Assembler::DecodeBranchOffset(next);
1288 }
1289 label->BindTo(bound_pc);
1290}
1291
1292
1293int32_t Arm32Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1294 // The offset is off by 8 due to the way the ARM CPUs read PC.
1295 offset -= 8;
1296 CHECK_ALIGNED(offset, 4);
1297 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
1298
1299 // Properly preserve only the bits supported in the instruction.
1300 offset >>= 2;
1301 offset &= kBranchOffsetMask;
1302 return (inst & ~kBranchOffsetMask) | offset;
1303}
1304
1305
1306int Arm32Assembler::DecodeBranchOffset(int32_t inst) {
1307 // Sign-extend, left-shift by 2, then add 8.
1308 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1309}
1310
1311
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001312uint32_t Arm32Assembler::GetAdjustedPosition(uint32_t old_position ATTRIBUTE_UNUSED) {
1313 LOG(FATAL) << "Unimplemented.";
1314 UNREACHABLE();
1315}
1316
1317Literal* Arm32Assembler::NewLiteral(size_t size ATTRIBUTE_UNUSED,
1318 const uint8_t* data ATTRIBUTE_UNUSED) {
1319 LOG(FATAL) << "Unimplemented.";
1320 UNREACHABLE();
1321}
1322
1323void Arm32Assembler::LoadLiteral(Register rt ATTRIBUTE_UNUSED,
1324 Literal* literal ATTRIBUTE_UNUSED) {
1325 LOG(FATAL) << "Unimplemented.";
1326 UNREACHABLE();
1327}
1328
1329void Arm32Assembler::LoadLiteral(Register rt ATTRIBUTE_UNUSED, Register rt2 ATTRIBUTE_UNUSED,
1330 Literal* literal ATTRIBUTE_UNUSED) {
1331 LOG(FATAL) << "Unimplemented.";
1332 UNREACHABLE();
1333}
1334
1335void Arm32Assembler::LoadLiteral(SRegister sd ATTRIBUTE_UNUSED,
1336 Literal* literal ATTRIBUTE_UNUSED) {
1337 LOG(FATAL) << "Unimplemented.";
1338 UNREACHABLE();
1339}
1340
1341void Arm32Assembler::LoadLiteral(DRegister dd ATTRIBUTE_UNUSED,
1342 Literal* literal ATTRIBUTE_UNUSED) {
1343 LOG(FATAL) << "Unimplemented.";
1344 UNREACHABLE();
1345}
1346
Dave Allison65fcc2c2014-04-28 13:45:27 -07001347
1348void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
Vladimir Marko449b1092015-09-08 12:16:45 +01001349 Condition cond, SetCc set_cc) {
1350 if (value == 0 && set_cc != kCcSet) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001351 if (rd != rn) {
Vladimir Marko449b1092015-09-08 12:16:45 +01001352 mov(rd, ShifterOperand(rn), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001353 }
1354 return;
1355 }
1356 // We prefer to select the shorter code sequence rather than selecting add for
1357 // positive values and sub for negatives ones, which would slightly improve
1358 // the readability of generated code for some constants.
1359 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001360 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Vladimir Marko449b1092015-09-08 12:16:45 +01001361 add(rd, rn, shifter_op, cond, set_cc);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001362 } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
Vladimir Marko449b1092015-09-08 12:16:45 +01001363 sub(rd, rn, shifter_op, cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001364 } else {
1365 CHECK(rn != IP);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001366 if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Vladimir Marko449b1092015-09-08 12:16:45 +01001367 mvn(IP, shifter_op, cond, kCcKeep);
1368 add(rd, rn, ShifterOperand(IP), cond, set_cc);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001369 } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
Vladimir Marko449b1092015-09-08 12:16:45 +01001370 mvn(IP, shifter_op, cond, kCcKeep);
1371 sub(rd, rn, ShifterOperand(IP), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001372 } else {
1373 movw(IP, Low16Bits(value), cond);
1374 uint16_t value_high = High16Bits(value);
1375 if (value_high != 0) {
1376 movt(IP, value_high, cond);
1377 }
Vladimir Marko449b1092015-09-08 12:16:45 +01001378 add(rd, rn, ShifterOperand(IP), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001379 }
1380 }
1381}
1382
1383
Dave Allison65fcc2c2014-04-28 13:45:27 -07001384void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1385 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001386 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001387 mov(rd, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001388 } else if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001389 mvn(rd, shifter_op, cond);
1390 } else {
1391 movw(rd, Low16Bits(value), cond);
1392 uint16_t value_high = High16Bits(value);
1393 if (value_high != 0) {
1394 movt(rd, value_high, cond);
1395 }
1396 }
1397}
1398
1399
1400// Implementation note: this method must emit at most one instruction when
1401// Address::CanHoldLoadOffsetArm.
1402void Arm32Assembler::LoadFromOffset(LoadOperandType type,
1403 Register reg,
1404 Register base,
1405 int32_t offset,
1406 Condition cond) {
1407 if (!Address::CanHoldLoadOffsetArm(type, offset)) {
1408 CHECK(base != IP);
1409 LoadImmediate(IP, offset, cond);
1410 add(IP, IP, ShifterOperand(base), cond);
1411 base = IP;
1412 offset = 0;
1413 }
1414 CHECK(Address::CanHoldLoadOffsetArm(type, offset));
1415 switch (type) {
1416 case kLoadSignedByte:
1417 ldrsb(reg, Address(base, offset), cond);
1418 break;
1419 case kLoadUnsignedByte:
1420 ldrb(reg, Address(base, offset), cond);
1421 break;
1422 case kLoadSignedHalfword:
1423 ldrsh(reg, Address(base, offset), cond);
1424 break;
1425 case kLoadUnsignedHalfword:
1426 ldrh(reg, Address(base, offset), cond);
1427 break;
1428 case kLoadWord:
1429 ldr(reg, Address(base, offset), cond);
1430 break;
1431 case kLoadWordPair:
1432 ldrd(reg, Address(base, offset), cond);
1433 break;
1434 default:
1435 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001436 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001437 }
1438}
1439
1440
1441// Implementation note: this method must emit at most one instruction when
1442// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1443void Arm32Assembler::LoadSFromOffset(SRegister reg,
1444 Register base,
1445 int32_t offset,
1446 Condition cond) {
1447 if (!Address::CanHoldLoadOffsetArm(kLoadSWord, offset)) {
1448 CHECK_NE(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(kLoadSWord, offset));
1455 vldrs(reg, Address(base, offset), cond);
1456}
1457
1458
1459// Implementation note: this method must emit at most one instruction when
1460// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1461void Arm32Assembler::LoadDFromOffset(DRegister reg,
1462 Register base,
1463 int32_t offset,
1464 Condition cond) {
1465 if (!Address::CanHoldLoadOffsetArm(kLoadDWord, offset)) {
1466 CHECK_NE(base, IP);
1467 LoadImmediate(IP, offset, cond);
1468 add(IP, IP, ShifterOperand(base), cond);
1469 base = IP;
1470 offset = 0;
1471 }
1472 CHECK(Address::CanHoldLoadOffsetArm(kLoadDWord, offset));
1473 vldrd(reg, Address(base, offset), cond);
1474}
1475
1476
1477// Implementation note: this method must emit at most one instruction when
1478// Address::CanHoldStoreOffsetArm.
1479void Arm32Assembler::StoreToOffset(StoreOperandType type,
1480 Register reg,
1481 Register base,
1482 int32_t offset,
1483 Condition cond) {
1484 if (!Address::CanHoldStoreOffsetArm(type, offset)) {
1485 CHECK(reg != IP);
1486 CHECK(base != IP);
1487 LoadImmediate(IP, offset, cond);
1488 add(IP, IP, ShifterOperand(base), cond);
1489 base = IP;
1490 offset = 0;
1491 }
1492 CHECK(Address::CanHoldStoreOffsetArm(type, offset));
1493 switch (type) {
1494 case kStoreByte:
1495 strb(reg, Address(base, offset), cond);
1496 break;
1497 case kStoreHalfword:
1498 strh(reg, Address(base, offset), cond);
1499 break;
1500 case kStoreWord:
1501 str(reg, Address(base, offset), cond);
1502 break;
1503 case kStoreWordPair:
1504 strd(reg, Address(base, offset), cond);
1505 break;
1506 default:
1507 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001508 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001509 }
1510}
1511
1512
1513// Implementation note: this method must emit at most one instruction when
1514// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreToOffset.
1515void Arm32Assembler::StoreSToOffset(SRegister reg,
1516 Register base,
1517 int32_t offset,
1518 Condition cond) {
1519 if (!Address::CanHoldStoreOffsetArm(kStoreSWord, offset)) {
1520 CHECK_NE(base, IP);
1521 LoadImmediate(IP, offset, cond);
1522 add(IP, IP, ShifterOperand(base), cond);
1523 base = IP;
1524 offset = 0;
1525 }
1526 CHECK(Address::CanHoldStoreOffsetArm(kStoreSWord, offset));
1527 vstrs(reg, Address(base, offset), cond);
1528}
1529
1530
1531// Implementation note: this method must emit at most one instruction when
1532// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreSToOffset.
1533void Arm32Assembler::StoreDToOffset(DRegister reg,
1534 Register base,
1535 int32_t offset,
1536 Condition cond) {
1537 if (!Address::CanHoldStoreOffsetArm(kStoreDWord, offset)) {
1538 CHECK_NE(base, IP);
1539 LoadImmediate(IP, offset, cond);
1540 add(IP, IP, ShifterOperand(base), cond);
1541 base = IP;
1542 offset = 0;
1543 }
1544 CHECK(Address::CanHoldStoreOffsetArm(kStoreDWord, offset));
1545 vstrd(reg, Address(base, offset), cond);
1546}
1547
1548
1549void Arm32Assembler::MemoryBarrier(ManagedRegister mscratch) {
1550 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001551 dmb(SY);
1552}
1553
1554
1555void Arm32Assembler::dmb(DmbOptions flavor) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001556 int32_t encoding = 0xf57ff05f; // dmb
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001557 Emit(encoding | flavor);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001558}
1559
1560
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001561void Arm32Assembler::cbz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001562 LOG(FATAL) << "cbz is not supported on ARM32";
1563}
1564
1565
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001566void Arm32Assembler::cbnz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001567 LOG(FATAL) << "cbnz is not supported on ARM32";
1568}
1569
1570
1571void Arm32Assembler::CompareAndBranchIfZero(Register r, Label* label) {
1572 cmp(r, ShifterOperand(0));
1573 b(label, EQ);
1574}
1575
1576
1577void Arm32Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
1578 cmp(r, ShifterOperand(0));
1579 b(label, NE);
1580}
1581
1582
1583} // namespace arm
1584} // namespace art