blob: 92a9f533eaf7e4093124c2e9fa1752f0f26b7538 [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_thumb2.h"
18
19#include "base/logging.h"
20#include "entrypoints/quick/quick_entrypoints.h"
21#include "offsets.h"
22#include "thread.h"
23#include "utils.h"
24
25namespace art {
26namespace arm {
27
28void Thumb2Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
29 Condition cond) {
30 EmitDataProcessing(cond, AND, 0, rn, rd, so);
31}
32
33
34void Thumb2Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
35 Condition cond) {
36 EmitDataProcessing(cond, EOR, 0, rn, rd, so);
37}
38
39
40void Thumb2Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
41 Condition cond) {
42 EmitDataProcessing(cond, SUB, 0, rn, rd, so);
43}
44
45
46void Thumb2Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
47 Condition cond) {
48 EmitDataProcessing(cond, RSB, 0, rn, rd, so);
49}
50
51
52void Thumb2Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
53 Condition cond) {
54 EmitDataProcessing(cond, RSB, 1, rn, rd, so);
55}
56
57
58void Thumb2Assembler::add(Register rd, Register rn, const ShifterOperand& so,
59 Condition cond) {
60 EmitDataProcessing(cond, ADD, 0, rn, rd, so);
61}
62
63
64void Thumb2Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
65 Condition cond) {
66 EmitDataProcessing(cond, ADD, 1, rn, rd, so);
67}
68
69
70void Thumb2Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
71 Condition cond) {
72 EmitDataProcessing(cond, SUB, 1, rn, rd, so);
73}
74
75
76void Thumb2Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
77 Condition cond) {
78 EmitDataProcessing(cond, ADC, 0, rn, rd, so);
79}
80
81
82void Thumb2Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
83 Condition cond) {
84 EmitDataProcessing(cond, SBC, 0, rn, rd, so);
85}
86
87
88void Thumb2Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
89 Condition cond) {
90 EmitDataProcessing(cond, RSC, 0, rn, rd, so);
91}
92
93
94void Thumb2Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
95 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
96 EmitDataProcessing(cond, TST, 1, rn, R0, so);
97}
98
99
100void Thumb2Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
101 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
102 EmitDataProcessing(cond, TEQ, 1, rn, R0, so);
103}
104
105
106void Thumb2Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
107 EmitDataProcessing(cond, CMP, 1, rn, R0, so);
108}
109
110
111void Thumb2Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
112 EmitDataProcessing(cond, CMN, 1, rn, R0, so);
113}
114
115
116void Thumb2Assembler::orr(Register rd, Register rn,
117 const ShifterOperand& so, Condition cond) {
118 EmitDataProcessing(cond, ORR, 0, rn, rd, so);
119}
120
121
122void Thumb2Assembler::orrs(Register rd, Register rn,
123 const ShifterOperand& so, Condition cond) {
124 EmitDataProcessing(cond, ORR, 1, rn, rd, so);
125}
126
127
128void Thumb2Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
129 EmitDataProcessing(cond, MOV, 0, R0, rd, so);
130}
131
132
133void Thumb2Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
134 EmitDataProcessing(cond, MOV, 1, R0, rd, so);
135}
136
137
138void Thumb2Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
139 Condition cond) {
140 EmitDataProcessing(cond, BIC, 0, rn, rd, so);
141}
142
143
144void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
145 EmitDataProcessing(cond, MVN, 0, R0, rd, so);
146}
147
148
149void Thumb2Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
150 EmitDataProcessing(cond, MVN, 1, R0, rd, so);
151}
152
153
154void Thumb2Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
155 if (rd == rm && !IsHighRegister(rd) && !IsHighRegister(rn) && !force_32bit_) {
156 // 16 bit.
157 int16_t encoding = B14 | B9 | B8 | B6 |
158 rn << 3 | rd;
159 Emit16(encoding);
160 } else {
161 // 32 bit.
162 uint32_t op1 = 0b000;
163 uint32_t op2 = 0b00;
164 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 |
165 op1 << 20 |
166 B15 | B14 | B13 | B12 |
167 op2 << 4 |
168 static_cast<uint32_t>(rd) << 8 |
169 static_cast<uint32_t>(rn) << 16 |
170 static_cast<uint32_t>(rm);
171
172 Emit32(encoding);
173 }
174}
175
176
177void Thumb2Assembler::mla(Register rd, Register rn, Register rm, Register ra,
178 Condition cond) {
179 uint32_t op1 = 0b000;
180 uint32_t op2 = 0b00;
181 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 |
182 op1 << 20 |
183 op2 << 4 |
184 static_cast<uint32_t>(rd) << 8 |
185 static_cast<uint32_t>(ra) << 12 |
186 static_cast<uint32_t>(rn) << 16 |
187 static_cast<uint32_t>(rm);
188
189 Emit32(encoding);
190}
191
192
193void Thumb2Assembler::mls(Register rd, Register rn, Register rm, Register ra,
194 Condition cond) {
195 uint32_t op1 = 0b000;
196 uint32_t op2 = 0b01;
197 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 |
198 op1 << 20 |
199 op2 << 4 |
200 static_cast<uint32_t>(rd) << 8 |
201 static_cast<uint32_t>(ra) << 12 |
202 static_cast<uint32_t>(rn) << 16 |
203 static_cast<uint32_t>(rm);
204
205 Emit32(encoding);
206}
207
208
209void Thumb2Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
210 Register rm, Condition cond) {
211 uint32_t op1 = 0b010;
212 uint32_t op2 = 0b0000;
213 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 |
214 op1 << 20 |
215 op2 << 4 |
216 static_cast<uint32_t>(rd_lo) << 12 |
217 static_cast<uint32_t>(rd_hi) << 8 |
218 static_cast<uint32_t>(rn) << 16 |
219 static_cast<uint32_t>(rm);
220
221 Emit32(encoding);
222}
223
224
225void Thumb2Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
226 uint32_t op1 = 0b001;
227 uint32_t op2 = 0b1111;
228 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 | B20 |
229 op1 << 20 |
230 op2 << 4 |
231 0xf << 12 |
232 static_cast<uint32_t>(rd) << 8 |
233 static_cast<uint32_t>(rn) << 16 |
234 static_cast<uint32_t>(rm);
235
236 Emit32(encoding);
237}
238
239
240void Thumb2Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
241 uint32_t op1 = 0b001;
242 uint32_t op2 = 0b1111;
243 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 | B21 | B20 |
244 op1 << 20 |
245 op2 << 4 |
246 0xf << 12 |
247 static_cast<uint32_t>(rd) << 8 |
248 static_cast<uint32_t>(rn) << 16 |
249 static_cast<uint32_t>(rm);
250
251 Emit32(encoding);
252}
253
254
255void Thumb2Assembler::ldr(Register rd, const Address& ad, Condition cond) {
256 EmitLoadStore(cond, true, false, false, false, rd, ad);
257}
258
259
260void Thumb2Assembler::str(Register rd, const Address& ad, Condition cond) {
261 EmitLoadStore(cond, false, false, false, false, rd, ad);
262}
263
264
265void Thumb2Assembler::ldrb(Register rd, const Address& ad, Condition cond) {
266 EmitLoadStore(cond, true, true, false, false, rd, ad);
267}
268
269
270void Thumb2Assembler::strb(Register rd, const Address& ad, Condition cond) {
271 EmitLoadStore(cond, false, true, false, false, rd, ad);
272}
273
274
275void Thumb2Assembler::ldrh(Register rd, const Address& ad, Condition cond) {
276 EmitLoadStore(cond, true, false, true, false, rd, ad);
277}
278
279
280void Thumb2Assembler::strh(Register rd, const Address& ad, Condition cond) {
281 EmitLoadStore(cond, false, false, true, false, rd, ad);
282}
283
284
285void Thumb2Assembler::ldrsb(Register rd, const Address& ad, Condition cond) {
286 EmitLoadStore(cond, true, true, false, true, rd, ad);
287}
288
289
290void Thumb2Assembler::ldrsh(Register rd, const Address& ad, Condition cond) {
291 EmitLoadStore(cond, true, false, true, true, rd, ad);
292}
293
294
295void Thumb2Assembler::ldrd(Register rd, const Address& ad, Condition cond) {
296 CHECK_EQ(rd % 2, 0);
297 // This is different from other loads. The encoding is like ARM.
298 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 |
299 static_cast<int32_t>(rd) << 12 |
300 (static_cast<int32_t>(rd) + 1) << 8 |
301 ad.encodingThumbLdrdStrd();
302 Emit32(encoding);
303}
304
305
306void Thumb2Assembler::strd(Register rd, const Address& ad, Condition cond) {
307 CHECK_EQ(rd % 2, 0);
308 // This is different from other loads. The encoding is like ARM.
309 int32_t encoding = B31 | B30 | B29 | B27 | B22 |
310 static_cast<int32_t>(rd) << 12 |
311 (static_cast<int32_t>(rd) + 1) << 8 |
312 ad.encodingThumbLdrdStrd();
313 Emit32(encoding);
314}
315
316
317void Thumb2Assembler::ldm(BlockAddressMode am,
318 Register base,
319 RegList regs,
320 Condition cond) {
321 if (__builtin_popcount(regs) == 1) {
322 // Thumb doesn't support one reg in the list.
323 // Find the register number.
324 int reg = 0;
325 while (reg < 16) {
326 if ((regs & (1 << reg)) != 0) {
327 break;
328 }
329 ++reg;
330 }
331 CHECK_LT(reg, 16);
Dave Allison20dfc792014-06-16 20:44:29 -0700332 CHECK(am == IA_W); // Only writeback is supported.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700333 ldr(static_cast<Register>(reg), Address(base, kRegisterSize, Address::PostIndex), cond);
334 } else {
335 EmitMultiMemOp(cond, am, true, base, regs);
336 }
337}
338
339
340void Thumb2Assembler::stm(BlockAddressMode am,
341 Register base,
342 RegList regs,
343 Condition cond) {
344 if (__builtin_popcount(regs) == 1) {
345 // Thumb doesn't support one reg in the list.
346 // Find the register number.
347 int reg = 0;
348 while (reg < 16) {
349 if ((regs & (1 << reg)) != 0) {
350 break;
351 }
352 ++reg;
353 }
354 CHECK_LT(reg, 16);
Dave Allison20dfc792014-06-16 20:44:29 -0700355 CHECK(am == DB || am == DB_W);
356 Address::Mode strmode = am == DB_W ? Address::PreIndex : Address::Offset;
Dave Allison65fcc2c2014-04-28 13:45:27 -0700357 str(static_cast<Register>(reg), Address(base, -kRegisterSize, strmode), cond);
358 } else {
359 EmitMultiMemOp(cond, am, false, base, regs);
360 }
361}
362
363
364bool Thumb2Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
365 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm);
366 if (((imm32 & ((1 << 19) - 1)) == 0) &&
367 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) ||
368 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) {
369 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) |
370 ((imm32 >> 19) & ((1 << 6) -1));
371 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf),
372 sd, S0, S0);
373 return true;
374 }
375 return false;
376}
377
378
379bool Thumb2Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
380 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm);
381 if (((imm64 & ((1LL << 48) - 1)) == 0) &&
382 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) ||
383 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) {
384 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) |
385 ((imm64 >> 48) & ((1 << 6) -1));
386 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf),
387 dd, D0, D0);
388 return true;
389 }
390 return false;
391}
392
393
394void Thumb2Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) {
395 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm);
396}
397
398
399void Thumb2Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
400 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
401}
402
403
404void Thumb2Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
405 Condition cond) {
406 EmitVFPsss(cond, B21 | B20, sd, sn, sm);
407}
408
409
410void Thumb2Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
411 Condition cond) {
412 EmitVFPddd(cond, B21 | B20, dd, dn, dm);
413}
414
415
416void Thumb2Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
417 Condition cond) {
418 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
419}
420
421
422void Thumb2Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
423 Condition cond) {
424 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
425}
426
427
428void Thumb2Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
429 Condition cond) {
430 EmitVFPsss(cond, B21, sd, sn, sm);
431}
432
433
434void Thumb2Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
435 Condition cond) {
436 EmitVFPddd(cond, B21, dd, dn, dm);
437}
438
439
440void Thumb2Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
441 Condition cond) {
442 EmitVFPsss(cond, 0, sd, sn, sm);
443}
444
445
446void Thumb2Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm,
447 Condition cond) {
448 EmitVFPddd(cond, 0, dd, dn, dm);
449}
450
451
452void Thumb2Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm,
453 Condition cond) {
454 EmitVFPsss(cond, B6, sd, sn, sm);
455}
456
457
458void Thumb2Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm,
459 Condition cond) {
460 EmitVFPddd(cond, B6, dd, dn, dm);
461}
462
463
464void Thumb2Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm,
465 Condition cond) {
466 EmitVFPsss(cond, B23, sd, sn, sm);
467}
468
469
470void Thumb2Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
471 Condition cond) {
472 EmitVFPddd(cond, B23, dd, dn, dm);
473}
474
475
476void Thumb2Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
477 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
478}
479
480
481void Thumb2Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
482 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
483}
484
485
486void Thumb2Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
487 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
488}
489
490
491void Thumb2Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) {
492 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm);
493}
494
495
496void Thumb2Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) {
497 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm);
498}
499
500void Thumb2Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
501 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
502}
503
504
505void Thumb2Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
506 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
507}
508
509
510void Thumb2Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
511 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
512}
513
514
515void Thumb2Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
516 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm);
517}
518
519
520void Thumb2Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
521 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
522}
523
524
525void Thumb2Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
526 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
527}
528
529
530void Thumb2Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
531 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
532}
533
534
535void Thumb2Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
536 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
537}
538
539
540void Thumb2Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
541 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
542}
543
544
545void Thumb2Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
546 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
547}
548
549
550void Thumb2Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
551 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
552}
553
554
555void Thumb2Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
556 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
557}
558
559
560void Thumb2Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
561 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
562}
563
564
565void Thumb2Assembler::vcmpsz(SRegister sd, Condition cond) {
566 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
567}
568
569
570void Thumb2Assembler::vcmpdz(DRegister dd, Condition cond) {
571 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
572}
573
574void Thumb2Assembler::b(Label* label, Condition cond) {
575 EmitBranch(cond, label, false, false);
576}
577
578
579void Thumb2Assembler::bl(Label* label, Condition cond) {
580 CheckCondition(cond);
581 EmitBranch(cond, label, true, false);
582}
583
584
585void Thumb2Assembler::blx(Label* label) {
586 EmitBranch(AL, label, true, true);
587}
588
589
590void Thumb2Assembler::MarkExceptionHandler(Label* label) {
591 EmitDataProcessing(AL, TST, 1, PC, R0, ShifterOperand(0));
592 Label l;
593 b(&l);
594 EmitBranch(AL, label, false, false);
595 Bind(&l);
596}
597
598
599void Thumb2Assembler::Emit32(int32_t value) {
600 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
601 buffer_.Emit<int16_t>(value >> 16);
602 buffer_.Emit<int16_t>(value & 0xffff);
603}
604
605
606void Thumb2Assembler::Emit16(int16_t value) {
607 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
608 buffer_.Emit<int16_t>(value);
609}
610
611
612bool Thumb2Assembler::Is32BitDataProcessing(Condition cond,
613 Opcode opcode,
614 int set_cc,
615 Register rn,
616 Register rd,
617 const ShifterOperand& so) {
618 if (force_32bit_) {
619 return true;
620 }
621
622 bool can_contain_high_register = opcode == MOV || opcode == ADD || opcode == SUB;
623
624 if (IsHighRegister(rd) || IsHighRegister(rn)) {
625 if (can_contain_high_register) {
626 // There are high register instructions available for this opcode.
627 // However, there is no RRX available.
628 if (so.IsShift() && so.GetShift() == RRX) {
629 return true;
630 }
631
632 // Check special case for SP relative ADD and SUB immediate.
633 if ((opcode == ADD || opcode == SUB) && so.IsImmediate()) {
634 // If rn is SP and rd is a high register we need to use a 32 bit encoding.
635 if (rn == SP && rd != SP && IsHighRegister(rd)) {
636 return true;
637 }
638
639 uint32_t imm = so.GetImmediate();
640 // If the immediates are out of range use 32 bit.
641 if (rd == SP && rn == SP) {
642 if (imm > (1 << 9)) { // 9 bit immediate.
643 return true;
644 }
Dave Allison20dfc792014-06-16 20:44:29 -0700645 return false; // 16 bit good.
Dave Allison65fcc2c2014-04-28 13:45:27 -0700646 } else if (opcode == ADD && rd != SP && rn == SP) { // 10 bit immediate.
647 if (imm > (1 << 10)) {
648 return true;
649 }
650 } else if (opcode == SUB && rd != SP && rn == SP) {
651 // SUB rd, SP, #imm is always 32 bit.
652 return true;
653 }
654 }
655 }
656
657 // The ADD,SUB and MOV instructions that work with high registers don't have
658 // immediate variants.
659 if (so.IsImmediate()) {
660 return true;
661 }
662 }
663
664 if (so.IsRegister() && IsHighRegister(so.GetRegister()) && !can_contain_high_register) {
665 return true;
666 }
667
668 // Check for MOV with an ROR.
669 if (opcode == MOV && so.IsRegister() && so.IsShift() && so.GetShift() == ROR) {
670 if (so.GetImmediate() != 0) {
671 return true;
672 }
673 }
674
675 bool rn_is_valid = true;
676
677 // Check for single operand instructions and ADD/SUB.
678 switch (opcode) {
679 case CMP:
680 case MOV:
681 case TST:
682 case MVN:
683 rn_is_valid = false; // There is no Rn for these instructions.
684 break;
685 case TEQ:
686 return true;
687 break;
688 case ADD:
689 case SUB:
690 break;
691 default:
692 if (so.IsRegister() && rd != rn) {
693 return true;
694 }
695 }
696
697 if (so.IsImmediate()) {
698 if (rn_is_valid && rn != rd) {
699 // The only thumb1 instruction with a register and an immediate are ADD and SUB. The
700 // immediate must be 3 bits.
701 if (opcode != ADD && opcode != SUB) {
702 return true;
703 } else {
704 // Check that the immediate is 3 bits for ADD and SUB.
705 if (so.GetImmediate() >= 8) {
706 return true;
707 }
708 }
709 } else {
710 // ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits.
711 if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) {
712 return true;
713 } else {
714 if (so.GetImmediate() > 255) {
715 return true;
716 }
717 }
718 }
719 }
720
721 // The instruction can be encoded in 16 bits.
722 return false;
723}
724
725
726void Thumb2Assembler::Emit32BitDataProcessing(Condition cond,
727 Opcode opcode,
728 int set_cc,
729 Register rn,
730 Register rd,
731 const ShifterOperand& so) {
732 uint8_t thumb_opcode = 0b11111111;
733 switch (opcode) {
734 case AND: thumb_opcode = 0b0000; break;
735 case EOR: thumb_opcode = 0b0100; break;
736 case SUB: thumb_opcode = 0b1101; break;
737 case RSB: thumb_opcode = 0b1110; break;
738 case ADD: thumb_opcode = 0b1000; break;
739 case ADC: thumb_opcode = 0b1010; break;
740 case SBC: thumb_opcode = 0b1011; break;
741 case RSC: break;
742 case TST: thumb_opcode = 0b0000; set_cc = true; rd = PC; break;
743 case TEQ: thumb_opcode = 0b0100; set_cc = true; rd = PC; break;
744 case CMP: thumb_opcode = 0b1101; set_cc = true; rd = PC; break;
745 case CMN: thumb_opcode = 0b1000; set_cc = true; rd = PC; break;
746 case ORR: thumb_opcode = 0b0010; break;
747 case MOV: thumb_opcode = 0b0010; rn = PC; break;
748 case BIC: thumb_opcode = 0b0001; break;
749 case MVN: thumb_opcode = 0b0011; rn = PC; break;
750 default:
751 break;
752 }
753
754 if (thumb_opcode == 0b11111111) {
755 LOG(FATAL) << "Invalid thumb2 opcode " << opcode;
756 }
757
758 int32_t encoding = 0;
759 if (so.IsImmediate()) {
760 // Check special cases.
761 if ((opcode == SUB || opcode == ADD) && rn == SP) {
762 // There are special ADD/SUB rd, SP, #imm12 instructions.
763 if (opcode == SUB) {
764 thumb_opcode = 0b0101;
765 } else {
766 thumb_opcode = 0;
767 }
768 uint32_t imm = so.GetImmediate();
769 CHECK_LT(imm, (1u << 12));
770
771 uint32_t i = (imm >> 11) & 1;
772 uint32_t imm3 = (imm >> 8) & 0b111;
773 uint32_t imm8 = imm & 0xff;
774
775 encoding = B31 | B30 | B29 | B28 | B25 |
776 B19 | B18 | B16 |
777 thumb_opcode << 21 |
778 rd << 8 |
779 i << 26 |
780 imm3 << 12 |
781 imm8;
782 } else {
783 // Modified immediate.
784 uint32_t imm = ModifiedImmediate(so.encodingThumb(2));
785 if (imm == kInvalidModifiedImmediate) {
786 LOG(FATAL) << "Immediate value cannot fit in thumb2 modified immediate";
787 }
788 encoding = B31 | B30 | B29 | B28 |
789 thumb_opcode << 21 |
790 set_cc << 20 |
791 rn << 16 |
792 rd << 8 |
793 imm;
794 }
795 } else if (so.IsRegister()) {
796 // Register (possibly shifted)
797 encoding = B31 | B30 | B29 | B27 | B25 |
798 thumb_opcode << 21 |
799 set_cc << 20 |
800 rn << 16 |
801 rd << 8 |
802 so.encodingThumb(2);
803 }
804 Emit32(encoding);
805}
806
807
808void Thumb2Assembler::Emit16BitDataProcessing(Condition cond,
809 Opcode opcode,
810 int set_cc,
811 Register rn,
812 Register rd,
813 const ShifterOperand& so) {
814 if (opcode == ADD || opcode == SUB) {
815 Emit16BitAddSub(cond, opcode, set_cc, rn, rd, so);
816 return;
817 }
818 uint8_t thumb_opcode = 0b11111111;
819 // Thumb1.
820 uint8_t dp_opcode = 0b01;
821 uint8_t opcode_shift = 6;
822 uint8_t rd_shift = 0;
823 uint8_t rn_shift = 3;
824 uint8_t immediate_shift = 0;
825 bool use_immediate = false;
826 uint8_t immediate = 0;
827
828 if (opcode == MOV && so.IsRegister() && so.IsShift()) {
829 // Convert shifted mov operand2 into 16 bit opcodes.
830 dp_opcode = 0;
831 opcode_shift = 11;
832
833 use_immediate = true;
834 immediate = so.GetImmediate();
835 immediate_shift = 6;
836
837 rn = so.GetRegister();
838
839 switch (so.GetShift()) {
840 case LSL: thumb_opcode = 0b00; break;
841 case LSR: thumb_opcode = 0b01; break;
842 case ASR: thumb_opcode = 0b10; break;
843 case ROR:
844 // ROR doesn't allow immediates.
845 thumb_opcode = 0b111;
846 dp_opcode = 0b01;
847 opcode_shift = 6;
848 use_immediate = false;
849 break;
850 case RRX: break;
851 default:
852 break;
853 }
854 } else {
855 if (so.IsImmediate()) {
856 use_immediate = true;
857 immediate = so.GetImmediate();
858 }
859
860 switch (opcode) {
861 case AND: thumb_opcode = 0b0000; break;
862 case EOR: thumb_opcode = 0b0001; break;
863 case SUB: break;
864 case RSB: thumb_opcode = 0b1001; break;
865 case ADD: break;
866 case ADC: thumb_opcode = 0b0101; break;
867 case SBC: thumb_opcode = 0b0110; break;
868 case RSC: break;
869 case TST: thumb_opcode = 0b1000; rn = so.GetRegister(); break;
870 case TEQ: break;
871 case CMP:
872 if (use_immediate) {
873 // T2 encoding.
874 dp_opcode = 0;
875 opcode_shift = 11;
876 thumb_opcode = 0b101;
877 rd_shift = 8;
878 rn_shift = 8;
879 } else {
880 thumb_opcode = 0b1010;
881 rn = so.GetRegister();
882 }
883
884 break;
885 case CMN: thumb_opcode = 0b1011; rn = so.GetRegister(); break;
886 case ORR: thumb_opcode = 0b1100; break;
887 case MOV:
888 dp_opcode = 0;
889 if (use_immediate) {
890 // T2 encoding.
891 opcode_shift = 11;
892 thumb_opcode = 0b100;
893 rd_shift = 8;
894 rn_shift = 8;
895 } else {
896 rn = so.GetRegister();
897 if (IsHighRegister(rn) || IsHighRegister(rd)) {
898 // Special mov for high registers.
899 dp_opcode = 0b01;
900 opcode_shift = 7;
901 // Put the top bit of rd into the bottom bit of the opcode.
902 thumb_opcode = 0b0001100 | static_cast<uint32_t>(rd) >> 3;
903 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111);
904 } else {
905 thumb_opcode = 0;
906 }
907 }
908 break;
909 case BIC: thumb_opcode = 0b1110; break;
910 case MVN: thumb_opcode = 0b1111; rn = so.GetRegister(); break;
911 default:
912 break;
913 }
914 }
915
916 if (thumb_opcode == 0b11111111) {
917 LOG(FATAL) << "Invalid thumb1 opcode " << opcode;
918 }
919
920 int16_t encoding = dp_opcode << 14 |
921 (thumb_opcode << opcode_shift) |
922 rd << rd_shift |
923 rn << rn_shift |
924 (use_immediate ? (immediate << immediate_shift) : 0);
925
926 Emit16(encoding);
927}
928
929
930// ADD and SUB are complex enough to warrant their own emitter.
931void Thumb2Assembler::Emit16BitAddSub(Condition cond,
932 Opcode opcode,
933 int set_cc,
934 Register rn,
935 Register rd,
936 const ShifterOperand& so) {
937 uint8_t dp_opcode = 0;
938 uint8_t opcode_shift = 6;
939 uint8_t rd_shift = 0;
940 uint8_t rn_shift = 3;
941 uint8_t immediate_shift = 0;
942 bool use_immediate = false;
943 uint8_t immediate = 0;
944 uint8_t thumb_opcode;;
945
946 if (so.IsImmediate()) {
947 use_immediate = true;
948 immediate = so.GetImmediate();
949 }
950
951 switch (opcode) {
952 case ADD:
953 if (so.IsRegister()) {
954 Register rm = so.GetRegister();
955 if (rn == rd) {
956 // Can use T2 encoding (allows 4 bit registers)
957 dp_opcode = 0b01;
958 opcode_shift = 10;
959 thumb_opcode = 0b0001;
960 // Make Rn also contain the top bit of rd.
961 rn = static_cast<Register>(static_cast<uint32_t>(rm) |
962 (static_cast<uint32_t>(rd) & 0b1000) << 1);
963 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111);
964 } else {
965 // T1.
966 opcode_shift = 9;
967 thumb_opcode = 0b01100;
968 immediate = static_cast<uint32_t>(so.GetRegister());
969 use_immediate = true;
970 immediate_shift = 6;
971 }
972 } else {
973 // Immediate.
974 if (rd == SP && rn == SP) {
975 // ADD sp, sp, #imm
976 dp_opcode = 0b10;
977 thumb_opcode = 0b11;
978 opcode_shift = 12;
979 CHECK_LT(immediate, (1 << 9));
980 CHECK_EQ((immediate & 0b11), 0);
981
982 // Remove rd and rn from instruction by orring it with immed and clearing bits.
983 rn = R0;
984 rd = R0;
985 rd_shift = 0;
986 rn_shift = 0;
987 immediate >>= 2;
988 } else if (rd != SP && rn == SP) {
989 // ADD rd, SP, #imm
990 dp_opcode = 0b10;
991 thumb_opcode = 0b101;
992 opcode_shift = 11;
993 CHECK_LT(immediate, (1 << 10));
994 CHECK_EQ((immediate & 0b11), 0);
995
996 // Remove rn from instruction.
997 rn = R0;
998 rn_shift = 0;
999 rd_shift = 8;
1000 immediate >>= 2;
1001 } else if (rn != rd) {
1002 // Must use T1.
1003 opcode_shift = 9;
1004 thumb_opcode = 0b01110;
1005 immediate_shift = 6;
1006 } else {
1007 // T2 encoding.
1008 opcode_shift = 11;
1009 thumb_opcode = 0b110;
1010 rd_shift = 8;
1011 rn_shift = 8;
1012 }
1013 }
1014 break;
1015
1016 case SUB:
1017 if (so.IsRegister()) {
1018 // T1.
1019 opcode_shift = 9;
1020 thumb_opcode = 0b01101;
1021 immediate = static_cast<uint32_t>(so.GetRegister());
1022 use_immediate = true;
1023 immediate_shift = 6;
1024 } else {
1025 if (rd == SP && rn == SP) {
1026 // SUB sp, sp, #imm
1027 dp_opcode = 0b10;
1028 thumb_opcode = 0b1100001;
1029 opcode_shift = 7;
1030 CHECK_LT(immediate, (1 << 9));
1031 CHECK_EQ((immediate & 0b11), 0);
1032
1033 // Remove rd and rn from instruction by orring it with immed and clearing bits.
1034 rn = R0;
1035 rd = R0;
1036 rd_shift = 0;
1037 rn_shift = 0;
1038 immediate >>= 2;
1039 } else if (rn != rd) {
1040 // Must use T1.
1041 opcode_shift = 9;
1042 thumb_opcode = 0b01111;
1043 immediate_shift = 6;
1044 } else {
1045 // T2 encoding.
1046 opcode_shift = 11;
1047 thumb_opcode = 0b111;
1048 rd_shift = 8;
1049 rn_shift = 8;
1050 }
1051 }
1052 break;
1053 default:
1054 LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode;
1055 return;
1056 }
1057
1058 int16_t encoding = dp_opcode << 14 |
1059 (thumb_opcode << opcode_shift) |
1060 rd << rd_shift |
1061 rn << rn_shift |
1062 (use_immediate ? (immediate << immediate_shift) : 0);
1063
1064 Emit16(encoding);
1065}
1066
1067
1068void Thumb2Assembler::EmitDataProcessing(Condition cond,
1069 Opcode opcode,
1070 int set_cc,
1071 Register rn,
1072 Register rd,
1073 const ShifterOperand& so) {
1074 CHECK_NE(rd, kNoRegister);
1075 CheckCondition(cond);
1076
1077 if (Is32BitDataProcessing(cond, opcode, set_cc, rn, rd, so)) {
1078 Emit32BitDataProcessing(cond, opcode, set_cc, rn, rd, so);
1079 } else {
1080 Emit16BitDataProcessing(cond, opcode, set_cc, rn, rd, so);
1081 }
1082}
1083
1084
1085void Thumb2Assembler::Branch::Emit(AssemblerBuffer* buffer) const {
1086 bool link = type_ == kUnconditionalLinkX || type_ == kUnconditionalLink;
1087 bool x = type_ == kUnconditionalX || type_ == kUnconditionalLinkX;
1088 int32_t offset = target_ - location_;
1089
1090 if (size_ == k32Bit) {
1091 int32_t encoding = B31 | B30 | B29 | B28 | B15;
1092 if (link) {
1093 // BL or BLX immediate.
1094 encoding |= B14;
1095 if (!x) {
1096 encoding |= B12;
1097 } else {
1098 // Bottom bit of offset must be 0.
1099 CHECK_EQ((offset & 1), 0);
1100 }
1101 } else {
1102 if (x) {
1103 LOG(FATAL) << "Invalid use of BX";
1104 } else {
1105 if (cond_ == AL) {
1106 // Can use the T4 encoding allowing a 24 bit offset.
1107 if (!x) {
1108 encoding |= B12;
1109 }
1110 } else {
1111 // Must be T3 encoding with a 20 bit offset.
1112 encoding |= cond_ << 22;
1113 }
1114 }
1115 }
1116 encoding = Thumb2Assembler::EncodeBranchOffset(offset, encoding);
1117 buffer->Store<int16_t>(location_, static_cast<int16_t>(encoding >> 16));
1118 buffer->Store<int16_t>(location_+2, static_cast<int16_t>(encoding & 0xffff));
1119 } else {
1120 if (IsCompareAndBranch()) {
1121 offset -= 4;
1122 uint16_t i = (offset >> 6) & 1;
1123 uint16_t imm5 = (offset >> 1) & 0b11111;
1124 int16_t encoding = B15 | B13 | B12 |
1125 (type_ == kCompareAndBranchNonZero ? B11 : 0) |
1126 static_cast<uint32_t>(rn_) |
1127 B8 |
1128 i << 9 |
1129 imm5 << 3;
1130 buffer->Store<int16_t>(location_, encoding);
1131 } else {
1132 offset -= 4; // Account for PC offset.
1133 int16_t encoding;
1134 // 16 bit.
1135 if (cond_ == AL) {
1136 encoding = B15 | B14 | B13 |
1137 ((offset >> 1) & 0x7ff);
1138 } else {
1139 encoding = B15 | B14 | B12 |
1140 cond_ << 8 | ((offset >> 1) & 0xff);
1141 }
1142 buffer->Store<int16_t>(location_, encoding);
1143 }
1144 }
1145}
1146
1147
1148uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) {
1149 uint32_t location = buffer_.Size();
1150
1151 // This is always unresolved as it must be a forward branch.
1152 Emit16(prev); // Previous link.
1153 return AddBranch(n ? Branch::kCompareAndBranchNonZero : Branch::kCompareAndBranchZero,
1154 location, rn);
1155}
1156
1157
1158// NOTE: this only support immediate offsets, not [rx,ry].
1159// TODO: support [rx,ry] instructions.
1160void Thumb2Assembler::EmitLoadStore(Condition cond,
1161 bool load,
1162 bool byte,
1163 bool half,
1164 bool is_signed,
1165 Register rd,
1166 const Address& ad) {
1167 CHECK_NE(rd, kNoRegister);
1168 CheckCondition(cond);
1169 bool must_be_32bit = force_32bit_;
1170 if (IsHighRegister(rd)) {
1171 must_be_32bit = true;
1172 }
1173
1174 Register rn = ad.GetRegister();
1175 if (IsHighRegister(rn) && rn != SP) {
1176 must_be_32bit = true;
1177 }
1178
1179 if (is_signed || ad.GetOffset() < 0 || ad.GetMode() != Address::Offset) {
1180 must_be_32bit = true;
1181 }
1182
1183 int32_t offset = ad.GetOffset();
1184
1185 // The 16 bit SP relative instruction can only have a 10 bit offset.
1186 if (rn == SP && offset > 1024) {
1187 must_be_32bit = true;
1188 }
1189
1190 if (byte) {
1191 // 5 bit offset, no shift.
1192 if (offset > 32) {
1193 must_be_32bit = true;
1194 }
1195 } else if (half) {
1196 // 6 bit offset, shifted by 1.
1197 if (offset > 64) {
1198 must_be_32bit = true;
1199 }
1200 } else {
1201 // 7 bit offset, shifted by 2.
1202 if (offset > 128) {
1203 must_be_32bit = true;
1204 }
1205 }
1206
1207 if (must_be_32bit) {
1208 int32_t encoding = B31 | B30 | B29 | B28 | B27 |
1209 (load ? B20 : 0) |
1210 (is_signed ? B24 : 0) |
1211 static_cast<uint32_t>(rd) << 12 |
1212 ad.encodingThumb(2) |
1213 (byte ? 0 : half ? B21 : B22);
1214 Emit32(encoding);
1215 } else {
1216 // 16 bit thumb1.
1217 uint8_t opA = 0;
1218 bool sp_relative = false;
1219
1220 if (byte) {
1221 opA = 0b0111;
1222 } else if (half) {
1223 opA = 0b1000;
1224 } else {
1225 if (rn == SP) {
1226 opA = 0b1001;
1227 sp_relative = true;
1228 } else {
1229 opA = 0b0110;
1230 }
1231 }
1232 int16_t encoding = opA << 12 |
1233 (load ? B11 : 0);
1234
1235 CHECK_GE(offset, 0);
1236 if (sp_relative) {
1237 // SP relative, 10 bit offset.
1238 CHECK_LT(offset, 1024);
1239 CHECK_EQ((offset & 0b11), 0);
1240 encoding |= rd << 8 | offset >> 2;
1241 } else {
1242 // No SP relative. The offset is shifted right depending on
1243 // the size of the load/store.
1244 encoding |= static_cast<uint32_t>(rd);
1245
1246 if (byte) {
1247 // 5 bit offset, no shift.
1248 CHECK_LT(offset, 32);
1249 } else if (half) {
1250 // 6 bit offset, shifted by 1.
1251 CHECK_LT(offset, 64);
1252 CHECK_EQ((offset & 0b1), 0);
1253 offset >>= 1;
1254 } else {
1255 // 7 bit offset, shifted by 2.
1256 CHECK_LT(offset, 128);
1257 CHECK_EQ((offset & 0b11), 0);
1258 offset >>= 2;
1259 }
1260 encoding |= rn << 3 | offset << 6;
1261 }
1262
1263 Emit16(encoding);
1264 }
1265}
1266
1267
1268void Thumb2Assembler::EmitMultiMemOp(Condition cond,
1269 BlockAddressMode am,
1270 bool load,
1271 Register base,
1272 RegList regs) {
1273 CHECK_NE(base, kNoRegister);
1274 CheckCondition(cond);
1275 bool must_be_32bit = force_32bit_;
1276
1277 if ((regs & 0xff00) != 0) {
1278 must_be_32bit = true;
1279 }
1280
1281 uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W;
1282 // 16 bit always uses writeback.
1283 if (!w_bit) {
1284 must_be_32bit = true;
1285 }
1286
1287 if (must_be_32bit) {
1288 uint32_t op = 0;
1289 switch (am) {
1290 case IA:
1291 case IA_W:
1292 op = 0b01;
1293 break;
1294 case DB:
1295 case DB_W:
1296 op = 0b10;
1297 break;
1298 case DA:
1299 case IB:
1300 case DA_W:
1301 case IB_W:
1302 LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am;
1303 }
1304 if (load) {
1305 // Cannot have SP in the list.
1306 CHECK_EQ((regs & (1 << SP)), 0);
1307 } else {
1308 // Cannot have PC or SP in the list.
1309 CHECK_EQ((regs & (1 << PC | 1 << SP)), 0);
1310 }
1311 int32_t encoding = B31 | B30 | B29 | B27 |
1312 (op << 23) |
1313 (load ? B20 : 0) |
1314 base << 16 |
1315 regs |
1316 (w_bit << 21);
1317 Emit32(encoding);
1318 } else {
1319 int16_t encoding = B15 | B14 |
1320 (load ? B11 : 0) |
1321 base << 8 |
1322 regs;
1323 Emit16(encoding);
1324 }
1325}
1326
1327
1328void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) {
1329 uint32_t pc = buffer_.Size();
1330 Branch::Type branch_type;
1331 if (cond == AL) {
1332 if (link) {
1333 if (x) {
1334 branch_type = Branch::kUnconditionalLinkX; // BLX.
1335 } else {
1336 branch_type = Branch::kUnconditionalLink; // BX.
1337 }
1338 } else {
1339 branch_type = Branch::kUnconditional; // B.
1340 }
1341 } else {
1342 branch_type = Branch::kConditional; // B<cond>.
1343 }
1344
1345 if (label->IsBound()) {
1346 Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond); // Resolved branch.
1347
1348 // The branch is to a bound label which means that it's a backwards branch. We know the
1349 // current size of it so we can emit the appropriate space. Note that if it's a 16 bit
1350 // branch the size may change if it so happens that other branches change size that change
1351 // the distance to the target and that distance puts this branch over the limit for 16 bits.
1352 if (size == Branch::k16Bit) {
1353 Emit16(0); // Space for a 16 bit branch.
1354 } else {
1355 Emit32(0); // Space for a 32 bit branch.
1356 }
1357 } else {
1358 // Branch is to an unbound label. Emit space for it.
1359 uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch.
1360 if (force_32bit_) {
1361 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link.
1362 Emit16(0); // another 16 bits.
1363 } else {
1364 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link.
1365 }
1366 label->LinkTo(branch_id); // Link to the branch ID.
1367 }
1368}
1369
1370
1371void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) {
1372 CHECK_NE(rd, kNoRegister);
1373 CHECK_NE(rm, kNoRegister);
1374 CheckCondition(cond);
1375 CHECK_NE(rd, PC);
1376 CHECK_NE(rm, PC);
1377 int32_t encoding = B31 | B30 | B29 | B28 | B27 |
1378 B25 | B23 | B21 | B20 |
1379 static_cast<uint32_t>(rm) << 16 |
1380 0xf << 12 |
1381 static_cast<uint32_t>(rd) << 8 |
1382 B7 |
1383 static_cast<uint32_t>(rm);
1384 Emit32(encoding);
1385}
1386
1387
1388void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
1389 CheckCondition(cond);
1390 bool must_be_32bit = force_32bit_;
1391 if (IsHighRegister(rd)|| imm16 >= 256u) {
1392 must_be_32bit = true;
1393 }
1394
1395 if (must_be_32bit) {
1396 // Use encoding T3.
1397 uint32_t imm4 = (imm16 >> 12) & 0b1111;
1398 uint32_t i = (imm16 >> 11) & 0b1;
1399 uint32_t imm3 = (imm16 >> 8) & 0b111;
1400 uint32_t imm8 = imm16 & 0xff;
1401 int32_t encoding = B31 | B30 | B29 | B28 |
1402 B25 | B22 |
1403 static_cast<uint32_t>(rd) << 8 |
1404 i << 26 |
1405 imm4 << 16 |
1406 imm3 << 12 |
1407 imm8;
1408 Emit32(encoding);
1409 } else {
1410 int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 |
1411 imm16;
1412 Emit16(encoding);
1413 }
1414}
1415
1416
1417void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
1418 CheckCondition(cond);
1419 // Always 32 bits.
1420 uint32_t imm4 = (imm16 >> 12) & 0b1111;
1421 uint32_t i = (imm16 >> 11) & 0b1;
1422 uint32_t imm3 = (imm16 >> 8) & 0b111;
1423 uint32_t imm8 = imm16 & 0xff;
1424 int32_t encoding = B31 | B30 | B29 | B28 |
1425 B25 | B23 | B22 |
1426 static_cast<uint32_t>(rd) << 8 |
1427 i << 26 |
1428 imm4 << 16 |
1429 imm3 << 12 |
1430 imm8;
1431 Emit32(encoding);
1432}
1433
1434
1435void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) {
1436 CHECK_NE(rn, kNoRegister);
1437 CHECK_NE(rt, kNoRegister);
1438 CheckCondition(cond);
1439 CHECK_NE(rn, kNoRegister);
1440 CHECK_NE(rt, kNoRegister);
1441 CheckCondition(cond);
1442 CHECK_LT(imm, (1u << 10));
1443
1444 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 |
1445 static_cast<uint32_t>(rn) << 16 |
1446 static_cast<uint32_t>(rt) << 12 |
1447 0xf << 8 |
1448 imm >> 2;
1449 Emit32(encoding);
1450}
1451
1452
1453void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) {
1454 ldrex(rt, rn, 0, cond);
1455}
1456
1457
1458void Thumb2Assembler::strex(Register rd,
1459 Register rt,
1460 Register rn,
1461 uint16_t imm,
1462 Condition cond) {
1463 CHECK_NE(rn, kNoRegister);
1464 CHECK_NE(rd, kNoRegister);
1465 CHECK_NE(rt, kNoRegister);
1466 CheckCondition(cond);
1467 CHECK_LT(imm, (1u << 10));
1468
1469 int32_t encoding = B31 | B30 | B29 | B27 | B22 |
1470 static_cast<uint32_t>(rn) << 16 |
1471 static_cast<uint32_t>(rt) << 12 |
1472 static_cast<uint32_t>(rd) << 8 |
1473 imm >> 2;
1474 Emit32(encoding);
1475}
1476
1477
1478void Thumb2Assembler::strex(Register rd,
1479 Register rt,
1480 Register rn,
1481 Condition cond) {
1482 strex(rd, rt, rn, 0, cond);
1483}
1484
1485
1486void Thumb2Assembler::clrex(Condition cond) {
1487 CheckCondition(cond);
1488 int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 |
1489 B21 | B20 |
1490 0xf << 16 |
1491 B15 |
1492 0xf << 8 |
1493 B5 |
1494 0xf;
1495 Emit32(encoding);
1496}
1497
1498
1499void Thumb2Assembler::nop(Condition cond) {
1500 CheckCondition(cond);
1501 int16_t encoding = B15 | B13 | B12 |
1502 B11 | B10 | B9 | B8;
1503 Emit16(encoding);
1504}
1505
1506
1507void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
1508 CHECK_NE(sn, kNoSRegister);
1509 CHECK_NE(rt, kNoRegister);
1510 CHECK_NE(rt, SP);
1511 CHECK_NE(rt, PC);
1512 CheckCondition(cond);
1513 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1514 B27 | B26 | B25 |
1515 ((static_cast<int32_t>(sn) >> 1)*B16) |
1516 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1517 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
1518 Emit32(encoding);
1519}
1520
1521
1522void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
1523 CHECK_NE(sn, kNoSRegister);
1524 CHECK_NE(rt, kNoRegister);
1525 CHECK_NE(rt, SP);
1526 CHECK_NE(rt, PC);
1527 CheckCondition(cond);
1528 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1529 B27 | B26 | B25 | B20 |
1530 ((static_cast<int32_t>(sn) >> 1)*B16) |
1531 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1532 ((static_cast<int32_t>(sn) & 1)*B7) | B4;
1533 Emit32(encoding);
1534}
1535
1536
1537void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
1538 Condition cond) {
1539 CHECK_NE(sm, kNoSRegister);
1540 CHECK_NE(sm, S31);
1541 CHECK_NE(rt, kNoRegister);
1542 CHECK_NE(rt, SP);
1543 CHECK_NE(rt, PC);
1544 CHECK_NE(rt2, kNoRegister);
1545 CHECK_NE(rt2, SP);
1546 CHECK_NE(rt2, PC);
1547 CheckCondition(cond);
1548 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1549 B27 | B26 | B22 |
1550 (static_cast<int32_t>(rt2)*B16) |
1551 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1552 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
1553 (static_cast<int32_t>(sm) >> 1);
1554 Emit32(encoding);
1555}
1556
1557
1558void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
1559 Condition cond) {
1560 CHECK_NE(sm, kNoSRegister);
1561 CHECK_NE(sm, S31);
1562 CHECK_NE(rt, kNoRegister);
1563 CHECK_NE(rt, SP);
1564 CHECK_NE(rt, PC);
1565 CHECK_NE(rt2, kNoRegister);
1566 CHECK_NE(rt2, SP);
1567 CHECK_NE(rt2, PC);
1568 CHECK_NE(rt, rt2);
1569 CheckCondition(cond);
1570 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1571 B27 | B26 | B22 | B20 |
1572 (static_cast<int32_t>(rt2)*B16) |
1573 (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1574 ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
1575 (static_cast<int32_t>(sm) >> 1);
1576 Emit32(encoding);
1577}
1578
1579
1580void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
1581 Condition cond) {
1582 CHECK_NE(dm, kNoDRegister);
1583 CHECK_NE(rt, kNoRegister);
1584 CHECK_NE(rt, SP);
1585 CHECK_NE(rt, PC);
1586 CHECK_NE(rt2, kNoRegister);
1587 CHECK_NE(rt2, SP);
1588 CHECK_NE(rt2, PC);
1589 CheckCondition(cond);
1590 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1591 B27 | B26 | B22 |
1592 (static_cast<int32_t>(rt2)*B16) |
1593 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
1594 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
1595 (static_cast<int32_t>(dm) & 0xf);
1596 Emit32(encoding);
1597}
1598
1599
1600void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
1601 Condition cond) {
1602 CHECK_NE(dm, kNoDRegister);
1603 CHECK_NE(rt, kNoRegister);
1604 CHECK_NE(rt, SP);
1605 CHECK_NE(rt, PC);
1606 CHECK_NE(rt2, kNoRegister);
1607 CHECK_NE(rt2, SP);
1608 CHECK_NE(rt2, PC);
1609 CHECK_NE(rt, rt2);
1610 CheckCondition(cond);
1611 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1612 B27 | B26 | B22 | B20 |
1613 (static_cast<int32_t>(rt2)*B16) |
1614 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
1615 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
1616 (static_cast<int32_t>(dm) & 0xf);
1617 Emit32(encoding);
1618}
1619
1620
1621void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
1622 const Address& addr = static_cast<const Address&>(ad);
1623 CHECK_NE(sd, kNoSRegister);
1624 CheckCondition(cond);
1625 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1626 B27 | B26 | B24 | B20 |
1627 ((static_cast<int32_t>(sd) & 1)*B22) |
1628 ((static_cast<int32_t>(sd) >> 1)*B12) |
1629 B11 | B9 | addr.vencoding();
1630 Emit32(encoding);
1631}
1632
1633
1634void Thumb2Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
1635 const Address& addr = static_cast<const Address&>(ad);
1636 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1637 CHECK_NE(sd, kNoSRegister);
1638 CheckCondition(cond);
1639 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1640 B27 | B26 | B24 |
1641 ((static_cast<int32_t>(sd) & 1)*B22) |
1642 ((static_cast<int32_t>(sd) >> 1)*B12) |
1643 B11 | B9 | addr.vencoding();
1644 Emit32(encoding);
1645}
1646
1647
1648void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
1649 const Address& addr = static_cast<const Address&>(ad);
1650 CHECK_NE(dd, kNoDRegister);
1651 CheckCondition(cond);
1652 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1653 B27 | B26 | B24 | B20 |
1654 ((static_cast<int32_t>(dd) >> 4)*B22) |
1655 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1656 B11 | B9 | B8 | addr.vencoding();
1657 Emit32(encoding);
1658}
1659
1660
1661void Thumb2Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
1662 const Address& addr = static_cast<const Address&>(ad);
1663 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1664 CHECK_NE(dd, kNoDRegister);
1665 CheckCondition(cond);
1666 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1667 B27 | B26 | B24 |
1668 ((static_cast<int32_t>(dd) >> 4)*B22) |
1669 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1670 B11 | B9 | B8 | addr.vencoding();
1671 Emit32(encoding);
1672}
1673
1674
1675void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
1676 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
1677}
1678
1679
1680void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
1681 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
1682}
1683
1684
1685void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) {
1686 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
1687}
1688
1689
1690void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
1691 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
1692}
1693
1694
1695void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
1696 CheckCondition(cond);
1697
1698 uint32_t D;
1699 uint32_t Vd;
1700 if (dbl) {
1701 // Encoded as D:Vd.
1702 D = (reg >> 4) & 1;
1703 Vd = reg & 0b1111;
1704 } else {
1705 // Encoded as Vd:D.
1706 D = reg & 1;
1707 Vd = (reg >> 1) & 0b1111;
1708 }
1709 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
1710 B11 | B9 |
1711 (dbl ? B8 : 0) |
1712 (push ? B24 : (B23 | B20)) |
1713 0b1110 << 28 |
1714 nregs << (dbl ? 1 : 0) |
1715 D << 22 |
1716 Vd << 12;
1717 Emit32(encoding);
1718}
1719
1720
1721void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode,
1722 SRegister sd, SRegister sn, SRegister sm) {
1723 CHECK_NE(sd, kNoSRegister);
1724 CHECK_NE(sn, kNoSRegister);
1725 CHECK_NE(sm, kNoSRegister);
1726 CheckCondition(cond);
1727 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1728 B27 | B26 | B25 | B11 | B9 | opcode |
1729 ((static_cast<int32_t>(sd) & 1)*B22) |
1730 ((static_cast<int32_t>(sn) >> 1)*B16) |
1731 ((static_cast<int32_t>(sd) >> 1)*B12) |
1732 ((static_cast<int32_t>(sn) & 1)*B7) |
1733 ((static_cast<int32_t>(sm) & 1)*B5) |
1734 (static_cast<int32_t>(sm) >> 1);
1735 Emit32(encoding);
1736}
1737
1738
1739void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1740 DRegister dd, DRegister dn, DRegister dm) {
1741 CHECK_NE(dd, kNoDRegister);
1742 CHECK_NE(dn, kNoDRegister);
1743 CHECK_NE(dm, kNoDRegister);
1744 CheckCondition(cond);
1745 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1746 B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1747 ((static_cast<int32_t>(dd) >> 4)*B22) |
1748 ((static_cast<int32_t>(dn) & 0xf)*B16) |
1749 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1750 ((static_cast<int32_t>(dn) >> 4)*B7) |
1751 ((static_cast<int32_t>(dm) >> 4)*B5) |
1752 (static_cast<int32_t>(dm) & 0xf);
1753 Emit32(encoding);
1754}
1755
1756
1757void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1758 SRegister sd, DRegister dm) {
1759 CHECK_NE(sd, kNoSRegister);
1760 CHECK_NE(dm, kNoDRegister);
1761 CheckCondition(cond);
1762 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1763 B27 | B26 | B25 | B11 | B9 | opcode |
1764 ((static_cast<int32_t>(sd) & 1)*B22) |
1765 ((static_cast<int32_t>(sd) >> 1)*B12) |
1766 ((static_cast<int32_t>(dm) >> 4)*B5) |
1767 (static_cast<int32_t>(dm) & 0xf);
1768 Emit32(encoding);
1769}
1770
1771
1772void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode,
1773 DRegister dd, SRegister sm) {
1774 CHECK_NE(dd, kNoDRegister);
1775 CHECK_NE(sm, kNoSRegister);
1776 CheckCondition(cond);
1777 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1778 B27 | B26 | B25 | B11 | B9 | opcode |
1779 ((static_cast<int32_t>(dd) >> 4)*B22) |
1780 ((static_cast<int32_t>(dd) & 0xf)*B12) |
1781 ((static_cast<int32_t>(sm) & 1)*B5) |
1782 (static_cast<int32_t>(sm) >> 1);
1783 Emit32(encoding);
1784}
1785
1786
1787void Thumb2Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR.
1788 CheckCondition(cond);
1789 UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction";
1790}
1791
1792
1793void Thumb2Assembler::svc(uint32_t imm8) {
1794 CHECK(IsUint(8, imm8)) << imm8;
1795 int16_t encoding = B15 | B14 | B12 |
1796 B11 | B10 | B9 | B8 |
1797 imm8;
1798 Emit16(encoding);
1799}
1800
1801
1802void Thumb2Assembler::bkpt(uint16_t imm8) {
1803 CHECK(IsUint(8, imm8)) << imm8;
1804 int16_t encoding = B15 | B13 | B12 |
1805 B11 | B10 | B9 |
1806 imm8;
1807 Emit16(encoding);
1808}
1809
1810// Convert the given IT state to a mask bit given bit 0 of the first
1811// condition and a shift position.
1812static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) {
1813 switch (s) {
1814 case kItOmitted: return 1 << shift;
1815 case kItThen: return firstcond0 << shift;
1816 case kItElse: return !firstcond0 << shift;
1817 }
1818 return 0;
1819}
1820
1821
1822// Set the IT condition in the given position for the given state. This is used
1823// to check that conditional instructions match the preceding IT statement.
1824void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) {
1825 switch (s) {
1826 case kItOmitted: it_conditions_[index] = AL; break;
1827 case kItThen: it_conditions_[index] = cond; break;
1828 case kItElse:
1829 it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1);
1830 break;
1831 }
1832}
1833
1834
1835void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) {
1836 CheckCondition(AL); // Not allowed in IT block.
1837 uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1;
1838
1839 // All conditions to AL.
1840 for (uint8_t i = 0; i < 4; ++i) {
1841 it_conditions_[i] = AL;
1842 }
1843
1844 SetItCondition(kItThen, firstcond, 0);
1845 uint8_t mask = ToItMask(i1, firstcond0, 3);
1846 SetItCondition(i1, firstcond, 1);
1847
1848 if (i1 != kItOmitted) {
1849 mask |= ToItMask(i2, firstcond0, 2);
1850 SetItCondition(i2, firstcond, 2);
1851 if (i2 != kItOmitted) {
1852 mask |= ToItMask(i3, firstcond0, 1);
1853 SetItCondition(i3, firstcond, 3);
1854 if (i3 != kItOmitted) {
1855 mask |= 0b0001;
1856 }
1857 }
1858 }
1859
1860 // Start at first condition.
1861 it_cond_index_ = 0;
1862 next_condition_ = it_conditions_[0];
1863 uint16_t encoding = B15 | B13 | B12 |
1864 B11 | B10 | B9 | B8 |
1865 firstcond << 4 |
1866 mask;
1867 Emit16(encoding);
1868}
1869
1870
1871void Thumb2Assembler::cbz(Register rn, Label* label) {
1872 CheckCondition(AL);
1873 if (label->IsBound()) {
1874 LOG(FATAL) << "cbz can only be used to branch forwards";
1875 } else {
1876 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false);
1877 label->LinkTo(branchid);
1878 }
1879}
1880
1881
1882void Thumb2Assembler::cbnz(Register rn, Label* label) {
1883 CheckCondition(AL);
1884 if (label->IsBound()) {
1885 LOG(FATAL) << "cbnz can only be used to branch forwards";
1886 } else {
1887 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true);
1888 label->LinkTo(branchid);
1889 }
1890}
1891
1892
1893void Thumb2Assembler::blx(Register rm, Condition cond) {
1894 CHECK_NE(rm, kNoRegister);
1895 CheckCondition(cond);
1896 int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3;
1897 Emit16(encoding);
1898}
1899
1900
1901void Thumb2Assembler::bx(Register rm, Condition cond) {
1902 CHECK_NE(rm, kNoRegister);
1903 CheckCondition(cond);
1904 int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3;
1905 Emit16(encoding);
1906}
1907
1908
1909void Thumb2Assembler::Push(Register rd, Condition cond) {
1910 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
1911}
1912
1913
1914void Thumb2Assembler::Pop(Register rd, Condition cond) {
1915 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
1916}
1917
1918
1919void Thumb2Assembler::PushList(RegList regs, Condition cond) {
1920 stm(DB_W, SP, regs, cond);
1921}
1922
1923
1924void Thumb2Assembler::PopList(RegList regs, Condition cond) {
1925 ldm(IA_W, SP, regs, cond);
1926}
1927
1928
1929void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) {
1930 if (cond != AL || rd != rm) {
1931 mov(rd, ShifterOperand(rm), cond);
1932 }
1933}
1934
1935
1936// A branch has changed size. Make a hole for it.
1937void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) {
1938 // Move the contents of the buffer using: Move(newposition, oldposition)
1939 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1940 buffer_.Move(location + delta, location);
1941}
1942
1943
1944void Thumb2Assembler::Bind(Label* label) {
1945 CHECK(!label->IsBound());
1946 uint32_t bound_pc = buffer_.Size();
1947 std::vector<Branch*> changed_branches;
1948
1949 while (label->IsLinked()) {
1950 uint16_t position = label->Position(); // Branch id for linked branch.
1951 Branch* branch = GetBranch(position); // Get the branch at this id.
1952 bool changed = branch->Resolve(bound_pc); // Branch can be resolved now.
1953 uint32_t branch_location = branch->GetLocation();
1954 uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain.
1955 if (changed) {
1956 MakeHoleForBranch(branch->GetLocation(), 2);
1957 if (branch->IsCompareAndBranch()) {
1958 // A cbz/cbnz instruction has changed size. There is no valid encoding for
1959 // a 32 bit cbz/cbnz so we need to change this to an instruction pair:
1960 // cmp rn, #0
1961 // b<eq|ne> target
1962 bool n = branch->GetType() == Branch::kCompareAndBranchNonZero;
1963 Condition cond = n ? NE : EQ;
1964 branch->Move(2); // Move the branch forward by 2 bytes.
1965 branch->ResetTypeAndCondition(Branch::kConditional, cond);
1966 branch->ResetSize(Branch::k16Bit);
1967
1968 // Now add a compare instruction in the place the branch was.
1969 int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8;
1970 buffer_.Store<int16_t>(branch_location, cmp);
1971
1972 // Since have moved made a hole in the code we need to reload the
1973 // current pc.
1974 bound_pc = buffer_.Size();
1975
1976 // Now resolve the newly added branch.
1977 changed = branch->Resolve(bound_pc);
1978 if (changed) {
1979 MakeHoleForBranch(branch->GetLocation(), 2);
1980 changed_branches.push_back(branch);
1981 }
1982 } else {
1983 changed_branches.push_back(branch);
1984 }
1985 }
1986 label->position_ = next; // Move to next.
1987 }
1988 label->BindTo(bound_pc);
1989
1990 // Now relocate any changed branches. Do this until there are no more changes.
1991 std::vector<Branch*> branches_to_process = changed_branches;
1992 while (branches_to_process.size() != 0) {
1993 changed_branches.clear();
1994 for (auto& changed_branch : branches_to_process) {
1995 for (auto& branch : branches_) {
1996 bool changed = branch->Relocate(changed_branch->GetLocation(), 2);
1997 if (changed) {
1998 changed_branches.push_back(branch);
1999 }
2000 }
2001 branches_to_process = changed_branches;
2002 }
2003 }
2004}
2005
2006
2007void Thumb2Assembler::EmitBranches() {
2008 for (auto& branch : branches_) {
2009 branch->Emit(&buffer_);
2010 }
2011}
2012
2013
2014void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
2015 Condition cond) {
2016 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
2017 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
2018}
2019
2020
2021void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
2022 Condition cond) {
2023 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
2024 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
2025 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
2026}
2027
2028
2029void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
2030 Condition cond) {
2031 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
2032 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
2033 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
2034}
2035
2036
2037void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
2038 Condition cond) {
2039 CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
2040 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
2041}
2042
2043
2044void Thumb2Assembler::Rrx(Register rd, Register rm, Condition cond) {
2045 mov(rd, ShifterOperand(rm, ROR, 0), cond);
2046}
2047
2048
2049int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
2050 // The offset is off by 4 due to the way the ARM CPUs read PC.
2051 offset -= 4;
2052 offset >>= 1;
2053
2054 uint32_t value = 0;
2055 // There are two different encodings depending on the value of bit 12. In one case
2056 // intermediate values are calculated using the sign bit.
2057 if ((inst & B12) == B12) {
2058 // 25 bits of offset.
2059 uint32_t signbit = (offset >> 31) & 0x1;
2060 uint32_t i1 = (offset >> 22) & 0x1;
2061 uint32_t i2 = (offset >> 21) & 0x1;
2062 uint32_t imm10 = (offset >> 11) & 0x03ff;
2063 uint32_t imm11 = offset & 0x07ff;
2064 uint32_t j1 = (i1 ^ signbit) ? 0 : 1;
2065 uint32_t j2 = (i2 ^ signbit) ? 0 : 1;
2066 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) |
2067 imm11;
2068 // Remove the offset from the current encoding.
2069 inst &= ~(0x3ff << 16 | 0x7ff);
2070 } else {
2071 uint32_t signbit = (offset >> 31) & 0x1;
2072 uint32_t imm6 = (offset >> 11) & 0x03f;
2073 uint32_t imm11 = offset & 0x07ff;
2074 uint32_t j1 = (offset >> 19) & 1;
2075 uint32_t j2 = (offset >> 17) & 1;
2076 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) |
2077 imm11;
2078 // Remove the offset from the current encoding.
2079 inst &= ~(0x3f << 16 | 0x7ff);
2080 }
2081 // Mask out offset bits in current instruction.
2082 inst &= ~(B26 | B13 | B11);
2083 inst |= value;
2084 return inst;
2085}
2086
2087
2088int Thumb2Assembler::DecodeBranchOffset(int32_t instr) {
2089 int32_t imm32;
2090 if ((instr & B12) == B12) {
2091 uint32_t S = (instr >> 26) & 1;
2092 uint32_t J2 = (instr >> 11) & 1;
2093 uint32_t J1 = (instr >> 13) & 1;
2094 uint32_t imm10 = (instr >> 16) & 0x3FF;
2095 uint32_t imm11 = instr & 0x7FF;
2096
2097 uint32_t I1 = ~(J1 ^ S) & 1;
2098 uint32_t I2 = ~(J2 ^ S) & 1;
2099 imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2100 imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate.
2101 } else {
2102 uint32_t S = (instr >> 26) & 1;
2103 uint32_t J2 = (instr >> 11) & 1;
2104 uint32_t J1 = (instr >> 13) & 1;
2105 uint32_t imm6 = (instr >> 16) & 0x3F;
2106 uint32_t imm11 = instr & 0x7FF;
2107
2108 imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2109 imm32 = (imm32 << 11) >> 11; // sign extend 21 bit immediate.
2110 }
2111 imm32 += 4;
2112 return imm32;
2113}
2114
2115
2116void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
2117 AddConstant(rd, rd, value, cond);
2118}
2119
2120
2121void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value,
2122 Condition cond) {
2123 if (value == 0) {
2124 if (rd != rn) {
2125 mov(rd, ShifterOperand(rn), cond);
2126 }
2127 return;
2128 }
2129 // We prefer to select the shorter code sequence rather than selecting add for
2130 // positive values and sub for negatives ones, which would slightly improve
2131 // the readability of generated code for some constants.
2132 ShifterOperand shifter_op;
2133 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
2134 add(rd, rn, shifter_op, cond);
2135 } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) {
2136 sub(rd, rn, shifter_op, cond);
2137 } else {
2138 CHECK(rn != IP);
2139 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
2140 mvn(IP, shifter_op, cond);
2141 add(rd, rn, ShifterOperand(IP), cond);
2142 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
2143 mvn(IP, shifter_op, cond);
2144 sub(rd, rn, ShifterOperand(IP), cond);
2145 } else {
2146 movw(IP, Low16Bits(value), cond);
2147 uint16_t value_high = High16Bits(value);
2148 if (value_high != 0) {
2149 movt(IP, value_high, cond);
2150 }
2151 add(rd, rn, ShifterOperand(IP), cond);
2152 }
2153 }
2154}
2155
2156
2157void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
2158 Condition cond) {
2159 ShifterOperand shifter_op;
2160 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
2161 adds(rd, rn, shifter_op, cond);
2162 } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) {
2163 subs(rd, rn, shifter_op, cond);
2164 } else {
2165 CHECK(rn != IP);
2166 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
2167 mvn(IP, shifter_op, cond);
2168 adds(rd, rn, ShifterOperand(IP), cond);
2169 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
2170 mvn(IP, shifter_op, cond);
2171 subs(rd, rn, ShifterOperand(IP), cond);
2172 } else {
2173 movw(IP, Low16Bits(value), cond);
2174 uint16_t value_high = High16Bits(value);
2175 if (value_high != 0) {
2176 movt(IP, value_high, cond);
2177 }
2178 adds(rd, rn, ShifterOperand(IP), cond);
2179 }
2180 }
2181}
2182
2183
2184void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
2185 ShifterOperand shifter_op;
2186 if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) {
2187 mov(rd, shifter_op, cond);
2188 } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) {
2189 mvn(rd, shifter_op, cond);
2190 } else {
2191 movw(rd, Low16Bits(value), cond);
2192 uint16_t value_high = High16Bits(value);
2193 if (value_high != 0) {
2194 movt(rd, value_high, cond);
2195 }
2196 }
2197}
2198
2199// Implementation note: this method must emit at most one instruction when
2200// Address::CanHoldLoadOffsetThumb.
2201void Thumb2Assembler::LoadFromOffset(LoadOperandType type,
2202 Register reg,
2203 Register base,
2204 int32_t offset,
2205 Condition cond) {
2206 if (!Address::CanHoldLoadOffsetThumb(type, offset)) {
2207 CHECK(base != IP);
2208 LoadImmediate(IP, offset, cond);
2209 add(IP, IP, ShifterOperand(base), cond);
2210 base = IP;
2211 offset = 0;
2212 }
2213 CHECK(Address::CanHoldLoadOffsetThumb(type, offset));
2214 switch (type) {
2215 case kLoadSignedByte:
2216 ldrsb(reg, Address(base, offset), cond);
2217 break;
2218 case kLoadUnsignedByte:
2219 ldrb(reg, Address(base, offset), cond);
2220 break;
2221 case kLoadSignedHalfword:
2222 ldrsh(reg, Address(base, offset), cond);
2223 break;
2224 case kLoadUnsignedHalfword:
2225 ldrh(reg, Address(base, offset), cond);
2226 break;
2227 case kLoadWord:
2228 ldr(reg, Address(base, offset), cond);
2229 break;
2230 case kLoadWordPair:
2231 ldrd(reg, Address(base, offset), cond);
2232 break;
2233 default:
2234 LOG(FATAL) << "UNREACHABLE";
2235 }
2236}
2237
2238
2239// Implementation note: this method must emit at most one instruction when
2240// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset.
2241void Thumb2Assembler::LoadSFromOffset(SRegister reg,
2242 Register base,
2243 int32_t offset,
2244 Condition cond) {
2245 if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) {
2246 CHECK_NE(base, IP);
2247 LoadImmediate(IP, offset, cond);
2248 add(IP, IP, ShifterOperand(base), cond);
2249 base = IP;
2250 offset = 0;
2251 }
2252 CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset));
2253 vldrs(reg, Address(base, offset), cond);
2254}
2255
2256
2257// Implementation note: this method must emit at most one instruction when
2258// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset.
2259void Thumb2Assembler::LoadDFromOffset(DRegister reg,
2260 Register base,
2261 int32_t offset,
2262 Condition cond) {
2263 if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) {
2264 CHECK_NE(base, IP);
2265 LoadImmediate(IP, offset, cond);
2266 add(IP, IP, ShifterOperand(base), cond);
2267 base = IP;
2268 offset = 0;
2269 }
2270 CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset));
2271 vldrd(reg, Address(base, offset), cond);
2272}
2273
2274
2275// Implementation note: this method must emit at most one instruction when
2276// Address::CanHoldStoreOffsetThumb.
2277void Thumb2Assembler::StoreToOffset(StoreOperandType type,
2278 Register reg,
2279 Register base,
2280 int32_t offset,
2281 Condition cond) {
2282 if (!Address::CanHoldStoreOffsetThumb(type, offset)) {
2283 CHECK(reg != IP);
2284 CHECK(base != IP);
2285 LoadImmediate(IP, offset, cond);
2286 add(IP, IP, ShifterOperand(base), cond);
2287 base = IP;
2288 offset = 0;
2289 }
2290 CHECK(Address::CanHoldStoreOffsetThumb(type, offset));
2291 switch (type) {
2292 case kStoreByte:
2293 strb(reg, Address(base, offset), cond);
2294 break;
2295 case kStoreHalfword:
2296 strh(reg, Address(base, offset), cond);
2297 break;
2298 case kStoreWord:
2299 str(reg, Address(base, offset), cond);
2300 break;
2301 case kStoreWordPair:
2302 strd(reg, Address(base, offset), cond);
2303 break;
2304 default:
2305 LOG(FATAL) << "UNREACHABLE";
2306 }
2307}
2308
2309
2310// Implementation note: this method must emit at most one instruction when
2311// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset.
2312void Thumb2Assembler::StoreSToOffset(SRegister reg,
2313 Register base,
2314 int32_t offset,
2315 Condition cond) {
2316 if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) {
2317 CHECK_NE(base, IP);
2318 LoadImmediate(IP, offset, cond);
2319 add(IP, IP, ShifterOperand(base), cond);
2320 base = IP;
2321 offset = 0;
2322 }
2323 CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset));
2324 vstrs(reg, Address(base, offset), cond);
2325}
2326
2327
2328// Implementation note: this method must emit at most one instruction when
2329// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset.
2330void Thumb2Assembler::StoreDToOffset(DRegister reg,
2331 Register base,
2332 int32_t offset,
2333 Condition cond) {
2334 if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) {
2335 CHECK_NE(base, IP);
2336 LoadImmediate(IP, offset, cond);
2337 add(IP, IP, ShifterOperand(base), cond);
2338 base = IP;
2339 offset = 0;
2340 }
2341 CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset));
2342 vstrd(reg, Address(base, offset), cond);
2343}
2344
2345
2346void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) {
2347 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
2348#if ANDROID_SMP != 0
2349 int32_t encoding = 0xf3bf8f5f; // dmb in T1 encoding.
2350 Emit32(encoding);
2351#endif
2352}
2353
2354
2355void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) {
2356 cbz(r, label);
2357}
2358
2359
2360void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
2361 cbnz(r, label);
2362}
2363} // namespace arm
2364} // namespace art