~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/JavaScriptCore/assembler/ARMv7Assembler.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

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