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