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