blob: 64fa9a4c0dde9c839580b779354d2248d3495109 [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 Marko73cf0fb2015-07-30 15:07:22 +0100133void Arm32Assembler::mov(Register rd, const ShifterOperand& so,
134 Condition cond, SetCc set_cc) {
135 EmitType01(cond, so.type(), MOV, set_cc, R0, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700136}
137
138
139void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100140 Condition cond, SetCc set_cc) {
141 EmitType01(cond, so.type(), BIC, set_cc, rn, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700142}
143
144
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100145void Arm32Assembler::mvn(Register rd, const ShifterOperand& so,
146 Condition cond, SetCc set_cc) {
147 EmitType01(cond, so.type(), MVN, set_cc, R0, rd, so);
Dave Allison65fcc2c2014-04-28 13:45:27 -0700148}
149
150
151void Arm32Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
152 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
153 EmitMulOp(cond, 0, R0, rd, rn, rm);
154}
155
156
157void Arm32Assembler::mla(Register rd, Register rn, Register rm, Register ra,
158 Condition cond) {
159 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
160 EmitMulOp(cond, B21, ra, rd, rn, rm);
161}
162
163
164void Arm32Assembler::mls(Register rd, Register rn, Register rm, Register ra,
165 Condition cond) {
166 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
167 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
168}
169
170
Zheng Xuc6667102015-05-15 16:08:45 +0800171void Arm32Assembler::smull(Register rd_lo, Register rd_hi, Register rn,
172 Register rm, Condition cond) {
173 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
174 EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
175}
176
177
Dave Allison65fcc2c2014-04-28 13:45:27 -0700178void Arm32Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
179 Register rm, Condition cond) {
180 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
181 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
182}
183
184
185void Arm32Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
186 CHECK_NE(rd, kNoRegister);
187 CHECK_NE(rn, kNoRegister);
188 CHECK_NE(rm, kNoRegister);
189 CHECK_NE(cond, kNoCondition);
190 int32_t encoding = B26 | B25 | B24 | B20 |
191 B15 | B14 | B13 | B12 |
192 (static_cast<int32_t>(cond) << kConditionShift) |
193 (static_cast<int32_t>(rn) << 0) |
194 (static_cast<int32_t>(rd) << 16) |
195 (static_cast<int32_t>(rm) << 8) |
196 B4;
197 Emit(encoding);
198}
199
200
201void Arm32Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
202 CHECK_NE(rd, kNoRegister);
203 CHECK_NE(rn, kNoRegister);
204 CHECK_NE(rm, kNoRegister);
205 CHECK_NE(cond, kNoCondition);
206 int32_t encoding = B26 | B25 | B24 | B21 | B20 |
207 B15 | B14 | B13 | B12 |
208 (static_cast<int32_t>(cond) << kConditionShift) |
209 (static_cast<int32_t>(rn) << 0) |
210 (static_cast<int32_t>(rd) << 16) |
211 (static_cast<int32_t>(rm) << 8) |
212 B4;
213 Emit(encoding);
214}
215
216
Roland Levillain51d3fc42014-11-13 14:11:42 +0000217void Arm32Assembler::sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
218 CHECK_NE(rd, kNoRegister);
219 CHECK_NE(rn, kNoRegister);
220 CHECK_NE(cond, kNoCondition);
221 CHECK_LE(lsb, 31U);
222 CHECK(1U <= width && width <= 32U) << width;
223 uint32_t widthminus1 = width - 1;
224
225 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
226 B26 | B25 | B24 | B23 | B21 |
227 (widthminus1 << 16) |
228 (static_cast<uint32_t>(rd) << 12) |
229 (lsb << 7) |
230 B6 | B4 |
231 static_cast<uint32_t>(rn);
232 Emit(encoding);
233}
234
235
Roland Levillain981e4542014-11-14 11:47:14 +0000236void Arm32Assembler::ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond) {
237 CHECK_NE(rd, kNoRegister);
238 CHECK_NE(rn, kNoRegister);
239 CHECK_NE(cond, kNoCondition);
240 CHECK_LE(lsb, 31U);
241 CHECK(1U <= width && width <= 32U) << width;
242 uint32_t widthminus1 = width - 1;
243
244 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
245 B26 | B25 | B24 | B23 | B22 | B21 |
246 (widthminus1 << 16) |
247 (static_cast<uint32_t>(rd) << 12) |
248 (lsb << 7) |
249 B6 | B4 |
250 static_cast<uint32_t>(rn);
251 Emit(encoding);
252}
253
254
Dave Allison65fcc2c2014-04-28 13:45:27 -0700255void Arm32Assembler::ldr(Register rd, const Address& ad, Condition cond) {
256 EmitMemOp(cond, true, false, rd, ad);
257}
258
259
260void Arm32Assembler::str(Register rd, const Address& ad, Condition cond) {
261 EmitMemOp(cond, false, false, rd, ad);
262}
263
264
265void Arm32Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
266 EmitMemOp(cond, true, true, rd, ad);
267}
268
269
270void Arm32Assembler::strb(Register rd, const Address& ad, Condition cond) {
271 EmitMemOp(cond, false, true, rd, ad);
272}
273
274
275void Arm32Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
276 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
277}
278
279
280void Arm32Assembler::strh(Register rd, const Address& ad, Condition cond) {
281 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad);
282}
283
284
285void Arm32Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
286 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
287}
288
289
290void Arm32Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
291 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
292}
293
294
295void Arm32Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
296 CHECK_EQ(rd % 2, 0);
297 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
298}
299
300
301void Arm32Assembler::strd(Register rd, const Address& ad, Condition cond) {
302 CHECK_EQ(rd % 2, 0);
303 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
304}
305
306
307void Arm32Assembler::ldm(BlockAddressMode am,
308 Register base,
309 RegList regs,
310 Condition cond) {
311 EmitMultiMemOp(cond, am, true, base, regs);
312}
313
314
315void Arm32Assembler::stm(BlockAddressMode am,
316 Register base,
317 RegList regs,
318 Condition cond) {
319 EmitMultiMemOp(cond, am, false, base, regs);
320}
321
322
323void Arm32Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
324 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
325}
326
327
328void Arm32Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
329 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
330}
331
332
333bool Arm32Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
334 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
335 if (((imm32 & ((1 << 19) - 1)) == 0) &&
336 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
337 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
338 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
339 ((imm32 >> 19) & ((1 << 6) -1));
340 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
341 sd, S0, S0);
342 return true;
343 }
344 return false;
345}
346
347
348bool Arm32Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
349 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
350 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
351 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
352 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
353 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
354 ((imm64 >> 48) & ((1 << 6) -1));
355 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
356 dd, D0, D0);
357 return true;
358 }
359 return false;
360}
361
362
363void Arm32Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
364 Condition cond) {
365 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
366}
367
368
369void Arm32Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
370 Condition cond) {
371 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
372}
373
374
375void Arm32Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
376 Condition cond) {
377 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
378}
379
380
381void Arm32Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
382 Condition cond) {
383 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
384}
385
386
387void Arm32Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
388 Condition cond) {
389 EmitVFPsss(cond, B21, sd, sn, sm);
390}
391
392
393void Arm32Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
394 Condition cond) {
395 EmitVFPddd(cond, B21, dd, dn, dm);
396}
397
398
399void Arm32Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
400 Condition cond) {
401 EmitVFPsss(cond, 0, sd, sn, sm);
402}
403
404
405void Arm32Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
406 Condition cond) {
407 EmitVFPddd(cond, 0, dd, dn, dm);
408}
409
410
411void Arm32Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
412 Condition cond) {
413 EmitVFPsss(cond, B6, sd, sn, sm);
414}
415
416
417void Arm32Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
418 Condition cond) {
419 EmitVFPddd(cond, B6, dd, dn, dm);
420}
421
422
423void Arm32Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
424 Condition cond) {
425 EmitVFPsss(cond, B23, sd, sn, sm);
426}
427
428
429void Arm32Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
430 Condition cond) {
431 EmitVFPddd(cond, B23, dd, dn, dm);
432}
433
434
435void Arm32Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
436 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
437}
438
439
440void Arm32Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
441 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
442}
443
444
445void Arm32Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
446 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
447}
448
449
450void Arm32Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
451 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
452}
453
454
455void Arm32Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
456 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
457}
458
459void Arm32Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
460 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
461}
462
463
464void Arm32Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
465 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
466}
467
468
469void Arm32Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
470 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
471}
472
473
474void Arm32Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
475 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
476}
477
478
479void Arm32Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
480 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
481}
482
483
484void Arm32Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
485 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
486}
487
488
489void Arm32Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
490 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
491}
492
493
494void Arm32Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
495 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
496}
497
498
499void Arm32Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
500 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
501}
502
503
504void Arm32Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
505 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
506}
507
508
509void Arm32Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
510 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
511}
512
513
514void Arm32Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
515 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
516}
517
518
519void Arm32Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
520 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
521}
522
523
524void Arm32Assembler::vcmpsz(SRegister sd, Condition cond) {
525 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
526}
527
528
529void Arm32Assembler::vcmpdz(DRegister dd, Condition cond) {
530 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
531}
532
533void Arm32Assembler::b(Label* label, Condition cond) {
534 EmitBranch(cond, label, false);
535}
536
537
538void Arm32Assembler::bl(Label* label, Condition cond) {
539 EmitBranch(cond, label, true);
540}
541
542
543void Arm32Assembler::MarkExceptionHandler(Label* label) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100544 EmitType01(AL, 1, TST, kCcSet, PC, R0, ShifterOperand(0));
Dave Allison65fcc2c2014-04-28 13:45:27 -0700545 Label l;
546 b(&l);
547 EmitBranch(AL, label, false);
548 Bind(&l);
549}
550
551
552void Arm32Assembler::Emit(int32_t value) {
553 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
554 buffer_.Emit<int32_t>(value);
555}
556
557
558void Arm32Assembler::EmitType01(Condition cond,
559 int type,
560 Opcode opcode,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100561 SetCc set_cc,
Dave Allison65fcc2c2014-04-28 13:45:27 -0700562 Register rn,
563 Register rd,
564 const ShifterOperand& so) {
565 CHECK_NE(rd, kNoRegister);
566 CHECK_NE(cond, kNoCondition);
567 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
568 type << kTypeShift |
569 static_cast<int32_t>(opcode) << kOpcodeShift |
Vladimir Marko73cf0fb2015-07-30 15:07:22 +0100570 (set_cc == kCcSet ? 1 : 0) << kSShift |
Dave Allison65fcc2c2014-04-28 13:45:27 -0700571 static_cast<int32_t>(rn) << kRnShift |
572 static_cast<int32_t>(rd) << kRdShift |
573 so.encodingArm();
574 Emit(encoding);
575}
576
577
578void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
579 CHECK_NE(cond, kNoCondition);
580 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
581 5 << kTypeShift |
582 (link ? 1 : 0) << kLinkShift;
583 Emit(Arm32Assembler::EncodeBranchOffset(offset, encoding));
584}
585
586
587void Arm32Assembler::EmitMemOp(Condition cond,
Dave Allison45fdb932014-06-25 12:37:10 -0700588 bool load,
589 bool byte,
590 Register rd,
591 const Address& ad) {
Dave Allison65fcc2c2014-04-28 13:45:27 -0700592 CHECK_NE(rd, kNoRegister);
593 CHECK_NE(cond, kNoCondition);
594 const Address& addr = static_cast<const Address&>(ad);
595
Dave Allison45fdb932014-06-25 12:37:10 -0700596 int32_t encoding = 0;
597 if (!ad.IsImmediate() && ad.GetRegisterOffset() == PC) {
598 // PC relative LDR(literal)
599 int32_t offset = ad.GetOffset();
600 int32_t u = B23;
601 if (offset < 0) {
602 offset = -offset;
603 u = 0;
604 }
605 CHECK_LT(offset, (1 << 12));
606 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
607 B26 | B24 | u | B20 |
608 (load ? L : 0) |
609 (byte ? B : 0) |
610 (static_cast<int32_t>(rd) << kRdShift) |
611 0xf << 16 |
612 (offset & 0xfff);
613
614 } else {
615 encoding = (static_cast<int32_t>(cond) << kConditionShift) |
616 B26 |
617 (load ? L : 0) |
618 (byte ? B : 0) |
619 (static_cast<int32_t>(rd) << kRdShift) |
620 addr.encodingArm();
621 }
Dave Allison65fcc2c2014-04-28 13:45:27 -0700622 Emit(encoding);
623}
624
625
626void Arm32Assembler::EmitMemOpAddressMode3(Condition cond,
627 int32_t mode,
628 Register rd,
629 const Address& ad) {
630 CHECK_NE(rd, kNoRegister);
631 CHECK_NE(cond, kNoCondition);
632 const Address& addr = static_cast<const Address&>(ad);
633 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
634 B22 |
635 mode |
636 (static_cast<int32_t>(rd) << kRdShift) |
637 addr.encoding3();
638 Emit(encoding);
639}
640
641
642void Arm32Assembler::EmitMultiMemOp(Condition cond,
643 BlockAddressMode am,
644 bool load,
645 Register base,
646 RegList regs) {
647 CHECK_NE(base, kNoRegister);
648 CHECK_NE(cond, kNoCondition);
649 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
650 B27 |
651 am |
652 (load ? L : 0) |
653 (static_cast<int32_t>(base) << kRnShift) |
654 regs;
655 Emit(encoding);
656}
657
658
659void Arm32Assembler::EmitShiftImmediate(Condition cond,
660 Shift opcode,
661 Register rd,
662 Register rm,
663 const ShifterOperand& so) {
664 CHECK_NE(cond, kNoCondition);
665 CHECK(so.IsImmediate());
666 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
667 static_cast<int32_t>(MOV) << kOpcodeShift |
668 static_cast<int32_t>(rd) << kRdShift |
669 so.encodingArm() << kShiftImmShift |
670 static_cast<int32_t>(opcode) << kShiftShift |
671 static_cast<int32_t>(rm);
672 Emit(encoding);
673}
674
675
676void Arm32Assembler::EmitShiftRegister(Condition cond,
677 Shift opcode,
678 Register rd,
679 Register rm,
680 const ShifterOperand& so) {
681 CHECK_NE(cond, kNoCondition);
682 CHECK(so.IsRegister());
683 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
684 static_cast<int32_t>(MOV) << kOpcodeShift |
685 static_cast<int32_t>(rd) << kRdShift |
686 so.encodingArm() << kShiftRegisterShift |
687 static_cast<int32_t>(opcode) << kShiftShift |
688 B4 |
689 static_cast<int32_t>(rm);
690 Emit(encoding);
691}
692
693
694void Arm32Assembler::EmitBranch(Condition cond, Label* label, bool link) {
695 if (label->IsBound()) {
696 EmitType5(cond, label->Position() - buffer_.Size(), link);
697 } else {
698 int position = buffer_.Size();
699 // Use the offset field of the branch instruction for linking the sites.
700 EmitType5(cond, label->position_, link);
701 label->LinkTo(position);
702 }
703}
704
705
706void Arm32Assembler::clz(Register rd, Register rm, Condition cond) {
707 CHECK_NE(rd, kNoRegister);
708 CHECK_NE(rm, kNoRegister);
709 CHECK_NE(cond, kNoCondition);
710 CHECK_NE(rd, PC);
711 CHECK_NE(rm, PC);
712 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
713 B24 | B22 | B21 | (0xf << 16) |
714 (static_cast<int32_t>(rd) << kRdShift) |
715 (0xf << 8) | B4 | static_cast<int32_t>(rm);
716 Emit(encoding);
717}
718
719
720void Arm32Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
721 CHECK_NE(cond, kNoCondition);
722 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
723 B25 | B24 | ((imm16 >> 12) << 16) |
724 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
725 Emit(encoding);
726}
727
728
729void Arm32Assembler::movt(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 | B22 | ((imm16 >> 12) << 16) |
733 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
734 Emit(encoding);
735}
736
737
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100738void Arm32Assembler::rbit(Register rd, Register rm, Condition cond) {
739 CHECK_NE(rd, kNoRegister);
740 CHECK_NE(rm, kNoRegister);
741 CHECK_NE(cond, kNoCondition);
742 CHECK_NE(rd, PC);
743 CHECK_NE(rm, PC);
744 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
745 B26 | B25 | B23 | B22 | B21 | B20 | (0xf << 16) |
746 (static_cast<int32_t>(rd) << kRdShift) |
747 (0xf << 8) | B5 | B4 | static_cast<int32_t>(rm);
748 Emit(encoding);
749}
750
751
Dave Allison65fcc2c2014-04-28 13:45:27 -0700752void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
753 Register rd, Register rn,
754 Register rm, Register rs) {
755 CHECK_NE(rd, kNoRegister);
756 CHECK_NE(rn, kNoRegister);
757 CHECK_NE(rm, kNoRegister);
758 CHECK_NE(rs, kNoRegister);
759 CHECK_NE(cond, kNoCondition);
760 int32_t encoding = opcode |
761 (static_cast<int32_t>(cond) << kConditionShift) |
762 (static_cast<int32_t>(rn) << kRnShift) |
763 (static_cast<int32_t>(rd) << kRdShift) |
764 (static_cast<int32_t>(rs) << kRsShift) |
765 B7 | B4 |
766 (static_cast<int32_t>(rm) << kRmShift);
767 Emit(encoding);
768}
769
Calin Juravle52c48962014-12-16 17:02:57 +0000770
Dave Allison65fcc2c2014-04-28 13:45:27 -0700771void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) {
772 CHECK_NE(rn, kNoRegister);
773 CHECK_NE(rt, kNoRegister);
774 CHECK_NE(cond, kNoCondition);
775 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
776 B24 |
777 B23 |
778 L |
779 (static_cast<int32_t>(rn) << kLdExRnShift) |
780 (static_cast<int32_t>(rt) << kLdExRtShift) |
781 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
782 Emit(encoding);
783}
784
785
Calin Juravle52c48962014-12-16 17:02:57 +0000786void Arm32Assembler::ldrexd(Register rt, Register rt2, Register rn, Condition cond) {
787 CHECK_NE(rn, kNoRegister);
788 CHECK_NE(rt, kNoRegister);
789 CHECK_NE(rt2, kNoRegister);
790 CHECK_NE(rt, R14);
791 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
792 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
793 CHECK_NE(cond, kNoCondition);
794
795 int32_t encoding =
796 (static_cast<uint32_t>(cond) << kConditionShift) |
797 B24 | B23 | B21 | B20 |
798 static_cast<uint32_t>(rn) << 16 |
799 static_cast<uint32_t>(rt) << 12 |
800 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0;
801 Emit(encoding);
802}
803
804
Dave Allison65fcc2c2014-04-28 13:45:27 -0700805void Arm32Assembler::strex(Register rd,
806 Register rt,
807 Register rn,
808 Condition cond) {
809 CHECK_NE(rn, kNoRegister);
810 CHECK_NE(rd, kNoRegister);
811 CHECK_NE(rt, kNoRegister);
812 CHECK_NE(cond, kNoCondition);
813 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
814 B24 |
815 B23 |
816 (static_cast<int32_t>(rn) << kStrExRnShift) |
817 (static_cast<int32_t>(rd) << kStrExRdShift) |
818 B11 | B10 | B9 | B8 | B7 | B4 |
819 (static_cast<int32_t>(rt) << kStrExRtShift);
820 Emit(encoding);
821}
822
Calin Juravle52c48962014-12-16 17:02:57 +0000823void Arm32Assembler::strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond) {
824 CHECK_NE(rd, kNoRegister);
825 CHECK_NE(rn, kNoRegister);
826 CHECK_NE(rt, kNoRegister);
827 CHECK_NE(rt2, kNoRegister);
828 CHECK_NE(rt, R14);
829 CHECK_NE(rd, rt);
830 CHECK_NE(rd, rt2);
831 CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2);
832 CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2));
833 CHECK_NE(cond, kNoCondition);
834
835 int32_t encoding =
836 (static_cast<uint32_t>(cond) << kConditionShift) |
837 B24 | B23 | B21 |
838 static_cast<uint32_t>(rn) << 16 |
839 static_cast<uint32_t>(rd) << 12 |
840 B11 | B10 | B9 | B8 | B7 | B4 |
841 static_cast<uint32_t>(rt);
842 Emit(encoding);
843}
844
Dave Allison65fcc2c2014-04-28 13:45:27 -0700845
846void Arm32Assembler::clrex(Condition cond) {
847 CHECK_EQ(cond, AL); // This cannot be conditional on ARM.
848 int32_t encoding = (kSpecialCondition << kConditionShift) |
849 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf;
850 Emit(encoding);
851}
852
853
854void Arm32Assembler::nop(Condition cond) {
855 CHECK_NE(cond, kNoCondition);
856 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
857 B25 | B24 | B21 | (0xf << 12);
858 Emit(encoding);
859}
860
861
862void Arm32Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
863 CHECK_NE(sn, kNoSRegister);
864 CHECK_NE(rt, kNoRegister);
865 CHECK_NE(rt, SP);
866 CHECK_NE(rt, PC);
867 CHECK_NE(cond, kNoCondition);
868 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
869 B27 | B26 | B25 |
870 ((static_cast<int32_t>(sn) >> 1)*B16) |
871 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
872 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
873 Emit(encoding);
874}
875
876
877void Arm32Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
878 CHECK_NE(sn, kNoSRegister);
879 CHECK_NE(rt, kNoRegister);
880 CHECK_NE(rt, SP);
881 CHECK_NE(rt, PC);
882 CHECK_NE(cond, kNoCondition);
883 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
884 B27 | B26 | B25 | B20 |
885 ((static_cast<int32_t>(sn) >> 1)*B16) |
886 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
887 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
888 Emit(encoding);
889}
890
891
892void Arm32Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
893 Condition cond) {
894 CHECK_NE(sm, kNoSRegister);
895 CHECK_NE(sm, S31);
896 CHECK_NE(rt, kNoRegister);
897 CHECK_NE(rt, SP);
898 CHECK_NE(rt, PC);
899 CHECK_NE(rt2, kNoRegister);
900 CHECK_NE(rt2, SP);
901 CHECK_NE(rt2, PC);
902 CHECK_NE(cond, kNoCondition);
903 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
904 B27 | B26 | B22 |
905 (static_cast<int32_t>(rt2)*B16) |
906 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
907 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
908 (static_cast<int32_t>(sm) >> 1);
909 Emit(encoding);
910}
911
912
913void Arm32Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
914 Condition cond) {
915 CHECK_NE(sm, kNoSRegister);
916 CHECK_NE(sm, S31);
917 CHECK_NE(rt, kNoRegister);
918 CHECK_NE(rt, SP);
919 CHECK_NE(rt, PC);
920 CHECK_NE(rt2, kNoRegister);
921 CHECK_NE(rt2, SP);
922 CHECK_NE(rt2, PC);
923 CHECK_NE(rt, rt2);
924 CHECK_NE(cond, kNoCondition);
925 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
926 B27 | B26 | B22 | B20 |
927 (static_cast<int32_t>(rt2)*B16) |
928 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
929 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
930 (static_cast<int32_t>(sm) >> 1);
931 Emit(encoding);
932}
933
934
935void Arm32Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
936 Condition cond) {
937 CHECK_NE(dm, kNoDRegister);
938 CHECK_NE(rt, kNoRegister);
939 CHECK_NE(rt, SP);
940 CHECK_NE(rt, PC);
941 CHECK_NE(rt2, kNoRegister);
942 CHECK_NE(rt2, SP);
943 CHECK_NE(rt2, PC);
944 CHECK_NE(cond, kNoCondition);
945 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
946 B27 | B26 | B22 |
947 (static_cast<int32_t>(rt2)*B16) |
948 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
949 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
950 (static_cast<int32_t>(dm) & 0xf);
951 Emit(encoding);
952}
953
954
955void Arm32Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
956 Condition cond) {
957 CHECK_NE(dm, kNoDRegister);
958 CHECK_NE(rt, kNoRegister);
959 CHECK_NE(rt, SP);
960 CHECK_NE(rt, PC);
961 CHECK_NE(rt2, kNoRegister);
962 CHECK_NE(rt2, SP);
963 CHECK_NE(rt2, PC);
964 CHECK_NE(rt, rt2);
965 CHECK_NE(cond, kNoCondition);
966 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
967 B27 | B26 | B22 | B20 |
968 (static_cast<int32_t>(rt2)*B16) |
969 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
970 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
971 (static_cast<int32_t>(dm) & 0xf);
972 Emit(encoding);
973}
974
975
976void Arm32Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
977 const Address& addr = static_cast<const Address&>(ad);
978 CHECK_NE(sd, kNoSRegister);
979 CHECK_NE(cond, kNoCondition);
980 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
981 B27 | B26 | B24 | B20 |
982 ((static_cast<int32_t>(sd) & 1)*B22) |
983 ((static_cast<int32_t>(sd) >> 1)*B12) |
984 B11 | B9 | addr.vencoding();
985 Emit(encoding);
986}
987
988
989void Arm32Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
990 const Address& addr = static_cast<const Address&>(ad);
991 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
992 CHECK_NE(sd, kNoSRegister);
993 CHECK_NE(cond, kNoCondition);
994 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
995 B27 | B26 | B24 |
996 ((static_cast<int32_t>(sd) & 1)*B22) |
997 ((static_cast<int32_t>(sd) >> 1)*B12) |
998 B11 | B9 | addr.vencoding();
999 Emit(encoding);
1000}
1001
1002
1003void Arm32Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
1004 const Address& addr = static_cast<const Address&>(ad);
1005 CHECK_NE(dd, kNoDRegister);
1006 CHECK_NE(cond, kNoCondition);
1007 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1008 B27 | B26 | B24 | B20 |
1009 ((static_cast<int32_t>(dd) >> 4)*B22) |
1010 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1011 B11 | B9 | B8 | addr.vencoding();
1012 Emit(encoding);
1013}
1014
1015
1016void Arm32Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
1017 const Address& addr = static_cast<const Address&>(ad);
1018 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1019 CHECK_NE(dd, kNoDRegister);
1020 CHECK_NE(cond, kNoCondition);
1021 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1022 B27 | B26 | B24 |
1023 ((static_cast<int32_t>(dd) >> 4)*B22) |
1024 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1025 B11 | B9 | B8 | addr.vencoding();
1026 Emit(encoding);
1027}
1028
1029
1030void Arm32Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
1031 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
1032}
1033
1034
1035void Arm32Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
1036 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
1037}
1038
1039
1040void Arm32Assembler::vpops(SRegister reg, int nregs, Condition cond) {
1041 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
1042}
1043
1044
1045void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
1046 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
1047}
1048
1049
1050void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
1051 CHECK_NE(cond, kNoCondition);
1052 CHECK_GT(nregs, 0);
1053 uint32_t D;
1054 uint32_t Vd;
1055 if (dbl) {
1056 // Encoded as D:Vd.
1057 D = (reg >> 4) & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001058 Vd = reg & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001059 } else {
1060 // Encoded as Vd:D.
1061 D = reg & 1;
Andreas Gampec8ccf682014-09-29 20:07:43 -07001062 Vd = (reg >> 1) & 15U /* 0b1111 */;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001063 }
1064 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
1065 B11 | B9 |
1066 (dbl ? B8 : 0) |
1067 (push ? B24 : (B23 | B20)) |
1068 static_cast<int32_t>(cond) << kConditionShift |
1069 nregs << (dbl ? 1 : 0) |
1070 D << 22 |
1071 Vd << 12;
1072 Emit(encoding);
1073}
1074
1075
1076void Arm32Assembler::EmitVFPsss(Condition cond, int32_t opcode,
1077 SRegister sd, SRegister sn, SRegister sm) {
1078 CHECK_NE(sd, kNoSRegister);
1079 CHECK_NE(sn, kNoSRegister);
1080 CHECK_NE(sm, kNoSRegister);
1081 CHECK_NE(cond, kNoCondition);
1082 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1083 B27 | B26 | B25 | B11 | B9 | opcode |
1084 ((static_cast<int32_t>(sd) & 1)*B22) |
1085 ((static_cast<int32_t>(sn) >> 1)*B16) |
1086 ((static_cast<int32_t>(sd) >> 1)*B12) |
1087 ((static_cast<int32_t>(sn) & 1)*B7) |
1088 ((static_cast<int32_t>(sm) & 1)*B5) |
1089 (static_cast<int32_t>(sm) >> 1);
1090 Emit(encoding);
1091}
1092
1093
1094void Arm32Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1095 DRegister dd, DRegister dn, DRegister dm) {
1096 CHECK_NE(dd, kNoDRegister);
1097 CHECK_NE(dn, kNoDRegister);
1098 CHECK_NE(dm, kNoDRegister);
1099 CHECK_NE(cond, kNoCondition);
1100 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1101 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1102 ((static_cast<int32_t>(dd) >> 4)*B22) |
1103 ((static_cast<int32_t>(dn) & 0xf)*B16) |
1104 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1105 ((static_cast<int32_t>(dn) >> 4)*B7) |
1106 ((static_cast<int32_t>(dm) >> 4)*B5) |
1107 (static_cast<int32_t>(dm) & 0xf);
1108 Emit(encoding);
1109}
1110
1111
1112void Arm32Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1113 SRegister sd, DRegister dm) {
1114 CHECK_NE(sd, kNoSRegister);
1115 CHECK_NE(dm, kNoDRegister);
1116 CHECK_NE(cond, kNoCondition);
1117 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1118 B27 | B26 | B25 | B11 | B9 | opcode |
1119 ((static_cast<int32_t>(sd) & 1)*B22) |
1120 ((static_cast<int32_t>(sd) >> 1)*B12) |
1121 ((static_cast<int32_t>(dm) >> 4)*B5) |
1122 (static_cast<int32_t>(dm) & 0xf);
1123 Emit(encoding);
1124}
1125
1126
1127void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
1128 DRegister dd, SRegister sm) {
1129 CHECK_NE(dd, kNoDRegister);
1130 CHECK_NE(sm, kNoSRegister);
1131 CHECK_NE(cond, kNoCondition);
1132 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1133 B27 | B26 | B25 | B11 | B9 | opcode |
1134 ((static_cast<int32_t>(dd) >> 4)*B22) |
1135 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1136 ((static_cast<int32_t>(sm) & 1)*B5) |
1137 (static_cast<int32_t>(sm) >> 1);
1138 Emit(encoding);
1139}
1140
1141
1142void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001143 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001144 CHECK_LE(shift_imm, 31u);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001145 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001146}
1147
1148
1149void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001150 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001151 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001152 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001153 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001154}
1155
1156
1157void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001158 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001159 CHECK(1u <= shift_imm && shift_imm <= 32u);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001160 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001161 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001162}
1163
1164
1165void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001166 Condition cond, SetCc set_cc) {
Calin Juravle9aec02f2014-11-18 23:06:35 +00001167 CHECK(1u <= shift_imm && shift_imm <= 31u);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001168 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001169}
1170
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001171void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
1172 mov(rd, ShifterOperand(rm, ROR, 0), cond, set_cc);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001173}
1174
1175
Dave Allison45fdb932014-06-25 12:37:10 -07001176void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001177 Condition cond, SetCc set_cc) {
1178 mov(rd, ShifterOperand(rm, LSL, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001179}
1180
1181
1182void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001183 Condition cond, SetCc set_cc) {
1184 mov(rd, ShifterOperand(rm, LSR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001185}
1186
1187
1188void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001189 Condition cond, SetCc set_cc) {
1190 mov(rd, ShifterOperand(rm, ASR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001191}
1192
1193
1194void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001195 Condition cond, SetCc set_cc) {
1196 mov(rd, ShifterOperand(rm, ROR, rn), cond, set_cc);
Dave Allison45fdb932014-06-25 12:37:10 -07001197}
1198
Dave Allison65fcc2c2014-04-28 13:45:27 -07001199void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
1200 CHECK_NE(cond, kNoCondition);
1201 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1202 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
1203 (static_cast<int32_t>(PC)*B12) |
1204 B11 | B9 | B4;
1205 Emit(encoding);
1206}
1207
1208
1209void Arm32Assembler::svc(uint32_t imm24) {
Andreas Gampeab1eb0d2015-02-13 19:23:55 -08001210 CHECK(IsUint<24>(imm24)) << imm24;
Dave Allison65fcc2c2014-04-28 13:45:27 -07001211 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
1212 Emit(encoding);
1213}
1214
1215
1216void Arm32Assembler::bkpt(uint16_t imm16) {
1217 int32_t encoding = (AL << kConditionShift) | B24 | B21 |
1218 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1219 Emit(encoding);
1220}
1221
1222
1223void Arm32Assembler::blx(Register rm, Condition cond) {
1224 CHECK_NE(rm, kNoRegister);
1225 CHECK_NE(cond, kNoCondition);
1226 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1227 B24 | B21 | (0xfff << 8) | B5 | B4 |
1228 (static_cast<int32_t>(rm) << kRmShift);
1229 Emit(encoding);
1230}
1231
1232
1233void Arm32Assembler::bx(Register rm, Condition cond) {
1234 CHECK_NE(rm, kNoRegister);
1235 CHECK_NE(cond, kNoCondition);
1236 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1237 B24 | B21 | (0xfff << 8) | B4 |
1238 (static_cast<int32_t>(rm) << kRmShift);
1239 Emit(encoding);
1240}
1241
1242
1243void Arm32Assembler::Push(Register rd, Condition cond) {
1244 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1245}
1246
1247
1248void Arm32Assembler::Pop(Register rd, Condition cond) {
1249 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1250}
1251
1252
1253void Arm32Assembler::PushList(RegList regs, Condition cond) {
1254 stm(DB_W, SP, regs, cond);
1255}
1256
1257
1258void Arm32Assembler::PopList(RegList regs, Condition cond) {
1259 ldm(IA_W, SP, regs, cond);
1260}
1261
1262
1263void Arm32Assembler::Mov(Register rd, Register rm, Condition cond) {
1264 if (rd != rm) {
1265 mov(rd, ShifterOperand(rm), cond);
1266 }
1267}
1268
1269
1270void Arm32Assembler::Bind(Label* label) {
1271 CHECK(!label->IsBound());
1272 int bound_pc = buffer_.Size();
1273 while (label->IsLinked()) {
1274 int32_t position = label->Position();
1275 int32_t next = buffer_.Load<int32_t>(position);
1276 int32_t encoded = Arm32Assembler::EncodeBranchOffset(bound_pc - position, next);
1277 buffer_.Store<int32_t>(position, encoded);
1278 label->position_ = Arm32Assembler::DecodeBranchOffset(next);
1279 }
1280 label->BindTo(bound_pc);
1281}
1282
1283
1284int32_t Arm32Assembler::EncodeBranchOffset(int offset, int32_t inst) {
1285 // The offset is off by 8 due to the way the ARM CPUs read PC.
1286 offset -= 8;
1287 CHECK_ALIGNED(offset, 4);
1288 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
1289
1290 // Properly preserve only the bits supported in the instruction.
1291 offset >>= 2;
1292 offset &= kBranchOffsetMask;
1293 return (inst & ~kBranchOffsetMask) | offset;
1294}
1295
1296
1297int Arm32Assembler::DecodeBranchOffset(int32_t inst) {
1298 // Sign-extend, left-shift by 2, then add 8.
1299 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
1300}
1301
1302
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001303uint32_t Arm32Assembler::GetAdjustedPosition(uint32_t old_position ATTRIBUTE_UNUSED) {
1304 LOG(FATAL) << "Unimplemented.";
1305 UNREACHABLE();
1306}
1307
1308Literal* Arm32Assembler::NewLiteral(size_t size ATTRIBUTE_UNUSED,
1309 const uint8_t* data ATTRIBUTE_UNUSED) {
1310 LOG(FATAL) << "Unimplemented.";
1311 UNREACHABLE();
1312}
1313
1314void Arm32Assembler::LoadLiteral(Register rt ATTRIBUTE_UNUSED,
1315 Literal* literal ATTRIBUTE_UNUSED) {
1316 LOG(FATAL) << "Unimplemented.";
1317 UNREACHABLE();
1318}
1319
1320void Arm32Assembler::LoadLiteral(Register rt ATTRIBUTE_UNUSED, Register rt2 ATTRIBUTE_UNUSED,
1321 Literal* literal ATTRIBUTE_UNUSED) {
1322 LOG(FATAL) << "Unimplemented.";
1323 UNREACHABLE();
1324}
1325
1326void Arm32Assembler::LoadLiteral(SRegister sd ATTRIBUTE_UNUSED,
1327 Literal* literal ATTRIBUTE_UNUSED) {
1328 LOG(FATAL) << "Unimplemented.";
1329 UNREACHABLE();
1330}
1331
1332void Arm32Assembler::LoadLiteral(DRegister dd ATTRIBUTE_UNUSED,
1333 Literal* literal ATTRIBUTE_UNUSED) {
1334 LOG(FATAL) << "Unimplemented.";
1335 UNREACHABLE();
1336}
1337
Dave Allison65fcc2c2014-04-28 13:45:27 -07001338void Arm32Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
1339 AddConstant(rd, rd, value, cond);
1340}
1341
1342
1343void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
1344 Condition cond) {
1345 if (value == 0) {
1346 if (rd != rn) {
1347 mov(rd, ShifterOperand(rn), cond);
1348 }
1349 return;
1350 }
1351 // We prefer to select the shorter code sequence rather than selecting add for
1352 // positive values and sub for negatives ones, which would slightly improve
1353 // the readability of generated code for some constants.
1354 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001355 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001356 add(rd, rn, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001357 } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001358 sub(rd, rn, shifter_op, cond);
1359 } else {
1360 CHECK(rn != IP);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001361 if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001362 mvn(IP, shifter_op, cond);
1363 add(rd, rn, ShifterOperand(IP), cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001364 } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001365 mvn(IP, shifter_op, cond);
1366 sub(rd, rn, ShifterOperand(IP), cond);
1367 } else {
1368 movw(IP, Low16Bits(value), cond);
1369 uint16_t value_high = High16Bits(value);
1370 if (value_high != 0) {
1371 movt(IP, value_high, cond);
1372 }
1373 add(rd, rn, ShifterOperand(IP), cond);
1374 }
1375 }
1376}
1377
1378
1379void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
1380 Condition cond) {
1381 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001382 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001383 add(rd, rn, shifter_op, cond, kCcSet);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001384 } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001385 sub(rd, rn, shifter_op, cond, kCcSet);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001386 } else {
1387 CHECK(rn != IP);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001388 if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001389 mvn(IP, shifter_op, cond);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001390 add(rd, rn, ShifterOperand(IP), cond, kCcSet);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001391 } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001392 mvn(IP, shifter_op, cond);
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001393 sub(rd, rn, ShifterOperand(IP), cond, kCcSet);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001394 } else {
1395 movw(IP, Low16Bits(value), cond);
1396 uint16_t value_high = High16Bits(value);
1397 if (value_high != 0) {
1398 movt(IP, value_high, cond);
1399 }
Vladimir Marko73cf0fb2015-07-30 15:07:22 +01001400 add(rd, rn, ShifterOperand(IP), cond, kCcSet);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001401 }
1402 }
1403}
1404
Dave Allison65fcc2c2014-04-28 13:45:27 -07001405void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
1406 ShifterOperand shifter_op;
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001407 if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001408 mov(rd, shifter_op, cond);
Nicolas Geoffray3bcc8ea2014-11-28 15:00:02 +00001409 } else if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001410 mvn(rd, shifter_op, cond);
1411 } else {
1412 movw(rd, Low16Bits(value), cond);
1413 uint16_t value_high = High16Bits(value);
1414 if (value_high != 0) {
1415 movt(rd, value_high, cond);
1416 }
1417 }
1418}
1419
1420
1421// Implementation note: this method must emit at most one instruction when
1422// Address::CanHoldLoadOffsetArm.
1423void Arm32Assembler::LoadFromOffset(LoadOperandType type,
1424 Register reg,
1425 Register base,
1426 int32_t offset,
1427 Condition cond) {
1428 if (!Address::CanHoldLoadOffsetArm(type, offset)) {
1429 CHECK(base != IP);
1430 LoadImmediate(IP, offset, cond);
1431 add(IP, IP, ShifterOperand(base), cond);
1432 base = IP;
1433 offset = 0;
1434 }
1435 CHECK(Address::CanHoldLoadOffsetArm(type, offset));
1436 switch (type) {
1437 case kLoadSignedByte:
1438 ldrsb(reg, Address(base, offset), cond);
1439 break;
1440 case kLoadUnsignedByte:
1441 ldrb(reg, Address(base, offset), cond);
1442 break;
1443 case kLoadSignedHalfword:
1444 ldrsh(reg, Address(base, offset), cond);
1445 break;
1446 case kLoadUnsignedHalfword:
1447 ldrh(reg, Address(base, offset), cond);
1448 break;
1449 case kLoadWord:
1450 ldr(reg, Address(base, offset), cond);
1451 break;
1452 case kLoadWordPair:
1453 ldrd(reg, Address(base, offset), cond);
1454 break;
1455 default:
1456 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001457 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001458 }
1459}
1460
1461
1462// Implementation note: this method must emit at most one instruction when
1463// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1464void Arm32Assembler::LoadSFromOffset(SRegister reg,
1465 Register base,
1466 int32_t offset,
1467 Condition cond) {
1468 if (!Address::CanHoldLoadOffsetArm(kLoadSWord, offset)) {
1469 CHECK_NE(base, IP);
1470 LoadImmediate(IP, offset, cond);
1471 add(IP, IP, ShifterOperand(base), cond);
1472 base = IP;
1473 offset = 0;
1474 }
1475 CHECK(Address::CanHoldLoadOffsetArm(kLoadSWord, offset));
1476 vldrs(reg, Address(base, offset), cond);
1477}
1478
1479
1480// Implementation note: this method must emit at most one instruction when
1481// Address::CanHoldLoadOffsetArm, as expected by JIT::GuardedLoadFromOffset.
1482void Arm32Assembler::LoadDFromOffset(DRegister reg,
1483 Register base,
1484 int32_t offset,
1485 Condition cond) {
1486 if (!Address::CanHoldLoadOffsetArm(kLoadDWord, offset)) {
1487 CHECK_NE(base, IP);
1488 LoadImmediate(IP, offset, cond);
1489 add(IP, IP, ShifterOperand(base), cond);
1490 base = IP;
1491 offset = 0;
1492 }
1493 CHECK(Address::CanHoldLoadOffsetArm(kLoadDWord, offset));
1494 vldrd(reg, Address(base, offset), cond);
1495}
1496
1497
1498// Implementation note: this method must emit at most one instruction when
1499// Address::CanHoldStoreOffsetArm.
1500void Arm32Assembler::StoreToOffset(StoreOperandType type,
1501 Register reg,
1502 Register base,
1503 int32_t offset,
1504 Condition cond) {
1505 if (!Address::CanHoldStoreOffsetArm(type, offset)) {
1506 CHECK(reg != IP);
1507 CHECK(base != IP);
1508 LoadImmediate(IP, offset, cond);
1509 add(IP, IP, ShifterOperand(base), cond);
1510 base = IP;
1511 offset = 0;
1512 }
1513 CHECK(Address::CanHoldStoreOffsetArm(type, offset));
1514 switch (type) {
1515 case kStoreByte:
1516 strb(reg, Address(base, offset), cond);
1517 break;
1518 case kStoreHalfword:
1519 strh(reg, Address(base, offset), cond);
1520 break;
1521 case kStoreWord:
1522 str(reg, Address(base, offset), cond);
1523 break;
1524 case kStoreWordPair:
1525 strd(reg, Address(base, offset), cond);
1526 break;
1527 default:
1528 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -07001529 UNREACHABLE();
Dave Allison65fcc2c2014-04-28 13:45:27 -07001530 }
1531}
1532
1533
1534// Implementation note: this method must emit at most one instruction when
1535// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreToOffset.
1536void Arm32Assembler::StoreSToOffset(SRegister reg,
1537 Register base,
1538 int32_t offset,
1539 Condition cond) {
1540 if (!Address::CanHoldStoreOffsetArm(kStoreSWord, offset)) {
1541 CHECK_NE(base, IP);
1542 LoadImmediate(IP, offset, cond);
1543 add(IP, IP, ShifterOperand(base), cond);
1544 base = IP;
1545 offset = 0;
1546 }
1547 CHECK(Address::CanHoldStoreOffsetArm(kStoreSWord, offset));
1548 vstrs(reg, Address(base, offset), cond);
1549}
1550
1551
1552// Implementation note: this method must emit at most one instruction when
1553// Address::CanHoldStoreOffsetArm, as expected by JIT::GuardedStoreSToOffset.
1554void Arm32Assembler::StoreDToOffset(DRegister reg,
1555 Register base,
1556 int32_t offset,
1557 Condition cond) {
1558 if (!Address::CanHoldStoreOffsetArm(kStoreDWord, offset)) {
1559 CHECK_NE(base, IP);
1560 LoadImmediate(IP, offset, cond);
1561 add(IP, IP, ShifterOperand(base), cond);
1562 base = IP;
1563 offset = 0;
1564 }
1565 CHECK(Address::CanHoldStoreOffsetArm(kStoreDWord, offset));
1566 vstrd(reg, Address(base, offset), cond);
1567}
1568
1569
1570void Arm32Assembler::MemoryBarrier(ManagedRegister mscratch) {
1571 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001572 dmb(SY);
1573}
1574
1575
1576void Arm32Assembler::dmb(DmbOptions flavor) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001577 int32_t encoding = 0xf57ff05f; // dmb
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001578 Emit(encoding | flavor);
Dave Allison65fcc2c2014-04-28 13:45:27 -07001579}
1580
1581
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001582void Arm32Assembler::cbz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001583 LOG(FATAL) << "cbz is not supported on ARM32";
1584}
1585
1586
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001587void Arm32Assembler::cbnz(Register rn ATTRIBUTE_UNUSED, Label* target ATTRIBUTE_UNUSED) {
Dave Allison65fcc2c2014-04-28 13:45:27 -07001588 LOG(FATAL) << "cbnz is not supported on ARM32";
1589}
1590
1591
1592void Arm32Assembler::CompareAndBranchIfZero(Register r, Label* label) {
1593 cmp(r, ShifterOperand(0));
1594 b(label, EQ);
1595}
1596
1597
1598void Arm32Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
1599 cmp(r, ShifterOperand(0));
1600 b(label, NE);
1601}
1602
1603
1604} // namespace arm
1605} // namespace art