]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/ARMv7Assembler.h
2faa3a6102acc3197a9e2ad4e48f9a425607e01a
[apple/javascriptcore.git] / assembler / ARMv7Assembler.h
1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 University of Szeged
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifndef ARMAssembler_h
28 #define ARMAssembler_h
29
30 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
31
32 #include "AssemblerBuffer.h"
33 #include <wtf/Assertions.h>
34 #include <wtf/Vector.h>
35 #include <stdint.h>
36
37 namespace JSC {
38
39 namespace ARMRegisters {
40 typedef enum {
41 r0,
42 r1,
43 r2,
44 r3,
45 r4,
46 r5,
47 r6,
48 r7, wr = r7, // thumb work register
49 r8,
50 r9, sb = r9, // static base
51 r10, sl = r10, // stack limit
52 r11, fp = r11, // frame pointer
53 r12, ip = r12,
54 r13, sp = r13,
55 r14, lr = r14,
56 r15, pc = r15,
57 } RegisterID;
58
59 typedef enum {
60 s0,
61 s1,
62 s2,
63 s3,
64 s4,
65 s5,
66 s6,
67 s7,
68 s8,
69 s9,
70 s10,
71 s11,
72 s12,
73 s13,
74 s14,
75 s15,
76 s16,
77 s17,
78 s18,
79 s19,
80 s20,
81 s21,
82 s22,
83 s23,
84 s24,
85 s25,
86 s26,
87 s27,
88 s28,
89 s29,
90 s30,
91 s31,
92 } FPSingleRegisterID;
93
94 typedef enum {
95 d0,
96 d1,
97 d2,
98 d3,
99 d4,
100 d5,
101 d6,
102 d7,
103 d8,
104 d9,
105 d10,
106 d11,
107 d12,
108 d13,
109 d14,
110 d15,
111 d16,
112 d17,
113 d18,
114 d19,
115 d20,
116 d21,
117 d22,
118 d23,
119 d24,
120 d25,
121 d26,
122 d27,
123 d28,
124 d29,
125 d30,
126 d31,
127 } FPDoubleRegisterID;
128
129 typedef enum {
130 q0,
131 q1,
132 q2,
133 q3,
134 q4,
135 q5,
136 q6,
137 q7,
138 q8,
139 q9,
140 q10,
141 q11,
142 q12,
143 q13,
144 q14,
145 q15,
146 q16,
147 q17,
148 q18,
149 q19,
150 q20,
151 q21,
152 q22,
153 q23,
154 q24,
155 q25,
156 q26,
157 q27,
158 q28,
159 q29,
160 q30,
161 q31,
162 } FPQuadRegisterID;
163
164 inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
165 {
166 ASSERT(reg < d16);
167 return (FPSingleRegisterID)(reg << 1);
168 }
169
170 inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
171 {
172 ASSERT(!(reg & 1));
173 return (FPDoubleRegisterID)(reg >> 1);
174 }
175 }
176
177 class ARMv7Assembler;
178 class ARMThumbImmediate {
179 friend class ARMv7Assembler;
180
181 typedef uint8_t ThumbImmediateType;
182 static const ThumbImmediateType TypeInvalid = 0;
183 static const ThumbImmediateType TypeEncoded = 1;
184 static const ThumbImmediateType TypeUInt16 = 2;
185
186 typedef union {
187 int16_t asInt;
188 struct {
189 unsigned imm8 : 8;
190 unsigned imm3 : 3;
191 unsigned i : 1;
192 unsigned imm4 : 4;
193 };
194 // If this is an encoded immediate, then it may describe a shift, or a pattern.
195 struct {
196 unsigned shiftValue7 : 7;
197 unsigned shiftAmount : 5;
198 };
199 struct {
200 unsigned immediate : 8;
201 unsigned pattern : 4;
202 };
203 } ThumbImmediateValue;
204
205 // byte0 contains least significant bit; not using an array to make client code endian agnostic.
206 typedef union {
207 int32_t asInt;
208 struct {
209 uint8_t byte0;
210 uint8_t byte1;
211 uint8_t byte2;
212 uint8_t byte3;
213 };
214 } PatternBytes;
215
216 ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
217 {
218 if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
219 value >>= N; /* if any were set, lose the bottom N */
220 else /* if none of the top N bits are set, */
221 zeros += N; /* then we have identified N leading zeros */
222 }
223
224 static int32_t countLeadingZeros(uint32_t value)
225 {
226 if (!value)
227 return 32;
228
229 int32_t zeros = 0;
230 countLeadingZerosPartial(value, zeros, 16);
231 countLeadingZerosPartial(value, zeros, 8);
232 countLeadingZerosPartial(value, zeros, 4);
233 countLeadingZerosPartial(value, zeros, 2);
234 countLeadingZerosPartial(value, zeros, 1);
235 return zeros;
236 }
237
238 ARMThumbImmediate()
239 : m_type(TypeInvalid)
240 {
241 m_value.asInt = 0;
242 }
243
244 ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
245 : m_type(type)
246 , m_value(value)
247 {
248 }
249
250 ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
251 : m_type(TypeUInt16)
252 {
253 // Make sure this constructor is only reached with type TypeUInt16;
254 // this extra parameter makes the code a little clearer by making it
255 // explicit at call sites which type is being constructed
256 ASSERT_UNUSED(type, type == TypeUInt16);
257
258 m_value.asInt = value;
259 }
260
261 public:
262 static ARMThumbImmediate makeEncodedImm(uint32_t value)
263 {
264 ThumbImmediateValue encoding;
265 encoding.asInt = 0;
266
267 // okay, these are easy.
268 if (value < 256) {
269 encoding.immediate = value;
270 encoding.pattern = 0;
271 return ARMThumbImmediate(TypeEncoded, encoding);
272 }
273
274 int32_t leadingZeros = countLeadingZeros(value);
275 // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
276 ASSERT(leadingZeros < 24);
277
278 // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
279 // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
280 // zero. count(B) == 8, so the count of bits to be checked is 24 - count(Z).
281 int32_t rightShiftAmount = 24 - leadingZeros;
282 if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
283 // Shift the value down to the low byte position. The assign to
284 // shiftValue7 drops the implicit top bit.
285 encoding.shiftValue7 = value >> rightShiftAmount;
286 // The endoded shift amount is the magnitude of a right rotate.
287 encoding.shiftAmount = 8 + leadingZeros;
288 return ARMThumbImmediate(TypeEncoded, encoding);
289 }
290
291 PatternBytes bytes;
292 bytes.asInt = value;
293
294 if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
295 encoding.immediate = bytes.byte0;
296 encoding.pattern = 3;
297 return ARMThumbImmediate(TypeEncoded, encoding);
298 }
299
300 if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
301 encoding.immediate = bytes.byte0;
302 encoding.pattern = 1;
303 return ARMThumbImmediate(TypeEncoded, encoding);
304 }
305
306 if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
307 encoding.immediate = bytes.byte0;
308 encoding.pattern = 2;
309 return ARMThumbImmediate(TypeEncoded, encoding);
310 }
311
312 return ARMThumbImmediate();
313 }
314
315 static ARMThumbImmediate makeUInt12(int32_t value)
316 {
317 return (!(value & 0xfffff000))
318 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
319 : ARMThumbImmediate();
320 }
321
322 static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
323 {
324 // If this is not a 12-bit unsigned it, try making an encoded immediate.
325 return (!(value & 0xfffff000))
326 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
327 : makeEncodedImm(value);
328 }
329
330 // The 'make' methods, above, return a !isValid() value if the argument
331 // cannot be represented as the requested type. This methods is called
332 // 'get' since the argument can always be represented.
333 static ARMThumbImmediate makeUInt16(uint16_t value)
334 {
335 return ARMThumbImmediate(TypeUInt16, value);
336 }
337
338 bool isValid()
339 {
340 return m_type != TypeInvalid;
341 }
342
343 // These methods rely on the format of encoded byte values.
344 bool isUInt3() { return !(m_value.asInt & 0xfff8); }
345 bool isUInt4() { return !(m_value.asInt & 0xfff0); }
346 bool isUInt5() { return !(m_value.asInt & 0xffe0); }
347 bool isUInt6() { return !(m_value.asInt & 0xffc0); }
348 bool isUInt7() { return !(m_value.asInt & 0xff80); }
349 bool isUInt8() { return !(m_value.asInt & 0xff00); }
350 bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
351 bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
352 bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
353 bool isUInt16() { return m_type == TypeUInt16; }
354 uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
355 uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
356 uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
357 uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
358 uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
359 uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
360 uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
361 uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
362 uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
363 uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
364
365 bool isEncodedImm() { return m_type == TypeEncoded; }
366
367 private:
368 ThumbImmediateType m_type;
369 ThumbImmediateValue m_value;
370 };
371
372 class VFPImmediate {
373 public:
374 VFPImmediate(double d)
375 : m_value(-1)
376 {
377 union {
378 uint64_t i;
379 double d;
380 } u;
381
382 u.d = d;
383
384 int sign = static_cast<int>(u.i >> 63);
385 int exponent = static_cast<int>(u.i >> 52) & 0x7ff;
386 uint64_t mantissa = u.i & 0x000fffffffffffffull;
387
388 if ((exponent >= 0x3fc) && (exponent <= 0x403) && !(mantissa & 0x0000ffffffffffffull))
389 m_value = (sign << 7) | ((exponent & 7) << 4) | (int)(mantissa >> 48);
390 }
391
392 bool isValid()
393 {
394 return m_value != -1;
395 }
396
397 uint8_t value()
398 {
399 return (uint8_t)m_value;
400 }
401
402 private:
403 int m_value;
404 };
405
406 typedef enum {
407 SRType_LSL,
408 SRType_LSR,
409 SRType_ASR,
410 SRType_ROR,
411
412 SRType_RRX = SRType_ROR
413 } ARMShiftType;
414
415 class ARMv7Assembler;
416 class ShiftTypeAndAmount {
417 friend class ARMv7Assembler;
418
419 public:
420 ShiftTypeAndAmount()
421 {
422 m_u.type = (ARMShiftType)0;
423 m_u.amount = 0;
424 }
425
426 ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
427 {
428 m_u.type = type;
429 m_u.amount = amount & 31;
430 }
431
432 unsigned lo4() { return m_u.lo4; }
433 unsigned hi4() { return m_u.hi4; }
434
435 private:
436 union {
437 struct {
438 unsigned lo4 : 4;
439 unsigned hi4 : 4;
440 };
441 struct {
442 unsigned type : 2;
443 unsigned amount : 5;
444 };
445 } m_u;
446 };
447
448
449 class ARMv7Assembler {
450 public:
451 ~ARMv7Assembler()
452 {
453 ASSERT(m_jumpsToLink.isEmpty());
454 }
455
456 typedef ARMRegisters::RegisterID RegisterID;
457 typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
458 typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
459 typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
460
461 // (HS, LO, HI, LS) -> (AE, B, A, BE)
462 // (VS, VC) -> (O, NO)
463 typedef enum {
464 ConditionEQ,
465 ConditionNE,
466 ConditionHS,
467 ConditionLO,
468 ConditionMI,
469 ConditionPL,
470 ConditionVS,
471 ConditionVC,
472 ConditionHI,
473 ConditionLS,
474 ConditionGE,
475 ConditionLT,
476 ConditionGT,
477 ConditionLE,
478 ConditionAL,
479
480 ConditionCS = ConditionHS,
481 ConditionCC = ConditionLO,
482 } Condition;
483
484 class JmpSrc {
485 friend class ARMv7Assembler;
486 friend class ARMInstructionFormatter;
487 public:
488 JmpSrc()
489 : m_offset(-1)
490 {
491 }
492
493 private:
494 JmpSrc(int offset)
495 : m_offset(offset)
496 {
497 }
498
499 int m_offset;
500 };
501
502 class JmpDst {
503 friend class ARMv7Assembler;
504 friend class ARMInstructionFormatter;
505 public:
506 JmpDst()
507 : m_offset(-1)
508 , m_used(false)
509 {
510 }
511
512 bool isUsed() const { return m_used; }
513 void used() { m_used = true; }
514 private:
515 JmpDst(int offset)
516 : m_offset(offset)
517 , m_used(false)
518 {
519 ASSERT(m_offset == offset);
520 }
521
522 int m_offset : 31;
523 int m_used : 1;
524 };
525
526 private:
527
528 struct LinkRecord {
529 LinkRecord(intptr_t from, intptr_t to)
530 : from(from)
531 , to(to)
532 {
533 }
534
535 intptr_t from;
536 intptr_t to;
537 };
538
539 // ARMv7, Appx-A.6.3
540 bool BadReg(RegisterID reg)
541 {
542 return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
543 }
544
545 uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
546 {
547 uint32_t rdMask = (rdNum >> 1) << highBitsShift;
548 if (rdNum & 1)
549 rdMask |= 1 << lowBitShift;
550 return rdMask;
551 }
552
553 uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
554 {
555 uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
556 if (rdNum & 16)
557 rdMask |= 1 << highBitShift;
558 return rdMask;
559 }
560
561 typedef enum {
562 OP_ADD_reg_T1 = 0x1800,
563 OP_SUB_reg_T1 = 0x1A00,
564 OP_ADD_imm_T1 = 0x1C00,
565 OP_SUB_imm_T1 = 0x1E00,
566 OP_MOV_imm_T1 = 0x2000,
567 OP_CMP_imm_T1 = 0x2800,
568 OP_ADD_imm_T2 = 0x3000,
569 OP_SUB_imm_T2 = 0x3800,
570 OP_AND_reg_T1 = 0x4000,
571 OP_EOR_reg_T1 = 0x4040,
572 OP_TST_reg_T1 = 0x4200,
573 OP_RSB_imm_T1 = 0x4240,
574 OP_CMP_reg_T1 = 0x4280,
575 OP_ORR_reg_T1 = 0x4300,
576 OP_MVN_reg_T1 = 0x43C0,
577 OP_ADD_reg_T2 = 0x4400,
578 OP_MOV_reg_T1 = 0x4600,
579 OP_BLX = 0x4700,
580 OP_BX = 0x4700,
581 OP_STR_reg_T1 = 0x5000,
582 OP_LDR_reg_T1 = 0x5800,
583 OP_LDRH_reg_T1 = 0x5A00,
584 OP_LDRB_reg_T1 = 0x5C00,
585 OP_STR_imm_T1 = 0x6000,
586 OP_LDR_imm_T1 = 0x6800,
587 OP_LDRB_imm_T1 = 0x7800,
588 OP_LDRH_imm_T1 = 0x8800,
589 OP_STR_imm_T2 = 0x9000,
590 OP_LDR_imm_T2 = 0x9800,
591 OP_ADD_SP_imm_T1 = 0xA800,
592 OP_ADD_SP_imm_T2 = 0xB000,
593 OP_SUB_SP_imm_T1 = 0xB080,
594 OP_BKPT = 0xBE00,
595 OP_IT = 0xBF00,
596 OP_NOP_T1 = 0xBF00,
597 } OpcodeID;
598
599 typedef enum {
600 OP_AND_reg_T2 = 0xEA00,
601 OP_TST_reg_T2 = 0xEA10,
602 OP_ORR_reg_T2 = 0xEA40,
603 OP_ORR_S_reg_T2 = 0xEA50,
604 OP_ASR_imm_T1 = 0xEA4F,
605 OP_LSL_imm_T1 = 0xEA4F,
606 OP_LSR_imm_T1 = 0xEA4F,
607 OP_ROR_imm_T1 = 0xEA4F,
608 OP_MVN_reg_T2 = 0xEA6F,
609 OP_EOR_reg_T2 = 0xEA80,
610 OP_ADD_reg_T3 = 0xEB00,
611 OP_ADD_S_reg_T3 = 0xEB10,
612 OP_SUB_reg_T2 = 0xEBA0,
613 OP_SUB_S_reg_T2 = 0xEBB0,
614 OP_CMP_reg_T2 = 0xEBB0,
615 OP_VSTR = 0xED00,
616 OP_VLDR = 0xED10,
617 OP_VMOV_StoC = 0xEE00,
618 OP_VMOV_CtoS = 0xEE10,
619 OP_VMUL_T2 = 0xEE20,
620 OP_VADD_T2 = 0xEE30,
621 OP_VSUB_T2 = 0xEE30,
622 OP_VDIV = 0xEE80,
623 OP_VCMP_T1 = 0xEEB0,
624 OP_VCVT_FPIVFP = 0xEEB0,
625 OP_VMOV_IMM_T2 = 0xEEB0,
626 OP_VMRS = 0xEEB0,
627 OP_B_T4a = 0xF000,
628 OP_AND_imm_T1 = 0xF000,
629 OP_TST_imm = 0xF010,
630 OP_ORR_imm_T1 = 0xF040,
631 OP_MOV_imm_T2 = 0xF040,
632 OP_MVN_imm = 0xF060,
633 OP_EOR_imm_T1 = 0xF080,
634 OP_ADD_imm_T3 = 0xF100,
635 OP_ADD_S_imm_T3 = 0xF110,
636 OP_CMN_imm = 0xF110,
637 OP_SUB_imm_T3 = 0xF1A0,
638 OP_SUB_S_imm_T3 = 0xF1B0,
639 OP_CMP_imm_T2 = 0xF1B0,
640 OP_RSB_imm_T2 = 0xF1C0,
641 OP_ADD_imm_T4 = 0xF200,
642 OP_MOV_imm_T3 = 0xF240,
643 OP_SUB_imm_T4 = 0xF2A0,
644 OP_MOVT = 0xF2C0,
645 OP_NOP_T2a = 0xF3AF,
646 OP_LDRB_imm_T3 = 0xF810,
647 OP_LDRB_reg_T2 = 0xF810,
648 OP_LDRH_reg_T2 = 0xF830,
649 OP_LDRH_imm_T3 = 0xF830,
650 OP_STR_imm_T4 = 0xF840,
651 OP_STR_reg_T2 = 0xF840,
652 OP_LDR_imm_T4 = 0xF850,
653 OP_LDR_reg_T2 = 0xF850,
654 OP_LDRB_imm_T2 = 0xF890,
655 OP_LDRH_imm_T2 = 0xF8B0,
656 OP_STR_imm_T3 = 0xF8C0,
657 OP_LDR_imm_T3 = 0xF8D0,
658 OP_LSL_reg_T2 = 0xFA00,
659 OP_LSR_reg_T2 = 0xFA20,
660 OP_ASR_reg_T2 = 0xFA40,
661 OP_ROR_reg_T2 = 0xFA60,
662 OP_SMULL_T1 = 0xFB80,
663 } OpcodeID1;
664
665 typedef enum {
666 OP_VADD_T2b = 0x0A00,
667 OP_VDIVb = 0x0A00,
668 OP_VLDRb = 0x0A00,
669 OP_VMOV_IMM_T2b = 0x0A00,
670 OP_VMUL_T2b = 0x0A00,
671 OP_VSTRb = 0x0A00,
672 OP_VMOV_CtoSb = 0x0A10,
673 OP_VMOV_StoCb = 0x0A10,
674 OP_VMRSb = 0x0A10,
675 OP_VCMP_T1b = 0x0A40,
676 OP_VCVT_FPIVFPb = 0x0A40,
677 OP_VSUB_T2b = 0x0A40,
678 OP_NOP_T2b = 0x8000,
679 OP_B_T4b = 0x9000,
680 } OpcodeID2;
681
682 struct FourFours {
683 FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
684 {
685 m_u.f0 = f0;
686 m_u.f1 = f1;
687 m_u.f2 = f2;
688 m_u.f3 = f3;
689 }
690
691 union {
692 unsigned value;
693 struct {
694 unsigned f0 : 4;
695 unsigned f1 : 4;
696 unsigned f2 : 4;
697 unsigned f3 : 4;
698 };
699 } m_u;
700 };
701
702 class ARMInstructionFormatter;
703
704 // false means else!
705 bool ifThenElseConditionBit(Condition condition, bool isIf)
706 {
707 return isIf ? (condition & 1) : !(condition & 1);
708 }
709 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
710 {
711 int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
712 | (ifThenElseConditionBit(condition, inst3if) << 2)
713 | (ifThenElseConditionBit(condition, inst4if) << 1)
714 | 1;
715 ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
716 return (condition << 4) | mask;
717 }
718 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
719 {
720 int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
721 | (ifThenElseConditionBit(condition, inst3if) << 2)
722 | 2;
723 ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
724 return (condition << 4) | mask;
725 }
726 uint8_t ifThenElse(Condition condition, bool inst2if)
727 {
728 int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
729 | 4;
730 ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
731 return (condition << 4) | mask;
732 }
733
734 uint8_t ifThenElse(Condition condition)
735 {
736 int mask = 8;
737 ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
738 return (condition << 4) | mask;
739 }
740
741 public:
742
743 void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
744 {
745 // Rd can only be SP if Rn is also SP.
746 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
747 ASSERT(rd != ARMRegisters::pc);
748 ASSERT(rn != ARMRegisters::pc);
749 ASSERT(imm.isValid());
750
751 if (rn == ARMRegisters::sp) {
752 if (!(rd & 8) && imm.isUInt10()) {
753 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
754 return;
755 } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
756 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
757 return;
758 }
759 } else if (!((rd | rn) & 8)) {
760 if (imm.isUInt3()) {
761 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
762 return;
763 } else if ((rd == rn) && imm.isUInt8()) {
764 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
765 return;
766 }
767 }
768
769 if (imm.isEncodedImm())
770 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
771 else {
772 ASSERT(imm.isUInt12());
773 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
774 }
775 }
776
777 void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
778 {
779 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
780 ASSERT(rd != ARMRegisters::pc);
781 ASSERT(rn != ARMRegisters::pc);
782 ASSERT(!BadReg(rm));
783 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
784 }
785
786 // NOTE: In an IT block, add doesn't modify the flags register.
787 void add(RegisterID rd, RegisterID rn, RegisterID rm)
788 {
789 if (rd == rn)
790 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
791 else if (rd == rm)
792 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
793 else if (!((rd | rn | rm) & 8))
794 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
795 else
796 add(rd, rn, rm, ShiftTypeAndAmount());
797 }
798
799 // Not allowed in an IT (if then) block.
800 void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
801 {
802 // Rd can only be SP if Rn is also SP.
803 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
804 ASSERT(rd != ARMRegisters::pc);
805 ASSERT(rn != ARMRegisters::pc);
806 ASSERT(imm.isEncodedImm());
807
808 if (!((rd | rn) & 8)) {
809 if (imm.isUInt3()) {
810 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
811 return;
812 } else if ((rd == rn) && imm.isUInt8()) {
813 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
814 return;
815 }
816 }
817
818 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
819 }
820
821 // Not allowed in an IT (if then) block?
822 void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
823 {
824 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
825 ASSERT(rd != ARMRegisters::pc);
826 ASSERT(rn != ARMRegisters::pc);
827 ASSERT(!BadReg(rm));
828 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
829 }
830
831 // Not allowed in an IT (if then) block.
832 void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
833 {
834 if (!((rd | rn | rm) & 8))
835 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
836 else
837 add_S(rd, rn, rm, ShiftTypeAndAmount());
838 }
839
840 void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
841 {
842 ASSERT(!BadReg(rd));
843 ASSERT(!BadReg(rn));
844 ASSERT(imm.isEncodedImm());
845 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
846 }
847
848 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
849 {
850 ASSERT(!BadReg(rd));
851 ASSERT(!BadReg(rn));
852 ASSERT(!BadReg(rm));
853 m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
854 }
855
856 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
857 {
858 if ((rd == rn) && !((rd | rm) & 8))
859 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
860 else if ((rd == rm) && !((rd | rn) & 8))
861 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
862 else
863 ARM_and(rd, rn, rm, ShiftTypeAndAmount());
864 }
865
866 void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
867 {
868 ASSERT(!BadReg(rd));
869 ASSERT(!BadReg(rm));
870 ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
871 m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
872 }
873
874 void asr(RegisterID rd, RegisterID rn, RegisterID rm)
875 {
876 ASSERT(!BadReg(rd));
877 ASSERT(!BadReg(rn));
878 ASSERT(!BadReg(rm));
879 m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
880 }
881
882 // Only allowed in IT (if then) block if last instruction.
883 JmpSrc b()
884 {
885 m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
886 return JmpSrc(m_formatter.size());
887 }
888
889 // Only allowed in IT (if then) block if last instruction.
890 JmpSrc blx(RegisterID rm)
891 {
892 ASSERT(rm != ARMRegisters::pc);
893 m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
894 return JmpSrc(m_formatter.size());
895 }
896
897 // Only allowed in IT (if then) block if last instruction.
898 JmpSrc bx(RegisterID rm)
899 {
900 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
901 return JmpSrc(m_formatter.size());
902 }
903
904 void bkpt(uint8_t imm=0)
905 {
906 m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
907 }
908
909 void cmn(RegisterID rn, ARMThumbImmediate imm)
910 {
911 ASSERT(rn != ARMRegisters::pc);
912 ASSERT(imm.isEncodedImm());
913
914 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
915 }
916
917 void cmp(RegisterID rn, ARMThumbImmediate imm)
918 {
919 ASSERT(rn != ARMRegisters::pc);
920 ASSERT(imm.isEncodedImm());
921
922 if (!(rn & 8) && imm.isUInt8())
923 m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
924 else
925 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
926 }
927
928 void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
929 {
930 ASSERT(rn != ARMRegisters::pc);
931 ASSERT(!BadReg(rm));
932 m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
933 }
934
935 void cmp(RegisterID rn, RegisterID rm)
936 {
937 if ((rn | rm) & 8)
938 cmp(rn, rm, ShiftTypeAndAmount());
939 else
940 m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
941 }
942
943 // xor is not spelled with an 'e'. :-(
944 void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
945 {
946 ASSERT(!BadReg(rd));
947 ASSERT(!BadReg(rn));
948 ASSERT(imm.isEncodedImm());
949 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
950 }
951
952 // xor is not spelled with an 'e'. :-(
953 void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
954 {
955 ASSERT(!BadReg(rd));
956 ASSERT(!BadReg(rn));
957 ASSERT(!BadReg(rm));
958 m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
959 }
960
961 // xor is not spelled with an 'e'. :-(
962 void eor(RegisterID rd, RegisterID rn, RegisterID rm)
963 {
964 if ((rd == rn) && !((rd | rm) & 8))
965 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
966 else if ((rd == rm) && !((rd | rn) & 8))
967 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
968 else
969 eor(rd, rn, rm, ShiftTypeAndAmount());
970 }
971
972 void it(Condition cond)
973 {
974 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
975 }
976
977 void it(Condition cond, bool inst2if)
978 {
979 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
980 }
981
982 void it(Condition cond, bool inst2if, bool inst3if)
983 {
984 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
985 }
986
987 void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
988 {
989 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
990 }
991
992 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
993 void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
994 {
995 ASSERT(rn != ARMRegisters::pc); // LDR (literal)
996 ASSERT(imm.isUInt12());
997
998 if (!((rt | rn) & 8) && imm.isUInt7())
999 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1000 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1001 m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
1002 else
1003 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
1004 }
1005
1006 // If index is set, this is a regular offset or a pre-indexed load;
1007 // if index is not set then is is a post-index load.
1008 //
1009 // If wback is set rn is updated - this is a pre or post index load,
1010 // if wback is not set this is a regular offset memory access.
1011 //
1012 // (-255 <= offset <= 255)
1013 // _reg = REG[rn]
1014 // _tmp = _reg + offset
1015 // MEM[index ? _tmp : _reg] = REG[rt]
1016 // if (wback) REG[rn] = _tmp
1017 void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1018 {
1019 ASSERT(rt != ARMRegisters::pc);
1020 ASSERT(rn != ARMRegisters::pc);
1021 ASSERT(index || wback);
1022 ASSERT(!wback | (rt != rn));
1023
1024 bool add = true;
1025 if (offset < 0) {
1026 add = false;
1027 offset = -offset;
1028 }
1029 ASSERT((offset & ~0xff) == 0);
1030
1031 offset |= (wback << 8);
1032 offset |= (add << 9);
1033 offset |= (index << 10);
1034 offset |= (1 << 11);
1035
1036 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1037 }
1038
1039 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1040 void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1041 {
1042 ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1043 ASSERT(!BadReg(rm));
1044 ASSERT(shift <= 3);
1045
1046 if (!shift && !((rt | rn | rm) & 8))
1047 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1048 else
1049 m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1050 }
1051
1052 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1053 void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1054 {
1055 ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1056 ASSERT(imm.isUInt12());
1057
1058 if (!((rt | rn) & 8) && imm.isUInt6())
1059 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1060 else
1061 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1062 }
1063
1064 // If index is set, this is a regular offset or a pre-indexed load;
1065 // if index is not set then is is a post-index load.
1066 //
1067 // If wback is set rn is updated - this is a pre or post index load,
1068 // if wback is not set this is a regular offset memory access.
1069 //
1070 // (-255 <= offset <= 255)
1071 // _reg = REG[rn]
1072 // _tmp = _reg + offset
1073 // MEM[index ? _tmp : _reg] = REG[rt]
1074 // if (wback) REG[rn] = _tmp
1075 void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1076 {
1077 ASSERT(rt != ARMRegisters::pc);
1078 ASSERT(rn != ARMRegisters::pc);
1079 ASSERT(index || wback);
1080 ASSERT(!wback | (rt != rn));
1081
1082 bool add = true;
1083 if (offset < 0) {
1084 add = false;
1085 offset = -offset;
1086 }
1087 ASSERT((offset & ~0xff) == 0);
1088
1089 offset |= (wback << 8);
1090 offset |= (add << 9);
1091 offset |= (index << 10);
1092 offset |= (1 << 11);
1093
1094 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1095 }
1096
1097 void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1098 {
1099 ASSERT(!BadReg(rt)); // Memory hint
1100 ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1101 ASSERT(!BadReg(rm));
1102 ASSERT(shift <= 3);
1103
1104 if (!shift && !((rt | rn | rm) & 8))
1105 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1106 else
1107 m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1108 }
1109
1110 void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1111 {
1112 ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1113 ASSERT(imm.isUInt12());
1114
1115 if (!((rt | rn) & 8) && imm.isUInt5())
1116 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1117 else
1118 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1119 }
1120
1121 void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1122 {
1123 ASSERT(rt != ARMRegisters::pc);
1124 ASSERT(rn != ARMRegisters::pc);
1125 ASSERT(index || wback);
1126 ASSERT(!wback | (rt != rn));
1127
1128 bool add = true;
1129 if (offset < 0) {
1130 add = false;
1131 offset = -offset;
1132 }
1133
1134 ASSERT(!(offset & ~0xff));
1135
1136 offset |= (wback << 8);
1137 offset |= (add << 9);
1138 offset |= (index << 10);
1139 offset |= (1 << 11);
1140
1141 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1142 }
1143
1144 void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1145 {
1146 ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1147 ASSERT(!BadReg(rm));
1148 ASSERT(shift <= 3);
1149
1150 if (!shift && !((rt | rn | rm) & 8))
1151 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1152 else
1153 m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1154 }
1155
1156 void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1157 {
1158 ASSERT(!BadReg(rd));
1159 ASSERT(!BadReg(rm));
1160 ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1161 m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1162 }
1163
1164 void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1165 {
1166 ASSERT(!BadReg(rd));
1167 ASSERT(!BadReg(rn));
1168 ASSERT(!BadReg(rm));
1169 m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1170 }
1171
1172 void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1173 {
1174 ASSERT(!BadReg(rd));
1175 ASSERT(!BadReg(rm));
1176 ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1177 m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1178 }
1179
1180 void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1181 {
1182 ASSERT(!BadReg(rd));
1183 ASSERT(!BadReg(rn));
1184 ASSERT(!BadReg(rm));
1185 m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1186 }
1187
1188 void movT3(RegisterID rd, ARMThumbImmediate imm)
1189 {
1190 ASSERT(imm.isValid());
1191 ASSERT(!imm.isEncodedImm());
1192 ASSERT(!BadReg(rd));
1193
1194 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1195 }
1196
1197 void mov(RegisterID rd, ARMThumbImmediate imm)
1198 {
1199 ASSERT(imm.isValid());
1200 ASSERT(!BadReg(rd));
1201
1202 if ((rd < 8) && imm.isUInt8())
1203 m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1204 else if (imm.isEncodedImm())
1205 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1206 else
1207 movT3(rd, imm);
1208 }
1209
1210 void mov(RegisterID rd, RegisterID rm)
1211 {
1212 m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1213 }
1214
1215 void movt(RegisterID rd, ARMThumbImmediate imm)
1216 {
1217 ASSERT(imm.isUInt16());
1218 ASSERT(!BadReg(rd));
1219 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1220 }
1221
1222 void mvn(RegisterID rd, ARMThumbImmediate imm)
1223 {
1224 ASSERT(imm.isEncodedImm());
1225 ASSERT(!BadReg(rd));
1226
1227 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1228 }
1229
1230 void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1231 {
1232 ASSERT(!BadReg(rd));
1233 ASSERT(!BadReg(rm));
1234 m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1235 }
1236
1237 void mvn(RegisterID rd, RegisterID rm)
1238 {
1239 if (!((rd | rm) & 8))
1240 m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1241 else
1242 mvn(rd, rm, ShiftTypeAndAmount());
1243 }
1244
1245 void neg(RegisterID rd, RegisterID rm)
1246 {
1247 ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1248 sub(rd, zero, rm);
1249 }
1250
1251 void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1252 {
1253 ASSERT(!BadReg(rd));
1254 ASSERT(!BadReg(rn));
1255 ASSERT(imm.isEncodedImm());
1256 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1257 }
1258
1259 void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1260 {
1261 ASSERT(!BadReg(rd));
1262 ASSERT(!BadReg(rn));
1263 ASSERT(!BadReg(rm));
1264 m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1265 }
1266
1267 void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1268 {
1269 if ((rd == rn) && !((rd | rm) & 8))
1270 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1271 else if ((rd == rm) && !((rd | rn) & 8))
1272 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1273 else
1274 orr(rd, rn, rm, ShiftTypeAndAmount());
1275 }
1276
1277 void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1278 {
1279 ASSERT(!BadReg(rd));
1280 ASSERT(!BadReg(rn));
1281 ASSERT(!BadReg(rm));
1282 m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1283 }
1284
1285 void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1286 {
1287 if ((rd == rn) && !((rd | rm) & 8))
1288 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1289 else if ((rd == rm) && !((rd | rn) & 8))
1290 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1291 else
1292 orr_S(rd, rn, rm, ShiftTypeAndAmount());
1293 }
1294
1295 void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1296 {
1297 ASSERT(!BadReg(rd));
1298 ASSERT(!BadReg(rm));
1299 ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1300 m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1301 }
1302
1303 void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1304 {
1305 ASSERT(!BadReg(rd));
1306 ASSERT(!BadReg(rn));
1307 ASSERT(!BadReg(rm));
1308 m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1309 }
1310
1311 void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1312 {
1313 ASSERT(!BadReg(rdLo));
1314 ASSERT(!BadReg(rdHi));
1315 ASSERT(!BadReg(rn));
1316 ASSERT(!BadReg(rm));
1317 ASSERT(rdLo != rdHi);
1318 m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1319 }
1320
1321 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1322 void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1323 {
1324 ASSERT(rt != ARMRegisters::pc);
1325 ASSERT(rn != ARMRegisters::pc);
1326 ASSERT(imm.isUInt12());
1327
1328 if (!((rt | rn) & 8) && imm.isUInt7())
1329 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1330 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1331 m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
1332 else
1333 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1334 }
1335
1336 // If index is set, this is a regular offset or a pre-indexed store;
1337 // if index is not set then is is a post-index store.
1338 //
1339 // If wback is set rn is updated - this is a pre or post index store,
1340 // if wback is not set this is a regular offset memory access.
1341 //
1342 // (-255 <= offset <= 255)
1343 // _reg = REG[rn]
1344 // _tmp = _reg + offset
1345 // MEM[index ? _tmp : _reg] = REG[rt]
1346 // if (wback) REG[rn] = _tmp
1347 void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1348 {
1349 ASSERT(rt != ARMRegisters::pc);
1350 ASSERT(rn != ARMRegisters::pc);
1351 ASSERT(index || wback);
1352 ASSERT(!wback | (rt != rn));
1353
1354 bool add = true;
1355 if (offset < 0) {
1356 add = false;
1357 offset = -offset;
1358 }
1359 ASSERT((offset & ~0xff) == 0);
1360
1361 offset |= (wback << 8);
1362 offset |= (add << 9);
1363 offset |= (index << 10);
1364 offset |= (1 << 11);
1365
1366 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1367 }
1368
1369 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1370 void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1371 {
1372 ASSERT(rn != ARMRegisters::pc);
1373 ASSERT(!BadReg(rm));
1374 ASSERT(shift <= 3);
1375
1376 if (!shift && !((rt | rn | rm) & 8))
1377 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1378 else
1379 m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1380 }
1381
1382 void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1383 {
1384 // Rd can only be SP if Rn is also SP.
1385 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1386 ASSERT(rd != ARMRegisters::pc);
1387 ASSERT(rn != ARMRegisters::pc);
1388 ASSERT(imm.isValid());
1389
1390 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1391 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1392 return;
1393 } else if (!((rd | rn) & 8)) {
1394 if (imm.isUInt3()) {
1395 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1396 return;
1397 } else if ((rd == rn) && imm.isUInt8()) {
1398 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1399 return;
1400 }
1401 }
1402
1403 if (imm.isEncodedImm())
1404 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1405 else {
1406 ASSERT(imm.isUInt12());
1407 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1408 }
1409 }
1410
1411 void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1412 {
1413 ASSERT(rd != ARMRegisters::pc);
1414 ASSERT(rn != ARMRegisters::pc);
1415 ASSERT(imm.isValid());
1416 ASSERT(imm.isUInt12());
1417
1418 if (!((rd | rn) & 8) && !imm.getUInt12())
1419 m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1420 else
1421 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1422 }
1423
1424 void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1425 {
1426 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1427 ASSERT(rd != ARMRegisters::pc);
1428 ASSERT(rn != ARMRegisters::pc);
1429 ASSERT(!BadReg(rm));
1430 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1431 }
1432
1433 // NOTE: In an IT block, add doesn't modify the flags register.
1434 void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1435 {
1436 if (!((rd | rn | rm) & 8))
1437 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1438 else
1439 sub(rd, rn, rm, ShiftTypeAndAmount());
1440 }
1441
1442 // Not allowed in an IT (if then) block.
1443 void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1444 {
1445 // Rd can only be SP if Rn is also SP.
1446 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1447 ASSERT(rd != ARMRegisters::pc);
1448 ASSERT(rn != ARMRegisters::pc);
1449 ASSERT(imm.isValid());
1450
1451 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1452 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1453 return;
1454 } else if (!((rd | rn) & 8)) {
1455 if (imm.isUInt3()) {
1456 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1457 return;
1458 } else if ((rd == rn) && imm.isUInt8()) {
1459 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1460 return;
1461 }
1462 }
1463
1464 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1465 }
1466
1467 // Not allowed in an IT (if then) block?
1468 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1469 {
1470 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1471 ASSERT(rd != ARMRegisters::pc);
1472 ASSERT(rn != ARMRegisters::pc);
1473 ASSERT(!BadReg(rm));
1474 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1475 }
1476
1477 // Not allowed in an IT (if then) block.
1478 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1479 {
1480 if (!((rd | rn | rm) & 8))
1481 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1482 else
1483 sub_S(rd, rn, rm, ShiftTypeAndAmount());
1484 }
1485
1486 void tst(RegisterID rn, ARMThumbImmediate imm)
1487 {
1488 ASSERT(!BadReg(rn));
1489 ASSERT(imm.isEncodedImm());
1490
1491 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1492 }
1493
1494 void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1495 {
1496 ASSERT(!BadReg(rn));
1497 ASSERT(!BadReg(rm));
1498 m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1499 }
1500
1501 void tst(RegisterID rn, RegisterID rm)
1502 {
1503 if ((rn | rm) & 8)
1504 tst(rn, rm, ShiftTypeAndAmount());
1505 else
1506 m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1507 }
1508
1509 void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1510 {
1511 m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1512 }
1513
1514 void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1515 {
1516 m_formatter.vfpOp(OP_VCMP_T1, OP_VCMP_T1b, true, VFPOperand(4), rd, rm);
1517 }
1518
1519 void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1520 {
1521 // boolean values are 64bit (toInt, unsigned, roundZero)
1522 m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
1523 }
1524
1525 void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1526 {
1527 // boolean values are 64bit (toInt, unsigned, roundZero)
1528 m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
1529 }
1530
1531 void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1532 {
1533 m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
1534 }
1535
1536 void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1537 {
1538 m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
1539 }
1540
1541 void vmov_F64_0(FPDoubleRegisterID rd)
1542 {
1543 m_formatter.vfpOp(OP_VMOV_IMM_T2, OP_VMOV_IMM_T2b, true, VFPOperand(0), rd, VFPOperand(0));
1544 }
1545
1546 void vmov(RegisterID rd, FPSingleRegisterID rn)
1547 {
1548 ASSERT(!BadReg(rd));
1549 m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
1550 }
1551
1552 void vmov(FPSingleRegisterID rd, RegisterID rn)
1553 {
1554 ASSERT(!BadReg(rn));
1555 m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
1556 }
1557
1558 void vmrs(RegisterID reg = ARMRegisters::pc)
1559 {
1560 ASSERT(reg != ARMRegisters::sp);
1561 m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
1562 }
1563
1564 void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1565 {
1566 m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
1567 }
1568
1569 void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1570 {
1571 m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
1572 }
1573
1574 void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1575 {
1576 m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1577 }
1578
1579 JmpDst label()
1580 {
1581 return JmpDst(m_formatter.size());
1582 }
1583
1584 JmpDst align(int alignment)
1585 {
1586 while (!m_formatter.isAligned(alignment))
1587 bkpt();
1588
1589 return label();
1590 }
1591
1592 static void* getRelocatedAddress(void* code, JmpSrc jump)
1593 {
1594 ASSERT(jump.m_offset != -1);
1595
1596 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1597 }
1598
1599 static void* getRelocatedAddress(void* code, JmpDst destination)
1600 {
1601 ASSERT(destination.m_offset != -1);
1602
1603 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1604 }
1605
1606 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1607 {
1608 return dst.m_offset - src.m_offset;
1609 }
1610
1611 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1612 {
1613 return dst.m_offset - src.m_offset;
1614 }
1615
1616 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1617 {
1618 return dst.m_offset - src.m_offset;
1619 }
1620
1621 // Assembler admin methods:
1622
1623 size_t size() const
1624 {
1625 return m_formatter.size();
1626 }
1627
1628 void* executableCopy(ExecutablePool* allocator)
1629 {
1630 void* copy = m_formatter.executableCopy(allocator);
1631
1632 unsigned jumpCount = m_jumpsToLink.size();
1633 for (unsigned i = 0; i < jumpCount; ++i) {
1634 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from);
1635 uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to);
1636 linkJumpAbsolute(location, target);
1637 }
1638 m_jumpsToLink.clear();
1639
1640 ASSERT(copy);
1641 return copy;
1642 }
1643
1644 static unsigned getCallReturnOffset(JmpSrc call)
1645 {
1646 ASSERT(call.m_offset >= 0);
1647 return call.m_offset;
1648 }
1649
1650 // Linking & patching:
1651 //
1652 // 'link' and 'patch' methods are for use on unprotected code - such as the code
1653 // within the AssemblerBuffer, and code being patched by the patch buffer. Once
1654 // code has been finalized it is (platform support permitting) within a non-
1655 // writable region of memory; to modify the code in an execute-only execuable
1656 // pool the 'repatch' and 'relink' methods should be used.
1657
1658 void linkJump(JmpSrc from, JmpDst to)
1659 {
1660 ASSERT(to.m_offset != -1);
1661 ASSERT(from.m_offset != -1);
1662 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset));
1663 }
1664
1665 static void linkJump(void* code, JmpSrc from, void* to)
1666 {
1667 ASSERT(from.m_offset != -1);
1668
1669 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1670 linkJumpAbsolute(location, to);
1671 }
1672
1673 // bah, this mathod should really be static, since it is used by the LinkBuffer.
1674 // return a bool saying whether the link was successful?
1675 static void linkCall(void* code, JmpSrc from, void* to)
1676 {
1677 ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1678 ASSERT(from.m_offset != -1);
1679 ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1680
1681 setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1682 }
1683
1684 static void linkPointer(void* code, JmpDst where, void* value)
1685 {
1686 setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1687 }
1688
1689 static void relinkJump(void* from, void* to)
1690 {
1691 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1692 ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1693
1694 linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
1695
1696 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
1697 }
1698
1699 static void relinkCall(void* from, void* to)
1700 {
1701 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1702 ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1703
1704 setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1705
1706 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
1707 }
1708
1709 static void repatchInt32(void* where, int32_t value)
1710 {
1711 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1712
1713 setInt32(where, value);
1714
1715 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1716 }
1717
1718 static void repatchPointer(void* where, void* value)
1719 {
1720 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1721
1722 setPointer(where, value);
1723
1724 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1725 }
1726
1727 static void repatchLoadPtrToLEA(void* where)
1728 {
1729 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1730 uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
1731
1732 ASSERT((loadOp[0] & 0xfff0) == OP_LDR_reg_T2);
1733 ASSERT((loadOp[1] & 0x0ff0) == 0);
1734 int rn = loadOp[0] & 0xf;
1735 int rt = loadOp[1] >> 12;
1736 int rm = loadOp[1] & 0xf;
1737
1738 loadOp[0] = OP_ADD_reg_T3 | rn;
1739 loadOp[1] = rt << 8 | rm;
1740 ExecutableAllocator::cacheFlush(loadOp, sizeof(uint32_t));
1741 }
1742
1743 private:
1744 // VFP operations commonly take one or more 5-bit operands, typically representing a
1745 // floating point register number. This will commonly be encoded in the instruction
1746 // in two parts, with one single bit field, and one 4-bit field. In the case of
1747 // double precision operands the high bit of the register number will be encoded
1748 // separately, and for single precision operands the high bit of the register number
1749 // will be encoded individually.
1750 // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
1751 // field to be encoded together in the instruction (the low 4-bits of a double
1752 // register number, or the high 4-bits of a single register number), and bit 4
1753 // contains the bit value to be encoded individually.
1754 struct VFPOperand {
1755 explicit VFPOperand(uint32_t value)
1756 : m_value(value)
1757 {
1758 ASSERT(!(m_value & ~0x1f));
1759 }
1760
1761 VFPOperand(FPDoubleRegisterID reg)
1762 : m_value(reg)
1763 {
1764 }
1765
1766 VFPOperand(RegisterID reg)
1767 : m_value(reg)
1768 {
1769 }
1770
1771 VFPOperand(FPSingleRegisterID reg)
1772 : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
1773 {
1774 }
1775
1776 uint32_t bits1()
1777 {
1778 return m_value >> 4;
1779 }
1780
1781 uint32_t bits4()
1782 {
1783 return m_value & 0xf;
1784 }
1785
1786 uint32_t m_value;
1787 };
1788
1789 VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
1790 {
1791 // Cannot specify rounding when converting to float.
1792 ASSERT(toInteger || !isRoundZero);
1793
1794 uint32_t op = 0x8;
1795 if (toInteger) {
1796 // opc2 indicates both toInteger & isUnsigned.
1797 op |= isUnsigned ? 0x4 : 0x5;
1798 // 'op' field in instruction is isRoundZero
1799 if (isRoundZero)
1800 op |= 0x10;
1801 } else {
1802 // 'op' field in instruction is isUnsigned
1803 if (!isUnsigned)
1804 op |= 0x10;
1805 }
1806 return VFPOperand(op);
1807 }
1808
1809 static void setInt32(void* code, uint32_t value)
1810 {
1811 uint16_t* location = reinterpret_cast<uint16_t*>(code);
1812 ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
1813
1814 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
1815 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
1816 location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1817 location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
1818 location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1819 location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
1820
1821 ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1822 }
1823
1824 static void setPointer(void* code, void* value)
1825 {
1826 setInt32(code, reinterpret_cast<uint32_t>(value));
1827 }
1828
1829 static bool isB(void* address)
1830 {
1831 uint16_t* instruction = static_cast<uint16_t*>(address);
1832 return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
1833 }
1834
1835 static bool isBX(void* address)
1836 {
1837 uint16_t* instruction = static_cast<uint16_t*>(address);
1838 return (instruction[0] & 0xff87) == OP_BX;
1839 }
1840
1841 static bool isMOV_imm_T3(void* address)
1842 {
1843 uint16_t* instruction = static_cast<uint16_t*>(address);
1844 return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
1845 }
1846
1847 static bool isMOVT(void* address)
1848 {
1849 uint16_t* instruction = static_cast<uint16_t*>(address);
1850 return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
1851 }
1852
1853 static bool isNOP_T1(void* address)
1854 {
1855 uint16_t* instruction = static_cast<uint16_t*>(address);
1856 return instruction[0] == OP_NOP_T1;
1857 }
1858
1859 static bool isNOP_T2(void* address)
1860 {
1861 uint16_t* instruction = static_cast<uint16_t*>(address);
1862 return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
1863 }
1864
1865 static void linkJumpAbsolute(uint16_t* instruction, void* target)
1866 {
1867 // FIMXE: this should be up in the MacroAssembler layer. :-(
1868 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
1869
1870 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1871 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1872
1873 ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
1874 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
1875
1876 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1877
1878 // From Cortex-A8 errata:
1879 // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
1880 // the target of the branch falls within the first region it is
1881 // possible for the processor to incorrectly determine the branch
1882 // instruction, and it is also possible in some cases for the processor
1883 // to enter a deadlock state.
1884 // The instruction is spanning two pages if it ends at an address ending 0x002
1885 bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
1886 // The target is in the first page if the jump branch back by [3..0x1002] bytes
1887 bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
1888 bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
1889
1890 if (((relative << 7) >> 7) == relative && !wouldTriggerA8Errata) {
1891 // ARM encoding for the top two bits below the sign bit is 'peculiar'.
1892 if (relative >= 0)
1893 relative ^= 0xC00000;
1894
1895 // All branch offsets should be an even distance.
1896 ASSERT(!(relative & 1));
1897 // There may be a better way to fix this, but right now put the NOPs first, since in the
1898 // case of an conditional branch this will be coming after an ITTT predicating *three*
1899 // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to
1900 // variable wdith encoding - the previous instruction might *look* like an ITTT but
1901 // actually be the second half of a 2-word op.
1902 instruction[-5] = OP_NOP_T1;
1903 instruction[-4] = OP_NOP_T2a;
1904 instruction[-3] = OP_NOP_T2b;
1905 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
1906 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
1907 } else {
1908 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
1909 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
1910 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1911 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
1912 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1913 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
1914 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
1915 }
1916 }
1917
1918 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
1919 {
1920 return op | (imm.m_value.i << 10) | imm.m_value.imm4;
1921 }
1922 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
1923 {
1924 return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
1925 }
1926
1927 class ARMInstructionFormatter {
1928 public:
1929 void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
1930 {
1931 m_buffer.putShort(op | (rd << 8) | imm);
1932 }
1933
1934 void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
1935 {
1936 m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
1937 }
1938
1939 void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
1940 {
1941 m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
1942 }
1943
1944 void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
1945 {
1946 m_buffer.putShort(op | imm);
1947 }
1948
1949 void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
1950 {
1951 m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
1952 }
1953 void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
1954 {
1955 m_buffer.putShort(op | imm);
1956 }
1957
1958 void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
1959 {
1960 m_buffer.putShort(op | (reg1 << 3) | reg2);
1961 }
1962
1963 void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
1964 {
1965 m_buffer.putShort(op | reg);
1966 m_buffer.putShort(ff.m_u.value);
1967 }
1968
1969 void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
1970 {
1971 m_buffer.putShort(op);
1972 m_buffer.putShort(ff.m_u.value);
1973 }
1974
1975 void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
1976 {
1977 m_buffer.putShort(op1);
1978 m_buffer.putShort(op2);
1979 }
1980
1981 void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
1982 {
1983 ARMThumbImmediate newImm = imm;
1984 newImm.m_value.imm4 = imm4;
1985
1986 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
1987 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
1988 }
1989
1990 void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
1991 {
1992 m_buffer.putShort(op | reg1);
1993 m_buffer.putShort((reg2 << 12) | imm);
1994 }
1995
1996 // Formats up instructions of the pattern:
1997 // 111111111B11aaaa:bbbb222SA2C2cccc
1998 // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
1999 // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
2000 void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
2001 {
2002 ASSERT(!(op1 & 0x004f));
2003 ASSERT(!(op2 & 0xf1af));
2004 m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2005 m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
2006 }
2007
2008 // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2009 // (i.e. +/-(0..255) 32-bit words)
2010 void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2011 {
2012 bool up = true;
2013 if (imm < 0) {
2014 imm = -imm;
2015 up = false;
2016 }
2017
2018 uint32_t offset = imm;
2019 ASSERT(!(offset & ~0x3fc));
2020 offset >>= 2;
2021
2022 m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2023 m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2024 }
2025
2026 // Administrative methods:
2027
2028 size_t size() const { return m_buffer.size(); }
2029 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2030 void* data() const { return m_buffer.data(); }
2031 void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
2032
2033 private:
2034 AssemblerBuffer m_buffer;
2035 } m_formatter;
2036
2037 Vector<LinkRecord> m_jumpsToLink;
2038 };
2039
2040 } // namespace JSC
2041
2042 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
2043
2044 #endif // ARMAssembler_h