~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Common/Arm64Emitter.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Dolphin Emulator Project
 
2
// Licensed under GPLv2
 
3
// Refer to the license.txt file included.
 
4
 
 
5
#include <limits>
 
6
#include <algorithm>
 
7
#include <vector>
 
8
#include <cmath>
 
9
#include <cinttypes>
 
10
 
 
11
#include <stdlib.h>
 
12
#include <string.h>
 
13
 
 
14
#include "base/basictypes.h"
 
15
 
 
16
#include "Arm64Emitter.h"
 
17
#include "MathUtil.h"
 
18
#include "CommonTypes.h"
 
19
#include "CPUDetect.h"
 
20
 
 
21
namespace Arm64Gen
 
22
{
 
23
 
 
24
const int kWRegSizeInBits = 32;
 
25
const int kXRegSizeInBits = 64;
 
26
 
 
27
// The below few functions are taken from V8.
 
28
int CountLeadingZeros(uint64_t value, int width) {
 
29
        // TODO(jbramley): Optimize this for ARM64 hosts.
 
30
        int count = 0;
 
31
        uint64_t bit_test = 1ULL << (width - 1);
 
32
        while ((count < width) && ((bit_test & value) == 0)) {
 
33
                count++;
 
34
                bit_test >>= 1;
 
35
        }
 
36
        return count;
 
37
}
 
38
 
 
39
uint64_t LargestPowerOf2Divisor(uint64_t value) {
 
40
        return value & -(int64_t)value;
 
41
}
 
42
 
 
43
bool IsPowerOfTwo(uint64_t x) {
 
44
        return (x != 0) && ((x & (x - 1)) == 0);
 
45
}
 
46
 
 
47
#define V8_UINT64_C(x) ((uint64_t)(x))
 
48
 
 
49
bool IsImmArithmetic(uint64_t input, u32 *val, bool *shift) {
 
50
        if (input < 4096) {
 
51
                if (val) *val = input;
 
52
                if (shift) *shift = false;
 
53
                return true;
 
54
        } else if ((input & 0xFFF000) == input) {
 
55
                if (val) *val = input >> 12;
 
56
                if (shift) *shift = true;
 
57
                return true;
 
58
        }
 
59
        return false;
 
60
}
 
61
 
 
62
bool IsImmLogical(uint64_t value, unsigned int width, unsigned int *n, unsigned int *imm_s, unsigned int *imm_r) {
 
63
  //DCHECK((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
 
64
  // DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
 
65
 
 
66
  bool negate = false;
 
67
 
 
68
  // Logical immediates are encoded using parameters n, imm_s and imm_r using
 
69
  // the following table:
 
70
  //
 
71
  //    N   imms    immr    size        S             R
 
72
  //    1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
 
73
  //    0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
 
74
  //    0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
 
75
  //    0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
 
76
  //    0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
 
77
  //    0  11110s  xxxxxr     2    UInt(s)       UInt(r)
 
78
  // (s bits must not be all set)
 
79
  //
 
80
  // A pattern is constructed of size bits, where the least significant S+1 bits
 
81
  // are set. The pattern is rotated right by R, and repeated across a 32 or
 
82
  // 64-bit value, depending on destination register width.
 
83
  //
 
84
  // Put another way: the basic format of a logical immediate is a single
 
85
  // contiguous stretch of 1 bits, repeated across the whole word at intervals
 
86
  // given by a power of 2. To identify them quickly, we first locate the
 
87
  // lowest stretch of 1 bits, then the next 1 bit above that; that combination
 
88
  // is different for every logical immediate, so it gives us all the
 
89
  // information we need to identify the only logical immediate that our input
 
90
  // could be, and then we simply check if that's the value we actually have.
 
91
  //
 
92
  // (The rotation parameter does give the possibility of the stretch of 1 bits
 
93
  // going 'round the end' of the word. To deal with that, we observe that in
 
94
  // any situation where that happens the bitwise NOT of the value is also a
 
95
  // valid logical immediate. So we simply invert the input whenever its low bit
 
96
  // is set, and then we know that the rotated case can't arise.)
 
97
 
 
98
  if (value & 1) {
 
99
    // If the low bit is 1, negate the value, and set a flag to remember that we
 
100
    // did (so that we can adjust the return values appropriately).
 
101
    negate = true;
 
102
    value = ~value;
 
103
  }
 
104
 
 
105
  if (width == kWRegSizeInBits) {
 
106
    // To handle 32-bit logical immediates, the very easiest thing is to repeat
 
107
    // the input value twice to make a 64-bit word. The correct encoding of that
 
108
    // as a logical immediate will also be the correct encoding of the 32-bit
 
109
    // value.
 
110
 
 
111
    // The most-significant 32 bits may not be zero (ie. negate is true) so
 
112
    // shift the value left before duplicating it.
 
113
    value <<= kWRegSizeInBits;
 
114
    value |= value >> kWRegSizeInBits;
 
115
  }
 
116
 
 
117
  // The basic analysis idea: imagine our input word looks like this.
 
118
  //
 
119
  //    0011111000111110001111100011111000111110001111100011111000111110
 
120
  //                                                          c  b    a
 
121
  //                                                          |<--d-->|
 
122
  //
 
123
  // We find the lowest set bit (as an actual power-of-2 value, not its index)
 
124
  // and call it a. Then we add a to our original number, which wipes out the
 
125
  // bottommost stretch of set bits and replaces it with a 1 carried into the
 
126
  // next zero bit. Then we look for the new lowest set bit, which is in
 
127
  // position b, and subtract it, so now our number is just like the original
 
128
  // but with the lowest stretch of set bits completely gone. Now we find the
 
129
  // lowest set bit again, which is position c in the diagram above. Then we'll
 
130
  // measure the distance d between bit positions a and c (using CLZ), and that
 
131
  // tells us that the only valid logical immediate that could possibly be equal
 
132
  // to this number is the one in which a stretch of bits running from a to just
 
133
  // below b is replicated every d bits.
 
134
  uint64_t a = LargestPowerOf2Divisor(value);
 
135
  uint64_t value_plus_a = value + a;
 
136
  uint64_t b = LargestPowerOf2Divisor(value_plus_a);
 
137
  uint64_t value_plus_a_minus_b = value_plus_a - b;
 
138
  uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b);
 
139
 
 
140
  int d, clz_a, out_n;
 
141
  uint64_t mask;
 
142
 
 
143
  if (c != 0) {
 
144
    // The general case, in which there is more than one stretch of set bits.
 
145
    // Compute the repeat distance d, and set up a bitmask covering the basic
 
146
    // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
 
147
    // of these cases the N bit of the output will be zero.
 
148
    clz_a = CountLeadingZeros(a, kXRegSizeInBits);
 
149
    int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
 
150
    d = clz_a - clz_c;
 
151
    mask = ((V8_UINT64_C(1) << d) - 1);
 
152
    out_n = 0;
 
153
  } else {
 
154
    // Handle degenerate cases.
 
155
    //
 
156
    // If any of those 'find lowest set bit' operations didn't find a set bit at
 
157
    // all, then the word will have been zero thereafter, so in particular the
 
158
    // last lowest_set_bit operation will have returned zero. So we can test for
 
159
    // all the special case conditions in one go by seeing if c is zero.
 
160
    if (a == 0) {
 
161
      // The input was zero (or all 1 bits, which will come to here too after we
 
162
      // inverted it at the start of the function), for which we just return
 
163
      // false.
 
164
      return false;
 
165
    } else {
 
166
      // Otherwise, if c was zero but a was not, then there's just one stretch
 
167
      // of set bits in our word, meaning that we have the trivial case of
 
168
      // d == 64 and only one 'repetition'. Set up all the same variables as in
 
169
      // the general case above, and set the N bit in the output.
 
170
      clz_a = CountLeadingZeros(a, kXRegSizeInBits);
 
171
      d = 64;
 
172
      mask = ~V8_UINT64_C(0);
 
173
      out_n = 1;
 
174
    }
 
175
  }
 
176
 
 
177
  // If the repeat period d is not a power of two, it can't be encoded.
 
178
  if (!IsPowerOfTwo(d)) {
 
179
    return false;
 
180
  }
 
181
 
 
182
  if (((b - a) & ~mask) != 0) {
 
183
    // If the bit stretch (b - a) does not fit within the mask derived from the
 
184
    // repeat period, then fail.
 
185
    return false;
 
186
  }
 
187
 
 
188
  // The only possible option is b - a repeated every d bits. Now we're going to
 
189
  // actually construct the valid logical immediate derived from that
 
190
  // specification, and see if it equals our original input.
 
191
  //
 
192
  // To repeat a value every d bits, we multiply it by a number of the form
 
193
  // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
 
194
  // be derived using a table lookup on CLZ(d).
 
195
  static const uint64_t multipliers[] = {
 
196
    0x0000000000000001UL,
 
197
    0x0000000100000001UL,
 
198
    0x0001000100010001UL,
 
199
    0x0101010101010101UL,
 
200
    0x1111111111111111UL,
 
201
    0x5555555555555555UL,
 
202
  };
 
203
  int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
 
204
  // Ensure that the index to the multipliers array is within bounds.
 
205
  _dbg_assert_(JIT, (multiplier_idx >= 0) &&
 
206
         (static_cast<size_t>(multiplier_idx) < ARRAY_SIZE(multipliers)));
 
207
  uint64_t multiplier = multipliers[multiplier_idx];
 
208
  uint64_t candidate = (b - a) * multiplier;
 
209
 
 
210
  if (value != candidate) {
 
211
    // The candidate pattern doesn't match our input value, so fail.
 
212
    return false;
 
213
  }
 
214
 
 
215
  // We have a match! This is a valid logical immediate, so now we have to
 
216
  // construct the bits and pieces of the instruction encoding that generates
 
217
  // it.
 
218
 
 
219
  // Count the set bits in our basic stretch. The special case of clz(0) == -1
 
220
  // makes the answer come out right for stretches that reach the very top of
 
221
  // the word (e.g. numbers like 0xffffc00000000000).
 
222
  int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
 
223
  int s = clz_a - clz_b;
 
224
 
 
225
  // Decide how many bits to rotate right by, to put the low bit of that basic
 
226
  // stretch in position a.
 
227
  int r;
 
228
  if (negate) {
 
229
    // If we inverted the input right at the start of this function, here's
 
230
    // where we compensate: the number of set bits becomes the number of clear
 
231
    // bits, and the rotation count is based on position b rather than position
 
232
    // a (since b is the location of the 'lowest' 1 bit after inversion).
 
233
    s = d - s;
 
234
    r = (clz_b + 1) & (d - 1);
 
235
  } else {
 
236
    r = (clz_a + 1) & (d - 1);
 
237
  }
 
238
 
 
239
  // Now we're done, except for having to encode the S output in such a way that
 
240
  // it gives both the number of set bits and the length of the repeated
 
241
  // segment. The s field is encoded like this:
 
242
  //
 
243
  //     imms    size        S
 
244
  //    ssssss    64    UInt(ssssss)
 
245
  //    0sssss    32    UInt(sssss)
 
246
  //    10ssss    16    UInt(ssss)
 
247
  //    110sss     8    UInt(sss)
 
248
  //    1110ss     4    UInt(ss)
 
249
  //    11110s     2    UInt(s)
 
250
  //
 
251
  // So we 'or' (-d << 1) with our computed s to form imms.
 
252
  *n = out_n;
 
253
  *imm_s = ((-d << 1) | (s - 1)) & 0x3f;
 
254
  *imm_r = r;
 
255
 
 
256
  return true;
 
257
}
 
258
 
 
259
static int EncodeSize(int size) {
 
260
        switch (size) {
 
261
        case 8: return 0;
 
262
        case 16: return 1;
 
263
        case 32: return 2;
 
264
        case 64: return 3;
 
265
        default: return 0;
 
266
        }
 
267
}
 
268
 
 
269
void ARM64XEmitter::SetCodePointer(u8* ptr)
 
270
{
 
271
        m_code = ptr;
 
272
        m_startcode = m_code;
 
273
        m_lastCacheFlushEnd = ptr;
 
274
}
 
275
 
 
276
const u8* ARM64XEmitter::GetCodePointer() const
 
277
{
 
278
        return m_code;
 
279
}
 
280
 
 
281
u8* ARM64XEmitter::GetWritableCodePtr()
 
282
{
 
283
        return m_code;
 
284
}
 
285
 
 
286
void ARM64XEmitter::ReserveCodeSpace(u32 bytes)
 
287
{
 
288
        for (u32 i = 0; i < bytes/4; i++)
 
289
                BRK(0);
 
290
}
 
291
 
 
292
const u8* ARM64XEmitter::AlignCode16()
 
293
{
 
294
        int c = int((u64)m_code & 15);
 
295
        if (c)
 
296
                ReserveCodeSpace(16-c);
 
297
        return m_code;
 
298
}
 
299
 
 
300
const u8* ARM64XEmitter::AlignCodePage()
 
301
{
 
302
        int c = int((u64)m_code & 4095);
 
303
        if (c)
 
304
                ReserveCodeSpace(4096-c);
 
305
        return m_code;
 
306
}
 
307
 
 
308
void ARM64XEmitter::FlushIcache()
 
309
{
 
310
        FlushIcacheSection(m_lastCacheFlushEnd, m_code);
 
311
        m_lastCacheFlushEnd = m_code;
 
312
}
 
313
 
 
314
void ARM64XEmitter::FlushIcacheSection(u8* start, u8* end)
 
315
{
 
316
#if defined(IOS)
 
317
        // Header file says this is equivalent to: sys_icache_invalidate(start, end - start);
 
318
        sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start);
 
319
#elif !defined(_M_IX86) && !defined(_M_X64)
 
320
        // Code from Dolphin, contributed by the Mono project.
 
321
 
 
322
        // Don't rely on GCC's __clear_cache implementation, as it caches
 
323
        // icache/dcache cache line sizes, that can vary between cores on
 
324
        // big.LITTLE architectures.
 
325
        size_t isize, dsize;
 
326
 
 
327
        if (cpu_info.sQuirks.bExynos8890DifferingCachelineSizes) {
 
328
                // Enforce the minimum cache line size to be completely safe on these CPUs.
 
329
                isize = 64;
 
330
                dsize = 64;
 
331
        } else {
 
332
                u64 ctr_el0;
 
333
                static size_t icache_line_size = 0xffff, dcache_line_size = 0xffff;
 
334
                __asm__ volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
 
335
                isize = 4 << ((ctr_el0 >> 0) & 0xf);
 
336
                dsize = 4 << ((ctr_el0 >> 16) & 0xf);
 
337
 
 
338
                // use the global minimum cache line size
 
339
                icache_line_size = isize = icache_line_size < isize ? icache_line_size : isize;
 
340
                dcache_line_size = dsize = dcache_line_size < dsize ? dcache_line_size : dsize;
 
341
        }
 
342
 
 
343
        u64 addr = (u64)start & ~(u64)(dsize - 1);
 
344
        for (; addr < (u64)end; addr += dsize)
 
345
                // use "civac" instead of "cvau", as this is the suggested workaround for
 
346
                // Cortex-A53 errata 819472, 826319, 827319 and 824069.
 
347
                __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory");
 
348
        __asm__ volatile("dsb ish" : : : "memory");
 
349
 
 
350
        addr = (u64)start & ~(u64)(isize - 1);
 
351
        for (; addr < (u64)end; addr += isize)
 
352
                __asm__ volatile("ic ivau, %0" : : "r"(addr) : "memory");
 
353
 
 
354
        __asm__ volatile("dsb ish" : : : "memory");
 
355
        __asm__ volatile("isb" : : : "memory");
 
356
#endif
 
357
}
 
358
 
 
359
// Exception generation
 
360
static const u32 ExcEnc[][3] = {
 
361
        {0, 0, 1}, // SVC
 
362
        {0, 0, 2}, // HVC
 
363
        {0, 0, 3}, // SMC
 
364
        {1, 0, 0}, // BRK
 
365
        {2, 0, 0}, // HLT
 
366
        {5, 0, 1}, // DCPS1
 
367
        {5, 0, 2}, // DCPS2
 
368
        {5, 0, 3}, // DCPS3
 
369
};
 
370
 
 
371
// Arithmetic generation
 
372
static const u32 ArithEnc[] = {
 
373
        0x058, // ADD
 
374
        0x258, // SUB
 
375
};
 
376
 
 
377
// Conditional Select
 
378
static const u32 CondSelectEnc[][2] = {
 
379
        {0, 0}, // CSEL
 
380
        {0, 1}, // CSINC
 
381
        {1, 0}, // CSINV
 
382
        {1, 1}, // CSNEG
 
383
};
 
384
 
 
385
// Data-Processing (1 source)
 
386
static const u32 Data1SrcEnc[][2] = {
 
387
        {0, 0}, // RBIT
 
388
        {0, 1}, // REV16
 
389
        {0, 2}, // REV32
 
390
        {0, 3}, // REV64
 
391
        {0, 4}, // CLZ
 
392
        {0, 5}, // CLS
 
393
};
 
394
 
 
395
// Data-Processing (2 source)
 
396
static const u32 Data2SrcEnc[] = {
 
397
        0x02, // UDIV
 
398
        0x03, // SDIV
 
399
        0x08, // LSLV
 
400
        0x09, // LSRV
 
401
        0x0A, // ASRV
 
402
        0x0B, // RORV
 
403
        0x10, // CRC32B
 
404
        0x11, // CRC32H
 
405
        0x12, // CRC32W
 
406
        0x14, // CRC32CB
 
407
        0x15, // CRC32CH
 
408
        0x16, // CRC32CW
 
409
        0x13, // CRC32X (64bit Only)
 
410
        0x17, // XRC32CX (64bit Only)
 
411
};
 
412
 
 
413
// Data-Processing (3 source)
 
414
static const u32 Data3SrcEnc[][2] = {
 
415
        {0, 0}, // MADD
 
416
        {0, 1}, // MSUB
 
417
        {1, 0}, // SMADDL (64Bit Only)
 
418
        {1, 1}, // SMSUBL (64Bit Only)
 
419
        {2, 0}, // SMULH (64Bit Only)
 
420
        {5, 0}, // UMADDL (64Bit Only)
 
421
        {5, 1}, // UMSUBL (64Bit Only)
 
422
        {6, 0}, // UMULH (64Bit Only)
 
423
};
 
424
 
 
425
// Logical (shifted register)
 
426
static const u32 LogicalEnc[][2] = {
 
427
        {0, 0}, // AND
 
428
        {0, 1}, // BIC
 
429
        {1, 0}, // OOR
 
430
        {1, 1}, // ORN
 
431
        {2, 0}, // EOR
 
432
        {2, 1}, // EON
 
433
        {3, 0}, // ANDS
 
434
        {3, 1}, // BICS
 
435
};
 
436
 
 
437
// Load/Store Exclusive
 
438
static const u32 LoadStoreExcEnc[][5] = {
 
439
        {0, 0, 0, 0, 0}, // STXRB
 
440
        {0, 0, 0, 0, 1}, // STLXRB
 
441
        {0, 0, 1, 0, 0}, // LDXRB
 
442
        {0, 0, 1, 0, 1}, // LDAXRB
 
443
        {0, 1, 0, 0, 1}, // STLRB
 
444
        {0, 1, 1, 0, 1}, // LDARB
 
445
        {1, 0, 0, 0, 0}, // STXRH
 
446
        {1, 0, 0, 0, 1}, // STLXRH
 
447
        {1, 0, 1, 0, 0}, // LDXRH
 
448
        {1, 0, 1, 0, 1}, // LDAXRH
 
449
        {1, 1, 0, 0, 1}, // STLRH
 
450
        {1, 1, 1, 0, 1}, // LDARH
 
451
        {2, 0, 0, 0, 0}, // STXR
 
452
        {3, 0, 0, 0, 0}, // (64bit) STXR
 
453
        {2, 0, 0, 0, 1}, // STLXR
 
454
        {3, 0, 0, 0, 1}, // (64bit) STLXR
 
455
        {2, 0, 0, 1, 0}, // STXP
 
456
        {3, 0, 0, 1, 0}, // (64bit) STXP
 
457
        {2, 0, 0, 1, 1}, // STLXP
 
458
        {3, 0, 0, 1, 1}, // (64bit) STLXP
 
459
        {2, 0, 1, 0, 0}, // LDXR
 
460
        {3, 0, 1, 0, 0}, // (64bit) LDXR
 
461
        {2, 0, 1, 0, 1}, // LDAXR
 
462
        {3, 0, 1, 0, 1}, // (64bit) LDAXR
 
463
        {2, 0, 1, 1, 0}, // LDXP
 
464
        {3, 0, 1, 1, 0}, // (64bit) LDXP
 
465
        {2, 0, 1, 1, 1}, // LDAXP
 
466
        {3, 0, 1, 1, 1}, // (64bit) LDAXP
 
467
        {2, 1, 0, 0, 1}, // STLR
 
468
        {3, 1, 0, 0, 1}, // (64bit) STLR
 
469
        {2, 1, 1, 0, 1}, // LDAR
 
470
        {3, 1, 1, 0, 1}, // (64bit) LDAR
 
471
};
 
472
 
 
473
void ARM64XEmitter::EncodeCompareBranchInst(u32 op, ARM64Reg Rt, const void* ptr)
 
474
{
 
475
        bool b64Bit = Is64Bit(Rt);
 
476
        s64 distance = (s64)ptr - (s64)m_code;
 
477
 
 
478
        _assert_msg_(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %llx", __FUNCTION__, distance);
 
479
 
 
480
        distance >>= 2;
 
481
 
 
482
        _assert_msg_(DYNA_REC, distance >= -0x40000 && distance <= 0x3FFFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
 
483
 
 
484
        Rt = DecodeReg(Rt);
 
485
        Write32((b64Bit << 31) | (0x34 << 24) | (op << 24) | \
 
486
                (((u32)distance << 5) & 0xFFFFE0) | Rt);
 
487
}
 
488
 
 
489
void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const void* ptr)
 
490
{
 
491
        bool b64Bit = Is64Bit(Rt);
 
492
        s64 distance = (s64)ptr - (s64)m_code;
 
493
 
 
494
        _assert_msg_(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %llx", __FUNCTION__, distance);
 
495
 
 
496
        distance >>= 2;
 
497
 
 
498
        _assert_msg_(DYNA_REC, distance >= -0x3FFF && distance < 0x3FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
 
499
 
 
500
        Rt = DecodeReg(Rt);
 
501
        Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | \
 
502
                (bits << 19) | (((u32)distance << 5) & 0x7FFE0) | Rt);
 
503
}
 
504
 
 
505
void ARM64XEmitter::EncodeUnconditionalBranchInst(u32 op, const void* ptr)
 
506
{
 
507
        s64 distance = (s64)ptr - s64(m_code);
 
508
 
 
509
        _assert_msg_(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %llx", __FUNCTION__, distance);
 
510
 
 
511
        distance >>= 2;
 
512
 
 
513
        _assert_msg_(DYNA_REC, distance >= -0x2000000LL && distance <= 0x1FFFFFFLL, "%s: Received too large distance: %llx", __FUNCTION__, distance);
 
514
 
 
515
        Write32((op << 31) | (0x5 << 26) | (distance & 0x3FFFFFF));
 
516
}
 
517
 
 
518
void ARM64XEmitter::EncodeUnconditionalBranchInst(u32 opc, u32 op2, u32 op3, u32 op4, ARM64Reg Rn)
 
519
{
 
520
        Rn = DecodeReg(Rn);
 
521
        Write32((0x6B << 25) | (opc << 21) | (op2 << 16) | (op3 << 10) | (Rn << 5) | op4);
 
522
}
 
523
 
 
524
void ARM64XEmitter::EncodeExceptionInst(u32 instenc, u32 imm)
 
525
{
 
526
        _assert_msg_(DYNA_REC, !(imm & ~0xFFFF), "%s: Exception instruction too large immediate: %d", __FUNCTION__, imm);
 
527
 
 
528
        Write32((0xD4 << 24) | (ExcEnc[instenc][0] << 21) | (imm << 5) | (ExcEnc[instenc][1] << 2) | ExcEnc[instenc][2]);
 
529
}
 
530
 
 
531
void ARM64XEmitter::EncodeSystemInst(u32 op0, u32 op1, u32 CRn, u32 CRm, u32 op2, ARM64Reg Rt)
 
532
{
 
533
        Write32((0x354 << 22) | (op0 << 19) | (op1 << 16) | (CRn << 12) | (CRm << 8) | (op2 << 5) | Rt);
 
534
}
 
535
 
 
536
void ARM64XEmitter::EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
537
{
 
538
        bool b64Bit = Is64Bit(Rd);
 
539
 
 
540
        Rd = DecodeReg(Rd);
 
541
        Rn = DecodeReg(Rn);
 
542
        Rm = DecodeReg(Rm);
 
543
        Write32((b64Bit << 31) | (flags << 29) | (ArithEnc[instenc] << 21) | \
 
544
                (Option.GetType() == ArithOption::TYPE_EXTENDEDREG ? (1 << 21) : 0) | (Rm << 16) | Option.GetData() | (Rn << 5) | Rd);
 
545
}
 
546
 
 
547
void ARM64XEmitter::EncodeArithmeticCarryInst(u32 op, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
548
{
 
549
        bool b64Bit = Is64Bit(Rd);
 
550
 
 
551
        Rd = DecodeReg(Rd);
 
552
        Rm = DecodeReg(Rm);
 
553
        Rn = DecodeReg(Rn);
 
554
        Write32((b64Bit << 31) | (op << 30) | (flags << 29) | \
 
555
                (0xD0 << 21) | (Rm << 16) | (Rn << 5) | Rd);
 
556
}
 
557
 
 
558
void ARM64XEmitter::EncodeCondCompareImmInst(u32 op, ARM64Reg Rn, u32 imm, u32 nzcv, CCFlags cond)
 
559
{
 
560
        bool b64Bit = Is64Bit(Rn);
 
561
 
 
562
        _assert_msg_(DYNA_REC, !(imm & ~0x1F), "%s: too large immediate: %d", __FUNCTION__, imm)
 
563
        _assert_msg_(DYNA_REC, !(nzcv & ~0xF), "%s: Flags out of range: %d", __FUNCTION__, nzcv)
 
564
 
 
565
        Rn = DecodeReg(Rn);
 
566
        Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | \
 
567
                (imm << 16) | (cond << 12) | (1 << 11) | (Rn << 5) | nzcv);
 
568
}
 
569
 
 
570
void ARM64XEmitter::EncodeCondCompareRegInst(u32 op, ARM64Reg Rn, ARM64Reg Rm, u32 nzcv, CCFlags cond)
 
571
{
 
572
        bool b64Bit = Is64Bit(Rm);
 
573
 
 
574
        _assert_msg_(DYNA_REC, !(nzcv & ~0xF), "%s: Flags out of range: %d", __FUNCTION__, nzcv)
 
575
 
 
576
        Rm = DecodeReg(Rm);
 
577
        Rn = DecodeReg(Rn);
 
578
        Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | \
 
579
                (Rm << 16) | (cond << 12) | (Rn << 5) | nzcv);
 
580
}
 
581
 
 
582
void ARM64XEmitter::EncodeCondSelectInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
583
{
 
584
        bool b64Bit = Is64Bit(Rd);
 
585
 
 
586
        Rd = DecodeReg(Rd);
 
587
        Rm = DecodeReg(Rm);
 
588
        Rn = DecodeReg(Rn);
 
589
        Write32((b64Bit << 31) | (CondSelectEnc[instenc][0] << 30) | \
 
590
                (0xD4 << 21) | (Rm << 16) | (cond << 12) | (CondSelectEnc[instenc][1] << 10) | \
 
591
                (Rn << 5) | Rd);
 
592
}
 
593
 
 
594
void ARM64XEmitter::EncodeData1SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn)
 
595
{
 
596
        bool b64Bit = Is64Bit(Rd);
 
597
 
 
598
        Rd = DecodeReg(Rd);
 
599
        Rn = DecodeReg(Rn);
 
600
        Write32((b64Bit << 31) | (0x2D6 << 21) | \
 
601
                (Data1SrcEnc[instenc][0] << 16) | (Data1SrcEnc[instenc][1] << 10) | \
 
602
                (Rn << 5) | Rd);
 
603
}
 
604
 
 
605
void ARM64XEmitter::EncodeData2SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
606
{
 
607
        bool b64Bit = Is64Bit(Rd);
 
608
 
 
609
        Rd = DecodeReg(Rd);
 
610
        Rm = DecodeReg(Rm);
 
611
        Rn = DecodeReg(Rn);
 
612
        Write32((b64Bit << 31) | (0x0D6 << 21) | \
 
613
                (Rm << 16) | (Data2SrcEnc[instenc] << 10) | \
 
614
                (Rn << 5) | Rd);
 
615
}
 
616
 
 
617
void ARM64XEmitter::EncodeData3SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
618
{
 
619
        bool b64Bit = Is64Bit(Rd);
 
620
 
 
621
        Rd = DecodeReg(Rd);
 
622
        Rm = DecodeReg(Rm);
 
623
        Rn = DecodeReg(Rn);
 
624
        Ra = DecodeReg(Ra);
 
625
        Write32((b64Bit << 31) | (0xD8 << 21) | (Data3SrcEnc[instenc][0] << 21) | \
 
626
                (Rm << 16) | (Data3SrcEnc[instenc][1] << 15) | \
 
627
                (Ra << 10) | (Rn << 5) | Rd);
 
628
}
 
629
 
 
630
void ARM64XEmitter::EncodeLogicalInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
631
{
 
632
        bool b64Bit = Is64Bit(Rd);
 
633
 
 
634
        Rd = DecodeReg(Rd);
 
635
        Rm = DecodeReg(Rm);
 
636
        Rn = DecodeReg(Rn);
 
637
        Write32((b64Bit << 31) | (LogicalEnc[instenc][0] << 29) | (0x5 << 25) | (LogicalEnc[instenc][1] << 21) | \
 
638
                Shift.GetData() | (Rm << 16) | (Rn << 5) | Rd);
 
639
}
 
640
 
 
641
void ARM64XEmitter::EncodeLoadRegisterInst(u32 bitop, ARM64Reg Rt, u32 imm)
 
642
{
 
643
        bool b64Bit = Is64Bit(Rt);
 
644
        bool bVec = IsVector(Rt);
 
645
 
 
646
        _assert_msg_(DYNA_REC, !(imm & 0xFFFFF), "%s: offset too large %d", __FUNCTION__, imm);
 
647
 
 
648
        Rt = DecodeReg(Rt);
 
649
        if (b64Bit && bitop != 0x2) // LDRSW(0x2) uses 64bit reg, doesn't have 64bit bit set
 
650
                bitop |= 0x1;
 
651
        Write32((bitop << 30) | (bVec << 26) | (0x18 << 24) | (imm << 5) | Rt);
 
652
}
 
653
 
 
654
void ARM64XEmitter::EncodeLoadStoreExcInst(u32 instenc,
 
655
                ARM64Reg Rs, ARM64Reg Rt2, ARM64Reg Rn, ARM64Reg Rt)
 
656
{
 
657
        Rs = DecodeReg(Rs);
 
658
        Rt2 = DecodeReg(Rt2);
 
659
        Rn = DecodeReg(Rn);
 
660
        Rt = DecodeReg(Rt);
 
661
        Write32((LoadStoreExcEnc[instenc][0] << 30) | (0x8 << 24) | (LoadStoreExcEnc[instenc][1] << 23) | \
 
662
                (LoadStoreExcEnc[instenc][2] << 22) | (LoadStoreExcEnc[instenc][3] << 21) | (Rs << 16) | \
 
663
                (LoadStoreExcEnc[instenc][4] << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
 
664
}
 
665
 
 
666
void ARM64XEmitter::EncodeLoadStorePairedInst(u32 op, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, u32 imm)
 
667
{
 
668
        bool b64Bit = Is64Bit(Rt);
 
669
        bool b128Bit = IsQuad(Rt);
 
670
        bool bVec = IsVector(Rt);
 
671
 
 
672
        if (b128Bit)
 
673
                imm >>= 4;
 
674
        else if (b64Bit)
 
675
                imm >>= 3;
 
676
        else
 
677
                imm >>= 2;
 
678
 
 
679
        _assert_msg_(DYNA_REC, !(imm & ~0xF), "%s: offset too large %d", __FUNCTION__, imm);
 
680
 
 
681
        u32 opc = 0;
 
682
        if (b128Bit)
 
683
                opc = 2;
 
684
        else if (b64Bit && bVec)
 
685
                opc = 1;
 
686
        else if (b64Bit && !bVec)
 
687
                opc = 2;
 
688
 
 
689
        Rt = DecodeReg(Rt);
 
690
        Rt2 = DecodeReg(Rt2);
 
691
        Rn = DecodeReg(Rn);
 
692
        Write32((opc << 30) | (bVec << 26) | (op << 22) | (imm << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
 
693
}
 
694
 
 
695
void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, u32 op2, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
696
{
 
697
        bool b64Bit = Is64Bit(Rt);
 
698
        bool bVec = IsVector(Rt);
 
699
 
 
700
        u32 offset = imm & 0x1FF;
 
701
 
 
702
        _assert_msg_(DYNA_REC, !(imm < -256 || imm > 255), "%s: offset too large %d", __FUNCTION__, imm);
 
703
 
 
704
        Rt = DecodeReg(Rt);
 
705
        Rn = DecodeReg(Rn);
 
706
        Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (offset << 12) | (op2 << 10) | (Rn << 5) | Rt);
 
707
}
 
708
 
 
709
void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm, u8 size)
 
710
{
 
711
        bool b64Bit = Is64Bit(Rt);
 
712
        bool bVec = IsVector(Rt);
 
713
 
 
714
        u8 shift = 0;
 
715
        if (size == 64)
 
716
                shift = 3;
 
717
        else if (size == 32)
 
718
                shift = 2;
 
719
        else if (size == 16)
 
720
                shift = 1;
 
721
 
 
722
        _assert_msg_(DYNA_REC, ((imm >> shift) << shift) == imm, "%s(INDEX_UNSIGNED): offset must be aligned %d", __FUNCTION__, imm);
 
723
 
 
724
        imm >>= shift;
 
725
        _assert_msg_(DYNA_REC, imm >= 0, "%s(INDEX_UNSIGNED): offset must be positive %d", __FUNCTION__, imm);
 
726
        _assert_msg_(DYNA_REC, !(imm & ~0xFFF), "%s(INDEX_UNSIGNED): offset too large %d", __FUNCTION__, imm);
 
727
 
 
728
        Rt = DecodeReg(Rt);
 
729
        Rn = DecodeReg(Rn);
 
730
        Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (imm << 10) | (Rn << 5) | Rt);
 
731
}
 
732
 
 
733
void ARM64XEmitter::EncodeMOVWideInst(u32 op, ARM64Reg Rd, u32 imm, ShiftAmount pos)
 
734
{
 
735
        bool b64Bit = Is64Bit(Rd);
 
736
 
 
737
        _assert_msg_(DYNA_REC, !(imm & ~0xFFFF), "%s: immediate out of range: %d", __FUNCTION__, imm);
 
738
 
 
739
        Rd = DecodeReg(Rd);
 
740
        Write32((b64Bit << 31) | (op << 29) | (0x25 << 23) | (pos << 21) | (imm << 5) | Rd);
 
741
}
 
742
 
 
743
void ARM64XEmitter::EncodeBitfieldMOVInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms)
 
744
{
 
745
        bool b64Bit = Is64Bit(Rd);
 
746
 
 
747
        Rd = DecodeReg(Rd);
 
748
        Rn = DecodeReg(Rn);
 
749
        Write32((b64Bit << 31) | (op << 29) | (0x26 << 23) | (b64Bit << 22) | \
 
750
                (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
 
751
}
 
752
 
 
753
void ARM64XEmitter::EncodeLoadStoreRegisterOffset(u32 size, u32 opc, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
754
{
 
755
        Rt = DecodeReg(Rt);
 
756
        Rn = DecodeReg(Rn);
 
757
        ARM64Reg decoded_Rm = DecodeReg(Rm.GetReg());
 
758
 
 
759
        Write32((size << 30) | (opc << 22) | (0x1C1 << 21) | (decoded_Rm << 16) | \
 
760
                Rm.GetData() | (1 << 11) | (Rn << 5) | Rt);
 
761
}
 
762
 
 
763
void ARM64XEmitter::EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm, ARM64Reg Rn, ARM64Reg Rd)
 
764
{
 
765
        bool b64Bit = Is64Bit(Rd);
 
766
 
 
767
        _assert_msg_(DYNA_REC, !(imm & ~0xFFF), "%s: immediate too large: %x", __FUNCTION__, imm);
 
768
 
 
769
        Rd = DecodeReg(Rd);
 
770
        Rn = DecodeReg(Rn);
 
771
        Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0x11 << 24) | (shift << 22) | \
 
772
                (imm << 10) | (Rn << 5) | Rd);
 
773
}
 
774
 
 
775
void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, int n)
 
776
{
 
777
        // Sometimes Rd is fixed to SP, but can still be 32bit or 64bit.
 
778
        // Use Rn to determine bitness here.
 
779
        bool b64Bit = Is64Bit(Rn);
 
780
 
 
781
        Rd = DecodeReg(Rd);
 
782
        Rn = DecodeReg(Rn);
 
783
 
 
784
        Write32((b64Bit << 31) | (op << 29) | (0x24 << 23) | (n << 22) | \
 
785
                (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
 
786
}
 
787
 
 
788
void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
789
{
 
790
        bool b64Bit = Is64Bit(Rt);
 
791
        u32 type_encode = 0;
 
792
 
 
793
        switch (type) {
 
794
        case INDEX_SIGNED:
 
795
                type_encode = 2;
 
796
                break;
 
797
        case INDEX_POST:
 
798
                type_encode = 1;
 
799
                break;
 
800
        case INDEX_PRE:
 
801
                type_encode = 3;
 
802
                break;
 
803
        case INDEX_UNSIGNED:
 
804
                _assert_msg_(DYNA_REC, false, "%s doesn't support INDEX_UNSIGNED!", __FUNCTION__);
 
805
                break;
 
806
        }
 
807
 
 
808
        if (b64Bit) {
 
809
                op |= 2;
 
810
                imm >>= 3;
 
811
        }
 
812
        else
 
813
        {
 
814
                imm >>= 2;
 
815
        }
 
816
 
 
817
        _assert_msg_(JIT, imm >= -64 && imm <= 63, "%s recieved too large imm: %d", __FUNCTION__, imm);
 
818
 
 
819
        Rt = DecodeReg(Rt);
 
820
        Rt2 = DecodeReg(Rt2);
 
821
        Rn = DecodeReg(Rn);
 
822
 
 
823
        Write32((op << 30) | (5 << 27) | (type_encode << 23) | (load << 22) | \
 
824
                (((uint32_t)imm & 0x7F) << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
 
825
}
 
826
void ARM64XEmitter::EncodeAddressInst(u32 op, ARM64Reg Rd, s32 imm)
 
827
{
 
828
        Rd = DecodeReg(Rd);
 
829
 
 
830
        Write32((op << 31) | ((imm & 0x3) << 29) | (0x10 << 24) | \
 
831
                ((imm & 0x1FFFFC) << 3) | Rd);
 
832
}
 
833
 
 
834
void ARM64XEmitter::EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
835
{
 
836
        _assert_msg_(DYNA_REC, !(imm < -256 || imm > 255), "%s received too large offset: %d", __FUNCTION__, imm);
 
837
        Rt = DecodeReg(Rt);
 
838
        Rn = DecodeReg(Rn);
 
839
 
 
840
        Write32((size << 30) | (7 << 27) | (op << 22) | ((imm & 0x1FF) << 12) | (Rn << 5) | Rt);
 
841
}
 
842
 
 
843
static inline bool IsInRangeImm19(s64 distance) {
 
844
        return (distance >= -0x40000 && distance <= 0x3FFFF);
 
845
}
 
846
 
 
847
static inline bool IsInRangeImm14(s64 distance) {
 
848
        return (distance >= -0x2000 && distance <= 0x1FFF);
 
849
}
 
850
 
 
851
static inline bool IsInRangeImm26(s64 distance) {
 
852
        return (distance >= -0x2000000 && distance <= 0x1FFFFFF);
 
853
}
 
854
 
 
855
static inline u32 MaskImm19(s64 distance) {
 
856
        return distance & 0x7FFFF;
 
857
}
 
858
 
 
859
static inline u32 MaskImm14(s64 distance) {
 
860
        return distance & 0x3FFF;
 
861
}
 
862
 
 
863
static inline u32 MaskImm26(s64 distance) {
 
864
        return distance & 0x3FFFFFF;
 
865
}
 
866
 
 
867
// FixupBranch branching
 
868
void ARM64XEmitter::SetJumpTarget(FixupBranch const& branch)
 
869
{
 
870
        bool Not = false;
 
871
        u32 inst = 0;
 
872
        s64 distance = (s64)(m_code - branch.ptr);
 
873
        distance >>= 2;
 
874
 
 
875
        switch (branch.type)
 
876
        {
 
877
                case 1: // CBNZ
 
878
                        Not = true;
 
879
                case 0: // CBZ
 
880
                {
 
881
                        _assert_msg_(DYNA_REC, IsInRangeImm19(distance), "%s(%d): Received too large distance: %llx", __FUNCTION__, branch.type, distance);
 
882
                        bool b64Bit = Is64Bit(branch.reg);
 
883
                        ARM64Reg reg = DecodeReg(branch.reg);
 
884
                        inst = (b64Bit << 31) | (0x1A << 25) | (Not << 24) | (MaskImm19(distance) << 5) | reg;
 
885
                }
 
886
                break;
 
887
                case 2: // B (conditional)
 
888
                        _assert_msg_(DYNA_REC, IsInRangeImm19(distance), "%s(%d): Received too large distance: %llx", __FUNCTION__, branch.type, distance);
 
889
                        inst = (0x2A << 25) | (MaskImm19(distance) << 5) | branch.cond;
 
890
                break;
 
891
                case 4: // TBNZ
 
892
                        Not = true;
 
893
                case 3: // TBZ
 
894
                {
 
895
                        _assert_msg_(DYNA_REC, IsInRangeImm14(distance), "%s(%d): Received too large distance: %llx", __FUNCTION__, branch.type, distance);
 
896
                        ARM64Reg reg = DecodeReg(branch.reg);
 
897
                        inst = ((branch.bit & 0x20) << 26) | (0x1B << 25) | (Not << 24) | ((branch.bit & 0x1F) << 19) | (MaskImm14(distance) << 5) | reg;
 
898
                }
 
899
                break;
 
900
                case 5: // B (uncoditional)
 
901
                        _assert_msg_(DYNA_REC, IsInRangeImm26(distance), "%s(%d): Received too large distance: %llx", __FUNCTION__, branch.type, distance);
 
902
                        inst = (0x5 << 26) | MaskImm26(distance);
 
903
                break;
 
904
                case 6: // BL (unconditional)
 
905
                        _assert_msg_(DYNA_REC, IsInRangeImm26(distance), "%s(%d): Received too large distance: %llx", __FUNCTION__, branch.type, distance);
 
906
                        inst = (0x25 << 26) | MaskImm26(distance);
 
907
                break;
 
908
        }
 
909
        *(u32*)branch.ptr = inst;
 
910
}
 
911
 
 
912
FixupBranch ARM64XEmitter::CBZ(ARM64Reg Rt)
 
913
{
 
914
        FixupBranch branch;
 
915
        branch.ptr = m_code;
 
916
        branch.type = 0;
 
917
        branch.reg = Rt;
 
918
        HINT(HINT_NOP);
 
919
        return branch;
 
920
}
 
921
FixupBranch ARM64XEmitter::CBNZ(ARM64Reg Rt)
 
922
{
 
923
        FixupBranch branch;
 
924
        branch.ptr = m_code;
 
925
        branch.type = 1;
 
926
        branch.reg = Rt;
 
927
        HINT(HINT_NOP);
 
928
        return branch;
 
929
}
 
930
FixupBranch ARM64XEmitter::B(CCFlags cond)
 
931
{
 
932
        FixupBranch branch;
 
933
        branch.ptr = m_code;
 
934
        branch.type = 2;
 
935
        branch.cond = cond;
 
936
        HINT(HINT_NOP);
 
937
        return branch;
 
938
}
 
939
FixupBranch ARM64XEmitter::TBZ(ARM64Reg Rt, u8 bit)
 
940
{
 
941
        FixupBranch branch;
 
942
        branch.ptr = m_code;
 
943
        branch.type = 3;
 
944
        branch.reg = Rt;
 
945
        branch.bit = bit;
 
946
        HINT(HINT_NOP);
 
947
        return branch;
 
948
}
 
949
FixupBranch ARM64XEmitter::TBNZ(ARM64Reg Rt, u8 bit)
 
950
{
 
951
        FixupBranch branch;
 
952
        branch.ptr = m_code;
 
953
        branch.type = 4;
 
954
        branch.reg = Rt;
 
955
        branch.bit = bit;
 
956
        HINT(HINT_NOP);
 
957
        return branch;
 
958
}
 
959
FixupBranch ARM64XEmitter::B()
 
960
{
 
961
        FixupBranch branch;
 
962
        branch.ptr = m_code;
 
963
        branch.type = 5;
 
964
        HINT(HINT_NOP);
 
965
        return branch;
 
966
}
 
967
FixupBranch ARM64XEmitter::BL()
 
968
{
 
969
        FixupBranch branch;
 
970
        branch.ptr = m_code;
 
971
        branch.type = 6;
 
972
        HINT(HINT_NOP);
 
973
        return branch;
 
974
}
 
975
 
 
976
// Compare and Branch
 
977
void ARM64XEmitter::CBZ(ARM64Reg Rt, const void* ptr)
 
978
{
 
979
        EncodeCompareBranchInst(0, Rt, ptr);
 
980
}
 
981
void ARM64XEmitter::CBNZ(ARM64Reg Rt, const void* ptr)
 
982
{
 
983
        EncodeCompareBranchInst(1, Rt, ptr);
 
984
}
 
985
 
 
986
// Conditional Branch
 
987
void ARM64XEmitter::B(CCFlags cond, const void* ptr)
 
988
{
 
989
        s64 distance = (s64)ptr - (s64)m_code;
 
990
 
 
991
        distance >>= 2;
 
992
 
 
993
        _assert_msg_(DYNA_REC, IsInRangeImm19(distance), "%s: Received too large distance: %p->%p %lld %llx", __FUNCTION__, m_code, ptr, distance, distance);
 
994
        Write32((0x54 << 24) | (MaskImm19(distance) << 5) | cond);
 
995
}
 
996
 
 
997
// Test and Branch
 
998
void ARM64XEmitter::TBZ(ARM64Reg Rt, u8 bits, const void* ptr)
 
999
{
 
1000
        EncodeTestBranchInst(0, Rt, bits, ptr);
 
1001
}
 
1002
void ARM64XEmitter::TBNZ(ARM64Reg Rt, u8 bits, const void* ptr)
 
1003
{
 
1004
        EncodeTestBranchInst(1, Rt, bits, ptr);
 
1005
}
 
1006
 
 
1007
// Unconditional Branch
 
1008
void ARM64XEmitter::B(const void* ptr)
 
1009
{
 
1010
        EncodeUnconditionalBranchInst(0, ptr);
 
1011
}
 
1012
void ARM64XEmitter::BL(const void* ptr)
 
1013
{
 
1014
        EncodeUnconditionalBranchInst(1, ptr);
 
1015
}
 
1016
 
 
1017
void ARM64XEmitter::QuickCallFunction(ARM64Reg scratchreg, const void *func) {
 
1018
        s64 distance = (s64)func - (s64)m_code;
 
1019
        distance >>= 2;  // Can only branch to opcode-aligned (4) addresses
 
1020
        if (!IsInRangeImm26(distance)) {
 
1021
                // WARN_LOG(DYNA_REC, "Distance too far in function call (%p to %p)! Using scratch.", m_code, func);
 
1022
                MOVI2R(scratchreg, (uintptr_t)func);
 
1023
                BLR(scratchreg);
 
1024
        } else {
 
1025
                BL(func);
 
1026
        }
 
1027
}
 
1028
 
 
1029
// Unconditional Branch (register)
 
1030
void ARM64XEmitter::BR(ARM64Reg Rn)
 
1031
{
 
1032
        EncodeUnconditionalBranchInst(0, 0x1F, 0, 0, Rn);
 
1033
}
 
1034
void ARM64XEmitter::BLR(ARM64Reg Rn)
 
1035
{
 
1036
        EncodeUnconditionalBranchInst(1, 0x1F, 0, 0, Rn);
 
1037
}
 
1038
void ARM64XEmitter::RET(ARM64Reg Rn)
 
1039
{
 
1040
        EncodeUnconditionalBranchInst(2, 0x1F, 0, 0, Rn);
 
1041
}
 
1042
void ARM64XEmitter::ERET()
 
1043
{
 
1044
        EncodeUnconditionalBranchInst(4, 0x1F, 0, 0, SP);
 
1045
}
 
1046
void ARM64XEmitter::DRPS()
 
1047
{
 
1048
        EncodeUnconditionalBranchInst(5, 0x1F, 0, 0, SP);
 
1049
}
 
1050
 
 
1051
// Exception generation
 
1052
void ARM64XEmitter::SVC(u32 imm)
 
1053
{
 
1054
        EncodeExceptionInst(0, imm);
 
1055
}
 
1056
 
 
1057
void ARM64XEmitter::HVC(u32 imm)
 
1058
{
 
1059
        EncodeExceptionInst(1, imm);
 
1060
}
 
1061
 
 
1062
void ARM64XEmitter::SMC(u32 imm)
 
1063
{
 
1064
        EncodeExceptionInst(2, imm);
 
1065
}
 
1066
 
 
1067
void ARM64XEmitter::BRK(u32 imm)
 
1068
{
 
1069
        EncodeExceptionInst(3, imm);
 
1070
}
 
1071
 
 
1072
void ARM64XEmitter::HLT(u32 imm)
 
1073
{
 
1074
        EncodeExceptionInst(4, imm);
 
1075
}
 
1076
 
 
1077
void ARM64XEmitter::DCPS1(u32 imm)
 
1078
{
 
1079
        EncodeExceptionInst(5, imm);
 
1080
}
 
1081
 
 
1082
void ARM64XEmitter::DCPS2(u32 imm)
 
1083
{
 
1084
        EncodeExceptionInst(6, imm);
 
1085
}
 
1086
 
 
1087
void ARM64XEmitter::DCPS3(u32 imm)
 
1088
{
 
1089
        EncodeExceptionInst(7, imm);
 
1090
}
 
1091
 
 
1092
// System
 
1093
void ARM64XEmitter::_MSR(PStateField field, u8 imm)
 
1094
{
 
1095
        u32 op1 = 0, op2 = 0;
 
1096
        switch (field)
 
1097
        {
 
1098
                case FIELD_SPSel: op1 = 0; op2 = 5; break;
 
1099
                case FIELD_DAIFSet: op1 = 3; op2 = 6; break;
 
1100
                case FIELD_DAIFClr: op1 = 3; op2 = 7; break;
 
1101
                default:
 
1102
                        _assert_msg_(JIT, false, "Invalid PStateField to do a imm move to");
 
1103
                        break;
 
1104
        }
 
1105
        EncodeSystemInst(0, op1, 4, imm, op2, WSP);
 
1106
}
 
1107
 
 
1108
static void GetSystemReg(PStateField field, int &o0, int &op1, int &CRn, int &CRm, int &op2) {
 
1109
        switch (field) {
 
1110
        case FIELD_NZCV:
 
1111
                o0 = 3; op1 = 3; CRn = 4; CRm = 2; op2 = 0;
 
1112
                break;
 
1113
        case FIELD_FPCR:
 
1114
                o0 = 3; op1 = 3; CRn = 4; CRm = 4; op2 = 0;
 
1115
                break;
 
1116
        case FIELD_FPSR:
 
1117
                o0 = 3; op1 = 3; CRn = 4; CRm = 4; op2 = 1;
 
1118
                break;
 
1119
        default:
 
1120
                _assert_msg_(JIT, false, "Invalid PStateField to do a register move from/to");
 
1121
                break;
 
1122
        }
 
1123
}
 
1124
 
 
1125
void ARM64XEmitter::_MSR(PStateField field, ARM64Reg Rt) {
 
1126
        int o0 = 0, op1 = 0, CRn = 0, CRm = 0, op2 = 0;
 
1127
        _assert_msg_(JIT, Is64Bit(Rt), "MSR: Rt must be 64-bit");
 
1128
        GetSystemReg(field, o0, op1, CRn, CRm, op2);
 
1129
        EncodeSystemInst(o0, op1, CRn, CRm, op2, DecodeReg(Rt));
 
1130
}
 
1131
 
 
1132
void ARM64XEmitter::MRS(ARM64Reg Rt, PStateField field) {
 
1133
        int o0 = 0, op1 = 0, CRn = 0, CRm = 0, op2 = 0;
 
1134
        _assert_msg_(JIT, Is64Bit(Rt), "MRS: Rt must be 64-bit");
 
1135
        GetSystemReg(field, o0, op1, CRn, CRm, op2);
 
1136
        EncodeSystemInst(o0 | 4, op1, CRn, CRm, op2, DecodeReg(Rt));
 
1137
}
 
1138
 
 
1139
void ARM64XEmitter::HINT(SystemHint op)
 
1140
{
 
1141
        EncodeSystemInst(0, 3, 2, 0, op, WSP);
 
1142
}
 
1143
void ARM64XEmitter::CLREX()
 
1144
{
 
1145
        EncodeSystemInst(0, 3, 3, 0, 2, WSP);
 
1146
}
 
1147
void ARM64XEmitter::DSB(BarrierType type)
 
1148
{
 
1149
        EncodeSystemInst(0, 3, 3, type, 4, WSP);
 
1150
}
 
1151
void ARM64XEmitter::DMB(BarrierType type)
 
1152
{
 
1153
        EncodeSystemInst(0, 3, 3, type, 5, WSP);
 
1154
}
 
1155
void ARM64XEmitter::ISB(BarrierType type)
 
1156
{
 
1157
        EncodeSystemInst(0, 3, 3, type, 6, WSP);
 
1158
}
 
1159
 
 
1160
// Add/Subtract (extended register)
 
1161
void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1162
{
 
1163
        ADD(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
 
1164
}
 
1165
 
 
1166
void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1167
{
 
1168
        EncodeArithmeticInst(0, false, Rd, Rn, Rm, Option);
 
1169
}
 
1170
 
 
1171
void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1172
{
 
1173
        EncodeArithmeticInst(0, true, Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
 
1174
}
 
1175
 
 
1176
void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1177
{
 
1178
        EncodeArithmeticInst(0, true, Rd, Rn, Rm, Option);
 
1179
}
 
1180
 
 
1181
void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1182
{
 
1183
        SUB(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
 
1184
}
 
1185
 
 
1186
void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1187
{
 
1188
        EncodeArithmeticInst(1, false, Rd, Rn, Rm, Option);
 
1189
}
 
1190
 
 
1191
void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1192
{
 
1193
        EncodeArithmeticInst(1, true, Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
 
1194
}
 
1195
 
 
1196
void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1197
{
 
1198
        EncodeArithmeticInst(1, true, Rd, Rn, Rm, Option);
 
1199
}
 
1200
 
 
1201
void ARM64XEmitter::CMN(ARM64Reg Rn, ARM64Reg Rm)
 
1202
{
 
1203
        CMN(Rn, Rm, ArithOption(Rn, ST_LSL, 0));
 
1204
}
 
1205
 
 
1206
void ARM64XEmitter::CMN(ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1207
{
 
1208
        EncodeArithmeticInst(0, true, Is64Bit(Rn) ? ZR : WZR, Rn, Rm, Option);
 
1209
}
 
1210
 
 
1211
void ARM64XEmitter::CMP(ARM64Reg Rn, ARM64Reg Rm)
 
1212
{
 
1213
        CMP(Rn, Rm, ArithOption(Rn, ST_LSL, 0));
 
1214
}
 
1215
 
 
1216
void ARM64XEmitter::CMP(ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
 
1217
{
 
1218
        EncodeArithmeticInst(1, true, Is64Bit(Rn) ? ZR : WZR, Rn, Rm, Option);
 
1219
}
 
1220
 
 
1221
// Add/Subtract (with carry)
 
1222
void ARM64XEmitter::ADC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1223
{
 
1224
        EncodeArithmeticCarryInst(0, false, Rd, Rn, Rm);
 
1225
}
 
1226
void ARM64XEmitter::ADCS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1227
{
 
1228
        EncodeArithmeticCarryInst(0, true, Rd, Rn, Rm);
 
1229
}
 
1230
void ARM64XEmitter::SBC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1231
{
 
1232
        EncodeArithmeticCarryInst(1, false, Rd, Rn, Rm);
 
1233
}
 
1234
void ARM64XEmitter::SBCS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1235
{
 
1236
        EncodeArithmeticCarryInst(1, true, Rd, Rn, Rm);
 
1237
}
 
1238
 
 
1239
// Conditional Compare (immediate)
 
1240
void ARM64XEmitter::CCMN(ARM64Reg Rn, u32 imm, u32 nzcv, CCFlags cond)
 
1241
{
 
1242
        EncodeCondCompareImmInst(0, Rn, imm, nzcv, cond);
 
1243
}
 
1244
void ARM64XEmitter::CCMP(ARM64Reg Rn, u32 imm, u32 nzcv, CCFlags cond)
 
1245
{
 
1246
        EncodeCondCompareImmInst(1, Rn, imm, nzcv, cond);
 
1247
}
 
1248
 
 
1249
// Conditiona Compare (register)
 
1250
void ARM64XEmitter::CCMN(ARM64Reg Rn, ARM64Reg Rm, u32 nzcv, CCFlags cond)
 
1251
{
 
1252
        EncodeCondCompareRegInst(0, Rn, Rm, nzcv, cond);
 
1253
}
 
1254
void ARM64XEmitter::CCMP(ARM64Reg Rn, ARM64Reg Rm, u32 nzcv, CCFlags cond)
 
1255
{
 
1256
        EncodeCondCompareRegInst(1, Rn, Rm, nzcv, cond);
 
1257
}
 
1258
 
 
1259
// Conditional Select
 
1260
void ARM64XEmitter::CSEL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
1261
{
 
1262
        EncodeCondSelectInst(0, Rd, Rn, Rm, cond);
 
1263
}
 
1264
void ARM64XEmitter::CSINC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
1265
{
 
1266
        EncodeCondSelectInst(1, Rd, Rn, Rm, cond);
 
1267
}
 
1268
void ARM64XEmitter::CSINV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
1269
{
 
1270
        EncodeCondSelectInst(2, Rd, Rn, Rm, cond);
 
1271
}
 
1272
void ARM64XEmitter::CSNEG(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
1273
{
 
1274
        EncodeCondSelectInst(3, Rd, Rn, Rm, cond);
 
1275
}
 
1276
 
 
1277
// Data-Processing 1 source
 
1278
void ARM64XEmitter::RBIT(ARM64Reg Rd, ARM64Reg Rn)
 
1279
{
 
1280
        EncodeData1SrcInst(0, Rd, Rn);
 
1281
}
 
1282
void ARM64XEmitter::REV16(ARM64Reg Rd, ARM64Reg Rn)
 
1283
{
 
1284
        EncodeData1SrcInst(1, Rd, Rn);
 
1285
}
 
1286
void ARM64XEmitter::REV32(ARM64Reg Rd, ARM64Reg Rn)
 
1287
{
 
1288
        EncodeData1SrcInst(2, Rd, Rn);
 
1289
}
 
1290
void ARM64XEmitter::REV64(ARM64Reg Rd, ARM64Reg Rn)
 
1291
{
 
1292
        EncodeData1SrcInst(3, Rd, Rn);
 
1293
}
 
1294
void ARM64XEmitter::CLZ(ARM64Reg Rd, ARM64Reg Rn)
 
1295
{
 
1296
        EncodeData1SrcInst(4, Rd, Rn);
 
1297
}
 
1298
void ARM64XEmitter::CLS(ARM64Reg Rd, ARM64Reg Rn)
 
1299
{
 
1300
        EncodeData1SrcInst(5, Rd, Rn);
 
1301
}
 
1302
 
 
1303
// Data-Processing 2 source
 
1304
void ARM64XEmitter::UDIV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1305
{
 
1306
        EncodeData2SrcInst(0, Rd, Rn, Rm);
 
1307
}
 
1308
void ARM64XEmitter::SDIV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1309
{
 
1310
        EncodeData2SrcInst(1, Rd, Rn, Rm);
 
1311
}
 
1312
void ARM64XEmitter::LSLV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1313
{
 
1314
        EncodeData2SrcInst(2, Rd, Rn, Rm);
 
1315
}
 
1316
void ARM64XEmitter::LSRV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1317
{
 
1318
        EncodeData2SrcInst(3, Rd, Rn, Rm);
 
1319
}
 
1320
void ARM64XEmitter::ASRV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1321
{
 
1322
        EncodeData2SrcInst(4, Rd, Rn, Rm);
 
1323
}
 
1324
void ARM64XEmitter::RORV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1325
{
 
1326
        EncodeData2SrcInst(5, Rd, Rn, Rm);
 
1327
}
 
1328
void ARM64XEmitter::CRC32B(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1329
{
 
1330
        EncodeData2SrcInst(6, Rd, Rn, Rm);
 
1331
}
 
1332
void ARM64XEmitter::CRC32H(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1333
{
 
1334
        EncodeData2SrcInst(7, Rd, Rn, Rm);
 
1335
}
 
1336
void ARM64XEmitter::CRC32W(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1337
{
 
1338
        EncodeData2SrcInst(8, Rd, Rn, Rm);
 
1339
}
 
1340
void ARM64XEmitter::CRC32CB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1341
{
 
1342
        EncodeData2SrcInst(9, Rd, Rn, Rm);
 
1343
}
 
1344
void ARM64XEmitter::CRC32CH(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1345
{
 
1346
        EncodeData2SrcInst(10, Rd, Rn, Rm);
 
1347
}
 
1348
void ARM64XEmitter::CRC32CW(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1349
{
 
1350
        EncodeData2SrcInst(11, Rd, Rn, Rm);
 
1351
}
 
1352
void ARM64XEmitter::CRC32X(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1353
{
 
1354
        EncodeData2SrcInst(12, Rd, Rn, Rm);
 
1355
}
 
1356
void ARM64XEmitter::CRC32CX(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1357
{
 
1358
        EncodeData2SrcInst(13, Rd, Rn, Rm);
 
1359
}
 
1360
 
 
1361
// Data-Processing 3 source
 
1362
void ARM64XEmitter::MADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1363
{
 
1364
        EncodeData3SrcInst(0, Rd, Rn, Rm, Ra);
 
1365
}
 
1366
void ARM64XEmitter::MSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1367
{
 
1368
        EncodeData3SrcInst(1, Rd, Rn, Rm, Ra);
 
1369
}
 
1370
void ARM64XEmitter::SMADDL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1371
{
 
1372
        EncodeData3SrcInst(2, Rd, Rn, Rm, Ra);
 
1373
}
 
1374
void ARM64XEmitter::SMULL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1375
{
 
1376
        SMADDL(Rd, Rn, Rm, SP);
 
1377
}
 
1378
void ARM64XEmitter::SMSUBL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1379
{
 
1380
        EncodeData3SrcInst(3, Rd, Rn, Rm, Ra);
 
1381
}
 
1382
void ARM64XEmitter::SMULH(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1383
{
 
1384
        EncodeData3SrcInst(4, Rd, Rn, Rm, SP);
 
1385
}
 
1386
void ARM64XEmitter::UMADDL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1387
{
 
1388
        EncodeData3SrcInst(5, Rd, Rn, Rm, Ra);
 
1389
}
 
1390
void ARM64XEmitter::UMULL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1391
{
 
1392
        UMADDL(Rd, Rn, Rm, SP);
 
1393
}
 
1394
void ARM64XEmitter::UMSUBL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
 
1395
{
 
1396
        EncodeData3SrcInst(6, Rd, Rn, Rm, Ra);
 
1397
}
 
1398
void ARM64XEmitter::UMULH(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1399
{
 
1400
        EncodeData3SrcInst(7, Rd, Rn, Rm, SP);
 
1401
}
 
1402
void ARM64XEmitter::MUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1403
{
 
1404
        EncodeData3SrcInst(0, Rd, Rn, Rm, SP);
 
1405
}
 
1406
void ARM64XEmitter::MNEG(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
1407
{
 
1408
        EncodeData3SrcInst(1, Rd, Rn, Rm, SP);
 
1409
}
 
1410
 
 
1411
// Logical (shifted register)
 
1412
void ARM64XEmitter::AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1413
{
 
1414
        EncodeLogicalInst(0, Rd, Rn, Rm, Shift);
 
1415
}
 
1416
void ARM64XEmitter::BIC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1417
{
 
1418
        EncodeLogicalInst(1, Rd, Rn, Rm, Shift);
 
1419
}
 
1420
void ARM64XEmitter::ORR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1421
{
 
1422
        EncodeLogicalInst(2, Rd, Rn, Rm, Shift);
 
1423
}
 
1424
void ARM64XEmitter::ORN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1425
{
 
1426
        EncodeLogicalInst(3, Rd, Rn, Rm, Shift);
 
1427
}
 
1428
void ARM64XEmitter::EOR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1429
{
 
1430
        EncodeLogicalInst(4, Rd, Rn, Rm, Shift);
 
1431
}
 
1432
void ARM64XEmitter::EON(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1433
{
 
1434
        EncodeLogicalInst(5, Rd, Rn, Rm, Shift);
 
1435
}
 
1436
void ARM64XEmitter::ANDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1437
{
 
1438
        EncodeLogicalInst(6, Rd, Rn, Rm, Shift);
 
1439
}
 
1440
void ARM64XEmitter::BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1441
{
 
1442
        EncodeLogicalInst(7, Rd, Rn, Rm, Shift);
 
1443
}
 
1444
void ARM64XEmitter::TST(ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift)
 
1445
{
 
1446
        ANDS(Is64Bit(Rn) ? ZR : WZR, Rn, Rm, Shift);
 
1447
}
 
1448
 
 
1449
void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm, ArithOption Shift) {
 
1450
        ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, Shift);
 
1451
}
 
1452
 
 
1453
void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm)
 
1454
{
 
1455
        if (IsGPR(Rd) && IsGPR(Rm)) {
 
1456
                ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_LSL, 0));
 
1457
        } else {
 
1458
                _assert_msg_(JIT, false, "Non-GPRs not supported in MOV");
 
1459
        }
 
1460
}
 
1461
void ARM64XEmitter::MVN(ARM64Reg Rd, ARM64Reg Rm)
 
1462
{
 
1463
        ORN(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_LSL, 0));
 
1464
}
 
1465
void ARM64XEmitter::LSL(ARM64Reg Rd, ARM64Reg Rm, int shift)
 
1466
{
 
1467
        ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_LSL, shift));
 
1468
}
 
1469
void ARM64XEmitter::LSR(ARM64Reg Rd, ARM64Reg Rm, int shift)
 
1470
{
 
1471
        ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_LSR, shift));
 
1472
}
 
1473
void ARM64XEmitter::ASR(ARM64Reg Rd, ARM64Reg Rm, int shift)
 
1474
{
 
1475
        ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_ASR, shift));
 
1476
}
 
1477
void ARM64XEmitter::ROR(ARM64Reg Rd, ARM64Reg Rm, int shift)
 
1478
{
 
1479
        ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_ROR, shift));
 
1480
}
 
1481
 
 
1482
// Logical (immediate)
 
1483
void ARM64XEmitter::AND(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert)
 
1484
{
 
1485
        EncodeLogicalImmInst(0, Rd, Rn, immr, imms, invert);
 
1486
}
 
1487
void ARM64XEmitter::ANDS(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert)
 
1488
{
 
1489
        EncodeLogicalImmInst(3, Rd, Rn, immr, imms, invert);
 
1490
}
 
1491
void ARM64XEmitter::EOR(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert)
 
1492
{
 
1493
        EncodeLogicalImmInst(2, Rd, Rn, immr, imms, invert);
 
1494
}
 
1495
void ARM64XEmitter::ORR(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert)
 
1496
{
 
1497
        EncodeLogicalImmInst(1, Rd, Rn, immr, imms, invert);
 
1498
}
 
1499
void ARM64XEmitter::TST(ARM64Reg Rn, u32 immr, u32 imms, bool invert)
 
1500
{
 
1501
        EncodeLogicalImmInst(3, Is64Bit(Rn) ? ZR : WZR, Rn, immr, imms, invert);
 
1502
}
 
1503
 
 
1504
// Add/subtract (immediate)
 
1505
void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, u32 imm, bool shift)
 
1506
{
 
1507
        EncodeAddSubImmInst(0, false, shift, imm, Rn, Rd);
 
1508
}
 
1509
void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, u32 imm, bool shift)
 
1510
{
 
1511
        EncodeAddSubImmInst(0, true, shift, imm, Rn, Rd);
 
1512
}
 
1513
void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, u32 imm, bool shift)
 
1514
{
 
1515
        EncodeAddSubImmInst(1, false, shift, imm, Rn, Rd);
 
1516
}
 
1517
void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, u32 imm, bool shift)
 
1518
{
 
1519
        EncodeAddSubImmInst(1, true, shift, imm, Rn, Rd);
 
1520
}
 
1521
void ARM64XEmitter::CMP(ARM64Reg Rn, u32 imm, bool shift)
 
1522
{
 
1523
        EncodeAddSubImmInst(1, true, shift, imm, Rn, Is64Bit(Rn) ? SP : WSP);
 
1524
}
 
1525
 
 
1526
// Data Processing (Immediate)
 
1527
void ARM64XEmitter::MOVZ(ARM64Reg Rd, u32 imm, ShiftAmount pos)
 
1528
{
 
1529
        EncodeMOVWideInst(2, Rd, imm, pos);
 
1530
}
 
1531
void ARM64XEmitter::MOVN(ARM64Reg Rd, u32 imm, ShiftAmount pos)
 
1532
{
 
1533
        EncodeMOVWideInst(0, Rd, imm, pos);
 
1534
}
 
1535
void ARM64XEmitter::MOVK(ARM64Reg Rd, u32 imm, ShiftAmount pos)
 
1536
{
 
1537
        EncodeMOVWideInst(3, Rd, imm, pos);
 
1538
}
 
1539
 
 
1540
// Bitfield move
 
1541
void ARM64XEmitter::BFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms)
 
1542
{
 
1543
        EncodeBitfieldMOVInst(1, Rd, Rn, immr, imms);
 
1544
}
 
1545
void ARM64XEmitter::SBFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms)
 
1546
{
 
1547
        EncodeBitfieldMOVInst(0, Rd, Rn, immr, imms);
 
1548
}
 
1549
void ARM64XEmitter::UBFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms)
 
1550
{
 
1551
        EncodeBitfieldMOVInst(2, Rd, Rn, immr, imms);
 
1552
}
 
1553
 
 
1554
void ARM64XEmitter::BFI(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
 
1555
{
 
1556
        u32 size = Is64Bit(Rn) ? 64 : 32;
 
1557
        _assert_msg_(DYNA_REC, (lsb + width) <= size, "%s passed lsb %d and width %d which is greater than the register size!",
 
1558
                        __FUNCTION__, lsb, width);
 
1559
        EncodeBitfieldMOVInst(1, Rd, Rn, (size - lsb) % size, width - 1);
 
1560
}
 
1561
void ARM64XEmitter::UBFIZ(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
 
1562
{
 
1563
        u32 size = Is64Bit(Rn) ? 64 : 32;
 
1564
        _assert_msg_(DYNA_REC, (lsb + width) <= size, "%s passed lsb %d and width %d which is greater than the register size!",
 
1565
                        __FUNCTION__, lsb, width);
 
1566
        EncodeBitfieldMOVInst(2, Rd, Rn, (size - lsb) % size, width - 1);
 
1567
}
 
1568
void ARM64XEmitter::EXTR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u32 shift) {
 
1569
        bool sf = Is64Bit(Rd);
 
1570
        bool N = sf;
 
1571
        Rd = DecodeReg(Rd);
 
1572
        Rn = DecodeReg(Rn);
 
1573
        Rm = DecodeReg(Rm);
 
1574
        Write32((sf << 31) | (0x27 << 23) | (N << 22) | (Rm << 16) | (shift << 10) | (Rm << 5) | Rd);
 
1575
}
 
1576
void ARM64XEmitter::SXTB(ARM64Reg Rd, ARM64Reg Rn)
 
1577
{
 
1578
        SBFM(Rd, Rn, 0, 7);
 
1579
}
 
1580
void ARM64XEmitter::SXTH(ARM64Reg Rd, ARM64Reg Rn)
 
1581
{
 
1582
        SBFM(Rd, Rn, 0, 15);
 
1583
}
 
1584
void ARM64XEmitter::SXTW(ARM64Reg Rd, ARM64Reg Rn)
 
1585
{
 
1586
        _assert_msg_(DYNA_REC, Is64Bit(Rd), "%s requires 64bit register as destination", __FUNCTION__);
 
1587
        SBFM(Rd, Rn, 0, 31);
 
1588
}
 
1589
void ARM64XEmitter::UXTB(ARM64Reg Rd, ARM64Reg Rn)
 
1590
{
 
1591
        UBFM(Rd, Rn, 0, 7);
 
1592
}
 
1593
void ARM64XEmitter::UXTH(ARM64Reg Rd, ARM64Reg Rn)
 
1594
{
 
1595
        UBFM(Rd, Rn, 0, 15);
 
1596
}
 
1597
 
 
1598
// Load Register (Literal)
 
1599
void ARM64XEmitter::LDR(ARM64Reg Rt, u32 imm)
 
1600
{
 
1601
        EncodeLoadRegisterInst(0, Rt, imm);
 
1602
}
 
1603
void ARM64XEmitter::LDRSW(ARM64Reg Rt, u32 imm)
 
1604
{
 
1605
        EncodeLoadRegisterInst(2, Rt, imm);
 
1606
}
 
1607
void ARM64XEmitter::PRFM(ARM64Reg Rt, u32 imm)
 
1608
{
 
1609
        EncodeLoadRegisterInst(3, Rt, imm);
 
1610
}
 
1611
 
 
1612
// Load/Store pair
 
1613
void ARM64XEmitter::LDP(IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
1614
{
 
1615
        EncodeLoadStorePair(0, 1, type, Rt, Rt2, Rn, imm);
 
1616
}
 
1617
void ARM64XEmitter::LDPSW(IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
1618
{
 
1619
        EncodeLoadStorePair(1, 1, type, Rt, Rt2, Rn, imm);
 
1620
}
 
1621
void ARM64XEmitter::STP(IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
1622
{
 
1623
        EncodeLoadStorePair(0, 0, type, Rt, Rt2, Rn, imm);
 
1624
}
 
1625
 
 
1626
// Load/Store Exclusive
 
1627
void ARM64XEmitter::STXRB(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1628
{
 
1629
        EncodeLoadStoreExcInst(0, Rs, SP, Rt, Rn);
 
1630
}
 
1631
void ARM64XEmitter::STLXRB(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1632
{
 
1633
        EncodeLoadStoreExcInst(1, Rs, SP, Rt, Rn);
 
1634
}
 
1635
void ARM64XEmitter::LDXRB(ARM64Reg Rt, ARM64Reg Rn)
 
1636
{
 
1637
        EncodeLoadStoreExcInst(2, SP, SP, Rt, Rn);
 
1638
}
 
1639
void ARM64XEmitter::LDAXRB(ARM64Reg Rt, ARM64Reg Rn)
 
1640
{
 
1641
        EncodeLoadStoreExcInst(3, SP, SP, Rt, Rn);
 
1642
}
 
1643
void ARM64XEmitter::STLRB(ARM64Reg Rt, ARM64Reg Rn)
 
1644
{
 
1645
        EncodeLoadStoreExcInst(4, SP, SP, Rt, Rn);
 
1646
}
 
1647
void ARM64XEmitter::LDARB(ARM64Reg Rt, ARM64Reg Rn)
 
1648
{
 
1649
        EncodeLoadStoreExcInst(5, SP, SP, Rt, Rn);
 
1650
}
 
1651
void ARM64XEmitter::STXRH(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1652
{
 
1653
        EncodeLoadStoreExcInst(6, Rs, SP, Rt, Rn);
 
1654
}
 
1655
void ARM64XEmitter::STLXRH(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1656
{
 
1657
        EncodeLoadStoreExcInst(7, Rs, SP, Rt, Rn);
 
1658
}
 
1659
void ARM64XEmitter::LDXRH(ARM64Reg Rt, ARM64Reg Rn)
 
1660
{
 
1661
        EncodeLoadStoreExcInst(8, SP, SP, Rt, Rn);
 
1662
}
 
1663
void ARM64XEmitter::LDAXRH(ARM64Reg Rt, ARM64Reg Rn)
 
1664
{
 
1665
        EncodeLoadStoreExcInst(9, SP, SP, Rt, Rn);
 
1666
}
 
1667
void ARM64XEmitter::STLRH(ARM64Reg Rt, ARM64Reg Rn)
 
1668
{
 
1669
        EncodeLoadStoreExcInst(10, SP, SP, Rt, Rn);
 
1670
}
 
1671
void ARM64XEmitter::LDARH(ARM64Reg Rt, ARM64Reg Rn)
 
1672
{
 
1673
        EncodeLoadStoreExcInst(11, SP, SP, Rt, Rn);
 
1674
}
 
1675
void ARM64XEmitter::STXR(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1676
{
 
1677
        EncodeLoadStoreExcInst(12 + Is64Bit(Rt), Rs, SP, Rt, Rn);
 
1678
}
 
1679
void ARM64XEmitter::STLXR(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rn)
 
1680
{
 
1681
        EncodeLoadStoreExcInst(14 + Is64Bit(Rt), Rs, SP, Rt, Rn);
 
1682
}
 
1683
void ARM64XEmitter::STXP(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn)
 
1684
{
 
1685
        EncodeLoadStoreExcInst(16 + Is64Bit(Rt), Rs, Rt2, Rt, Rn);
 
1686
}
 
1687
void ARM64XEmitter::STLXP(ARM64Reg Rs, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn)
 
1688
{
 
1689
        EncodeLoadStoreExcInst(18 + Is64Bit(Rt), Rs, Rt2, Rt, Rn);
 
1690
}
 
1691
void ARM64XEmitter::LDXR(ARM64Reg Rt, ARM64Reg Rn)
 
1692
{
 
1693
        EncodeLoadStoreExcInst(20 + Is64Bit(Rt), SP, SP, Rt, Rn);
 
1694
}
 
1695
void ARM64XEmitter::LDAXR(ARM64Reg Rt, ARM64Reg Rn)
 
1696
{
 
1697
        EncodeLoadStoreExcInst(22 + Is64Bit(Rt), SP, SP, Rt, Rn);
 
1698
}
 
1699
void ARM64XEmitter::LDXP(ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn)
 
1700
{
 
1701
        EncodeLoadStoreExcInst(24 + Is64Bit(Rt), SP, Rt2, Rt, Rn);
 
1702
}
 
1703
void ARM64XEmitter::LDAXP(ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn)
 
1704
{
 
1705
        EncodeLoadStoreExcInst(26 + Is64Bit(Rt), SP, Rt2, Rt, Rn);
 
1706
}
 
1707
void ARM64XEmitter::STLR(ARM64Reg Rt, ARM64Reg Rn)
 
1708
{
 
1709
        EncodeLoadStoreExcInst(28 + Is64Bit(Rt), SP, SP, Rt, Rn);
 
1710
}
 
1711
void ARM64XEmitter::LDAR(ARM64Reg Rt, ARM64Reg Rn)
 
1712
{
 
1713
        EncodeLoadStoreExcInst(30 + Is64Bit(Rt), SP, SP, Rt, Rn);
 
1714
}
 
1715
 
 
1716
// Load/Store no-allocate pair (offset)
 
1717
void ARM64XEmitter::STNP(ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, u32 imm)
 
1718
{
 
1719
        EncodeLoadStorePairedInst(0xA0, Rt, Rt2, Rn, imm);
 
1720
}
 
1721
void ARM64XEmitter::LDNP(ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, u32 imm)
 
1722
{
 
1723
        EncodeLoadStorePairedInst(0xA1, Rt, Rt2, Rn, imm);
 
1724
}
 
1725
 
 
1726
// Load/Store register (immediate post-indexed)
 
1727
// XXX: Most of these support vectors
 
1728
void ARM64XEmitter::STRB(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1729
{
 
1730
        if (type == INDEX_UNSIGNED)
 
1731
                EncodeLoadStoreIndexedInst(0x0E4, Rt, Rn, imm, 8);
 
1732
        else
 
1733
                EncodeLoadStoreIndexedInst(0x0E0,
 
1734
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1735
}
 
1736
void ARM64XEmitter::LDRB(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1737
{
 
1738
        if (type == INDEX_UNSIGNED)
 
1739
                EncodeLoadStoreIndexedInst(0x0E5, Rt, Rn, imm, 8);
 
1740
        else
 
1741
                EncodeLoadStoreIndexedInst(0x0E1,
 
1742
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1743
}
 
1744
void ARM64XEmitter::LDRSB(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1745
{
 
1746
        if (type == INDEX_UNSIGNED)
 
1747
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x0E6 : 0x0E7, Rt, Rn, imm, 8);
 
1748
        else
 
1749
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x0E2 : 0x0E3,
 
1750
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1751
}
 
1752
void ARM64XEmitter::STRH(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1753
{
 
1754
        if (type == INDEX_UNSIGNED)
 
1755
                EncodeLoadStoreIndexedInst(0x1E4, Rt, Rn, imm, 16);
 
1756
        else
 
1757
                EncodeLoadStoreIndexedInst(0x1E0,
 
1758
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1759
}
 
1760
void ARM64XEmitter::LDRH(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1761
{
 
1762
        if (type == INDEX_UNSIGNED)
 
1763
                EncodeLoadStoreIndexedInst(0x1E5, Rt, Rn, imm, 16);
 
1764
        else
 
1765
                EncodeLoadStoreIndexedInst(0x1E1,
 
1766
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1767
}
 
1768
void ARM64XEmitter::LDRSH(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1769
{
 
1770
        if (type == INDEX_UNSIGNED)
 
1771
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x1E6 : 0x1E7, Rt, Rn, imm, 16);
 
1772
        else
 
1773
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x1E2 : 0x1E3,
 
1774
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1775
}
 
1776
void ARM64XEmitter::STR(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1777
{
 
1778
        if (type == INDEX_UNSIGNED)
 
1779
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x3E4 : 0x2E4, Rt, Rn, imm, Is64Bit(Rt) ? 64 : 32);
 
1780
        else
 
1781
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x3E0 : 0x2E0,
 
1782
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1783
}
 
1784
void ARM64XEmitter::LDR(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1785
{
 
1786
        if (type == INDEX_UNSIGNED)
 
1787
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x3E5 : 0x2E5, Rt, Rn, imm, Is64Bit(Rt) ? 64 : 32);
 
1788
        else
 
1789
                EncodeLoadStoreIndexedInst(Is64Bit(Rt) ? 0x3E1 : 0x2E1,
 
1790
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1791
}
 
1792
void ARM64XEmitter::LDRSW(IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1793
{
 
1794
        if (type == INDEX_UNSIGNED)
 
1795
                EncodeLoadStoreIndexedInst(0x2E6, Rt, Rn, imm, 32);
 
1796
        else
 
1797
                EncodeLoadStoreIndexedInst(0x2E2,
 
1798
                                type == INDEX_POST ? 1 : 3, Rt, Rn, imm);
 
1799
}
 
1800
 
 
1801
// Load/Store register (register offset)
 
1802
void ARM64XEmitter::STRB(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1803
{
 
1804
        EncodeLoadStoreRegisterOffset(0, 0, Rt, Rn, Rm);
 
1805
}
 
1806
void ARM64XEmitter::LDRB(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1807
{
 
1808
        EncodeLoadStoreRegisterOffset(0, 1, Rt, Rn, Rm);
 
1809
}
 
1810
void ARM64XEmitter::LDRSB(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1811
{
 
1812
        bool b64Bit = Is64Bit(Rt);
 
1813
        EncodeLoadStoreRegisterOffset(0, 3 - b64Bit, Rt, Rn, Rm);
 
1814
}
 
1815
void ARM64XEmitter::STRH(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1816
{
 
1817
        EncodeLoadStoreRegisterOffset(1, 0, Rt, Rn, Rm);
 
1818
}
 
1819
void ARM64XEmitter::LDRH(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1820
{
 
1821
        EncodeLoadStoreRegisterOffset(1, 1, Rt, Rn, Rm);
 
1822
}
 
1823
void ARM64XEmitter::LDRSH(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1824
{
 
1825
        bool b64Bit = Is64Bit(Rt);
 
1826
        EncodeLoadStoreRegisterOffset(1, 3 - b64Bit, Rt, Rn, Rm);
 
1827
}
 
1828
void ARM64XEmitter::STR(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1829
{
 
1830
        bool b64Bit = Is64Bit(Rt);
 
1831
        EncodeLoadStoreRegisterOffset(2 + b64Bit, 0, Rt, Rn, Rm);
 
1832
}
 
1833
void ARM64XEmitter::LDR(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1834
{
 
1835
        bool b64Bit = Is64Bit(Rt);
 
1836
        EncodeLoadStoreRegisterOffset(2 + b64Bit, 1, Rt, Rn, Rm);
 
1837
}
 
1838
void ARM64XEmitter::LDRSW(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1839
{
 
1840
        EncodeLoadStoreRegisterOffset(2, 2, Rt, Rn, Rm);
 
1841
}
 
1842
void ARM64XEmitter::PRFM(ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
1843
{
 
1844
        EncodeLoadStoreRegisterOffset(3, 2, Rt, Rn, Rm);
 
1845
}
 
1846
 
 
1847
// Load/Store register (unscaled offset)
 
1848
void ARM64XEmitter::STURB(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1849
{
 
1850
        EncodeLoadStoreUnscaled(0, 0, Rt, Rn, imm);
 
1851
}
 
1852
void ARM64XEmitter::LDURB(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1853
{
 
1854
        EncodeLoadStoreUnscaled(0, 1, Rt, Rn, imm);
 
1855
}
 
1856
void ARM64XEmitter::LDURSB(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1857
{
 
1858
        EncodeLoadStoreUnscaled(0, Is64Bit(Rt) ? 2 : 3, Rt, Rn, imm);
 
1859
}
 
1860
void ARM64XEmitter::STURH(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1861
{
 
1862
        EncodeLoadStoreUnscaled(1, 0, Rt, Rn, imm);
 
1863
}
 
1864
void ARM64XEmitter::LDURH(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1865
{
 
1866
        EncodeLoadStoreUnscaled(1, 1, Rt, Rn, imm);
 
1867
}
 
1868
void ARM64XEmitter::LDURSH(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1869
{
 
1870
        EncodeLoadStoreUnscaled(1, Is64Bit(Rt) ? 2 : 3, Rt, Rn, imm);
 
1871
}
 
1872
void ARM64XEmitter::STUR(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1873
{
 
1874
        EncodeLoadStoreUnscaled(Is64Bit(Rt) ? 3 : 2, 0, Rt, Rn, imm);
 
1875
}
 
1876
void ARM64XEmitter::LDUR(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1877
{
 
1878
        EncodeLoadStoreUnscaled(Is64Bit(Rt) ? 3 : 2, 1, Rt, Rn, imm);
 
1879
}
 
1880
void ARM64XEmitter::LDURSW(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
1881
{
 
1882
        _assert_msg_(DYNA_REC, !Is64Bit(Rt), "%s must have a 64bit destination register!", __FUNCTION__);
 
1883
        EncodeLoadStoreUnscaled(2, 2, Rt, Rn, imm);
 
1884
}
 
1885
 
 
1886
// Address of label/page PC-relative
 
1887
void ARM64XEmitter::ADR(ARM64Reg Rd, s32 imm)
 
1888
{
 
1889
        EncodeAddressInst(0, Rd, imm);
 
1890
}
 
1891
void ARM64XEmitter::ADRP(ARM64Reg Rd, s32 imm)
 
1892
{
 
1893
        EncodeAddressInst(1, Rd, imm >> 12);
 
1894
}
 
1895
 
 
1896
// LLVM is unhappy about the regular abs function, so here we go.
 
1897
inline int64_t abs64(int64_t x) {
 
1898
        return x >= 0 ? x : -x;
 
1899
}
 
1900
 
 
1901
// Wrapper around MOVZ+MOVK (and later MOVN)
 
1902
void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize)
 
1903
{
 
1904
        unsigned int parts = Is64Bit(Rd) ? 4 : 2;
 
1905
        BitSet32 upload_part(0);
 
1906
 
 
1907
        // Always start with a movz! Kills the dependency on the register.
 
1908
        bool use_movz = true;
 
1909
 
 
1910
        if (!imm)
 
1911
        {
 
1912
                // Zero immediate, just clear the register. EOR is pointless when we have MOVZ, which looks clearer in disasm too.
 
1913
                MOVZ(Rd, 0, SHIFT_0);
 
1914
                return;
 
1915
        }
 
1916
 
 
1917
        if ((Is64Bit(Rd) && imm == std::numeric_limits<u64>::max()) ||
 
1918
            (!Is64Bit(Rd) && imm == std::numeric_limits<u32>::max()))
 
1919
        {
 
1920
                // Max unsigned value (or if signed, -1)
 
1921
                // Set to ~ZR
 
1922
                ARM64Reg ZR = Is64Bit(Rd) ? SP : WSP;
 
1923
                ORN(Rd, ZR, ZR, ArithOption(ZR, ST_LSL, 0));
 
1924
                return;
 
1925
        }
 
1926
 
 
1927
        // TODO: Make some more systemic use of MOVN, but this will take care of most cases.
 
1928
        // Small negative integer. Use MOVN
 
1929
        if (!Is64Bit(Rd) && (imm | 0xFFFF0000) == imm) {
 
1930
                MOVN(Rd, ~imm, SHIFT_0);
 
1931
                return;
 
1932
        }
 
1933
 
 
1934
 
 
1935
        // XXX: Use MOVN when possible.
 
1936
        // XXX: Optimize more
 
1937
        // XXX: Support rotating immediates to save instructions
 
1938
        if (optimize)
 
1939
        {
 
1940
                for (unsigned int i = 0; i < parts; ++i)
 
1941
                {
 
1942
                        if ((imm >> (i * 16)) & 0xFFFF)
 
1943
                                upload_part[i] = 1;
 
1944
                }
 
1945
        }
 
1946
 
 
1947
        u64 aligned_pc = (u64)GetCodePointer() & ~0xFFF;
 
1948
        s64 aligned_offset = (s64)imm - (s64)aligned_pc;
 
1949
        if (upload_part.Count() > 1 && abs64(aligned_offset) < 0xFFFFFFFFLL)
 
1950
        {
 
1951
                // Immediate we are loading is within 4GB of our aligned range
 
1952
                // Most likely a address that we can load in one or two instructions
 
1953
                if (!(abs64(aligned_offset) & 0xFFF))
 
1954
                {
 
1955
                        // Aligned ADR
 
1956
                        ADRP(Rd, (s32)aligned_offset);
 
1957
                        return;
 
1958
                }
 
1959
                else
 
1960
                {
 
1961
                        // If the address is within 1MB of PC we can load it in a single instruction still
 
1962
                        s64 offset = (s64)imm - (s64)GetCodePointer();
 
1963
                        if (offset >= -0xFFFFF && offset <= 0xFFFFF)
 
1964
                        {
 
1965
                                ADR(Rd, (s32)offset);
 
1966
                                return;
 
1967
                        }
 
1968
                        else
 
1969
                        {
 
1970
                                ADRP(Rd, (s32)(aligned_offset & ~0xFFF));
 
1971
                                ADD(Rd, Rd, imm & 0xFFF);
 
1972
                                return;
 
1973
                        }
 
1974
                }
 
1975
        }
 
1976
 
 
1977
        for (unsigned i = 0; i < parts; ++i)
 
1978
        {
 
1979
                if (use_movz && upload_part[i])
 
1980
                {
 
1981
                        MOVZ(Rd, (imm >> (i * 16)) & 0xFFFF, (ShiftAmount)i);
 
1982
                        use_movz = false;
 
1983
                }
 
1984
                else
 
1985
                {
 
1986
                        if (upload_part[i] || !optimize)
 
1987
                                MOVK(Rd, (imm >> (i * 16)) & 0xFFFF, (ShiftAmount)i);
 
1988
                }
 
1989
        }
 
1990
}
 
1991
 
 
1992
void ARM64XEmitter::PUSH(ARM64Reg Rd) {
 
1993
        STR(INDEX_PRE, Rd, SP, -16);
 
1994
}
 
1995
 
 
1996
void ARM64XEmitter::POP(ARM64Reg Rd) {
 
1997
        LDR(INDEX_POST, Rd, SP, 16);
 
1998
}
 
1999
 
 
2000
void ARM64XEmitter::PUSH2(ARM64Reg Rd, ARM64Reg Rn) {
 
2001
        STP(INDEX_PRE, Rd, Rn, SP, -16);
 
2002
}
 
2003
void ARM64XEmitter::POP2(ARM64Reg Rd, ARM64Reg Rn) {
 
2004
        LDP(INDEX_POST, Rd, Rn, SP, 16);
 
2005
}
 
2006
 
 
2007
 
 
2008
void ARM64XEmitter::ABI_PushRegisters(BitSet32 registers)
 
2009
{
 
2010
        int num_regs = registers.Count();
 
2011
 
 
2012
        if (num_regs % 2)
 
2013
        {
 
2014
                bool first = true;
 
2015
 
 
2016
                // Stack is required to be quad-word aligned.
 
2017
                u32 stack_size = ROUND_UP(num_regs * 8, 16);
 
2018
                u32 current_offset = 0;
 
2019
                std::vector<ARM64Reg> reg_pair;
 
2020
 
 
2021
                for (auto it : registers)
 
2022
                {
 
2023
                        if (first)
 
2024
                        {
 
2025
                                STR(INDEX_PRE, (ARM64Reg)(X0 + it), SP, -(s32)stack_size);
 
2026
                                first = false;
 
2027
                                current_offset += 16;
 
2028
                        }
 
2029
                        else
 
2030
                        {
 
2031
                                reg_pair.push_back((ARM64Reg)(X0 + it));
 
2032
                                if (reg_pair.size() == 2)
 
2033
                                {
 
2034
                                        STP(INDEX_UNSIGNED, reg_pair[0], reg_pair[1], SP, current_offset);
 
2035
                                        reg_pair.clear();
 
2036
                                        current_offset += 16;
 
2037
                                }
 
2038
                        }
 
2039
                }
 
2040
        }
 
2041
        else
 
2042
        {
 
2043
                std::vector<ARM64Reg> reg_pair;
 
2044
 
 
2045
                for (auto it : registers)
 
2046
                {
 
2047
                        reg_pair.push_back((ARM64Reg)(X0 + it));
 
2048
                        if (reg_pair.size() == 2)
 
2049
                        {
 
2050
                                STP(INDEX_PRE, reg_pair[0], reg_pair[1], SP, -16);
 
2051
                                reg_pair.clear();
 
2052
                        }
 
2053
                }
 
2054
        }
 
2055
}
 
2056
 
 
2057
void ARM64XEmitter::ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask)
 
2058
{
 
2059
        int num_regs = registers.Count();
 
2060
 
 
2061
        if (num_regs % 2)
 
2062
        {
 
2063
                bool first = true;
 
2064
 
 
2065
                std::vector<ARM64Reg> reg_pair;
 
2066
 
 
2067
                for (auto it : registers)
 
2068
                {
 
2069
                        if (ignore_mask[it])
 
2070
                                it = WSP;
 
2071
 
 
2072
                        if (first)
 
2073
                        {
 
2074
                                LDR(INDEX_POST, (ARM64Reg)(X0 + it), SP, 16);
 
2075
                                first = false;
 
2076
                        }
 
2077
                        else
 
2078
                        {
 
2079
                                reg_pair.push_back((ARM64Reg)(X0 + it));
 
2080
                                if (reg_pair.size() == 2)
 
2081
                                {
 
2082
                                        LDP(INDEX_POST, reg_pair[0], reg_pair[1], SP, 16);
 
2083
                                        reg_pair.clear();
 
2084
                                }
 
2085
                        }
 
2086
                }
 
2087
        }
 
2088
        else
 
2089
        {
 
2090
                std::vector<ARM64Reg> reg_pair;
 
2091
 
 
2092
                for (int i = 31; i >= 0; --i)
 
2093
                {
 
2094
                        if (!registers[i])
 
2095
                                continue;
 
2096
 
 
2097
                        int reg = i;
 
2098
 
 
2099
                        if (ignore_mask[reg])
 
2100
                                reg = WSP;
 
2101
 
 
2102
                        reg_pair.push_back((ARM64Reg)(X0 + reg));
 
2103
                        if (reg_pair.size() == 2)
 
2104
                        {
 
2105
                                LDP(INDEX_POST, reg_pair[1], reg_pair[0], SP, 16);
 
2106
                                reg_pair.clear();
 
2107
                        }
 
2108
                }
 
2109
        }
 
2110
}
 
2111
 
 
2112
// Float Emitter
 
2113
void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2114
{
 
2115
        Rt = DecodeReg(Rt);
 
2116
        Rn = DecodeReg(Rn);
 
2117
        u32 encoded_size = 0;
 
2118
        u32 encoded_imm = 0;
 
2119
 
 
2120
        if (size == 8)
 
2121
                encoded_size = 0;
 
2122
        else if (size == 16)
 
2123
                encoded_size = 1;
 
2124
        else if (size == 32)
 
2125
                encoded_size = 2;
 
2126
        else if (size == 64)
 
2127
                encoded_size = 3;
 
2128
        else if (size == 128)
 
2129
                encoded_size = 0;
 
2130
 
 
2131
        if (type == INDEX_UNSIGNED)
 
2132
        {
 
2133
                _assert_msg_(DYNA_REC, !(imm & ((size - 1) >> 3)), "%s(INDEX_UNSIGNED) immediate offset must be aligned to size! (%d) (%p)", __FUNCTION__, imm, m_emit->GetCodePointer());
 
2134
                _assert_msg_(DYNA_REC, imm >= 0, "%s(INDEX_UNSIGNED) immediate offset must be positive!", __FUNCTION__);
 
2135
                if (size == 16)
 
2136
                        imm >>= 1;
 
2137
                else if (size == 32)
 
2138
                        imm >>= 2;
 
2139
                else if (size == 64)
 
2140
                        imm >>= 3;
 
2141
                else if (size == 128)
 
2142
                        imm >>= 4;
 
2143
                encoded_imm = (imm & 0xFFF);
 
2144
        }
 
2145
        else
 
2146
        {
 
2147
                _assert_msg_(DYNA_REC, !(imm < -256 || imm > 255), "%s immediate offset must be within range of -256 to 256!", __FUNCTION__);
 
2148
                encoded_imm = (imm & 0x1FF) << 2;
 
2149
                if (type == INDEX_POST)
 
2150
                        encoded_imm |= 1;
 
2151
                else
 
2152
                        encoded_imm |= 3;
 
2153
        }
 
2154
 
 
2155
        Write32((encoded_size << 30) | (0xF << 26) | (type == INDEX_UNSIGNED ? (1 << 24) : 0) | \
 
2156
                (size == 128 ? (1 << 23) : 0) | (opc << 22) | (encoded_imm << 10) | (Rn << 5) | Rt);
 
2157
}
 
2158
 
 
2159
void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2160
{
 
2161
        _assert_msg_(DYNA_REC, !IsQuad(Rd), "%s only supports double and single registers!", __FUNCTION__);
 
2162
        Rd = DecodeReg(Rd);
 
2163
        Rn = DecodeReg(Rn);
 
2164
        Rm = DecodeReg(Rm);
 
2165
 
 
2166
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (Rm << 16) | \
 
2167
                (opcode << 12) | (1 << 11) | (Rn << 5) | Rd);
 
2168
}
 
2169
 
 
2170
void ARM64FloatEmitter::EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2171
{
 
2172
        _assert_msg_(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__);
 
2173
        bool quad = IsQuad(Rd);
 
2174
        Rd = DecodeReg(Rd);
 
2175
        Rn = DecodeReg(Rn);
 
2176
        Rm = DecodeReg(Rm);
 
2177
 
 
2178
        Write32((quad << 30) | (U << 29) | (0x71 << 21) | (size << 22) | \
 
2179
                (Rm << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
 
2180
}
 
2181
 
 
2182
void ARM64FloatEmitter::EmitCopy(bool Q, u32 op, u32 imm5, u32 imm4, ARM64Reg Rd, ARM64Reg Rn)
 
2183
{
 
2184
        Rd = DecodeReg(Rd);
 
2185
        Rn = DecodeReg(Rn);
 
2186
 
 
2187
        Write32((Q << 30) | (op << 29) | (0x7 << 25) | (imm5 << 16) | (imm4 << 11) | \
 
2188
                (1 << 10) | (Rn << 5) | Rd);
 
2189
}
 
2190
 
 
2191
void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
 
2192
{
 
2193
        _assert_msg_(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__);
 
2194
        Rd = DecodeReg(Rd);
 
2195
        Rn = DecodeReg(Rn);
 
2196
 
 
2197
        Write32((Q << 30) | (U << 29) | (0x71 << 21) | (size << 22) | \
 
2198
                (opcode << 12) | (1 << 11) | (Rn << 5) | Rd);
 
2199
}
 
2200
 
 
2201
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn)
 
2202
{
 
2203
        _assert_msg_(DYNA_REC, !IsSingle(Rt), "%s doesn't support singles!", __FUNCTION__);
 
2204
        bool quad = IsQuad(Rt);
 
2205
        Rt = DecodeReg(Rt);
 
2206
        Rn = DecodeReg(Rn);
 
2207
 
 
2208
        Write32((quad << 30) | (0xD << 24) | (L << 22) | (R << 21) | (opcode << 13) | \
 
2209
                (S << 12) | (size << 10) | (Rn << 5) | Rt);
 
2210
}
 
2211
 
 
2212
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2213
{
 
2214
        _assert_msg_(DYNA_REC, !IsSingle(Rt), "%s doesn't support singles!", __FUNCTION__);
 
2215
        bool quad = IsQuad(Rt);
 
2216
        Rt = DecodeReg(Rt);
 
2217
        Rn = DecodeReg(Rn);
 
2218
        Rm = DecodeReg(Rm);
 
2219
 
 
2220
        Write32((quad << 30) | (0x1B << 23) | (L << 22) | (R << 21) | (Rm << 16) | \
 
2221
                (opcode << 13) | (S << 12) | (size << 10) | (Rn << 5) | Rt);
 
2222
}
 
2223
 
 
2224
void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
 
2225
{
 
2226
        _assert_msg_(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __FUNCTION__);
 
2227
        Rd = DecodeReg(Rd);
 
2228
        Rn = DecodeReg(Rn);
 
2229
 
 
2230
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | \
 
2231
                (1 << 14) | (Rn << 5) | Rd);
 
2232
}
 
2233
 
 
2234
void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
 
2235
{
 
2236
        _assert_msg_(DYNA_REC, Rn <= SP, "%s only supports GPR as source!", __FUNCTION__);
 
2237
        Rd = DecodeReg(Rd);
 
2238
        Rn = DecodeReg(Rn);
 
2239
 
 
2240
        Write32((sf << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (rmode << 19) | \
 
2241
                (opcode << 16) | (Rn << 5) | Rd);
 
2242
}
 
2243
 
 
2244
void ARM64FloatEmitter::EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round, bool sign)
 
2245
{
 
2246
        _dbg_assert_msg_(JIT, IsScalar(Rn), "fcvts: Rn must be floating point");
 
2247
        if (IsGPR(Rd)) {
 
2248
                // Use the encoding that transfers the result to a GPR.
 
2249
                bool sf = Is64Bit(Rd);
 
2250
                int type = IsDouble(Rn) ? 1 : 0;
 
2251
                Rd = DecodeReg(Rd);
 
2252
                Rn = DecodeReg(Rn);
 
2253
                int opcode = (sign ? 1 : 0);
 
2254
                int rmode = 0;
 
2255
                switch (round) {
 
2256
                case ROUND_A: rmode = 0; opcode |= 4; break;
 
2257
                case ROUND_P: rmode = 1; break;
 
2258
                case ROUND_M: rmode = 2; break;
 
2259
                case ROUND_Z: rmode = 3; break;
 
2260
                case ROUND_N: rmode = 0; break;
 
2261
                }
 
2262
                EmitConversion2(sf, 0, true, type, rmode, opcode, 0, Rd, Rn);
 
2263
        }
 
2264
        else
 
2265
        {
 
2266
                // Use the encoding (vector, single) that keeps the result in the fp register.
 
2267
                int sz = IsDouble(Rn);
 
2268
                Rd = DecodeReg(Rd);
 
2269
                Rn = DecodeReg(Rn);
 
2270
                int opcode = 0;
 
2271
                switch (round) {
 
2272
                case ROUND_A: opcode = 0x1C; break;
 
2273
                case ROUND_N: opcode = 0x1A; break;
 
2274
                case ROUND_M: opcode = 0x1B; break;
 
2275
                case ROUND_P: opcode = 0x1A; sz |= 2; break;
 
2276
                case ROUND_Z: opcode = 0x1B; sz |= 2; break;
 
2277
                }
 
2278
                Write32((0x5E << 24) | (sign << 29) | (sz << 22) | (1 << 21) | (opcode << 12) | (2 << 10) | (Rn << 5) | Rd);
 
2279
        }
 
2280
}
 
2281
 
 
2282
void ARM64FloatEmitter::FCVTS(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round) {
 
2283
        EmitConvertScalarToInt(Rd, Rn, round, false);
 
2284
}
 
2285
 
 
2286
void ARM64FloatEmitter::FCVTU(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round) {
 
2287
        EmitConvertScalarToInt(Rd, Rn, round, true);
 
2288
}
 
2289
 
 
2290
void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn)
 
2291
{
 
2292
        Rd = DecodeReg(Rd);
 
2293
        Rn = DecodeReg(Rn);
 
2294
 
 
2295
        Write32((sf << 31) | (S << 29) | (0xF0 << 21) | (direction << 21) | (type << 22) | (rmode << 19) | \
 
2296
                (opcode << 16) | (scale << 10) | (Rn << 5) | Rd);
 
2297
}
 
2298
 
 
2299
void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm)
 
2300
{
 
2301
        _assert_msg_(DYNA_REC, !IsQuad(Rn), "%s doesn't support vector!", __FUNCTION__);
 
2302
        bool is_double = IsDouble(Rn);
 
2303
 
 
2304
        Rn = DecodeReg(Rn);
 
2305
        Rm = DecodeReg(Rm);
 
2306
 
 
2307
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | \
 
2308
                (op << 14) | (1 << 13) | (Rn << 5) | opcode2);
 
2309
}
 
2310
 
 
2311
void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2312
{
 
2313
        _assert_msg_(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __FUNCTION__);
 
2314
        bool is_double = IsDouble(Rd);
 
2315
 
 
2316
        Rd = DecodeReg(Rd);
 
2317
        Rn = DecodeReg(Rn);
 
2318
        Rm = DecodeReg(Rm);
 
2319
 
 
2320
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | \
 
2321
                (cond << 12) | (3 << 10) | (Rn << 5) | Rd);
 
2322
}
 
2323
 
 
2324
void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2325
{
 
2326
        _assert_msg_(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__);
 
2327
 
 
2328
        bool quad = IsQuad(Rd);
 
2329
 
 
2330
        u32 encoded_size = 0;
 
2331
        if (size == 16)
 
2332
                encoded_size = 1;
 
2333
        else if (size == 32)
 
2334
                encoded_size = 2;
 
2335
        else if (size == 64)
 
2336
                encoded_size = 3;
 
2337
 
 
2338
        Rd = DecodeReg(Rd);
 
2339
        Rn = DecodeReg(Rn);
 
2340
        Rm = DecodeReg(Rm);
 
2341
 
 
2342
        Write32((quad << 30) | (7 << 25) | (encoded_size << 22) | (Rm << 16) | (op << 12) | \
 
2343
                (1 << 11) | (Rn << 5) | Rd);
 
2344
}
 
2345
 
 
2346
void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8)
 
2347
{
 
2348
        _assert_msg_(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __FUNCTION__);
 
2349
 
 
2350
        bool is_double = !IsSingle(Rd);
 
2351
 
 
2352
        Rd = DecodeReg(Rd);
 
2353
 
 
2354
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (type << 22) | \
 
2355
                (imm8 << 13) | (1 << 12) | (imm5 << 5) | Rd);
 
2356
}
 
2357
 
 
2358
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
 
2359
{
 
2360
        _assert_msg_(DYNA_REC, immh, "%s bad encoding! Can't have zero immh", __FUNCTION__);
 
2361
 
 
2362
        Rd = DecodeReg(Rd);
 
2363
        Rn = DecodeReg(Rn);
 
2364
 
 
2365
        Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | \
 
2366
                (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
 
2367
}
 
2368
 
 
2369
void ARM64FloatEmitter::EmitScalarShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
 
2370
        Rd = DecodeReg(Rd);
 
2371
        Rn = DecodeReg(Rn);
 
2372
 
 
2373
        Write32((2 << 30) | (U << 29) | (0x3E << 23) | (immh << 19) | (immb << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
 
2374
}
 
2375
 
 
2376
void ARM64FloatEmitter::EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn)
 
2377
{
 
2378
        bool quad = IsQuad(Rt);
 
2379
        u32 encoded_size = 0;
 
2380
 
 
2381
        if (size == 16)
 
2382
                encoded_size = 1;
 
2383
        else if (size == 32)
 
2384
                encoded_size = 2;
 
2385
        else if (size == 64)
 
2386
                encoded_size = 3;
 
2387
 
 
2388
        Rt = DecodeReg(Rt);
 
2389
        Rn = DecodeReg(Rn);
 
2390
 
 
2391
        Write32((quad << 30) | (3 << 26) | (L << 22) | (opcode << 12) | \
 
2392
                (encoded_size << 10) | (Rn << 5) | Rt);
 
2393
}
 
2394
 
 
2395
void ARM64FloatEmitter::EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2396
{
 
2397
        bool quad = IsQuad(Rt);
 
2398
        u32 encoded_size = 0;
 
2399
 
 
2400
        if (size == 16)
 
2401
                encoded_size = 1;
 
2402
        else if (size == 32)
 
2403
                encoded_size = 2;
 
2404
        else if (size == 64)
 
2405
                encoded_size = 3;
 
2406
 
 
2407
        Rt = DecodeReg(Rt);
 
2408
        Rn = DecodeReg(Rn);
 
2409
        Rm = DecodeReg(Rm);
 
2410
 
 
2411
        Write32((quad << 30) | (0x19 << 23) | (L << 22) | (Rm << 16) | (opcode << 12) | \
 
2412
                (encoded_size << 10) | (Rn << 5) | Rt);
 
2413
 
 
2414
}
 
2415
 
 
2416
void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
 
2417
{
 
2418
        _assert_msg_(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __FUNCTION__);
 
2419
 
 
2420
        Rd = DecodeReg(Rd);
 
2421
        Rn = DecodeReg(Rn);
 
2422
 
 
2423
        Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | \
 
2424
                (opcode << 15) | (1 << 14) | (Rn << 5) | Rd);
 
2425
}
 
2426
 
 
2427
void ARM64FloatEmitter::EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2428
{
 
2429
        bool quad = IsQuad(Rd);
 
2430
 
 
2431
        Rd = DecodeReg(Rd);
 
2432
        Rn = DecodeReg(Rn);
 
2433
        Rm = DecodeReg(Rm);
 
2434
 
 
2435
        Write32((quad << 30) | (U << 29) | (0xF <<  24) | (size << 22) | (L << 21) | \
 
2436
                (Rm << 16) | (opcode << 12) | (H << 11) | (Rn << 5) | Rd);
 
2437
}
 
2438
 
 
2439
void ARM64FloatEmitter::EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2440
{
 
2441
        _assert_msg_(DYNA_REC, !(imm < -256 || imm > 255), "%s received too large offset: %d", __FUNCTION__, imm);
 
2442
        Rt = DecodeReg(Rt);
 
2443
        Rn = DecodeReg(Rn);
 
2444
 
 
2445
        Write32((size << 30) | (0xF << 26) | (op << 22) | ((imm & 0x1FF) << 12) | (Rn << 5) | Rt);
 
2446
}
 
2447
 
 
2448
void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
2449
{
 
2450
        u32 type_encode = 0;
 
2451
        u32 opc = 0;
 
2452
 
 
2453
        switch (type)
 
2454
        {
 
2455
        case INDEX_SIGNED:
 
2456
                type_encode = 2;
 
2457
                break;
 
2458
        case INDEX_POST:
 
2459
                type_encode = 1;
 
2460
                break;
 
2461
        case INDEX_PRE:
 
2462
                type_encode = 3;
 
2463
                break;
 
2464
        case INDEX_UNSIGNED:
 
2465
                _assert_msg_(DYNA_REC, false, "%s doesn't support INDEX_UNSIGNED!", __FUNCTION__);
 
2466
                break;
 
2467
        }
 
2468
 
 
2469
        if (size == 128)
 
2470
        {
 
2471
                _assert_msg_(DYNA_REC, !(imm & 0xF), "%s received invalid offset 0x%x!", __FUNCTION__, imm);
 
2472
                opc = 2;
 
2473
                imm >>= 4;
 
2474
        }
 
2475
        else if (size == 64)
 
2476
        {
 
2477
                _assert_msg_(DYNA_REC, !(imm & 0x7), "%s received invalid offset 0x%x!", __FUNCTION__, imm);
 
2478
                opc = 1;
 
2479
                imm >>= 3;
 
2480
        }
 
2481
        else if (size == 32)
 
2482
        {
 
2483
                _assert_msg_(DYNA_REC, !(imm & 0x3), "%s received invalid offset 0x%x!", __FUNCTION__, imm);
 
2484
                opc = 0;
 
2485
                imm >>= 2;
 
2486
        }
 
2487
 
 
2488
        Rt = DecodeReg(Rt);
 
2489
        Rt2 = DecodeReg(Rt2);
 
2490
        Rn = DecodeReg(Rn);
 
2491
 
 
2492
        Write32((opc << 30) | (0xB << 26) | (type_encode << 23) | (load << 22) | \
 
2493
                ((imm & 0x7F) << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
 
2494
 
 
2495
}
 
2496
 
 
2497
void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
2498
{
 
2499
        _assert_msg_(DYNA_REC, Rm.GetType() == ArithOption::TYPE_EXTENDEDREG, "%s must contain an extended reg as Rm!", __FUNCTION__);
 
2500
 
 
2501
        u32 encoded_size = 0;
 
2502
        u32 encoded_op = 0;
 
2503
 
 
2504
        if (size == 8)
 
2505
        {
 
2506
                encoded_size = 0;
 
2507
                encoded_op = 0;
 
2508
        }
 
2509
        else if (size == 16)
 
2510
        {
 
2511
                encoded_size = 1;
 
2512
                encoded_op = 0;
 
2513
        }
 
2514
        else if (size == 32)
 
2515
        {
 
2516
                encoded_size = 2;
 
2517
                encoded_op = 0;
 
2518
        }
 
2519
        else if (size == 64)
 
2520
        {
 
2521
                encoded_size = 3;
 
2522
                encoded_op = 0;
 
2523
        }
 
2524
        else if (size == 128)
 
2525
        {
 
2526
                encoded_size = 0;
 
2527
                encoded_op = 2;
 
2528
        }
 
2529
 
 
2530
        if (load)
 
2531
                encoded_op |= 1;
 
2532
 
 
2533
        Rt = DecodeReg(Rt);
 
2534
        Rn = DecodeReg(Rn);
 
2535
        ARM64Reg decoded_Rm = DecodeReg(Rm.GetReg());
 
2536
 
 
2537
        Write32((encoded_size << 30) | (encoded_op << 22) | (0x1E1 << 21) | (decoded_Rm << 16) | \
 
2538
                Rm.GetData() | (1 << 11) | (Rn << 5) | Rt);
 
2539
}
 
2540
 
 
2541
void ARM64FloatEmitter::LDR(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2542
{
 
2543
        EmitLoadStoreImmediate(size, 1, type, Rt, Rn, imm);
 
2544
}
 
2545
void ARM64FloatEmitter::STR(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2546
{
 
2547
        EmitLoadStoreImmediate(size, 0, type, Rt, Rn, imm);
 
2548
}
 
2549
 
 
2550
// Loadstore unscaled
 
2551
void ARM64FloatEmitter::LDUR(u8 size, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2552
{
 
2553
        u32 encoded_size = 0;
 
2554
        u32 encoded_op = 0;
 
2555
 
 
2556
        if (size == 8)
 
2557
        {
 
2558
                encoded_size = 0;
 
2559
                encoded_op = 1;
 
2560
        }
 
2561
        else if (size == 16)
 
2562
        {
 
2563
                encoded_size = 1;
 
2564
                encoded_op = 1;
 
2565
        }
 
2566
        else if (size == 32)
 
2567
        {
 
2568
                encoded_size = 2;
 
2569
                encoded_op = 1;
 
2570
        }
 
2571
        else if (size == 64)
 
2572
        {
 
2573
                encoded_size = 3;
 
2574
                encoded_op = 1;
 
2575
        }
 
2576
        else if (size == 128)
 
2577
        {
 
2578
                encoded_size = 0;
 
2579
                encoded_op = 3;
 
2580
        }
 
2581
 
 
2582
        EmitLoadStoreUnscaled(encoded_size, encoded_op, Rt, Rn, imm);
 
2583
}
 
2584
void ARM64FloatEmitter::STUR(u8 size, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
 
2585
{
 
2586
        u32 encoded_size = 0;
 
2587
        u32 encoded_op = 0;
 
2588
 
 
2589
        if (size == 8)
 
2590
        {
 
2591
                encoded_size = 0;
 
2592
                encoded_op = 0;
 
2593
        }
 
2594
        else if (size == 16)
 
2595
        {
 
2596
                encoded_size = 1;
 
2597
                encoded_op = 0;
 
2598
        }
 
2599
        else if (size == 32)
 
2600
        {
 
2601
                encoded_size = 2;
 
2602
                encoded_op = 0;
 
2603
        }
 
2604
        else if (size == 64)
 
2605
        {
 
2606
                encoded_size = 3;
 
2607
                encoded_op = 0;
 
2608
        }
 
2609
        else if (size == 128)
 
2610
        {
 
2611
                encoded_size = 0;
 
2612
                encoded_op = 2;
 
2613
        }
 
2614
 
 
2615
        EmitLoadStoreUnscaled(encoded_size, encoded_op, Rt, Rn, imm);
 
2616
 
 
2617
}
 
2618
 
 
2619
// Loadstore single structure
 
2620
void ARM64FloatEmitter::LD1(u8 size, ARM64Reg Rt, u8 index, ARM64Reg Rn)
 
2621
{
 
2622
        bool S = 0;
 
2623
        u32 opcode = 0;
 
2624
        u32 encoded_size = 0;
 
2625
        ARM64Reg encoded_reg = INVALID_REG;
 
2626
 
 
2627
        if (size == 8)
 
2628
        {
 
2629
                S = (index & 4) != 0;
 
2630
                opcode = 0;
 
2631
                encoded_size = index & 3;
 
2632
                if (index & 8)
 
2633
                        encoded_reg = EncodeRegToQuad(Rt);
 
2634
                else
 
2635
                        encoded_reg = EncodeRegToDouble(Rt);
 
2636
 
 
2637
        }
 
2638
        else if (size == 16)
 
2639
        {
 
2640
                S = (index & 2) != 0;
 
2641
                opcode = 2;
 
2642
                encoded_size = (index & 1) << 1;
 
2643
                if (index & 4)
 
2644
                        encoded_reg = EncodeRegToQuad(Rt);
 
2645
                else
 
2646
                        encoded_reg = EncodeRegToDouble(Rt);
 
2647
 
 
2648
        }
 
2649
        else if (size == 32)
 
2650
        {
 
2651
                S = (index & 1) != 0;
 
2652
                opcode = 4;
 
2653
                encoded_size = 0;
 
2654
                if (index & 2)
 
2655
                        encoded_reg = EncodeRegToQuad(Rt);
 
2656
                else
 
2657
                        encoded_reg = EncodeRegToDouble(Rt);
 
2658
        }
 
2659
        else if (size == 64)
 
2660
        {
 
2661
                S = 0;
 
2662
                opcode = 4;
 
2663
                encoded_size = 1;
 
2664
                if (index == 1)
 
2665
                        encoded_reg = EncodeRegToQuad(Rt);
 
2666
                else
 
2667
                        encoded_reg = EncodeRegToDouble(Rt);
 
2668
        }
 
2669
 
 
2670
        EmitLoadStoreSingleStructure(1, 0, opcode, S, encoded_size, encoded_reg, Rn);
 
2671
}
 
2672
 
 
2673
void ARM64FloatEmitter::LD1(u8 size, ARM64Reg Rt, u8 index, ARM64Reg Rn, ARM64Reg Rm)
 
2674
{
 
2675
        bool S = 0;
 
2676
        u32 opcode = 0;
 
2677
        u32 encoded_size = 0;
 
2678
        ARM64Reg encoded_reg = INVALID_REG;
 
2679
 
 
2680
        if (size == 8)
 
2681
        {
 
2682
                S = (index & 4) != 0;
 
2683
                opcode = 0;
 
2684
                encoded_size = index & 3;
 
2685
                if (index & 8)
 
2686
                        encoded_reg = EncodeRegToQuad(Rt);
 
2687
                else
 
2688
                        encoded_reg = EncodeRegToDouble(Rt);
 
2689
 
 
2690
        }
 
2691
        else if (size == 16)
 
2692
        {
 
2693
                S = (index & 2) != 0;
 
2694
                opcode = 2;
 
2695
                encoded_size = (index & 1) << 1;
 
2696
                if (index & 4)
 
2697
                        encoded_reg = EncodeRegToQuad(Rt);
 
2698
                else
 
2699
                        encoded_reg = EncodeRegToDouble(Rt);
 
2700
 
 
2701
        }
 
2702
        else if (size == 32)
 
2703
        {
 
2704
                S = (index & 1) != 0;
 
2705
                opcode = 4;
 
2706
                encoded_size = 0;
 
2707
                if (index & 2)
 
2708
                        encoded_reg = EncodeRegToQuad(Rt);
 
2709
                else
 
2710
                        encoded_reg = EncodeRegToDouble(Rt);
 
2711
        }
 
2712
        else if (size == 64)
 
2713
        {
 
2714
                S = 0;
 
2715
                opcode = 4;
 
2716
                encoded_size = 1;
 
2717
                if (index == 1)
 
2718
                        encoded_reg = EncodeRegToQuad(Rt);
 
2719
                else
 
2720
                        encoded_reg = EncodeRegToDouble(Rt);
 
2721
        }
 
2722
 
 
2723
        EmitLoadStoreSingleStructure(1, 0, opcode, S, encoded_size, encoded_reg, Rn, Rm);
 
2724
}
 
2725
 
 
2726
void ARM64FloatEmitter::LD1R(u8 size, ARM64Reg Rt, ARM64Reg Rn)
 
2727
{
 
2728
        EmitLoadStoreSingleStructure(1, 0, 6, 0, size >> 4, Rt, Rn);
 
2729
}
 
2730
void ARM64FloatEmitter::LD2R(u8 size, ARM64Reg Rt, ARM64Reg Rn)
 
2731
{
 
2732
        EmitLoadStoreSingleStructure(1, 1, 6, 0, size >> 4, Rt, Rn);
 
2733
}
 
2734
void ARM64FloatEmitter::LD1R(u8 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2735
{
 
2736
        EmitLoadStoreSingleStructure(1, 0, 6, 0, size >> 4, Rt, Rn, Rm);
 
2737
}
 
2738
void ARM64FloatEmitter::LD2R(u8 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2739
{
 
2740
        EmitLoadStoreSingleStructure(1, 1, 6, 0, size >> 4, Rt, Rn, Rm);
 
2741
}
 
2742
 
 
2743
void ARM64FloatEmitter::ST1(u8 size, ARM64Reg Rt, u8 index, ARM64Reg Rn)
 
2744
{
 
2745
        bool S = 0;
 
2746
        u32 opcode = 0;
 
2747
        u32 encoded_size = 0;
 
2748
        ARM64Reg encoded_reg = INVALID_REG;
 
2749
 
 
2750
        if (size == 8)
 
2751
        {
 
2752
                S = (index & 4) != 0;
 
2753
                opcode = 0;
 
2754
                encoded_size = index & 3;
 
2755
                if (index & 8)
 
2756
                        encoded_reg = EncodeRegToQuad(Rt);
 
2757
                else
 
2758
                        encoded_reg = EncodeRegToDouble(Rt);
 
2759
 
 
2760
        }
 
2761
        else if (size == 16)
 
2762
        {
 
2763
                S = (index & 2) != 0;
 
2764
                opcode = 2;
 
2765
                encoded_size = (index & 1) << 1;
 
2766
                if (index & 4)
 
2767
                        encoded_reg = EncodeRegToQuad(Rt);
 
2768
                else
 
2769
                        encoded_reg = EncodeRegToDouble(Rt);
 
2770
 
 
2771
        }
 
2772
        else if (size == 32)
 
2773
        {
 
2774
                S = (index & 1) != 0;
 
2775
                opcode = 4;
 
2776
                encoded_size = 0;
 
2777
                if (index & 2)
 
2778
                        encoded_reg = EncodeRegToQuad(Rt);
 
2779
                else
 
2780
                        encoded_reg = EncodeRegToDouble(Rt);
 
2781
        }
 
2782
        else if (size == 64)
 
2783
        {
 
2784
                S = 0;
 
2785
                opcode = 4;
 
2786
                encoded_size = 1;
 
2787
                if (index == 1)
 
2788
                        encoded_reg = EncodeRegToQuad(Rt);
 
2789
                else
 
2790
                        encoded_reg = EncodeRegToDouble(Rt);
 
2791
        }
 
2792
 
 
2793
        EmitLoadStoreSingleStructure(0, 0, opcode, S, encoded_size, encoded_reg, Rn);
 
2794
}
 
2795
 
 
2796
void ARM64FloatEmitter::ST1(u8 size, ARM64Reg Rt, u8 index, ARM64Reg Rn, ARM64Reg Rm)
 
2797
{
 
2798
        bool S = 0;
 
2799
        u32 opcode = 0;
 
2800
        u32 encoded_size = 0;
 
2801
        ARM64Reg encoded_reg = INVALID_REG;
 
2802
 
 
2803
        if (size == 8)
 
2804
        {
 
2805
                S = (index & 4) != 0;
 
2806
                opcode = 0;
 
2807
                encoded_size = index & 3;
 
2808
                if (index & 8)
 
2809
                        encoded_reg = EncodeRegToQuad(Rt);
 
2810
                else
 
2811
                        encoded_reg = EncodeRegToDouble(Rt);
 
2812
 
 
2813
        }
 
2814
        else if (size == 16)
 
2815
        {
 
2816
                S = (index & 2) != 0;
 
2817
                opcode = 2;
 
2818
                encoded_size = (index & 1) << 1;
 
2819
                if (index & 4)
 
2820
                        encoded_reg = EncodeRegToQuad(Rt);
 
2821
                else
 
2822
                        encoded_reg = EncodeRegToDouble(Rt);
 
2823
 
 
2824
        }
 
2825
        else if (size == 32)
 
2826
        {
 
2827
                S = (index & 1) != 0;
 
2828
                opcode = 4;
 
2829
                encoded_size = 0;
 
2830
                if (index & 2)
 
2831
                        encoded_reg = EncodeRegToQuad(Rt);
 
2832
                else
 
2833
                        encoded_reg = EncodeRegToDouble(Rt);
 
2834
        }
 
2835
        else if (size == 64)
 
2836
        {
 
2837
                S = 0;
 
2838
                opcode = 4;
 
2839
                encoded_size = 1;
 
2840
                if (index == 1)
 
2841
                        encoded_reg = EncodeRegToQuad(Rt);
 
2842
                else
 
2843
                        encoded_reg = EncodeRegToDouble(Rt);
 
2844
        }
 
2845
 
 
2846
        EmitLoadStoreSingleStructure(0, 0, opcode, S, encoded_size, encoded_reg, Rn, Rm);
 
2847
}
 
2848
 
 
2849
// Loadstore multiple structure
 
2850
void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
 
2851
{
 
2852
        _assert_msg_(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!", __FUNCTION__);
 
2853
        u32 opcode = 0;
 
2854
        if (count == 1)
 
2855
                opcode = 7;
 
2856
        else if (count == 2)
 
2857
                opcode = 0xA;
 
2858
        else if (count == 3)
 
2859
                opcode = 6;
 
2860
        else if (count == 4)
 
2861
                opcode = 2;
 
2862
        EmitLoadStoreMultipleStructure(size, 1, opcode, Rt, Rn);
 
2863
}
 
2864
void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2865
{
 
2866
        _assert_msg_(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!", __FUNCTION__);
 
2867
        _assert_msg_(DYNA_REC, type == INDEX_POST, "%s only supports post indexing!", __FUNCTION__);
 
2868
 
 
2869
        u32 opcode = 0;
 
2870
        if (count == 1)
 
2871
                opcode = 7;
 
2872
        else if (count == 2)
 
2873
                opcode = 0xA;
 
2874
        else if (count == 3)
 
2875
                opcode = 6;
 
2876
        else if (count == 4)
 
2877
                opcode = 2;
 
2878
        EmitLoadStoreMultipleStructurePost(size, 1, opcode, Rt, Rn, Rm);
 
2879
}
 
2880
void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
 
2881
{
 
2882
        _assert_msg_(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!", __FUNCTION__);
 
2883
        u32 opcode = 0;
 
2884
        if (count == 1)
 
2885
                opcode = 7;
 
2886
        else if (count == 2)
 
2887
                opcode = 0xA;
 
2888
        else if (count == 3)
 
2889
                opcode = 6;
 
2890
        else if (count == 4)
 
2891
                opcode = 2;
 
2892
        EmitLoadStoreMultipleStructure(size, 0, opcode, Rt, Rn);
 
2893
}
 
2894
void ARM64FloatEmitter::ST1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
 
2895
{
 
2896
        _assert_msg_(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!", __FUNCTION__);
 
2897
        _assert_msg_(DYNA_REC, type == INDEX_POST, "%s only supports post indexing!", __FUNCTION__);
 
2898
 
 
2899
        u32 opcode = 0;
 
2900
        if (count == 1)
 
2901
                opcode = 7;
 
2902
        else if (count == 2)
 
2903
                opcode = 0xA;
 
2904
        else if (count == 3)
 
2905
                opcode = 6;
 
2906
        else if (count == 4)
 
2907
                opcode = 2;
 
2908
        EmitLoadStoreMultipleStructurePost(size, 0, opcode, Rt, Rn, Rm);
 
2909
}
 
2910
 
 
2911
// Scalar - 1 Source
 
2912
void ARM64FloatEmitter::FMOV(ARM64Reg Rd, ARM64Reg Rn, bool top)
 
2913
{
 
2914
        if (IsScalar(Rd) && IsScalar(Rn)) {
 
2915
                EmitScalar1Source(0, 0, IsDouble(Rd), 0, Rd, Rn);
 
2916
        } else {
 
2917
                _assert_msg_(JIT, !IsQuad(Rd) && !IsQuad(Rn), "FMOV can't move to/from quads");
 
2918
                int rmode = 0;
 
2919
                int opcode = 6;
 
2920
                int sf = 0;
 
2921
                if (IsSingle(Rd) && !Is64Bit(Rn) && !top) {
 
2922
                        // GPR to scalar single
 
2923
                        opcode |= 1;
 
2924
                } else if (!Is64Bit(Rd) && IsSingle(Rn) && !top) {
 
2925
                        // Scalar single to GPR - defaults are correct
 
2926
                } else {
 
2927
                        // TODO
 
2928
                        _assert_msg_(JIT, 0, "FMOV: Unhandled case");
 
2929
                }
 
2930
                Rd = DecodeReg(Rd);
 
2931
                Rn = DecodeReg(Rn);
 
2932
                Write32((sf << 31) | (0x1e2 << 20) | (rmode << 19) | (opcode << 16) | (Rn << 5) | Rd);
 
2933
        }
 
2934
}
 
2935
 
 
2936
// Loadstore paired
 
2937
void ARM64FloatEmitter::LDP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
2938
{
 
2939
        EncodeLoadStorePair(size, true, type, Rt, Rt2, Rn, imm);
 
2940
}
 
2941
void ARM64FloatEmitter::STP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm)
 
2942
{
 
2943
        EncodeLoadStorePair(size, false, type, Rt, Rt2, Rn, imm);
 
2944
}
 
2945
 
 
2946
// Loadstore register offset
 
2947
void ARM64FloatEmitter::STR(u8 size, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
2948
{
 
2949
        EncodeLoadStoreRegisterOffset(size, false, Rt, Rn, Rm);
 
2950
}
 
2951
void ARM64FloatEmitter::LDR(u8 size, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm)
 
2952
{
 
2953
        EncodeLoadStoreRegisterOffset(size, true, Rt, Rn, Rm);
 
2954
}
 
2955
 
 
2956
void ARM64FloatEmitter::FABS(ARM64Reg Rd, ARM64Reg Rn)
 
2957
{
 
2958
        EmitScalar1Source(0, 0, IsDouble(Rd), 1, Rd, Rn);
 
2959
}
 
2960
void ARM64FloatEmitter::FNEG(ARM64Reg Rd, ARM64Reg Rn)
 
2961
{
 
2962
        EmitScalar1Source(0, 0, IsDouble(Rd), 2, Rd, Rn);
 
2963
}
 
2964
void ARM64FloatEmitter::FSQRT(ARM64Reg Rd, ARM64Reg Rn)
 
2965
{
 
2966
        EmitScalar1Source(0, 0, IsDouble(Rd), 3, Rd, Rn);
 
2967
}
 
2968
 
 
2969
 
 
2970
// Scalar - 2 Source
 
2971
void ARM64FloatEmitter::FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2972
{
 
2973
        EmitScalar2Source(0, 0, IsDouble(Rd), 2, Rd, Rn, Rm);
 
2974
}
 
2975
void ARM64FloatEmitter::FMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2976
{
 
2977
        EmitScalar2Source(0, 0, IsDouble(Rd), 0, Rd, Rn, Rm);
 
2978
}
 
2979
void ARM64FloatEmitter::FSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2980
{
 
2981
        EmitScalar2Source(0, 0, IsDouble(Rd), 3, Rd, Rn, Rm);
 
2982
}
 
2983
void ARM64FloatEmitter::FDIV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2984
{
 
2985
        EmitScalar2Source(0, 0, IsDouble(Rd), 1, Rd, Rn, Rm);
 
2986
}
 
2987
void ARM64FloatEmitter::FMAX(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2988
{
 
2989
        EmitScalar2Source(0, 0, IsDouble(Rd), 4, Rd, Rn, Rm);
 
2990
}
 
2991
void ARM64FloatEmitter::FMIN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2992
{
 
2993
        EmitScalar2Source(0, 0, IsDouble(Rd), 5, Rd, Rn, Rm);
 
2994
}
 
2995
void ARM64FloatEmitter::FMAXNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
2996
{
 
2997
        EmitScalar2Source(0, 0, IsDouble(Rd), 6, Rd, Rn, Rm);
 
2998
}
 
2999
void ARM64FloatEmitter::FMINNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3000
{
 
3001
        EmitScalar2Source(0, 0, IsDouble(Rd), 7, Rd, Rn, Rm);
 
3002
}
 
3003
void ARM64FloatEmitter::FNMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3004
{
 
3005
        EmitScalar2Source(0, 0, IsDouble(Rd), 8, Rd, Rn, Rm);
 
3006
}
 
3007
 
 
3008
void ARM64FloatEmitter::FMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
 
3009
        EmitScalar3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 0);
 
3010
}
 
3011
void ARM64FloatEmitter::FMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
 
3012
        EmitScalar3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 1);
 
3013
}
 
3014
void ARM64FloatEmitter::FNMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
 
3015
        EmitScalar3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 2);
 
3016
}
 
3017
void ARM64FloatEmitter::FNMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
 
3018
        EmitScalar3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 3);
 
3019
}
 
3020
 
 
3021
void ARM64FloatEmitter::EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode) {
 
3022
        int type = isDouble ? 1 : 0;
 
3023
        Rd = DecodeReg(Rd);
 
3024
        Rn = DecodeReg(Rn);
 
3025
        Rm = DecodeReg(Rm);
 
3026
        Ra = DecodeReg(Ra);
 
3027
        int o1 = opcode >> 1;
 
3028
        int o0 = opcode & 1;
 
3029
        m_emit->Write32((0x1F << 24) | (type << 22) | (o1 << 21) | (Rm << 16) | (o0 << 15) | (Ra << 10) | (Rn << 5) | Rd);
 
3030
}
 
3031
 
 
3032
// Scalar floating point immediate
 
3033
void ARM64FloatEmitter::FMOV(ARM64Reg Rd, uint8_t imm8)
 
3034
{
 
3035
        EmitScalarImm(0, 0, 0, 0, Rd, imm8);
 
3036
}
 
3037
 
 
3038
// Vector
 
3039
void ARM64FloatEmitter::AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3040
{
 
3041
        EmitThreeSame(0, 0, 3, Rd, Rn, Rm);
 
3042
}
 
3043
void ARM64FloatEmitter::EOR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3044
{
 
3045
        EmitThreeSame(1, 0, 3, Rd, Rn, Rm);
 
3046
}
 
3047
void ARM64FloatEmitter::BSL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3048
{
 
3049
        EmitThreeSame(1, 1, 3, Rd, Rn, Rm);
 
3050
}
 
3051
void ARM64FloatEmitter::DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
 
3052
{
 
3053
        u32 imm5 = 0;
 
3054
 
 
3055
        if (size == 8)
 
3056
        {
 
3057
                imm5 = 1;
 
3058
                imm5 |= index << 1;
 
3059
        }
 
3060
        else if (size == 16)
 
3061
        {
 
3062
                imm5 = 2;
 
3063
                imm5 |= index << 2;
 
3064
        }
 
3065
        else if (size == 32)
 
3066
        {
 
3067
                imm5 = 4;
 
3068
                imm5 |= index << 3;
 
3069
        }
 
3070
        else if (size == 64)
 
3071
        {
 
3072
                imm5 = 8;
 
3073
                imm5 |= index << 4;
 
3074
        }
 
3075
 
 
3076
        EmitCopy(IsQuad(Rd), 0, imm5, 0, Rd, Rn);
 
3077
}
 
3078
void ARM64FloatEmitter::FABS(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3079
{
 
3080
        Emit2RegMisc(IsQuad(Rd), 0, 2 | (size >> 6), 0xF, Rd, Rn);
 
3081
}
 
3082
void ARM64FloatEmitter::FADD(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3083
{
 
3084
        EmitThreeSame(0, size >> 6, 0x1A, Rd, Rn, Rm);
 
3085
}
 
3086
void ARM64FloatEmitter::FMAX(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3087
{
 
3088
        EmitThreeSame(0, size >> 6, 0x1E, Rd, Rn, Rm);
 
3089
}
 
3090
void ARM64FloatEmitter::FMLA(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3091
{
 
3092
        EmitThreeSame(0, size >> 6, 0x19, Rd, Rn, Rm);
 
3093
}
 
3094
void ARM64FloatEmitter::FMIN(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3095
{
 
3096
        EmitThreeSame(0, 2 | size >> 6, 0x1E, Rd, Rn, Rm);
 
3097
}
 
3098
void ARM64FloatEmitter::FCVTL(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3099
{
 
3100
        Emit2RegMisc(false, 0, size >> 6, 0x17, Rd, Rn);
 
3101
}
 
3102
void ARM64FloatEmitter::FCVTL2(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3103
{
 
3104
        Emit2RegMisc(true, 0, size >> 6, 0x17, Rd, Rn);
 
3105
}
 
3106
void ARM64FloatEmitter::FCVTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3107
{
 
3108
        Emit2RegMisc(IsQuad(Rd), 0, dest_size >> 5, 0x16, Rd, Rn);
 
3109
}
 
3110
void ARM64FloatEmitter::FCVTZS(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3111
{
 
3112
        Emit2RegMisc(IsQuad(Rd), 0, 2 | (size >> 6), 0x1B, Rd, Rn);
 
3113
}
 
3114
void ARM64FloatEmitter::FCVTZU(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3115
{
 
3116
        Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0x1B, Rd, Rn);
 
3117
}
 
3118
void ARM64FloatEmitter::FDIV(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3119
{
 
3120
        EmitThreeSame(1, size >> 6, 0x1F, Rd, Rn, Rm);
 
3121
}
 
3122
void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3123
{
 
3124
        EmitThreeSame(1, size >> 6, 0x1B, Rd, Rn, Rm);
 
3125
}
 
3126
void ARM64FloatEmitter::UMIN(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3127
{
 
3128
        EmitThreeSame(1, EncodeSize(size), 0xD, Rd, Rn, Rm);
 
3129
}
 
3130
void ARM64FloatEmitter::UMAX(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3131
{
 
3132
        EmitThreeSame(1, EncodeSize(size), 0xC, Rd, Rn, Rm);
 
3133
}
 
3134
void ARM64FloatEmitter::SMIN(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3135
{
 
3136
        EmitThreeSame(0, EncodeSize(size), 0xD, Rd, Rn, Rm);
 
3137
}
 
3138
void ARM64FloatEmitter::SMAX(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3139
{
 
3140
        EmitThreeSame(0, EncodeSize(size), 0xC, Rd, Rn, Rm);
 
3141
}
 
3142
void ARM64FloatEmitter::FNEG(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3143
{
 
3144
        Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0xF, Rd, Rn);
 
3145
}
 
3146
void ARM64FloatEmitter::FRSQRTE(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3147
{
 
3148
        Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0x1D, Rd, Rn);
 
3149
}
 
3150
void ARM64FloatEmitter::FSUB(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3151
{
 
3152
        EmitThreeSame(0, 2 | (size >> 6), 0x1A, Rd, Rn, Rm);
 
3153
}
 
3154
void ARM64FloatEmitter::FMLS(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3155
{
 
3156
        EmitThreeSame(0, 2 | (size >> 6), 0x19, Rd, Rn, Rm);
 
3157
}
 
3158
void ARM64FloatEmitter::NOT(ARM64Reg Rd, ARM64Reg Rn)
 
3159
{
 
3160
        Emit2RegMisc(IsQuad(Rd), 1, 0, 5, Rd, Rn);
 
3161
}
 
3162
void ARM64FloatEmitter::ORR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3163
{
 
3164
        EmitThreeSame(0, 2, 3, Rd, Rn, Rm);
 
3165
}
 
3166
void ARM64FloatEmitter::REV16(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3167
{
 
3168
        Emit2RegMisc(IsQuad(Rd), 0, size >> 4, 1, Rd, Rn);
 
3169
}
 
3170
void ARM64FloatEmitter::REV32(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3171
{
 
3172
        Emit2RegMisc(IsQuad(Rd), 1, size >> 4, 0, Rd, Rn);
 
3173
}
 
3174
void ARM64FloatEmitter::REV64(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3175
{
 
3176
        Emit2RegMisc(IsQuad(Rd), 0, size >> 4, 0, Rd, Rn);
 
3177
}
 
3178
void ARM64FloatEmitter::SCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3179
{
 
3180
        Emit2RegMisc(IsQuad(Rd), 0, size >> 6, 0x1D, Rd, Rn);
 
3181
}
 
3182
void ARM64FloatEmitter::UCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3183
{
 
3184
        Emit2RegMisc(IsQuad(Rd), 1, size >> 6, 0x1D, Rd, Rn);
 
3185
}
 
3186
void ARM64FloatEmitter::SCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale)
 
3187
{
 
3188
        int imm = size * 2 - scale;
 
3189
        EmitShiftImm(IsQuad(Rd), 0, imm >> 3, imm & 7, 0x1C, Rd, Rn);
 
3190
}
 
3191
void ARM64FloatEmitter::UCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale)
 
3192
{
 
3193
        int imm = size * 2 - scale;
 
3194
        EmitShiftImm(IsQuad(Rd), 1, imm >> 3, imm & 7, 0x1C, Rd, Rn);
 
3195
}
 
3196
void ARM64FloatEmitter::SQXTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3197
{
 
3198
        Emit2RegMisc(false, 0, dest_size >> 4, 0x14, Rd, Rn);
 
3199
}
 
3200
void ARM64FloatEmitter::SQXTN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3201
{
 
3202
        Emit2RegMisc(true, 0, dest_size >> 4, 0x14, Rd, Rn);
 
3203
}
 
3204
void ARM64FloatEmitter::UQXTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3205
{
 
3206
        Emit2RegMisc(false, 1, dest_size >> 4, 0x14, Rd, Rn);
 
3207
}
 
3208
void ARM64FloatEmitter::UQXTN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3209
{
 
3210
        Emit2RegMisc(true, 1, dest_size >> 4, 0x14, Rd, Rn);
 
3211
}
 
3212
void ARM64FloatEmitter::XTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3213
{
 
3214
        Emit2RegMisc(false, 0, dest_size >> 4, 0x12, Rd, Rn);
 
3215
}
 
3216
void ARM64FloatEmitter::XTN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn)
 
3217
{
 
3218
        Emit2RegMisc(true, 0, dest_size >> 4, 0x12, Rd, Rn);
 
3219
}
 
3220
 
 
3221
// Move
 
3222
void ARM64FloatEmitter::DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3223
{
 
3224
        u32 imm5 = 0;
 
3225
 
 
3226
        if (size == 8)
 
3227
                imm5 = 1;
 
3228
        else if (size == 16)
 
3229
                imm5 = 2;
 
3230
        else if (size == 32)
 
3231
                imm5 = 4;
 
3232
        else if (size == 64)
 
3233
                imm5 = 8;
 
3234
 
 
3235
        EmitCopy(IsQuad(Rd), 0, imm5, 1, Rd, Rn);
 
3236
 
 
3237
}
 
3238
void ARM64FloatEmitter::INS(u8 size, ARM64Reg Rd, u8 index, ARM64Reg Rn)
 
3239
{
 
3240
        u32 imm5 = 0;
 
3241
 
 
3242
        if (size == 8)
 
3243
        {
 
3244
                imm5 = 1;
 
3245
                imm5 |= index << 1;
 
3246
        }
 
3247
        else if (size == 16)
 
3248
        {
 
3249
                imm5 = 2;
 
3250
                imm5 |= index << 2;
 
3251
        }
 
3252
        else if (size == 32)
 
3253
        {
 
3254
                imm5 = 4;
 
3255
                imm5 |= index << 3;
 
3256
        }
 
3257
        else if (size == 64)
 
3258
        {
 
3259
                imm5 = 8;
 
3260
                imm5 |= index << 4;
 
3261
        }
 
3262
 
 
3263
        EmitCopy(1, 0, imm5, 3, Rd, Rn);
 
3264
}
 
3265
void ARM64FloatEmitter::INS(u8 size, ARM64Reg Rd, u8 index1, ARM64Reg Rn, u8 index2)
 
3266
{
 
3267
        u32 imm5 = 0, imm4 = 0;
 
3268
 
 
3269
        if (size == 8)
 
3270
        {
 
3271
                imm5 = 1;
 
3272
                imm5 |= index1 << 1;
 
3273
                imm4 = index2;
 
3274
        }
 
3275
        else if (size == 16)
 
3276
        {
 
3277
                imm5 = 2;
 
3278
                imm5 |= index1 << 2;
 
3279
                imm4 = index2 << 1;
 
3280
        }
 
3281
        else if (size == 32)
 
3282
        {
 
3283
                imm5 = 4;
 
3284
                imm5 |= index1 << 3;
 
3285
                imm4 = index2 << 2;
 
3286
        }
 
3287
        else if (size == 64)
 
3288
        {
 
3289
                imm5 = 8;
 
3290
                imm5 |= index1 << 4;
 
3291
                imm4 = index2 << 3;
 
3292
        }
 
3293
 
 
3294
        EmitCopy(1, 1, imm5, imm4, Rd, Rn);
 
3295
}
 
3296
 
 
3297
void ARM64FloatEmitter::UMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
 
3298
{
 
3299
        bool b64Bit = Is64Bit(Rd);
 
3300
        _assert_msg_(DYNA_REC, Rd < SP, "%s destination must be a GPR!", __FUNCTION__);
 
3301
        _assert_msg_(DYNA_REC, !(b64Bit && size != 64), "%s must have a size of 64 when destination is 64bit!", __FUNCTION__);
 
3302
        u32 imm5 = 0;
 
3303
 
 
3304
        if (size == 8)
 
3305
        {
 
3306
                imm5 = 1;
 
3307
                imm5 |= index << 1;
 
3308
        }
 
3309
        else if (size == 16)
 
3310
        {
 
3311
                imm5 = 2;
 
3312
                imm5 |= index << 2;
 
3313
        }
 
3314
        else if (size == 32)
 
3315
        {
 
3316
                imm5 = 4;
 
3317
                imm5 |= index << 3;
 
3318
        }
 
3319
        else if (size == 64)
 
3320
        {
 
3321
                imm5 = 8;
 
3322
                imm5 |= index << 4;
 
3323
        }
 
3324
 
 
3325
        EmitCopy(b64Bit, 0, imm5, 7, Rd, Rn);
 
3326
}
 
3327
void ARM64FloatEmitter::SMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
 
3328
{
 
3329
        bool b64Bit = Is64Bit(Rd);
 
3330
        _assert_msg_(DYNA_REC, Rd < SP, "%s destination must be a GPR!", __FUNCTION__);
 
3331
        _assert_msg_(DYNA_REC, size != 64, "%s doesn't support 64bit destination. Use UMOV!", __FUNCTION__);
 
3332
        u32 imm5 = 0;
 
3333
 
 
3334
        if (size == 8)
 
3335
        {
 
3336
                imm5 = 1;
 
3337
                imm5 |= index << 1;
 
3338
        }
 
3339
        else if (size == 16)
 
3340
        {
 
3341
                imm5 = 2;
 
3342
                imm5 |= index << 2;
 
3343
        }
 
3344
        else if (size == 32)
 
3345
        {
 
3346
                imm5 = 4;
 
3347
                imm5 |= index << 3;
 
3348
        }
 
3349
 
 
3350
        EmitCopy(b64Bit, 0, imm5, 5, Rd, Rn);
 
3351
}
 
3352
 
 
3353
// One source
 
3354
void ARM64FloatEmitter::FCVT(u8 size_to, u8 size_from, ARM64Reg Rd, ARM64Reg Rn)
 
3355
{
 
3356
        u32 dst_encoding = 0;
 
3357
        u32 src_encoding = 0;
 
3358
 
 
3359
        if (size_to == 16)
 
3360
                dst_encoding = 3;
 
3361
        else if (size_to == 32)
 
3362
                dst_encoding = 0;
 
3363
        else if (size_to == 64)
 
3364
                dst_encoding = 1;
 
3365
 
 
3366
        if (size_from == 16)
 
3367
                src_encoding = 3;
 
3368
        else if (size_from == 32)
 
3369
                src_encoding = 0;
 
3370
        else if (size_from == 64)
 
3371
                src_encoding = 1;
 
3372
 
 
3373
        Emit1Source(0, 0, src_encoding, 4 | dst_encoding, Rd, Rn);
 
3374
}
 
3375
 
 
3376
void ARM64FloatEmitter::SCVTF(ARM64Reg Rd, ARM64Reg Rn)
 
3377
{
 
3378
        if (IsScalar(Rn)) {
 
3379
                // Source is in FP register (like destination!). We must use a vector encoding.
 
3380
                bool sign = false;
 
3381
                Rd = DecodeReg(Rd);
 
3382
                Rn = DecodeReg(Rn);
 
3383
                int sz = IsDouble(Rn);
 
3384
                Write32((0x5e << 24) | (sign << 29) | (sz << 22) | (0x876 << 10) | (Rn << 5) | Rd);
 
3385
        } else {
 
3386
                bool sf = Is64Bit(Rn);
 
3387
                u32 type = 0;
 
3388
                if (IsDouble(Rd))
 
3389
                        type = 1;
 
3390
                EmitConversion(sf, 0, type, 0, 2, Rd, Rn);
 
3391
        }
 
3392
}
 
3393
 
 
3394
void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn)
 
3395
{
 
3396
        if (IsScalar(Rn)) {
 
3397
                // Source is in FP register (like destination!). We must use a vector encoding.
 
3398
                bool sign = true;
 
3399
                Rd = DecodeReg(Rd);
 
3400
                Rn = DecodeReg(Rn);
 
3401
                int sz = IsDouble(Rn);
 
3402
                Write32((0x5e << 24) | (sign << 29) | (sz << 22) | (0x876 << 10) | (Rn << 5) | Rd);
 
3403
        } else {
 
3404
                bool sf = Is64Bit(Rn);
 
3405
                u32 type = 0;
 
3406
                if (IsDouble(Rd))
 
3407
                        type = 1;
 
3408
 
 
3409
                EmitConversion(sf, 0, type, 0, 3, Rd, Rn);
 
3410
        }
 
3411
}
 
3412
 
 
3413
void ARM64FloatEmitter::SCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale)
 
3414
{
 
3415
        bool sf = Is64Bit(Rn);
 
3416
        u32 type = 0;
 
3417
        if (IsDouble(Rd))
 
3418
                type = 1;
 
3419
 
 
3420
        EmitConversion2(sf, 0, false, type, 0, 2, 64 - scale, Rd, Rn);
 
3421
}
 
3422
 
 
3423
void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale)
 
3424
{
 
3425
        bool sf = Is64Bit(Rn);
 
3426
        u32 type = 0;
 
3427
        if (IsDouble(Rd))
 
3428
                type = 1;
 
3429
 
 
3430
        EmitConversion2(sf, 0, false, type, 0, 3, 64 - scale, Rd, Rn);
 
3431
}
 
3432
 
 
3433
void ARM64FloatEmitter::FCMP(ARM64Reg Rn, ARM64Reg Rm)
 
3434
{
 
3435
        EmitCompare(0, 0, 0, 0, Rn, Rm);
 
3436
}
 
3437
void ARM64FloatEmitter::FCMP(ARM64Reg Rn)
 
3438
{
 
3439
        EmitCompare(0, 0, 0, 8, Rn, (ARM64Reg)0);
 
3440
}
 
3441
void ARM64FloatEmitter::FCMPE(ARM64Reg Rn, ARM64Reg Rm)
 
3442
{
 
3443
        EmitCompare(0, 0, 0, 0x10, Rn, Rm);
 
3444
}
 
3445
void ARM64FloatEmitter::FCMPE(ARM64Reg Rn)
 
3446
{
 
3447
        EmitCompare(0, 0, 0, 0x18, Rn, (ARM64Reg)0);
 
3448
}
 
3449
void ARM64FloatEmitter::FCMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3450
{
 
3451
        EmitThreeSame(0, size >> 6, 0x1C, Rd, Rn, Rm);
 
3452
}
 
3453
void ARM64FloatEmitter::FCMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3454
{
 
3455
        Emit2RegMisc(IsQuad(Rd), 0, 2 | (size >> 6), 0xD, Rd, Rn);
 
3456
}
 
3457
void ARM64FloatEmitter::FCMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3458
{
 
3459
        EmitThreeSame(1, size >> 6, 0x1C, Rd, Rn, Rm);
 
3460
}
 
3461
void ARM64FloatEmitter::FCMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3462
{
 
3463
        Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0xC, Rd, Rn);
 
3464
}
 
3465
void ARM64FloatEmitter::FCMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3466
{
 
3467
        EmitThreeSame(1, 2 | (size >> 6), 0x1C, Rd, Rn, Rm);
 
3468
}
 
3469
void ARM64FloatEmitter::FCMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3470
{
 
3471
        Emit2RegMisc(IsQuad(Rd), 0, 2 | (size >> 6), 0x0C, Rd, Rn);
 
3472
}
 
3473
void ARM64FloatEmitter::FCMLE(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3474
{
 
3475
        Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0xD, Rd, Rn);
 
3476
}
 
3477
void ARM64FloatEmitter::FCMLT(u8 size, ARM64Reg Rd, ARM64Reg Rn)
 
3478
{
 
3479
        Emit2RegMisc(IsQuad(Rd), 0, 2 | (size >> 6), 0xE, Rd, Rn);
 
3480
}
 
3481
 
 
3482
void ARM64FloatEmitter::FCSEL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond)
 
3483
{
 
3484
        EmitCondSelect(0, 0, cond, Rd, Rn, Rm);
 
3485
}
 
3486
 
 
3487
// Permute
 
3488
void ARM64FloatEmitter::UZP1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3489
{
 
3490
        EmitPermute(size, 1, Rd, Rn, Rm);
 
3491
}
 
3492
void ARM64FloatEmitter::TRN1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3493
{
 
3494
        EmitPermute(size, 2, Rd, Rn, Rm);
 
3495
}
 
3496
void ARM64FloatEmitter::ZIP1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3497
{
 
3498
        EmitPermute(size, 3, Rd, Rn, Rm);
 
3499
}
 
3500
void ARM64FloatEmitter::UZP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3501
{
 
3502
        EmitPermute(size, 5, Rd, Rn, Rm);
 
3503
}
 
3504
void ARM64FloatEmitter::TRN2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3505
{
 
3506
        EmitPermute(size, 6, Rd, Rn, Rm);
 
3507
}
 
3508
void ARM64FloatEmitter::ZIP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
 
3509
{
 
3510
        EmitPermute(size, 7, Rd, Rn, Rm);
 
3511
}
 
3512
 
 
3513
// Shift by immediate
 
3514
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3515
{
 
3516
        SSHLL(src_size, Rd, Rn, shift, false);
 
3517
}
 
3518
void ARM64FloatEmitter::SSHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3519
{
 
3520
        SSHLL(src_size, Rd, Rn, shift, true);
 
3521
}
 
3522
void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3523
{
 
3524
        SHRN(dest_size, Rd, Rn, shift, false);
 
3525
}
 
3526
void ARM64FloatEmitter::SHRN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3527
{
 
3528
        SHRN(dest_size, Rd, Rn, shift, true);
 
3529
}
 
3530
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3531
{
 
3532
        USHLL(src_size, Rd, Rn, shift, false);
 
3533
}
 
3534
void ARM64FloatEmitter::USHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
 
3535
{
 
3536
        USHLL(src_size, Rd, Rn, shift, true);
 
3537
}
 
3538
void ARM64FloatEmitter::SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
 
3539
{
 
3540
        SXTL(src_size, Rd, Rn, false);
 
3541
}
 
3542
void ARM64FloatEmitter::SXTL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
 
3543
{
 
3544
        SXTL(src_size, Rd, Rn, true);
 
3545
}
 
3546
void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
 
3547
{
 
3548
        UXTL(src_size, Rd, Rn, false);
 
3549
}
 
3550
void ARM64FloatEmitter::UXTL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
 
3551
{
 
3552
        UXTL(src_size, Rd, Rn, true);
 
3553
}
 
3554
 
 
3555
static u32 EncodeImmShiftLeft(u8 src_size, u32 shift) {
 
3556
        return src_size + shift;
 
3557
}
 
3558
 
 
3559
static u32 EncodeImmShiftRight(u8 src_size, u32 shift) {
 
3560
        return src_size * 2 - shift;
 
3561
}
 
3562
 
 
3563
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
 
3564
{
 
3565
        _assert_msg_(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!", __FUNCTION__);
 
3566
        u32 imm = EncodeImmShiftLeft(src_size, shift);
 
3567
        EmitShiftImm(upper, 0, imm >> 3, imm & 7, 0x14, Rd, Rn);
 
3568
}
 
3569
 
 
3570
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
 
3571
{
 
3572
        _assert_msg_(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!", __FUNCTION__);
 
3573
        u32 imm = EncodeImmShiftLeft(src_size, shift);
 
3574
        EmitShiftImm(upper, 1, imm >> 3, imm & 7, 0x14, Rd, Rn);
 
3575
}
 
3576
 
 
3577
void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
 
3578
{
 
3579
        _assert_msg_(DYNA_REC, shift > 0, "%s shift amount must be greater than zero!", __FUNCTION__);
 
3580
        _assert_msg_(DYNA_REC, shift <= dest_size, "%s shift amount must less than or equal to the element size!", __FUNCTION__);
 
3581
        u32 imm = EncodeImmShiftRight(dest_size, shift);
 
3582
        EmitShiftImm(upper, 0, imm >> 3, imm & 7, 0x10, Rd, Rn);
 
3583
}
 
3584
 
 
3585
void ARM64FloatEmitter::SHL(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift) {
 
3586
        _assert_msg_(DYNA_REC, shift < dest_size, "%s shift amount must less than the element size!", __FUNCTION__);
 
3587
        u32 imm = EncodeImmShiftLeft(dest_size, shift);
 
3588
        EmitShiftImm(IsQuad(Rd), false, imm >> 3, imm & 7, 0xA, Rd, Rn);
 
3589
}
 
3590
 
 
3591
void ARM64FloatEmitter::USHR(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift) {
 
3592
        _assert_msg_(DYNA_REC, shift < dest_size, "%s shift amount must less than the element size!", __FUNCTION__);
 
3593
        u32 imm = EncodeImmShiftRight(dest_size, shift);
 
3594
        EmitShiftImm(IsQuad(Rd), true, imm >> 3, imm & 7, 0x0, Rd, Rn);
 
3595
}
 
3596
 
 
3597
void ARM64FloatEmitter::SSHR(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift) {
 
3598
        _assert_msg_(DYNA_REC, shift < dest_size, "%s shift amount must less than the element size!", __FUNCTION__);
 
3599
        u32 imm = EncodeImmShiftRight(dest_size, shift);
 
3600
        EmitShiftImm(IsQuad(Rd), false, imm >> 3, imm & 7, 0x0, Rd, Rn);
 
3601
}
 
3602
 
 
3603
void ARM64FloatEmitter::SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper)
 
3604
{
 
3605
        SSHLL(src_size, Rd, Rn, 0, upper);
 
3606
}
 
3607
 
 
3608
void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper)
 
3609
{
 
3610
        USHLL(src_size, Rd, Rn, 0, upper);
 
3611
}
 
3612
 
 
3613
// vector x indexed element
 
3614
void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
 
3615
{
 
3616
        _assert_msg_(DYNA_REC, size == 32 || size == 64, "%s only supports 32bit or 64bit size!", __FUNCTION__);
 
3617
 
 
3618
        bool L = false;
 
3619
        bool H = false;
 
3620
        if (size == 32) {
 
3621
                L = index & 1;
 
3622
                H = (index >> 1) & 1;
 
3623
        } else if (size == 64) {
 
3624
                H = index == 1;
 
3625
        }
 
3626
 
 
3627
        EmitVectorxElement(0, 2 | (size >> 6), L, 0x9, H, Rd, Rn, Rm);
 
3628
}
 
3629
 
 
3630
void ARM64FloatEmitter::FMLA(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
 
3631
{
 
3632
        _assert_msg_(DYNA_REC, size == 32 || size == 64, "%s only supports 32bit or 64bit size!", __FUNCTION__);
 
3633
 
 
3634
        bool L = false;
 
3635
        bool H = false;
 
3636
        if (size == 32) {
 
3637
                L = index & 1;
 
3638
                H = (index >> 1) & 1;
 
3639
        } else if (size == 64) {
 
3640
                H = index == 1;
 
3641
        }
 
3642
 
 
3643
        EmitVectorxElement(0, 2 | (size >> 6), L, 1, H, Rd, Rn, Rm);
 
3644
}
 
3645
 
 
3646
void ARM64FloatEmitter::ABI_PushRegisters(BitSet32 registers, ARM64Reg tmp)
 
3647
{
 
3648
        bool bundled_loadstore = false;
 
3649
 
 
3650
        for (int i = 0; i < 32; ++i)
 
3651
        {
 
3652
                if (!registers[i])
 
3653
                        continue;
 
3654
 
 
3655
                int count = 0;
 
3656
                while (++count < 4 && (i + count) < 32 && registers[i + count]) {}
 
3657
                if (count > 1)
 
3658
                {
 
3659
                        bundled_loadstore = true;
 
3660
                        break;
 
3661
                }
 
3662
        }
 
3663
 
 
3664
        if (bundled_loadstore && tmp != INVALID_REG)
 
3665
        {
 
3666
                int num_regs = registers.Count();
 
3667
                m_emit->SUB(SP, SP, num_regs * 16);
 
3668
                m_emit->ADD(tmp, SP, 0);
 
3669
                std::vector<ARM64Reg> island_regs;
 
3670
                for (int i = 0; i < 32; ++i)
 
3671
                {
 
3672
                        if (!registers[i])
 
3673
                                continue;
 
3674
 
 
3675
                        int count = 0;
 
3676
 
 
3677
                        // 0 = true
 
3678
                        // 1 < 4 && registers[i + 1] true!
 
3679
                        // 2 < 4 && registers[i + 2] true!
 
3680
                        // 3 < 4 && registers[i + 3] true!
 
3681
                        // 4 < 4 && registers[i + 4] false!
 
3682
                        while (++count < 4 && (i + count) < 32 && registers[i + count]) {}
 
3683
 
 
3684
                        if (count == 1)
 
3685
                                island_regs.push_back((ARM64Reg)(Q0 + i));
 
3686
                        else
 
3687
                                ST1(64, count, INDEX_POST, (ARM64Reg)(Q0 + i), tmp);
 
3688
 
 
3689
                        i += count - 1;
 
3690
                }
 
3691
 
 
3692
                // Handle island registers
 
3693
                std::vector<ARM64Reg> pair_regs;
 
3694
                for (auto& it : island_regs)
 
3695
                {
 
3696
                        pair_regs.push_back(it);
 
3697
                        if (pair_regs.size() == 2)
 
3698
                        {
 
3699
                                STP(128, INDEX_POST, pair_regs[0], pair_regs[1], tmp, 32);
 
3700
                                pair_regs.clear();
 
3701
                        }
 
3702
                }
 
3703
                if (pair_regs.size())
 
3704
                        STR(128, INDEX_POST, pair_regs[0], tmp, 16);
 
3705
        }
 
3706
        else
 
3707
        {
 
3708
                std::vector<ARM64Reg> pair_regs;
 
3709
                for (auto it : registers)
 
3710
                {
 
3711
                        pair_regs.push_back((ARM64Reg)(Q0 + it));
 
3712
                        if (pair_regs.size() == 2)
 
3713
                        {
 
3714
                                STP(128, INDEX_PRE, pair_regs[0], pair_regs[1], SP, -32);
 
3715
                                pair_regs.clear();
 
3716
                        }
 
3717
                }
 
3718
                if (pair_regs.size())
 
3719
                        STR(128, INDEX_PRE, pair_regs[0], SP, -16);
 
3720
        }
 
3721
}
 
3722
void ARM64FloatEmitter::ABI_PopRegisters(BitSet32 registers, ARM64Reg tmp)
 
3723
{
 
3724
        bool bundled_loadstore = false;
 
3725
        int num_regs = registers.Count();
 
3726
 
 
3727
        for (int i = 0; i < 32; ++i)
 
3728
        {
 
3729
                if (!registers[i])
 
3730
                        continue;
 
3731
 
 
3732
                int count = 0;
 
3733
                while (++count < 4 && (i + count) < 32 && registers[i + count]) {}
 
3734
                if (count > 1)
 
3735
                {
 
3736
                        bundled_loadstore = true;
 
3737
                        break;
 
3738
                }
 
3739
        }
 
3740
 
 
3741
        if (bundled_loadstore && tmp != INVALID_REG)
 
3742
        {
 
3743
                // The temporary register is only used to indicate that we can use this code path
 
3744
                std::vector<ARM64Reg> island_regs;
 
3745
                for (int i = 0; i < 32; ++i)
 
3746
                {
 
3747
                        if (!registers[i])
 
3748
                                continue;
 
3749
 
 
3750
                        int count = 0;
 
3751
                        while (++count < 4 && (i + count) < 32 && registers[i + count]) {}
 
3752
 
 
3753
                        if (count == 1)
 
3754
                                island_regs.push_back((ARM64Reg)(Q0 + i));
 
3755
                        else
 
3756
                                LD1(64, count, INDEX_POST, (ARM64Reg)(Q0 + i), SP);
 
3757
 
 
3758
                        i += count - 1;
 
3759
                }
 
3760
 
 
3761
                // Handle island registers
 
3762
                std::vector<ARM64Reg> pair_regs;
 
3763
                for (auto& it : island_regs)
 
3764
                {
 
3765
                        pair_regs.push_back(it);
 
3766
                        if (pair_regs.size() == 2)
 
3767
                        {
 
3768
                                LDP(128, INDEX_POST, pair_regs[0], pair_regs[1], SP, 32);
 
3769
                                pair_regs.clear();
 
3770
                        }
 
3771
                }
 
3772
                if (pair_regs.size())
 
3773
                        LDR(128, INDEX_POST, pair_regs[0], SP, 16);
 
3774
        }
 
3775
        else
 
3776
        {
 
3777
                bool odd = (num_regs % 2) != 0;
 
3778
                std::vector<ARM64Reg> pair_regs;
 
3779
                for (int i = 31; i >= 0; --i)
 
3780
                {
 
3781
                        if (!registers[i])
 
3782
                                continue;
 
3783
 
 
3784
                        if (odd)
 
3785
                        {
 
3786
                                // First load must be a regular LDR if odd
 
3787
                                odd = false;
 
3788
                                LDR(128, INDEX_POST, (ARM64Reg)(Q0 + i), SP, 16);
 
3789
                        }
 
3790
                        else
 
3791
                        {
 
3792
                                pair_regs.push_back((ARM64Reg)(Q0 + i));
 
3793
                                if (pair_regs.size() == 2)
 
3794
                                {
 
3795
                                        LDP(128, INDEX_POST, pair_regs[1], pair_regs[0], SP, 32);
 
3796
                                        pair_regs.clear();
 
3797
                                }
 
3798
                        }
 
3799
                }
 
3800
        }
 
3801
}
 
3802
 
 
3803
void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3804
        unsigned int n, imm_s, imm_r;
 
3805
        if (!Is64Bit(Rn))
 
3806
                imm &= 0xFFFFFFFF;
 
3807
        if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) {
 
3808
                AND(Rd, Rn, imm_r, imm_s, n != 0);
 
3809
        } else {
 
3810
                _assert_msg_(JIT, scratch != INVALID_REG, "ANDSI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm);
 
3811
                MOVI2R(scratch, imm);
 
3812
                AND(Rd, Rn, scratch);
 
3813
        }
 
3814
}
 
3815
 
 
3816
void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3817
        unsigned int n, imm_s, imm_r;
 
3818
        if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) {
 
3819
                ORR(Rd, Rn, imm_r, imm_s, n != 0);
 
3820
        } else {
 
3821
                _assert_msg_(JIT, scratch != INVALID_REG, "ORRI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm);
 
3822
                MOVI2R(scratch, imm);
 
3823
                ORR(Rd, Rn, scratch);
 
3824
        }
 
3825
}
 
3826
 
 
3827
void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3828
        unsigned int n, imm_s, imm_r;
 
3829
        if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) {
 
3830
                EOR(Rd, Rn, imm_r, imm_s, n != 0);
 
3831
        } else {
 
3832
                _assert_msg_(JIT, scratch != INVALID_REG, "EORI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm);
 
3833
                MOVI2R(scratch, imm);
 
3834
                EOR(Rd, Rn, scratch);
 
3835
        }
 
3836
}
 
3837
 
 
3838
void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3839
        unsigned int n, imm_s, imm_r;
 
3840
        if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) {
 
3841
                ANDS(Rd, Rn, imm_r, imm_s, n != 0);
 
3842
        } else {
 
3843
                _assert_msg_(JIT, scratch != INVALID_REG, "ANDSI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm);
 
3844
                MOVI2R(scratch, imm);
 
3845
                ANDS(Rd, Rn, scratch);
 
3846
        }
 
3847
}
 
3848
 
 
3849
void ARM64XEmitter::ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3850
        u32 val;
 
3851
        bool shift;
 
3852
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3853
                ADD(Rd, Rn, val, shift);
 
3854
        } else {
 
3855
                _assert_msg_(JIT, scratch != INVALID_REG, "ADDI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm);
 
3856
                MOVI2R(scratch, imm);
 
3857
                ADD(Rd, Rn, scratch);
 
3858
        }
 
3859
}
 
3860
 
 
3861
void ARM64XEmitter::SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3862
        u32 val;
 
3863
        bool shift;
 
3864
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3865
                SUB(Rd, Rn, val, shift);
 
3866
        } else {
 
3867
                _assert_msg_(JIT, scratch != INVALID_REG, "SUBI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm);
 
3868
                MOVI2R(scratch, imm);
 
3869
                SUB(Rd, Rn, scratch);
 
3870
        }
 
3871
}
 
3872
 
 
3873
void ARM64XEmitter::CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
3874
        u32 val;
 
3875
        bool shift;
 
3876
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3877
                CMP(Rn, val, shift);
 
3878
        } else {
 
3879
                _assert_msg_(JIT, scratch != INVALID_REG, "CMPI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm);
 
3880
                MOVI2R(scratch, imm);
 
3881
                CMP(Rn, scratch);
 
3882
        }
 
3883
}
 
3884
 
 
3885
bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
 
3886
        u32 val;
 
3887
        bool shift;
 
3888
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3889
                ADD(Rd, Rn, val, shift);
 
3890
                return true;
 
3891
        } else {
 
3892
                return false;
 
3893
        }
 
3894
}
 
3895
 
 
3896
bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
 
3897
        u32 val;
 
3898
        bool shift;
 
3899
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3900
                SUB(Rd, Rn, val, shift);
 
3901
                return true;
 
3902
        } else {
 
3903
                return false;
 
3904
        }
 
3905
}
 
3906
 
 
3907
bool ARM64XEmitter::TryCMPI2R(ARM64Reg Rn, u32 imm) {
 
3908
        u32 val;
 
3909
        bool shift;
 
3910
        if (IsImmArithmetic(imm, &val, &shift)) {
 
3911
                CMP(Rn, val, shift);
 
3912
                return true;
 
3913
        } else {
 
3914
                return false;
 
3915
        }
 
3916
}
 
3917
 
 
3918
bool ARM64XEmitter::TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
 
3919
        u32 n, imm_r, imm_s;
 
3920
        if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) {
 
3921
                AND(Rd, Rn, imm_r, imm_s, n != 0);
 
3922
                return true;
 
3923
        } else {
 
3924
                return false;
 
3925
        }
 
3926
}
 
3927
bool ARM64XEmitter::TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
 
3928
        u32 n, imm_r, imm_s;
 
3929
        if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) {
 
3930
                ORR(Rd, Rn, imm_r, imm_s, n != 0);
 
3931
                return true;
 
3932
        } else {
 
3933
                return false;
 
3934
        }
 
3935
}
 
3936
bool ARM64XEmitter::TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
 
3937
        u32 n, imm_r, imm_s;
 
3938
        if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) {
 
3939
                EOR(Rd, Rn, imm_r, imm_s, n != 0);
 
3940
                return true;
 
3941
        } else {
 
3942
                return false;
 
3943
        }
 
3944
}
 
3945
 
 
3946
float FPImm8ToFloat(uint8_t bits) {
 
3947
        int E = 8;
 
3948
        int F = 32 - 8 - 1;
 
3949
        int sign = bits >> 7;
 
3950
        uint32_t f = 0;
 
3951
        f |= (sign << 31);
 
3952
        int bit6 = (bits >> 6) & 1;
 
3953
        uint32_t exp = ((!bit6) << 7) | (0x7C * bit6) | ((bits >> 4) & 3);
 
3954
        uint32_t mantissa = (bits & 0xF) << 19;
 
3955
        f |= exp << 23;
 
3956
        f |= mantissa;
 
3957
        float fl;
 
3958
        memcpy(&fl, &f, sizeof(float));
 
3959
        return fl;
 
3960
}
 
3961
 
 
3962
bool FPImm8FromFloat(float value, uint8_t *immOut) {
 
3963
        uint32_t f;
 
3964
        memcpy(&f, &value, sizeof(float));
 
3965
        uint32_t mantissa4 = (f & 0x7FFFFF) >> 19;
 
3966
        uint32_t exponent = (f >> 23) & 0xFF;
 
3967
        uint32_t sign = f >> 31;
 
3968
        if ((exponent >> 7) == ((exponent >> 6) & 1))
 
3969
                return false;
 
3970
        uint8_t imm8 = (sign << 7) | ((!(exponent >> 7)) << 6) | ((exponent & 3) << 4) | mantissa4;
 
3971
        float newFloat = FPImm8ToFloat(imm8);
 
3972
        if (newFloat == value) {
 
3973
                *immOut = imm8;
 
3974
                return true;
 
3975
        } else {
 
3976
                return false;
 
3977
        }
 
3978
}
 
3979
 
 
3980
void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool negate) {
 
3981
        _assert_msg_(JIT, !IsDouble(Rd), "MOVI2F does not yet support double precision");
 
3982
        uint8_t imm8;
 
3983
        if (value == 0.0) {
 
3984
                if (std::signbit(value)) {
 
3985
                        negate = !negate;
 
3986
                }
 
3987
                FMOV(Rd, IsDouble(Rd) ? ZR : WZR);
 
3988
                if (negate) {
 
3989
                        FNEG(Rd, Rd);
 
3990
                }
 
3991
                // TODO: There are some other values we could generate with the float-imm instruction, like 1.0...
 
3992
        } else if (negate && FPImm8FromFloat(-value, &imm8)) {
 
3993
                FMOV(Rd, imm8);
 
3994
        } else if (FPImm8FromFloat(value, &imm8)) {
 
3995
                FMOV(Rd, imm8);
 
3996
                if (negate) {
 
3997
                        FNEG(Rd, Rd);
 
3998
                }
 
3999
        } else {
 
4000
                _assert_msg_(JIT, scratch != INVALID_REG, "Failed to find a way to generate FP immediate %f without scratch", value);
 
4001
                u32 ival;
 
4002
                if (negate) {
 
4003
                        value = -value;
 
4004
                }
 
4005
                memcpy(&ival, &value, sizeof(ival));
 
4006
                m_emit->MOVI2R(scratch, ival);
 
4007
                FMOV(Rd, scratch);
 
4008
        }
 
4009
}
 
4010
 
 
4011
// TODO: Quite a few values could be generated easily using the MOVI instruction and friends.
 
4012
void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch) {
 
4013
        // TODO: Make it work with more element sizes
 
4014
        // TODO: Optimize - there are shorter solution for many values
 
4015
        ARM64Reg s = (ARM64Reg)(S0 + DecodeReg(Rd));
 
4016
        int ival;
 
4017
        memcpy(&ival, &value, 4);
 
4018
        if (ival == 0) {  // Make sure to not catch negative zero here
 
4019
                EOR(Rd, Rd, Rd);
 
4020
        } else {
 
4021
                MOVI2F(s, value, scratch);
 
4022
                DUP(32, Rd, Rd, 0);
 
4023
        }
 
4024
}
 
4025
 
 
4026
void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
 
4027
        u32 val;
 
4028
        bool shift;
 
4029
        if (IsImmArithmetic(imm, &val, &shift)) {
 
4030
                SUBS(Rd, Rn, val, shift);
 
4031
        } else {
 
4032
                _assert_msg_(JIT, scratch != INVALID_REG, "ANDSI2R - failed to construct immediate value from %08x, need scratch", (u32)imm);
 
4033
                MOVI2R(scratch, imm);
 
4034
                SUBS(Rd, Rn, scratch);
 
4035
        }
 
4036
}
 
4037
 
 
4038
}  // namespace