assembler_thumb2.cc revision 3c7bb98698f77af10372cf31824d3bb115d9bf0f
1/*
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);
332    CHECK(am == DB_W);      // Only writeback is supported.
333    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);
355    CHECK(am == IA || am == IA_W);
356    Address::Mode strmode = am == IA ? Address::PreIndex : Address::Offset;
357    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)
623      || ((opcode == ADD || opcode == SUB) && (rn == rd));
624
625  if (IsHighRegister(rd) || IsHighRegister(rn)) {
626    if (can_contain_high_register) {
627      // There are high register instructions available for this opcode.
628      // However, there is no RRX available.
629      if (so.IsShift() && so.GetShift() == RRX) {
630        return true;
631      }
632
633      // Check special case for SP relative ADD and SUB immediate.
634      if ((opcode == ADD || opcode == SUB) && so.IsImmediate()) {
635        // If rn is SP and rd is a high register we need to use a 32 bit encoding.
636         if (rn == SP && rd != SP && IsHighRegister(rd)) {
637           return true;
638         }
639
640         uint32_t imm = so.GetImmediate();
641         // If the immediates are out of range use 32 bit.
642         if (rd == SP && rn == SP) {
643           if (imm > (1 << 9)) {    // 9 bit immediate.
644             return true;
645           }
646         } 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    if (!can_contain_high_register) {
664      return true;
665    }
666  }
667
668  if (so.IsRegister() && IsHighRegister(so.GetRegister()) && !can_contain_high_register) {
669    return true;
670  }
671
672  // Check for MOV with an ROR.
673  if (opcode == MOV && so.IsRegister() && so.IsShift() && so.GetShift() == ROR) {
674    if (so.GetImmediate() != 0) {
675      return true;
676    }
677  }
678
679  bool rn_is_valid = true;
680
681  // Check for single operand instructions and ADD/SUB.
682  switch (opcode) {
683    case CMP:
684    case MOV:
685    case TST:
686    case MVN:
687      rn_is_valid = false;      // There is no Rn for these instructions.
688      break;
689    case TEQ:
690      return true;
691      break;
692    case ADD:
693    case SUB:
694      break;
695    default:
696      if (so.IsRegister() && rd != rn) {
697        return true;
698      }
699  }
700
701  if (so.IsImmediate()) {
702    if (rn_is_valid && rn != rd) {
703      // The only thumb1 instruction with a register and an immediate are ADD and SUB.  The
704      // immediate must be 3 bits.
705      if (opcode != ADD && opcode != SUB) {
706        return true;
707      } else {
708        // Check that the immediate is 3 bits for ADD and SUB.
709        if (so.GetImmediate() >= 8) {
710          return true;
711        }
712      }
713    } else {
714      // ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits.
715      if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) {
716        return true;
717      } else {
718        if (so.GetImmediate() > 255) {
719          return true;
720        }
721      }
722    }
723  }
724
725  // The instruction can be encoded in 16 bits.
726  return false;
727}
728
729
730void Thumb2Assembler::Emit32BitDataProcessing(Condition cond,
731                                              Opcode opcode,
732                                              int set_cc,
733                                              Register rn,
734                                              Register rd,
735                                              const ShifterOperand& so) {
736  uint8_t thumb_opcode = 0b11111111;
737  switch (opcode) {
738    case AND: thumb_opcode = 0b0000; break;
739    case EOR: thumb_opcode = 0b0100; break;
740    case SUB: thumb_opcode = 0b1101; break;
741    case RSB: thumb_opcode = 0b1110; break;
742    case ADD: thumb_opcode = 0b1000; break;
743    case ADC: thumb_opcode = 0b1010; break;
744    case SBC: thumb_opcode = 0b1011; break;
745    case RSC: break;
746    case TST: thumb_opcode = 0b0000; set_cc = true; rd = PC; break;
747    case TEQ: thumb_opcode = 0b0100; set_cc = true; rd = PC; break;
748    case CMP: thumb_opcode = 0b1101; set_cc = true; rd = PC; break;
749    case CMN: thumb_opcode = 0b1000; set_cc = true; rd = PC; break;
750    case ORR: thumb_opcode = 0b0010; break;
751    case MOV: thumb_opcode = 0b0010; rn = PC; break;
752    case BIC: thumb_opcode = 0b0001; break;
753    case MVN: thumb_opcode = 0b0011; rn = PC; break;
754    default:
755      break;
756  }
757
758  if (thumb_opcode == 0b11111111) {
759    LOG(FATAL) << "Invalid thumb2 opcode " << opcode;
760  }
761
762  int32_t encoding = 0;
763  if (so.IsImmediate()) {
764    // Check special cases.
765    if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
766      if (opcode == SUB) {
767        thumb_opcode = 0b0101;
768      } else {
769        thumb_opcode = 0;
770      }
771      uint32_t imm = so.GetImmediate();
772
773      uint32_t i = (imm >> 11) & 1;
774      uint32_t imm3 = (imm >> 8) & 0b111;
775      uint32_t imm8 = imm & 0xff;
776
777      encoding = B31 | B30 | B29 | B28 | B25 |
778           thumb_opcode << 21 |
779           rn << 16 |
780           rd << 8 |
781           i << 26 |
782           imm3 << 12 |
783           imm8;
784    } else {
785      // Modified immediate.
786      uint32_t imm = ModifiedImmediate(so.encodingThumb());
787      if (imm == kInvalidModifiedImmediate) {
788        LOG(FATAL) << "Immediate value cannot fit in thumb2 modified immediate";
789      }
790      encoding = B31 | B30 | B29 | B28 |
791          thumb_opcode << 21 |
792          set_cc << 20 |
793          rn << 16 |
794          rd << 8 |
795          imm;
796    }
797  } else if (so.IsRegister()) {
798     // Register (possibly shifted)
799     encoding = B31 | B30 | B29 | B27 | B25 |
800         thumb_opcode << 21 |
801         set_cc << 20 |
802         rn << 16 |
803         rd << 8 |
804         so.encodingThumb();
805  }
806  Emit32(encoding);
807}
808
809
810void Thumb2Assembler::Emit16BitDataProcessing(Condition cond,
811                                              Opcode opcode,
812                                              int set_cc,
813                                              Register rn,
814                                              Register rd,
815                                              const ShifterOperand& so) {
816  if (opcode == ADD || opcode == SUB) {
817    Emit16BitAddSub(cond, opcode, set_cc, rn, rd, so);
818    return;
819  }
820  uint8_t thumb_opcode = 0b11111111;
821  // Thumb1.
822  uint8_t dp_opcode = 0b01;
823  uint8_t opcode_shift = 6;
824  uint8_t rd_shift = 0;
825  uint8_t rn_shift = 3;
826  uint8_t immediate_shift = 0;
827  bool use_immediate = false;
828  uint8_t immediate = 0;
829
830  if (opcode == MOV && so.IsRegister() && so.IsShift()) {
831    // Convert shifted mov operand2 into 16 bit opcodes.
832    dp_opcode = 0;
833    opcode_shift = 11;
834
835    use_immediate = true;
836    immediate = so.GetImmediate();
837    immediate_shift = 6;
838
839    rn = so.GetRegister();
840
841    switch (so.GetShift()) {
842    case LSL: thumb_opcode = 0b00; break;
843    case LSR: thumb_opcode = 0b01; break;
844    case ASR: thumb_opcode = 0b10; break;
845    case ROR:
846      // ROR doesn't allow immediates.
847      thumb_opcode = 0b111;
848      dp_opcode = 0b01;
849      opcode_shift = 6;
850      use_immediate = false;
851      break;
852    case RRX: break;
853    default:
854     break;
855    }
856  } else {
857    if (so.IsImmediate()) {
858      use_immediate = true;
859      immediate = so.GetImmediate();
860    }
861
862    switch (opcode) {
863      case AND: thumb_opcode = 0b0000; break;
864      case EOR: thumb_opcode = 0b0001; break;
865      case SUB: break;
866      case RSB: thumb_opcode = 0b1001; break;
867      case ADD: break;
868      case ADC: thumb_opcode = 0b0101; break;
869      case SBC: thumb_opcode = 0b0110; break;
870      case RSC: break;
871      case TST: thumb_opcode = 0b1000; rn = so.GetRegister(); break;
872      case TEQ: break;
873      case CMP:
874        if (use_immediate) {
875          // T2 encoding.
876           dp_opcode = 0;
877           opcode_shift = 11;
878           thumb_opcode = 0b101;
879           rd_shift = 8;
880           rn_shift = 8;
881        } else {
882          thumb_opcode = 0b1010;
883          rd = rn;
884          rn = so.GetRegister();
885        }
886
887        break;
888      case CMN: {
889        thumb_opcode = 0b1011;
890        rd = rn;
891        rn = so.GetRegister();
892        break;
893      }
894      case ORR: thumb_opcode = 0b1100; break;
895      case MOV:
896        dp_opcode = 0;
897        if (use_immediate) {
898          // T2 encoding.
899          opcode_shift = 11;
900          thumb_opcode = 0b100;
901          rd_shift = 8;
902          rn_shift = 8;
903        } else {
904          rn = so.GetRegister();
905          if (IsHighRegister(rn) || IsHighRegister(rd)) {
906            // Special mov for high registers.
907            dp_opcode = 0b01;
908            opcode_shift = 7;
909            // Put the top bit of rd into the bottom bit of the opcode.
910            thumb_opcode = 0b0001100 | static_cast<uint32_t>(rd) >> 3;
911            rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111);
912          } else {
913            thumb_opcode = 0;
914          }
915        }
916        break;
917      case BIC: thumb_opcode = 0b1110; break;
918      case MVN: thumb_opcode = 0b1111; rn = so.GetRegister(); break;
919      default:
920        break;
921    }
922  }
923
924  if (thumb_opcode == 0b11111111) {
925    LOG(FATAL) << "Invalid thumb1 opcode " << opcode;
926  }
927
928  int16_t encoding = dp_opcode << 14 |
929      (thumb_opcode << opcode_shift) |
930      rd << rd_shift |
931      rn << rn_shift |
932      (use_immediate ? (immediate << immediate_shift) : 0);
933
934  Emit16(encoding);
935}
936
937
938// ADD and SUB are complex enough to warrant their own emitter.
939void Thumb2Assembler::Emit16BitAddSub(Condition cond,
940                                      Opcode opcode,
941                                      int set_cc,
942                                      Register rn,
943                                      Register rd,
944                                      const ShifterOperand& so) {
945  uint8_t dp_opcode = 0;
946  uint8_t opcode_shift = 6;
947  uint8_t rd_shift = 0;
948  uint8_t rn_shift = 3;
949  uint8_t immediate_shift = 0;
950  bool use_immediate = false;
951  uint8_t immediate = 0;
952  uint8_t thumb_opcode;;
953
954  if (so.IsImmediate()) {
955    use_immediate = true;
956    immediate = so.GetImmediate();
957  }
958
959  switch (opcode) {
960    case ADD:
961      if (so.IsRegister()) {
962        Register rm = so.GetRegister();
963        if (rn == rd) {
964          // Can use T2 encoding (allows 4 bit registers)
965          dp_opcode = 0b01;
966          opcode_shift = 10;
967          thumb_opcode = 0b0001;
968          // Make Rn also contain the top bit of rd.
969          rn = static_cast<Register>(static_cast<uint32_t>(rm) |
970                                     (static_cast<uint32_t>(rd) & 0b1000) << 1);
971          rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111);
972        } else {
973          // T1.
974          opcode_shift = 9;
975          thumb_opcode = 0b01100;
976          immediate = static_cast<uint32_t>(so.GetRegister());
977          use_immediate = true;
978          immediate_shift = 6;
979        }
980      } else {
981        // Immediate.
982        if (rd == SP && rn == SP) {
983          // ADD sp, sp, #imm
984          dp_opcode = 0b10;
985          thumb_opcode = 0b11;
986          opcode_shift = 12;
987          CHECK_LT(immediate, (1 << 9));
988          CHECK_EQ((immediate & 0b11), 0);
989
990          // Remove rd and rn from instruction by orring it with immed and clearing bits.
991          rn = R0;
992          rd = R0;
993          rd_shift = 0;
994          rn_shift = 0;
995          immediate >>= 2;
996        } else if (rd != SP && rn == SP) {
997          // ADD rd, SP, #imm
998          dp_opcode = 0b10;
999          thumb_opcode = 0b101;
1000          opcode_shift = 11;
1001          CHECK_LT(immediate, (1 << 10));
1002          CHECK_EQ((immediate & 0b11), 0);
1003
1004          // Remove rn from instruction.
1005          rn = R0;
1006          rn_shift = 0;
1007          rd_shift = 8;
1008          immediate >>= 2;
1009        } else if (rn != rd) {
1010          // Must use T1.
1011          opcode_shift = 9;
1012          thumb_opcode = 0b01110;
1013          immediate_shift = 6;
1014        } else {
1015          // T2 encoding.
1016          opcode_shift = 11;
1017          thumb_opcode = 0b110;
1018          rd_shift = 8;
1019          rn_shift = 8;
1020        }
1021      }
1022      break;
1023
1024    case SUB:
1025      if (so.IsRegister()) {
1026         // T1.
1027         opcode_shift = 9;
1028         thumb_opcode = 0b01101;
1029         immediate = static_cast<uint32_t>(so.GetRegister());
1030         use_immediate = true;
1031         immediate_shift = 6;
1032       } else {
1033         if (rd == SP && rn == SP) {
1034           // SUB sp, sp, #imm
1035           dp_opcode = 0b10;
1036           thumb_opcode = 0b1100001;
1037           opcode_shift = 7;
1038           CHECK_LT(immediate, (1 << 9));
1039           CHECK_EQ((immediate & 0b11), 0);
1040
1041           // Remove rd and rn from instruction by orring it with immed and clearing bits.
1042           rn = R0;
1043           rd = R0;
1044           rd_shift = 0;
1045           rn_shift = 0;
1046           immediate >>= 2;
1047         } else if (rn != rd) {
1048           // Must use T1.
1049           opcode_shift = 9;
1050           thumb_opcode = 0b01111;
1051           immediate_shift = 6;
1052         } else {
1053           // T2 encoding.
1054           opcode_shift = 11;
1055           thumb_opcode = 0b111;
1056           rd_shift = 8;
1057           rn_shift = 8;
1058         }
1059       }
1060      break;
1061    default:
1062      LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode;
1063      return;
1064  }
1065
1066  int16_t encoding = dp_opcode << 14 |
1067      (thumb_opcode << opcode_shift) |
1068      rd << rd_shift |
1069      rn << rn_shift |
1070      (use_immediate ? (immediate << immediate_shift) : 0);
1071
1072  Emit16(encoding);
1073}
1074
1075
1076void Thumb2Assembler::EmitDataProcessing(Condition cond,
1077                                         Opcode opcode,
1078                                         int set_cc,
1079                                         Register rn,
1080                                         Register rd,
1081                                         const ShifterOperand& so) {
1082  CHECK_NE(rd, kNoRegister);
1083  CheckCondition(cond);
1084
1085  if (Is32BitDataProcessing(cond, opcode, set_cc, rn, rd, so)) {
1086    Emit32BitDataProcessing(cond, opcode, set_cc, rn, rd, so);
1087  } else {
1088    Emit16BitDataProcessing(cond, opcode, set_cc, rn, rd, so);
1089  }
1090}
1091
1092void Thumb2Assembler::EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc) {
1093  CHECK_LT(amount, (1 << 5));
1094  if (IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) {
1095    uint16_t opcode = 0;
1096    switch (shift) {
1097      case LSL: opcode = 0b00; break;
1098      case LSR: opcode = 0b01; break;
1099      case ASR: opcode = 0b10; break;
1100      case ROR: opcode = 0b11; break;
1101      case RRX: opcode = 0b11; amount = 0; break;
1102      default:
1103        LOG(FATAL) << "Unsupported thumb2 shift opcode";
1104    }
1105    // 32 bit.
1106    int32_t encoding = B31 | B30 | B29 | B27 | B25 | B22 |
1107        0xf << 16 | (setcc ? B20 : 0);
1108    uint32_t imm3 = amount >> 2;
1109    uint32_t imm2 = amount & 0b11;
1110    encoding |= imm3 << 12 | imm2 << 6 | static_cast<int16_t>(rm) |
1111        static_cast<int16_t>(rd) << 8 | opcode << 4;
1112    Emit32(encoding);
1113  } else {
1114    // 16 bit shift
1115    uint16_t opcode = 0;
1116    switch (shift) {
1117      case LSL: opcode = 0b00; break;
1118      case LSR: opcode = 0b01; break;
1119      case ASR: opcode = 0b10; break;
1120      default:
1121         LOG(FATAL) << "Unsupported thumb2 shift opcode";
1122    }
1123    int16_t encoding = opcode << 11 | amount << 6 | static_cast<int16_t>(rm) << 3 |
1124        static_cast<int16_t>(rd);
1125    Emit16(encoding);
1126  }
1127}
1128
1129void Thumb2Assembler::EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc) {
1130  CHECK_NE(shift, RRX);
1131  bool must_be_32bit = false;
1132  if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn) {
1133    must_be_32bit = true;
1134  }
1135
1136  if (must_be_32bit) {
1137    uint16_t opcode = 0;
1138     switch (shift) {
1139       case LSL: opcode = 0b00; break;
1140       case LSR: opcode = 0b01; break;
1141       case ASR: opcode = 0b10; break;
1142       case ROR: opcode = 0b11; break;
1143       default:
1144         LOG(FATAL) << "Unsupported thumb2 shift opcode";
1145     }
1146     // 32 bit.
1147     int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 |
1148         0xf << 12 | (setcc ? B20 : 0);
1149     encoding |= static_cast<int16_t>(rn) << 16 | static_cast<int16_t>(rm) |
1150         static_cast<int16_t>(rd) << 8 | opcode << 21;
1151     Emit32(encoding);
1152  } else {
1153    uint16_t opcode = 0;
1154    switch (shift) {
1155      case LSL: opcode = 0b0010; break;
1156      case LSR: opcode = 0b0011; break;
1157      case ASR: opcode = 0b0100; break;
1158      default:
1159         LOG(FATAL) << "Unsupported thumb2 shift opcode";
1160    }
1161    int16_t encoding = B14 | opcode << 6 | static_cast<int16_t>(rm) << 3 |
1162        static_cast<int16_t>(rd);
1163    Emit16(encoding);
1164  }
1165}
1166
1167
1168
1169void Thumb2Assembler::Branch::Emit(AssemblerBuffer* buffer) const {
1170  bool link = type_ == kUnconditionalLinkX || type_ == kUnconditionalLink;
1171  bool x = type_ == kUnconditionalX || type_ == kUnconditionalLinkX;
1172  int32_t offset = target_ - location_;
1173
1174  if (size_ == k32Bit) {
1175    int32_t encoding = B31 | B30 | B29 | B28 | B15;
1176    if (link) {
1177      // BL or BLX immediate.
1178      encoding |= B14;
1179      if (!x) {
1180        encoding |= B12;
1181      } else {
1182        // Bottom bit of offset must be 0.
1183        CHECK_EQ((offset & 1), 0);
1184      }
1185    } else {
1186      if (x) {
1187        LOG(FATAL) << "Invalid use of BX";
1188      } else {
1189        if (cond_ == AL) {
1190          // Can use the T4 encoding allowing a 24 bit offset.
1191          if (!x) {
1192            encoding |= B12;
1193          }
1194        } else {
1195          // Must be T3 encoding with a 20 bit offset.
1196          encoding |= cond_ << 22;
1197        }
1198      }
1199    }
1200    encoding = Thumb2Assembler::EncodeBranchOffset(offset, encoding);
1201    buffer->Store<int16_t>(location_, static_cast<int16_t>(encoding >> 16));
1202    buffer->Store<int16_t>(location_+2, static_cast<int16_t>(encoding & 0xffff));
1203  } else {
1204    if (IsCompareAndBranch()) {
1205      offset -= 4;
1206      uint16_t i = (offset >> 6) & 1;
1207      uint16_t imm5 = (offset >> 1) & 0b11111;
1208      int16_t encoding = B15 | B13 | B12 |
1209            (type_ ==  kCompareAndBranchNonZero ? B11 : 0) |
1210            static_cast<uint32_t>(rn_) |
1211            B8 |
1212            i << 9 |
1213            imm5 << 3;
1214      buffer->Store<int16_t>(location_, encoding);
1215    } else {
1216      offset -= 4;    // Account for PC offset.
1217      int16_t encoding;
1218      // 16 bit.
1219      if (cond_ == AL) {
1220        encoding = B15 | B14 | B13 |
1221            ((offset >> 1) & 0x7ff);
1222      } else {
1223        encoding = B15 | B14 | B12 |
1224            cond_ << 8 | ((offset >> 1) & 0xff);
1225      }
1226      buffer->Store<int16_t>(location_, encoding);
1227    }
1228  }
1229}
1230
1231
1232uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) {
1233  uint32_t location = buffer_.Size();
1234
1235  // This is always unresolved as it must be a forward branch.
1236  Emit16(prev);      // Previous link.
1237  return AddBranch(n ? Branch::kCompareAndBranchNonZero : Branch::kCompareAndBranchZero,
1238      location, rn);
1239}
1240
1241
1242// NOTE: this only support immediate offsets, not [rx,ry].
1243// TODO: support [rx,ry] instructions.
1244void Thumb2Assembler::EmitLoadStore(Condition cond,
1245                                    bool load,
1246                                    bool byte,
1247                                    bool half,
1248                                    bool is_signed,
1249                                    Register rd,
1250                                    const Address& ad) {
1251  CHECK_NE(rd, kNoRegister);
1252  CheckCondition(cond);
1253  bool must_be_32bit = force_32bit_;
1254  if (IsHighRegister(rd)) {
1255    must_be_32bit = true;
1256  }
1257
1258  Register rn = ad.GetRegister();
1259  if (IsHighRegister(rn) && rn != SP && rn != PC) {
1260    must_be_32bit = true;
1261  }
1262
1263  if (is_signed || ad.GetOffset() < 0 || ad.GetMode() != Address::Offset) {
1264    must_be_32bit = true;
1265  }
1266
1267  if (ad.IsImmediate()) {
1268    // Immediate offset
1269    int32_t offset = ad.GetOffset();
1270
1271    // The 16 bit SP relative instruction can only have a 10 bit offset.
1272    if (rn == SP && offset >= (1 << 10)) {
1273      must_be_32bit = true;
1274    }
1275
1276    if (byte) {
1277      // 5 bit offset, no shift.
1278      if (offset >= (1 << 5)) {
1279        must_be_32bit = true;
1280      }
1281    } else if (half) {
1282      // 6 bit offset, shifted by 1.
1283      if (offset >= (1 << 6)) {
1284        must_be_32bit = true;
1285      }
1286    } else {
1287      // 7 bit offset, shifted by 2.
1288      if (offset >= (1 << 7)) {
1289        must_be_32bit = true;
1290      }
1291    }
1292
1293    if (must_be_32bit) {
1294      int32_t encoding = B31 | B30 | B29 | B28 | B27 |
1295          (load ? B20 : 0) |
1296          (is_signed ? B24 : 0) |
1297          static_cast<uint32_t>(rd) << 12 |
1298          ad.encodingThumb(true) |
1299          (byte ? 0 : half ? B21 : B22);
1300      Emit32(encoding);
1301    } else {
1302      // 16 bit thumb1.
1303      uint8_t opA = 0;
1304      bool sp_relative = false;
1305
1306      if (byte) {
1307        opA = 0b0111;
1308      } else if (half) {
1309        opA = 0b1000;
1310      } else {
1311        if (rn == SP) {
1312          opA = 0b1001;
1313          sp_relative = true;
1314        } else {
1315          opA = 0b0110;
1316        }
1317      }
1318      int16_t encoding = opA << 12 |
1319          (load ? B11 : 0);
1320
1321      CHECK_GE(offset, 0);
1322      if (sp_relative) {
1323        // SP relative, 10 bit offset.
1324        CHECK_LT(offset, (1 << 10));
1325        CHECK_EQ((offset & 0b11), 0);
1326        encoding |= rd << 8 | offset >> 2;
1327      } else {
1328        // No SP relative.  The offset is shifted right depending on
1329        // the size of the load/store.
1330        encoding |= static_cast<uint32_t>(rd);
1331
1332        if (byte) {
1333          // 5 bit offset, no shift.
1334          CHECK_LT(offset, (1 << 5));
1335        } else if (half) {
1336          // 6 bit offset, shifted by 1.
1337          CHECK_LT(offset, (1 << 6));
1338          CHECK_EQ((offset & 0b1), 0);
1339          offset >>= 1;
1340        } else {
1341          // 7 bit offset, shifted by 2.
1342          CHECK_LT(offset, (1 << 7));
1343          CHECK_EQ((offset & 0b11), 0);
1344          offset >>= 2;
1345        }
1346        encoding |= rn << 3 | offset  << 6;
1347      }
1348
1349      Emit16(encoding);
1350    }
1351  } else {
1352    // Register shift.
1353    if (ad.GetRegister() == PC) {
1354       // PC relative literal encoding.
1355      int32_t offset = ad.GetOffset();
1356      if (must_be_32bit || offset < 0 || offset >= (1 << 10) || !load) {
1357        int32_t up = B23;
1358        if (offset < 0) {
1359          offset = -offset;
1360          up = 0;
1361        }
1362        CHECK_LT(offset, (1 << 12));
1363        int32_t encoding = 0x1f << 27 | 0xf << 16 | B22 | (load ? B20 : 0) |
1364            offset | up |
1365            static_cast<uint32_t>(rd) << 12;
1366        Emit32(encoding);
1367      } else {
1368        // 16 bit literal load.
1369        CHECK_GE(offset, 0);
1370        CHECK_LT(offset, (1 << 10));
1371        int32_t encoding = B14 | (load ? B11 : 0) | static_cast<uint32_t>(rd) << 8 | offset >> 2;
1372        Emit16(encoding);
1373      }
1374    } else {
1375      if (ad.GetShiftCount() != 0) {
1376        // If there is a shift count this must be 32 bit.
1377        must_be_32bit = true;
1378      } else if (IsHighRegister(ad.GetRegisterOffset())) {
1379        must_be_32bit = true;
1380      }
1381
1382      if (must_be_32bit) {
1383        int32_t encoding = 0x1f << 27 | (load ? B20 : 0) | static_cast<uint32_t>(rd) << 12 |
1384            ad.encodingThumb(true);
1385        if (half) {
1386          encoding |= B21;
1387        } else if (!byte) {
1388          encoding |= B22;
1389        }
1390        Emit32(encoding);
1391      } else {
1392        // 16 bit register offset.
1393        int32_t encoding = B14 | B12 | (load ? B11 : 0) | static_cast<uint32_t>(rd) |
1394            ad.encodingThumb(false);
1395        if (byte) {
1396          encoding |= B10;
1397        } else if (half) {
1398          encoding |= B9;
1399        }
1400        Emit16(encoding);
1401      }
1402    }
1403  }
1404}
1405
1406
1407void Thumb2Assembler::EmitMultiMemOp(Condition cond,
1408                                     BlockAddressMode am,
1409                                     bool load,
1410                                     Register base,
1411                                     RegList regs) {
1412  CHECK_NE(base, kNoRegister);
1413  CheckCondition(cond);
1414  bool must_be_32bit = force_32bit_;
1415
1416  if ((regs & 0xff00) != 0) {
1417    must_be_32bit = true;
1418  }
1419
1420  uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W;
1421  // 16 bit always uses writeback.
1422  if (!w_bit) {
1423    must_be_32bit = true;
1424  }
1425
1426  if (must_be_32bit) {
1427    uint32_t op = 0;
1428    switch (am) {
1429      case IA:
1430      case IA_W:
1431        op = 0b01;
1432        break;
1433      case DB:
1434      case DB_W:
1435        op = 0b10;
1436        break;
1437      case DA:
1438      case IB:
1439      case DA_W:
1440      case IB_W:
1441        LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am;
1442    }
1443    if (load) {
1444      // Cannot have SP in the list.
1445      CHECK_EQ((regs & (1 << SP)), 0);
1446    } else {
1447      // Cannot have PC or SP in the list.
1448      CHECK_EQ((regs & (1 << PC | 1 << SP)), 0);
1449    }
1450    int32_t encoding = B31 | B30 | B29 | B27 |
1451                    (op << 23) |
1452                    (load ? B20 : 0) |
1453                    base << 16 |
1454                    regs |
1455                    (w_bit << 21);
1456    Emit32(encoding);
1457  } else {
1458    int16_t encoding = B15 | B14 |
1459                    (load ? B11 : 0) |
1460                    base << 8 |
1461                    regs;
1462    Emit16(encoding);
1463  }
1464}
1465
1466
1467void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) {
1468  uint32_t pc = buffer_.Size();
1469  Branch::Type branch_type;
1470  if (cond == AL) {
1471    if (link) {
1472      if (x) {
1473        branch_type = Branch::kUnconditionalLinkX;      // BLX.
1474      } else {
1475        branch_type = Branch::kUnconditionalLink;       // BX.
1476      }
1477    } else {
1478      branch_type = Branch::kUnconditional;             // B.
1479    }
1480  } else {
1481    branch_type = Branch::kConditional;                 // B<cond>.
1482  }
1483
1484  if (label->IsBound()) {
1485    Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond);  // Resolved branch.
1486
1487    // The branch is to a bound label which means that it's a backwards branch.  We know the
1488    // current size of it so we can emit the appropriate space.  Note that if it's a 16 bit
1489    // branch the size may change if it so happens that other branches change size that change
1490    // the distance to the target and that distance puts this branch over the limit for 16 bits.
1491    if (size == Branch::k16Bit) {
1492      DCHECK(!force_32bit_branches_);
1493      Emit16(0);          // Space for a 16 bit branch.
1494    } else {
1495      Emit32(0);            // Space for a 32 bit branch.
1496    }
1497  } else {
1498    // Branch is to an unbound label.  Emit space for it.
1499    uint16_t branch_id = AddBranch(branch_type, pc, cond);    // Unresolved branch.
1500    if (force_32bit_branches_ || force_32bit_) {
1501      Emit16(static_cast<uint16_t>(label->position_));    // Emit current label link.
1502      Emit16(0);                   // another 16 bits.
1503    } else {
1504      Emit16(static_cast<uint16_t>(label->position_));    // Emit current label link.
1505    }
1506    label->LinkTo(branch_id);           // Link to the branch ID.
1507  }
1508}
1509
1510
1511void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) {
1512  CHECK_NE(rd, kNoRegister);
1513  CHECK_NE(rm, kNoRegister);
1514  CheckCondition(cond);
1515  CHECK_NE(rd, PC);
1516  CHECK_NE(rm, PC);
1517  int32_t encoding = B31 | B30 | B29 | B28 | B27 |
1518      B25 | B23 | B21 | B20 |
1519      static_cast<uint32_t>(rm) << 16 |
1520      0xf << 12 |
1521      static_cast<uint32_t>(rd) << 8 |
1522      B7 |
1523      static_cast<uint32_t>(rm);
1524  Emit32(encoding);
1525}
1526
1527
1528void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
1529  CheckCondition(cond);
1530  bool must_be_32bit = force_32bit_;
1531  if (IsHighRegister(rd)|| imm16 >= 256u) {
1532    must_be_32bit = true;
1533  }
1534
1535  if (must_be_32bit) {
1536    // Use encoding T3.
1537    uint32_t imm4 = (imm16 >> 12) & 0b1111;
1538    uint32_t i = (imm16 >> 11) & 0b1;
1539    uint32_t imm3 = (imm16 >> 8) & 0b111;
1540    uint32_t imm8 = imm16 & 0xff;
1541    int32_t encoding = B31 | B30 | B29 | B28 |
1542                    B25 | B22 |
1543                    static_cast<uint32_t>(rd) << 8 |
1544                    i << 26 |
1545                    imm4 << 16 |
1546                    imm3 << 12 |
1547                    imm8;
1548    Emit32(encoding);
1549  } else {
1550    int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 |
1551                imm16;
1552    Emit16(encoding);
1553  }
1554}
1555
1556
1557void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
1558  CheckCondition(cond);
1559  // Always 32 bits.
1560  uint32_t imm4 = (imm16 >> 12) & 0b1111;
1561  uint32_t i = (imm16 >> 11) & 0b1;
1562  uint32_t imm3 = (imm16 >> 8) & 0b111;
1563  uint32_t imm8 = imm16 & 0xff;
1564  int32_t encoding = B31 | B30 | B29 | B28 |
1565                  B25 | B23 | B22 |
1566                  static_cast<uint32_t>(rd) << 8 |
1567                  i << 26 |
1568                  imm4 << 16 |
1569                  imm3 << 12 |
1570                  imm8;
1571  Emit32(encoding);
1572}
1573
1574
1575void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) {
1576  CHECK_NE(rn, kNoRegister);
1577  CHECK_NE(rt, kNoRegister);
1578  CheckCondition(cond);
1579  CHECK_NE(rn, kNoRegister);
1580  CHECK_NE(rt, kNoRegister);
1581  CheckCondition(cond);
1582  CHECK_LT(imm, (1u << 10));
1583
1584  int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 |
1585      static_cast<uint32_t>(rn) << 16 |
1586      static_cast<uint32_t>(rt) << 12 |
1587      0xf << 8 |
1588      imm >> 2;
1589  Emit32(encoding);
1590}
1591
1592
1593void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) {
1594  ldrex(rt, rn, 0, cond);
1595}
1596
1597
1598void Thumb2Assembler::strex(Register rd,
1599                            Register rt,
1600                            Register rn,
1601                            uint16_t imm,
1602                            Condition cond) {
1603  CHECK_NE(rn, kNoRegister);
1604  CHECK_NE(rd, kNoRegister);
1605  CHECK_NE(rt, kNoRegister);
1606  CheckCondition(cond);
1607  CHECK_LT(imm, (1u << 10));
1608
1609  int32_t encoding = B31 | B30 | B29 | B27 | B22 |
1610      static_cast<uint32_t>(rn) << 16 |
1611      static_cast<uint32_t>(rt) << 12 |
1612      static_cast<uint32_t>(rd) << 8 |
1613      imm >> 2;
1614  Emit32(encoding);
1615}
1616
1617
1618void Thumb2Assembler::strex(Register rd,
1619                            Register rt,
1620                            Register rn,
1621                            Condition cond) {
1622  strex(rd, rt, rn, 0, cond);
1623}
1624
1625
1626void Thumb2Assembler::clrex(Condition cond) {
1627  CheckCondition(cond);
1628  int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 |
1629      B21 | B20 |
1630      0xf << 16 |
1631      B15 |
1632      0xf << 8 |
1633      B5 |
1634      0xf;
1635  Emit32(encoding);
1636}
1637
1638
1639void Thumb2Assembler::nop(Condition cond) {
1640  CheckCondition(cond);
1641  int16_t encoding = B15 | B13 | B12 |
1642      B11 | B10 | B9 | B8;
1643  Emit16(encoding);
1644}
1645
1646
1647void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
1648  CHECK_NE(sn, kNoSRegister);
1649  CHECK_NE(rt, kNoRegister);
1650  CHECK_NE(rt, SP);
1651  CHECK_NE(rt, PC);
1652  CheckCondition(cond);
1653  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1654                     B27 | B26 | B25 |
1655                     ((static_cast<int32_t>(sn) >> 1)*B16) |
1656                     (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1657                     ((static_cast<int32_t>(sn) & 1)*B7) | B4;
1658  Emit32(encoding);
1659}
1660
1661
1662void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
1663  CHECK_NE(sn, kNoSRegister);
1664  CHECK_NE(rt, kNoRegister);
1665  CHECK_NE(rt, SP);
1666  CHECK_NE(rt, PC);
1667  CheckCondition(cond);
1668  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1669                     B27 | B26 | B25 | B20 |
1670                     ((static_cast<int32_t>(sn) >> 1)*B16) |
1671                     (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1672                     ((static_cast<int32_t>(sn) & 1)*B7) | B4;
1673  Emit32(encoding);
1674}
1675
1676
1677void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
1678                              Condition cond) {
1679  CHECK_NE(sm, kNoSRegister);
1680  CHECK_NE(sm, S31);
1681  CHECK_NE(rt, kNoRegister);
1682  CHECK_NE(rt, SP);
1683  CHECK_NE(rt, PC);
1684  CHECK_NE(rt2, kNoRegister);
1685  CHECK_NE(rt2, SP);
1686  CHECK_NE(rt2, PC);
1687  CheckCondition(cond);
1688  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1689                     B27 | B26 | B22 |
1690                     (static_cast<int32_t>(rt2)*B16) |
1691                     (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1692                     ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
1693                     (static_cast<int32_t>(sm) >> 1);
1694  Emit32(encoding);
1695}
1696
1697
1698void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
1699                              Condition cond) {
1700  CHECK_NE(sm, kNoSRegister);
1701  CHECK_NE(sm, S31);
1702  CHECK_NE(rt, kNoRegister);
1703  CHECK_NE(rt, SP);
1704  CHECK_NE(rt, PC);
1705  CHECK_NE(rt2, kNoRegister);
1706  CHECK_NE(rt2, SP);
1707  CHECK_NE(rt2, PC);
1708  CHECK_NE(rt, rt2);
1709  CheckCondition(cond);
1710  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1711                     B27 | B26 | B22 | B20 |
1712                     (static_cast<int32_t>(rt2)*B16) |
1713                     (static_cast<int32_t>(rt)*B12) | B11 | B9 |
1714                     ((static_cast<int32_t>(sm) & 1)*B5) | B4 |
1715                     (static_cast<int32_t>(sm) >> 1);
1716  Emit32(encoding);
1717}
1718
1719
1720void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
1721                              Condition cond) {
1722  CHECK_NE(dm, kNoDRegister);
1723  CHECK_NE(rt, kNoRegister);
1724  CHECK_NE(rt, SP);
1725  CHECK_NE(rt, PC);
1726  CHECK_NE(rt2, kNoRegister);
1727  CHECK_NE(rt2, SP);
1728  CHECK_NE(rt2, PC);
1729  CheckCondition(cond);
1730  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1731                     B27 | B26 | B22 |
1732                     (static_cast<int32_t>(rt2)*B16) |
1733                     (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
1734                     ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
1735                     (static_cast<int32_t>(dm) & 0xf);
1736  Emit32(encoding);
1737}
1738
1739
1740void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
1741                              Condition cond) {
1742  CHECK_NE(dm, kNoDRegister);
1743  CHECK_NE(rt, kNoRegister);
1744  CHECK_NE(rt, SP);
1745  CHECK_NE(rt, PC);
1746  CHECK_NE(rt2, kNoRegister);
1747  CHECK_NE(rt2, SP);
1748  CHECK_NE(rt2, PC);
1749  CHECK_NE(rt, rt2);
1750  CheckCondition(cond);
1751  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1752                     B27 | B26 | B22 | B20 |
1753                     (static_cast<int32_t>(rt2)*B16) |
1754                     (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 |
1755                     ((static_cast<int32_t>(dm) >> 4)*B5) | B4 |
1756                     (static_cast<int32_t>(dm) & 0xf);
1757  Emit32(encoding);
1758}
1759
1760
1761void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) {
1762  const Address& addr = static_cast<const Address&>(ad);
1763  CHECK_NE(sd, kNoSRegister);
1764  CheckCondition(cond);
1765  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1766                     B27 | B26 | B24 | B20 |
1767                     ((static_cast<int32_t>(sd) & 1)*B22) |
1768                     ((static_cast<int32_t>(sd) >> 1)*B12) |
1769                     B11 | B9 | addr.vencoding();
1770  Emit32(encoding);
1771}
1772
1773
1774void Thumb2Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) {
1775  const Address& addr = static_cast<const Address&>(ad);
1776  CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1777  CHECK_NE(sd, kNoSRegister);
1778  CheckCondition(cond);
1779  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1780                     B27 | B26 | B24 |
1781                     ((static_cast<int32_t>(sd) & 1)*B22) |
1782                     ((static_cast<int32_t>(sd) >> 1)*B12) |
1783                     B11 | B9 | addr.vencoding();
1784  Emit32(encoding);
1785}
1786
1787
1788void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) {
1789  const Address& addr = static_cast<const Address&>(ad);
1790  CHECK_NE(dd, kNoDRegister);
1791  CheckCondition(cond);
1792  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1793                     B27 | B26 | B24 | B20 |
1794                     ((static_cast<int32_t>(dd) >> 4)*B22) |
1795                     ((static_cast<int32_t>(dd) & 0xf)*B12) |
1796                     B11 | B9 | B8 | addr.vencoding();
1797  Emit32(encoding);
1798}
1799
1800
1801void Thumb2Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) {
1802  const Address& addr = static_cast<const Address&>(ad);
1803  CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC);
1804  CHECK_NE(dd, kNoDRegister);
1805  CheckCondition(cond);
1806  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1807                     B27 | B26 | B24 |
1808                     ((static_cast<int32_t>(dd) >> 4)*B22) |
1809                     ((static_cast<int32_t>(dd) & 0xf)*B12) |
1810                     B11 | B9 | B8 | addr.vencoding();
1811  Emit32(encoding);
1812}
1813
1814
1815void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) {
1816  EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond);
1817}
1818
1819
1820void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) {
1821  EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond);
1822}
1823
1824
1825void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) {
1826  EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond);
1827}
1828
1829
1830void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) {
1831  EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond);
1832}
1833
1834
1835void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) {
1836  CheckCondition(cond);
1837
1838  uint32_t D;
1839  uint32_t Vd;
1840  if (dbl) {
1841    // Encoded as D:Vd.
1842    D = (reg >> 4) & 1;
1843    Vd = reg & 0b1111;
1844  } else {
1845    // Encoded as Vd:D.
1846    D = reg & 1;
1847    Vd = (reg >> 1) & 0b1111;
1848  }
1849  int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 |
1850                    B11 | B9 |
1851        (dbl ? B8 : 0) |
1852        (push ? B24 : (B23 | B20)) |
1853        0b1110 << 28 |
1854        nregs << (dbl ? 1 : 0) |
1855        D << 22 |
1856        Vd << 12;
1857  Emit32(encoding);
1858}
1859
1860
1861void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode,
1862                                 SRegister sd, SRegister sn, SRegister sm) {
1863  CHECK_NE(sd, kNoSRegister);
1864  CHECK_NE(sn, kNoSRegister);
1865  CHECK_NE(sm, kNoSRegister);
1866  CheckCondition(cond);
1867  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1868                     B27 | B26 | B25 | B11 | B9 | opcode |
1869                     ((static_cast<int32_t>(sd) & 1)*B22) |
1870                     ((static_cast<int32_t>(sn) >> 1)*B16) |
1871                     ((static_cast<int32_t>(sd) >> 1)*B12) |
1872                     ((static_cast<int32_t>(sn) & 1)*B7) |
1873                     ((static_cast<int32_t>(sm) & 1)*B5) |
1874                     (static_cast<int32_t>(sm) >> 1);
1875  Emit32(encoding);
1876}
1877
1878
1879void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode,
1880                                 DRegister dd, DRegister dn, DRegister dm) {
1881  CHECK_NE(dd, kNoDRegister);
1882  CHECK_NE(dn, kNoDRegister);
1883  CHECK_NE(dm, kNoDRegister);
1884  CheckCondition(cond);
1885  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1886                     B27 | B26 | B25 | B11 | B9 | B8 | opcode |
1887                     ((static_cast<int32_t>(dd) >> 4)*B22) |
1888                     ((static_cast<int32_t>(dn) & 0xf)*B16) |
1889                     ((static_cast<int32_t>(dd) & 0xf)*B12) |
1890                     ((static_cast<int32_t>(dn) >> 4)*B7) |
1891                     ((static_cast<int32_t>(dm) >> 4)*B5) |
1892                     (static_cast<int32_t>(dm) & 0xf);
1893  Emit32(encoding);
1894}
1895
1896
1897void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode,
1898                                SRegister sd, DRegister dm) {
1899  CHECK_NE(sd, kNoSRegister);
1900  CHECK_NE(dm, kNoDRegister);
1901  CheckCondition(cond);
1902  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1903                     B27 | B26 | B25 | B11 | B9 | opcode |
1904                     ((static_cast<int32_t>(sd) & 1)*B22) |
1905                     ((static_cast<int32_t>(sd) >> 1)*B12) |
1906                     ((static_cast<int32_t>(dm) >> 4)*B5) |
1907                     (static_cast<int32_t>(dm) & 0xf);
1908  Emit32(encoding);
1909}
1910
1911
1912void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode,
1913                                DRegister dd, SRegister sm) {
1914  CHECK_NE(dd, kNoDRegister);
1915  CHECK_NE(sm, kNoSRegister);
1916  CheckCondition(cond);
1917  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1918                     B27 | B26 | B25 | B11 | B9 | opcode |
1919                     ((static_cast<int32_t>(dd) >> 4)*B22) |
1920                     ((static_cast<int32_t>(dd) & 0xf)*B12) |
1921                     ((static_cast<int32_t>(sm) & 1)*B5) |
1922                     (static_cast<int32_t>(sm) >> 1);
1923  Emit32(encoding);
1924}
1925
1926
1927void Thumb2Assembler::vmstat(Condition cond) {  // VMRS APSR_nzcv, FPSCR.
1928  CheckCondition(cond);
1929  UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction";
1930}
1931
1932
1933void Thumb2Assembler::svc(uint32_t imm8) {
1934  CHECK(IsUint(8, imm8)) << imm8;
1935  int16_t encoding = B15 | B14 | B12 |
1936       B11 | B10 | B9 | B8 |
1937       imm8;
1938  Emit16(encoding);
1939}
1940
1941
1942void Thumb2Assembler::bkpt(uint16_t imm8) {
1943  CHECK(IsUint(8, imm8)) << imm8;
1944  int16_t encoding = B15 | B13 | B12 |
1945      B11 | B10 | B9 |
1946      imm8;
1947  Emit16(encoding);
1948}
1949
1950// Convert the given IT state to a mask bit given bit 0 of the first
1951// condition and a shift position.
1952static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) {
1953  switch (s) {
1954  case kItOmitted: return 1 << shift;
1955  case kItThen: return firstcond0 << shift;
1956  case kItElse: return !firstcond0 << shift;
1957  }
1958  return 0;
1959}
1960
1961
1962// Set the IT condition in the given position for the given state.  This is used
1963// to check that conditional instructions match the preceding IT statement.
1964void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) {
1965  switch (s) {
1966  case kItOmitted: it_conditions_[index] = AL; break;
1967  case kItThen: it_conditions_[index] = cond; break;
1968  case kItElse:
1969    it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1);
1970    break;
1971  }
1972}
1973
1974
1975void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) {
1976  CheckCondition(AL);       // Not allowed in IT block.
1977  uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1;
1978
1979  // All conditions to AL.
1980  for (uint8_t i = 0; i < 4; ++i) {
1981    it_conditions_[i] = AL;
1982  }
1983
1984  SetItCondition(kItThen, firstcond, 0);
1985  uint8_t mask = ToItMask(i1, firstcond0, 3);
1986  SetItCondition(i1, firstcond, 1);
1987
1988  if (i1 != kItOmitted) {
1989    mask |= ToItMask(i2, firstcond0, 2);
1990    SetItCondition(i2, firstcond, 2);
1991    if (i2 != kItOmitted) {
1992      mask |= ToItMask(i3, firstcond0, 1);
1993      SetItCondition(i3, firstcond, 3);
1994      if (i3 != kItOmitted) {
1995        mask |= 0b0001;
1996      }
1997    }
1998  }
1999
2000  // Start at first condition.
2001  it_cond_index_ = 0;
2002  next_condition_ = it_conditions_[0];
2003  uint16_t encoding = B15 | B13 | B12 |
2004        B11 | B10 | B9 | B8 |
2005        firstcond << 4 |
2006        mask;
2007  Emit16(encoding);
2008}
2009
2010
2011void Thumb2Assembler::cbz(Register rn, Label* label) {
2012  CheckCondition(AL);
2013  if (label->IsBound()) {
2014    LOG(FATAL) << "cbz can only be used to branch forwards";
2015  } else {
2016    uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false);
2017    label->LinkTo(branchid);
2018  }
2019}
2020
2021
2022void Thumb2Assembler::cbnz(Register rn, Label* label) {
2023  CheckCondition(AL);
2024  if (label->IsBound()) {
2025    LOG(FATAL) << "cbnz can only be used to branch forwards";
2026  } else {
2027    uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true);
2028    label->LinkTo(branchid);
2029  }
2030}
2031
2032
2033void Thumb2Assembler::blx(Register rm, Condition cond) {
2034  CHECK_NE(rm, kNoRegister);
2035  CheckCondition(cond);
2036  int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3;
2037  Emit16(encoding);
2038}
2039
2040
2041void Thumb2Assembler::bx(Register rm, Condition cond) {
2042  CHECK_NE(rm, kNoRegister);
2043  CheckCondition(cond);
2044  int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3;
2045  Emit16(encoding);
2046}
2047
2048
2049void Thumb2Assembler::Push(Register rd, Condition cond) {
2050  str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond);
2051}
2052
2053
2054void Thumb2Assembler::Pop(Register rd, Condition cond) {
2055  ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond);
2056}
2057
2058
2059void Thumb2Assembler::PushList(RegList regs, Condition cond) {
2060  stm(DB_W, SP, regs, cond);
2061}
2062
2063
2064void Thumb2Assembler::PopList(RegList regs, Condition cond) {
2065  ldm(IA_W, SP, regs, cond);
2066}
2067
2068
2069void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) {
2070  if (cond != AL || rd != rm) {
2071    mov(rd, ShifterOperand(rm), cond);
2072  }
2073}
2074
2075
2076// A branch has changed size.  Make a hole for it.
2077void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) {
2078  // Move the contents of the buffer using: Move(newposition, oldposition)
2079  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2080  buffer_.Move(location + delta, location);
2081}
2082
2083
2084void Thumb2Assembler::Bind(Label* label) {
2085  CHECK(!label->IsBound());
2086  uint32_t bound_pc = buffer_.Size();
2087  std::vector<Branch*> changed_branches;
2088
2089  while (label->IsLinked()) {
2090    uint16_t position = label->Position();                  // Branch id for linked branch.
2091    Branch* branch = GetBranch(position);                   // Get the branch at this id.
2092    bool changed = branch->Resolve(bound_pc);               // Branch can be resolved now.
2093    uint32_t branch_location = branch->GetLocation();
2094    uint16_t next = buffer_.Load<uint16_t>(branch_location);       // Get next in chain.
2095    if (changed) {
2096      DCHECK(!force_32bit_branches_);
2097      MakeHoleForBranch(branch->GetLocation(), 2);
2098      if (branch->IsCompareAndBranch()) {
2099        // A cbz/cbnz instruction has changed size.  There is no valid encoding for
2100        // a 32 bit cbz/cbnz so we need to change this to an instruction pair:
2101        // cmp rn, #0
2102        // b<eq|ne> target
2103        bool n = branch->GetType() == Branch::kCompareAndBranchNonZero;
2104        Condition cond = n ? NE : EQ;
2105        branch->Move(2);      // Move the branch forward by 2 bytes.
2106        branch->ResetTypeAndCondition(Branch::kConditional, cond);
2107        branch->ResetSize(Branch::k16Bit);
2108
2109        // Now add a compare instruction in the place the branch was.
2110        int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8;
2111        buffer_.Store<int16_t>(branch_location, cmp);
2112
2113        // Since have moved made a hole in the code we need to reload the
2114        // current pc.
2115        bound_pc = buffer_.Size();
2116
2117        // Now resolve the newly added branch.
2118        changed = branch->Resolve(bound_pc);
2119        if (changed) {
2120          MakeHoleForBranch(branch->GetLocation(), 2);
2121          changed_branches.push_back(branch);
2122        }
2123      } else {
2124        changed_branches.push_back(branch);
2125      }
2126    }
2127    label->position_ = next;                                // Move to next.
2128  }
2129  label->BindTo(bound_pc);
2130
2131  // Now relocate any changed branches.  Do this until there are no more changes.
2132  std::vector<Branch*> branches_to_process = changed_branches;
2133  while (branches_to_process.size() != 0) {
2134    changed_branches.clear();
2135    for (auto& changed_branch : branches_to_process) {
2136      for (auto& branch : branches_) {
2137        bool changed = branch->Relocate(changed_branch->GetLocation(), 2);
2138        if (changed) {
2139          changed_branches.push_back(branch);
2140        }
2141      }
2142      branches_to_process = changed_branches;
2143    }
2144  }
2145}
2146
2147
2148void Thumb2Assembler::EmitBranches() {
2149  for (auto& branch : branches_) {
2150    branch->Emit(&buffer_);
2151  }
2152}
2153
2154
2155void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
2156                          bool setcc, Condition cond) {
2157  CHECK_NE(shift_imm, 0u);  // Do not use Lsl if no shift is wanted.
2158  CheckCondition(cond);
2159  EmitShift(rd, rm, LSL, shift_imm, setcc);
2160}
2161
2162
2163void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
2164                          bool setcc, Condition cond) {
2165  CHECK_NE(shift_imm, 0u);  // Do not use Lsr if no shift is wanted.
2166  if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
2167  CheckCondition(cond);
2168  EmitShift(rd, rm, LSR, shift_imm, setcc);
2169}
2170
2171
2172void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
2173                          bool setcc, Condition cond) {
2174  CHECK_NE(shift_imm, 0u);  // Do not use Asr if no shift is wanted.
2175  if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
2176  CheckCondition(cond);
2177  EmitShift(rd, rm, ASR, shift_imm, setcc);
2178}
2179
2180
2181void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
2182                          bool setcc, Condition cond) {
2183  CHECK_NE(shift_imm, 0u);  // Use Rrx instruction.
2184  CheckCondition(cond);
2185  EmitShift(rd, rm, ROR, shift_imm, setcc);
2186}
2187
2188
2189void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
2190  CheckCondition(cond);
2191  EmitShift(rd, rm, RRX, rm, setcc);
2192}
2193
2194
2195void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn,
2196                          bool setcc, Condition cond) {
2197  CheckCondition(cond);
2198  EmitShift(rd, rm, LSL, rn, setcc);
2199}
2200
2201
2202void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn,
2203                          bool setcc, Condition cond) {
2204  CheckCondition(cond);
2205  EmitShift(rd, rm, LSR, rn, setcc);
2206}
2207
2208
2209void Thumb2Assembler::Asr(Register rd, Register rm, Register rn,
2210                          bool setcc, Condition cond) {
2211  CheckCondition(cond);
2212  EmitShift(rd, rm, ASR, rn, setcc);
2213}
2214
2215
2216void Thumb2Assembler::Ror(Register rd, Register rm, Register rn,
2217                          bool setcc, Condition cond) {
2218  CheckCondition(cond);
2219  EmitShift(rd, rm, ROR, rn, setcc);
2220}
2221
2222
2223int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
2224  // The offset is off by 4 due to the way the ARM CPUs read PC.
2225  offset -= 4;
2226  offset >>= 1;
2227
2228  uint32_t value = 0;
2229  // There are two different encodings depending on the value of bit 12.  In one case
2230  // intermediate values are calculated using the sign bit.
2231  if ((inst & B12) == B12) {
2232    // 25 bits of offset.
2233    uint32_t signbit = (offset >> 31) & 0x1;
2234    uint32_t i1 = (offset >> 22) & 0x1;
2235    uint32_t i2 = (offset >> 21) & 0x1;
2236    uint32_t imm10 = (offset >> 11) & 0x03ff;
2237    uint32_t imm11 = offset & 0x07ff;
2238    uint32_t j1 = (i1 ^ signbit) ? 0 : 1;
2239    uint32_t j2 = (i2 ^ signbit) ? 0 : 1;
2240    value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) |
2241                      imm11;
2242    // Remove the offset from the current encoding.
2243    inst &= ~(0x3ff << 16 | 0x7ff);
2244  } else {
2245    uint32_t signbit = (offset >> 31) & 0x1;
2246    uint32_t imm6 = (offset >> 11) & 0x03f;
2247    uint32_t imm11 = offset & 0x07ff;
2248    uint32_t j1 = (offset >> 19) & 1;
2249    uint32_t j2 = (offset >> 17) & 1;
2250    value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) |
2251        imm11;
2252    // Remove the offset from the current encoding.
2253    inst &= ~(0x3f << 16 | 0x7ff);
2254  }
2255  // Mask out offset bits in current instruction.
2256  inst &= ~(B26 | B13 | B11);
2257  inst |= value;
2258  return inst;
2259}
2260
2261
2262int Thumb2Assembler::DecodeBranchOffset(int32_t instr) {
2263  int32_t imm32;
2264  if ((instr & B12) == B12) {
2265    uint32_t S = (instr >> 26) & 1;
2266    uint32_t J2 = (instr >> 11) & 1;
2267    uint32_t J1 = (instr >> 13) & 1;
2268    uint32_t imm10 = (instr >> 16) & 0x3FF;
2269    uint32_t imm11 = instr & 0x7FF;
2270
2271    uint32_t I1 = ~(J1 ^ S) & 1;
2272    uint32_t I2 = ~(J2 ^ S) & 1;
2273    imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2274    imm32 = (imm32 << 8) >> 8;  // sign extend 24 bit immediate.
2275  } else {
2276    uint32_t S = (instr >> 26) & 1;
2277    uint32_t J2 = (instr >> 11) & 1;
2278    uint32_t J1 = (instr >> 13) & 1;
2279    uint32_t imm6 = (instr >> 16) & 0x3F;
2280    uint32_t imm11 = instr & 0x7FF;
2281
2282    imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2283    imm32 = (imm32 << 11) >> 11;  // sign extend 21 bit immediate.
2284  }
2285  imm32 += 4;
2286  return imm32;
2287}
2288
2289
2290void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
2291  AddConstant(rd, rd, value, cond);
2292}
2293
2294
2295void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value,
2296                                  Condition cond) {
2297  if (value == 0) {
2298    if (rd != rn) {
2299      mov(rd, ShifterOperand(rn), cond);
2300    }
2301    return;
2302  }
2303  // We prefer to select the shorter code sequence rather than selecting add for
2304  // positive values and sub for negatives ones, which would slightly improve
2305  // the readability of generated code for some constants.
2306  ShifterOperand shifter_op;
2307  if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
2308    add(rd, rn, shifter_op, cond);
2309  } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) {
2310    sub(rd, rn, shifter_op, cond);
2311  } else {
2312    CHECK(rn != IP);
2313    if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
2314      mvn(IP, shifter_op, cond);
2315      add(rd, rn, ShifterOperand(IP), cond);
2316    } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
2317      mvn(IP, shifter_op, cond);
2318      sub(rd, rn, ShifterOperand(IP), cond);
2319    } else {
2320      movw(IP, Low16Bits(value), cond);
2321      uint16_t value_high = High16Bits(value);
2322      if (value_high != 0) {
2323        movt(IP, value_high, cond);
2324      }
2325      add(rd, rn, ShifterOperand(IP), cond);
2326    }
2327  }
2328}
2329
2330
2331void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
2332                                          Condition cond) {
2333  ShifterOperand shifter_op;
2334  if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
2335    adds(rd, rn, shifter_op, cond);
2336  } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) {
2337    subs(rd, rn, shifter_op, cond);
2338  } else {
2339    CHECK(rn != IP);
2340    if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
2341      mvn(IP, shifter_op, cond);
2342      adds(rd, rn, ShifterOperand(IP), cond);
2343    } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
2344      mvn(IP, shifter_op, cond);
2345      subs(rd, rn, ShifterOperand(IP), cond);
2346    } else {
2347      movw(IP, Low16Bits(value), cond);
2348      uint16_t value_high = High16Bits(value);
2349      if (value_high != 0) {
2350        movt(IP, value_high, cond);
2351      }
2352      adds(rd, rn, ShifterOperand(IP), cond);
2353    }
2354  }
2355}
2356
2357
2358void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
2359  ShifterOperand shifter_op;
2360  if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) {
2361    mov(rd, shifter_op, cond);
2362  } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) {
2363    mvn(rd, shifter_op, cond);
2364  } else {
2365    movw(rd, Low16Bits(value), cond);
2366    uint16_t value_high = High16Bits(value);
2367    if (value_high != 0) {
2368      movt(rd, value_high, cond);
2369    }
2370  }
2371}
2372
2373// Implementation note: this method must emit at most one instruction when
2374// Address::CanHoldLoadOffsetThumb.
2375void Thumb2Assembler::LoadFromOffset(LoadOperandType type,
2376                                     Register reg,
2377                                     Register base,
2378                                     int32_t offset,
2379                                     Condition cond) {
2380  if (!Address::CanHoldLoadOffsetThumb(type, offset)) {
2381    CHECK(base != IP);
2382    LoadImmediate(IP, offset, cond);
2383    add(IP, IP, ShifterOperand(base), cond);
2384    base = IP;
2385    offset = 0;
2386  }
2387  CHECK(Address::CanHoldLoadOffsetThumb(type, offset));
2388  switch (type) {
2389    case kLoadSignedByte:
2390      ldrsb(reg, Address(base, offset), cond);
2391      break;
2392    case kLoadUnsignedByte:
2393      ldrb(reg, Address(base, offset), cond);
2394      break;
2395    case kLoadSignedHalfword:
2396      ldrsh(reg, Address(base, offset), cond);
2397      break;
2398    case kLoadUnsignedHalfword:
2399      ldrh(reg, Address(base, offset), cond);
2400      break;
2401    case kLoadWord:
2402      ldr(reg, Address(base, offset), cond);
2403      break;
2404    case kLoadWordPair:
2405      ldrd(reg, Address(base, offset), cond);
2406      break;
2407    default:
2408      LOG(FATAL) << "UNREACHABLE";
2409  }
2410}
2411
2412
2413// Implementation note: this method must emit at most one instruction when
2414// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset.
2415void Thumb2Assembler::LoadSFromOffset(SRegister reg,
2416                                      Register base,
2417                                      int32_t offset,
2418                                      Condition cond) {
2419  if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) {
2420    CHECK_NE(base, IP);
2421    LoadImmediate(IP, offset, cond);
2422    add(IP, IP, ShifterOperand(base), cond);
2423    base = IP;
2424    offset = 0;
2425  }
2426  CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset));
2427  vldrs(reg, Address(base, offset), cond);
2428}
2429
2430
2431// Implementation note: this method must emit at most one instruction when
2432// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset.
2433void Thumb2Assembler::LoadDFromOffset(DRegister reg,
2434                                      Register base,
2435                                      int32_t offset,
2436                                      Condition cond) {
2437  if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) {
2438    CHECK_NE(base, IP);
2439    LoadImmediate(IP, offset, cond);
2440    add(IP, IP, ShifterOperand(base), cond);
2441    base = IP;
2442    offset = 0;
2443  }
2444  CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset));
2445  vldrd(reg, Address(base, offset), cond);
2446}
2447
2448
2449// Implementation note: this method must emit at most one instruction when
2450// Address::CanHoldStoreOffsetThumb.
2451void Thumb2Assembler::StoreToOffset(StoreOperandType type,
2452                                    Register reg,
2453                                    Register base,
2454                                    int32_t offset,
2455                                    Condition cond) {
2456  if (!Address::CanHoldStoreOffsetThumb(type, offset)) {
2457    CHECK(reg != IP);
2458    CHECK(base != IP);
2459    LoadImmediate(IP, offset, cond);
2460    add(IP, IP, ShifterOperand(base), cond);
2461    base = IP;
2462    offset = 0;
2463  }
2464  CHECK(Address::CanHoldStoreOffsetThumb(type, offset));
2465  switch (type) {
2466    case kStoreByte:
2467      strb(reg, Address(base, offset), cond);
2468      break;
2469    case kStoreHalfword:
2470      strh(reg, Address(base, offset), cond);
2471      break;
2472    case kStoreWord:
2473      str(reg, Address(base, offset), cond);
2474      break;
2475    case kStoreWordPair:
2476      strd(reg, Address(base, offset), cond);
2477      break;
2478    default:
2479      LOG(FATAL) << "UNREACHABLE";
2480  }
2481}
2482
2483
2484// Implementation note: this method must emit at most one instruction when
2485// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset.
2486void Thumb2Assembler::StoreSToOffset(SRegister reg,
2487                                     Register base,
2488                                     int32_t offset,
2489                                     Condition cond) {
2490  if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) {
2491    CHECK_NE(base, IP);
2492    LoadImmediate(IP, offset, cond);
2493    add(IP, IP, ShifterOperand(base), cond);
2494    base = IP;
2495    offset = 0;
2496  }
2497  CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset));
2498  vstrs(reg, Address(base, offset), cond);
2499}
2500
2501
2502// Implementation note: this method must emit at most one instruction when
2503// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset.
2504void Thumb2Assembler::StoreDToOffset(DRegister reg,
2505                                     Register base,
2506                                     int32_t offset,
2507                                     Condition cond) {
2508  if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) {
2509    CHECK_NE(base, IP);
2510    LoadImmediate(IP, offset, cond);
2511    add(IP, IP, ShifterOperand(base), cond);
2512    base = IP;
2513    offset = 0;
2514  }
2515  CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset));
2516  vstrd(reg, Address(base, offset), cond);
2517}
2518
2519
2520void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) {
2521  CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12);
2522#if ANDROID_SMP != 0
2523  int32_t encoding = 0xf3bf8f5f;  // dmb in T1 encoding.
2524  Emit32(encoding);
2525#endif
2526}
2527
2528
2529void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) {
2530  if (force_32bit_branches_) {
2531    cmp(r, ShifterOperand(0));
2532    b(label, EQ);
2533  } else {
2534    cbz(r, label);
2535  }
2536}
2537
2538
2539void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
2540  if (force_32bit_branches_) {
2541    cmp(r, ShifterOperand(0));
2542    b(label, NE);
2543  } else {
2544    cbnz(r, label);
2545  }
2546}
2547}  // namespace arm
2548}  // namespace art
2549