< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page
rev 61868 : manual merge with default


1313   INSN(ldr, 0b01, 0);
1314   INSN(ldrsw, 0b10, 0);
1315 
1316 #undef INSN
1317 
1318 #define INSN(NAME, opc, V)                                              \
1319   void NAME(FloatRegister Rt, address dest) {                           \
1320     long offset = (dest - pc()) >> 2;                                   \
1321     starti;                                                             \
1322     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1323       sf(offset, 23, 5);                                                \
1324     rf((Register)Rt, 0);                                                \
1325   }
1326 
1327   INSN(ldrs, 0b00, 1);
1328   INSN(ldrd, 0b01, 1);
1329   INSN(ldrq, 0b10, 1);
1330 
1331 #undef INSN
1332 















1333 #define INSN(NAME, opc, V)                                              \
1334   void NAME(address dest, prfop op = PLDL1KEEP) {                       \
1335     long offset = (dest - pc()) >> 2;                                   \
1336     starti;                                                             \
1337     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1338       sf(offset, 23, 5);                                                \
1339     f(op, 4, 0);                                                        \
1340   }                                                                     \
1341   void NAME(Label &L, prfop op = PLDL1KEEP) {                           \
1342     wrap_label(L, op, &Assembler::NAME);                                \
1343   }
1344 
1345   INSN(prfm, 0b11, 0);
1346 
1347 #undef INSN
1348 
1349   // Load/store
1350   void ld_st1(int opc, int p1, int V, int L,
1351               Register Rt1, Register Rt2, Address adr, bool no_allocate) {
1352     starti;


1450   INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with
1451                           // writeback modes, but the assembler
1452                           // doesn't enfore that.
1453 
1454 #undef INSN
1455 
1456 #define INSN(NAME, size, op)                            \
1457   void NAME(FloatRegister Rt, const Address &adr) {     \
1458     ld_st2((Register)Rt, adr, size, op, 1);             \
1459   }
1460 
1461   INSN(strd, 0b11, 0b00);
1462   INSN(strs, 0b10, 0b00);
1463   INSN(ldrd, 0b11, 0b01);
1464   INSN(ldrs, 0b10, 0b01);
1465   INSN(strq, 0b00, 0b10);
1466   INSN(ldrq, 0x00, 0b11);
1467 
1468 #undef INSN
1469 















1470   enum shift_kind { LSL, LSR, ASR, ROR };
1471 
1472   void op_shifted_reg(unsigned decode,
1473                       enum shift_kind kind, unsigned shift,
1474                       unsigned size, unsigned op) {
1475     f(size, 31);
1476     f(op, 30, 29);
1477     f(decode, 28, 24);
1478     f(shift, 15, 10);
1479     f(kind, 23, 22);
1480   }
1481 
1482   // Logical (shifted register)
1483 #define INSN(NAME, size, op, N)                                 \
1484   void NAME(Register Rd, Register Rn, Register Rm,              \
1485             enum shift_kind kind = LSL, unsigned shift = 0) {   \
1486     starti;                                                     \
1487     guarantee(size == 1 || shift < 32, "incorrect shift");      \
1488     f(N, 21);                                                   \
1489     zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0);                        \


1824   INSN(fcvts, 0b000, 0b00, 0b000101);   // Single-precision to double-precision
1825 
1826 private:
1827   INSN(i_fmovd, 0b000, 0b01, 0b000000);
1828 public:
1829   INSN(fabsd, 0b000, 0b01, 0b000001);
1830   INSN(fnegd, 0b000, 0b01, 0b000010);
1831   INSN(fsqrtd, 0b000, 0b01, 0b000011);
1832   INSN(fcvtd, 0b000, 0b01, 0b000100);   // Double-precision to single-precision
1833 
1834   void fmovd(FloatRegister Vd, FloatRegister Vn) {
1835     assert(Vd != Vn, "should be");
1836     i_fmovd(Vd, Vn);
1837   }
1838 
1839   void fmovs(FloatRegister Vd, FloatRegister Vn) {
1840     assert(Vd != Vn, "should be");
1841     i_fmovs(Vd, Vn);
1842   }
1843 
























1844 #undef INSN
1845 
1846   // Floating-point data-processing (2 source)
1847   void data_processing(unsigned op31, unsigned type, unsigned opcode,
1848                        FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {
1849     starti;
1850     f(op31, 31, 29);
1851     f(0b11110, 28, 24);
1852     f(type, 23, 22), f(1, 21), f(opcode, 15, 12), f(0b10, 11, 10);
1853     rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);
1854   }
1855 
1856 #define INSN(NAME, op31, type, opcode)                  \
1857   void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {     \
1858     data_processing(op31, type, opcode, Vd, Vn, Vm);    \
1859   }
1860 
1861   INSN(fmuls, 0b000, 0b00, 0b0000);
1862   INSN(fdivs, 0b000, 0b00, 0b0001);
1863   INSN(fadds, 0b000, 0b00, 0b0010);


1960 
1961 #undef INSN
1962 
1963 #define INSN(NAME, op31, type, rmode, opcode)                           \
1964   void NAME(FloatRegister Vd, Register Rn) {                            \
1965     float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn);     \
1966   }
1967 
1968   INSN(fmovs, 0b000, 0b00, 0b00, 0b111);
1969   INSN(fmovd, 0b100, 0b01, 0b00, 0b111);
1970 
1971   INSN(scvtfws, 0b000, 0b00, 0b00, 0b010);
1972   INSN(scvtfs,  0b100, 0b00, 0b00, 0b010);
1973   INSN(scvtfwd, 0b000, 0b01, 0b00, 0b010);
1974   INSN(scvtfd,  0b100, 0b01, 0b00, 0b010);
1975 
1976   // INSN(fmovhid, 0b100, 0b10, 0b01, 0b111);
1977 
1978 #undef INSN
1979 





































1980   // Floating-point compare
1981   void float_compare(unsigned op31, unsigned type,
1982                      unsigned op, unsigned op2,
1983                      FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) {
1984     starti;
1985     f(op31, 31, 29);
1986     f(0b11110, 28, 24);
1987     f(type, 23, 22), f(1, 21);
1988     f(op, 15, 14), f(0b1000, 13, 10), f(op2, 4, 0);
1989     rf(Vn, 5), rf(Vm, 16);
1990   }
1991 
1992 
1993 #define INSN(NAME, op31, type, op, op2)                 \
1994   void NAME(FloatRegister Vn, FloatRegister Vm) {       \
1995     float_compare(op31, type, op, op2, Vn, Vm);         \
1996   }
1997 
1998 #define INSN1(NAME, op31, type, op, op2)        \
1999   void NAME(FloatRegister Vn, double d) {       \


2074   INSN(frintxh, 0b11, 0b110);
2075   INSN(frintzh, 0b11, 0b011);
2076 
2077   INSN(frintas, 0b00, 0b100);
2078   INSN(frintis, 0b00, 0b111);
2079   INSN(frintms, 0b00, 0b010);
2080   INSN(frintns, 0b00, 0b000);
2081   INSN(frintps, 0b00, 0b001);
2082   INSN(frintxs, 0b00, 0b110);
2083   INSN(frintzs, 0b00, 0b011);
2084 
2085   INSN(frintad, 0b01, 0b100);
2086   INSN(frintid, 0b01, 0b111);
2087   INSN(frintmd, 0b01, 0b010);
2088   INSN(frintnd, 0b01, 0b000);
2089   INSN(frintpd, 0b01, 0b001);
2090   INSN(frintxd, 0b01, 0b110);
2091   INSN(frintzd, 0b01, 0b011);
2092 #undef INSN
2093 
2094 /* SIMD extensions
2095  *
2096  * We just use FloatRegister in the following. They are exactly the same
2097  * as SIMD registers.
2098  */
2099  public:
2100 
2101   enum SIMD_Arrangement {
2102        T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
2103   };
2104 
2105   enum SIMD_RegVariant {
2106        B, H, S, D, Q
2107   };
2108 
2109 private:
2110   static short SIMD_Size_in_bytes[];
2111 
2112 public:
2113 #define INSN(NAME, op)                                            \
2114   void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) {   \
2115     ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
2116   }                                                                      \
2117 
2118   INSN(ldr, 1);
2119   INSN(str, 0);
2120 
2121 #undef INSN
2122 
2123  private:
2124 
2125   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) {
2126     starti;
2127     f(0,31), f((int)T & 1, 30);
2128     f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12);


2246   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2247     guarantee(T != T1Q && T != T1D, "incorrect arrangement");                           \
2248     if (!acceptT2D) guarantee(T != T2D, "incorrect arrangement");                       \
2249     starti;                                                                             \
2250     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2251     f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10);                      \
2252     rf(Vn, 5), rf(Vd, 0);                                                               \
2253   }
2254 
2255   INSN(addv,   0, 0b100001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2256   INSN(subv,   1, 0b100001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2257   INSN(mulv,   0, 0b100111, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2258   INSN(mlav,   0, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2259   INSN(mlsv,   1, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2260   INSN(sshl,   0, 0b010001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2261   INSN(ushl,   1, 0b010001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2262   INSN(addpv,  0, 0b101111, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2263   INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2264   INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2265   INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S





2266 
2267 #undef INSN
2268 
2269 #define INSN(NAME, opc, opc2, accepted) \
2270   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                   \
2271     guarantee(T != T1Q && T != T1D, "incorrect arrangement");                           \
2272     if (accepted < 3) guarantee(T != T2D, "incorrect arrangement");                     \
2273     if (accepted < 2) guarantee(T != T2S, "incorrect arrangement");                     \
2274     if (accepted < 1) guarantee(T == T8B || T == T16B, "incorrect arrangement");        \
2275     starti;                                                                             \
2276     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2277     f((int)T >> 1, 23, 22), f(opc2, 21, 10);                                            \
2278     rf(Vn, 5), rf(Vd, 0);                                                               \
2279   }
2280 
2281   INSN(absr,   0, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2282   INSN(negr,   1, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2283   INSN(notr,   1, 0b100000010110, 0); // accepted arrangements: T8B, T16B
2284   INSN(addv,   0, 0b110001101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S


2285   INSN(cls,    0, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2286   INSN(clz,    1, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2287   INSN(cnt,    0, 0b100000010110, 0); // accepted arrangements: T8B, T16B
2288   INSN(uaddlp, 1, 0b100000001010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2289   INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2290 
2291 #undef INSN
2292 
2293 #define INSN(NAME, opc) \
2294   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                  \
2295     starti;                                                                            \
2296     assert(T == T4S, "arrangement must be T4S");                                       \
2297     f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24), f(opc, 23),                      \
2298     f(T == T4S ? 0 : 1, 22), f(0b110000111110, 21, 10); rf(Vn, 5), rf(Vd, 0);          \
2299   }
2300 
2301   INSN(fmaxv, 0);
2302   INSN(fminv, 1);
2303 
2304 #undef INSN


2329   INSN(bici, 1, 1);
2330 
2331 #undef INSN
2332 
2333 #define INSN(NAME, op1, op2, op3) \
2334   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2335     starti;                                                                             \
2336     assert(T == T2S || T == T4S || T == T2D, "invalid arrangement");                    \
2337     f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23);            \
2338     f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0);    \
2339   }
2340 
2341   INSN(fadd, 0, 0, 0b110101);
2342   INSN(fdiv, 1, 0, 0b111111);
2343   INSN(fmul, 1, 0, 0b110111);
2344   INSN(fsub, 0, 1, 0b110101);
2345   INSN(fmla, 0, 0, 0b110011);
2346   INSN(fmls, 0, 1, 0b110011);
2347   INSN(fmax, 0, 0, 0b111101);
2348   INSN(fmin, 0, 1, 0b111101);



2349 
2350 #undef INSN
2351 
2352 #define INSN(NAME, opc)                                                                 \
2353   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2354     starti;                                                                             \
2355     assert(T == T4S, "arrangement must be T4S");                                        \
2356     f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0);         \
2357   }
2358 
2359   INSN(sha1c,     0b000000);
2360   INSN(sha1m,     0b001000);
2361   INSN(sha1p,     0b000100);
2362   INSN(sha1su0,   0b001100);
2363   INSN(sha256h2,  0b010100);
2364   INSN(sha256h,   0b010000);
2365   INSN(sha256su1, 0b011000);
2366 
2367 #undef INSN
2368 


2404   }
2405 
2406   // FMLA/FMLS - Vector - Scalar
2407   INSN(fmlavs, 0, 0b0001);
2408   INSN(fmlsvs, 0, 0b0101);
2409   // FMULX - Vector - Scalar
2410   INSN(fmulxvs, 1, 0b1001);
2411 
2412 #undef INSN
2413 
2414   // Floating-point Reciprocal Estimate
2415   void frecpe(FloatRegister Vd, FloatRegister Vn, SIMD_RegVariant type) {
2416     assert(type == D || type == S, "Wrong type for frecpe");
2417     starti;
2418     f(0b010111101, 31, 23);
2419     f(type == D ? 1 : 0, 22);
2420     f(0b100001110110, 21, 10);
2421     rf(Vn, 5), rf(Vd, 0);
2422   }
2423 
2424   // (double) {a, b} -> (a + b)
2425   void faddpd(FloatRegister Vd, FloatRegister Vn) {
2426     starti;
2427     f(0b0111111001110000110110, 31, 10);










2428     rf(Vn, 5), rf(Vd, 0);
2429   }
2430 
2431   void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {
2432     starti;
2433     assert(T != Q, "invalid register variant");
2434     f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15);
2435     f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);
2436   }
2437 
2438   void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
2439     starti;
2440     f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
2441     f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);
2442     rf(Vn, 5), rf(Rd, 0);
2443   }
2444 








2445 #define INSN(NAME, opc, opc2, isSHR)                                    \
2446   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
2447     starti;                                                             \
2448     /* The encodings for the immh:immb fields (bits 22:16) in *SHR are  \
2449      *   0001 xxx       8B/16B, shift = 16  - UInt(immh:immb)           \
2450      *   001x xxx       4H/8H,  shift = 32  - UInt(immh:immb)           \
2451      *   01xx xxx       2S/4S,  shift = 64  - UInt(immh:immb)           \
2452      *   1xxx xxx       1D/2D,  shift = 128 - UInt(immh:immb)           \
2453      *   (1D is RESERVED)                                               \
2454      * for SHL shift is calculated as:                                  \
2455      *   0001 xxx       8B/16B, shift = UInt(immh:immb) - 8             \
2456      *   001x xxx       4H/8H,  shift = UInt(immh:immb) - 16            \
2457      *   01xx xxx       2S/4S,  shift = UInt(immh:immb) - 32            \
2458      *   1xxx xxx       1D/2D,  shift = UInt(immh:immb) - 64            \
2459      *   (1D is RESERVED)                                               \
2460      */                                                                 \
2461     assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value");           \
2462     int cVal = (1 << (((T >> 1) + 3) + (isSHR ? 1 : 0)));               \
2463     int encodedShift = isSHR ? cVal - shift : cVal + shift;             \
2464     f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23),            \
2465     f(encodedShift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0);     \
2466   }
2467 
2468   INSN(shl,  0, 0b010101, /* isSHR = */ false);
2469   INSN(sshr, 0, 0b000001, /* isSHR = */ true);
2470   INSN(ushr, 1, 0b000001, /* isSHR = */ true);
2471 
2472 #undef INSN
2473 
2474 private:
2475   void _ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
2476     starti;
2477     /* The encodings for the immh:immb fields (bits 22:16) are
2478      *   0001 xxx       8H, 8B/16b shift = xxx
2479      *   001x xxx       4S, 4H/8H  shift = xxxx
2480      *   01xx xxx       2D, 2S/4S  shift = xxxxx
2481      *   1xxx xxx       RESERVED
2482      */
2483     assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement");
2484     assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value");
2485     f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16);

2486     f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2487   }
2488 
2489 public:
2490   void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2491     assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement");
2492     _ushll(Vd, Ta, Vn, Tb, shift);
2493   }
2494 
2495   void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2496     assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement");
2497     _ushll(Vd, Ta, Vn, Tb, shift);


















2498   }
2499 
2500   // Move from general purpose register
2501   //   mov  Vd.T[index], Rn
2502   void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) {
2503     starti;
2504     f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2505     f(0b000111, 15, 10), zrf(Xn, 5), rf(Vd, 0);
2506   }
2507 
2508   // Move to general purpose register
2509   //   mov  Rd, Vn.T[index]
2510   void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) {
2511     guarantee(T >= T2S && T < T1Q, "only D and S arrangements are supported");
2512     starti;
2513     f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21);
2514     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2515     f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0);
2516   }
2517 


2526   }
2527 
2528 public:
2529   void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2530     assert(Tb == T1D || Tb == T8B, "pmull assumes T1D or T8B as the second size specifier");
2531     _pmull(Vd, Ta, Vn, Vm, Tb);
2532   }
2533 
2534   void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2535     assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier");
2536     _pmull(Vd, Ta, Vn, Vm, Tb);
2537   }
2538 
2539   void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
2540     starti;
2541     int size_b = (int)Tb >> 1;
2542     int size_a = (int)Ta >> 1;
2543     assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");
2544     f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22);
2545     f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);









2546   }
2547 
2548   void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
2549   {
2550     starti;
2551     assert(T != T1D, "reserved encoding");
2552     f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2553     f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), zrf(Xs, 5), rf(Vd, 0);
2554   }
2555 
2556   void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)
2557   {
2558     starti;
2559     assert(T != T1D, "reserved encoding");
2560     f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2561     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2562     f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2563   }
2564 
2565   // AdvSIMD ZIP/UZP/TRN




1313   INSN(ldr, 0b01, 0);
1314   INSN(ldrsw, 0b10, 0);
1315 
1316 #undef INSN
1317 
1318 #define INSN(NAME, opc, V)                                              \
1319   void NAME(FloatRegister Rt, address dest) {                           \
1320     long offset = (dest - pc()) >> 2;                                   \
1321     starti;                                                             \
1322     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1323       sf(offset, 23, 5);                                                \
1324     rf((Register)Rt, 0);                                                \
1325   }
1326 
1327   INSN(ldrs, 0b00, 1);
1328   INSN(ldrd, 0b01, 1);
1329   INSN(ldrq, 0b10, 1);
1330 
1331 #undef INSN
1332 
1333 #define INSN(NAME, size, opc)                                           \
1334   void NAME(FloatRegister Rt, Register Rn) {                            \
1335     starti;                                                             \
1336     f(size, 31, 30), f(0b111100, 29, 24), f(opc, 23, 22), f(0, 21);     \
1337     f(0, 20, 12), f(0b01, 11, 10);                                      \
1338     rf(Rn, 5), rf((Register)Rt, 0);                                     \
1339   }
1340 
1341   INSN(ldrs, 0b10, 0b01);
1342   INSN(ldrd, 0b11, 0b01);
1343   INSN(ldrq, 0b00, 0b11);
1344 
1345 #undef INSN
1346 
1347 
1348 #define INSN(NAME, opc, V)                                              \
1349   void NAME(address dest, prfop op = PLDL1KEEP) {                       \
1350     long offset = (dest - pc()) >> 2;                                   \
1351     starti;                                                             \
1352     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1353       sf(offset, 23, 5);                                                \
1354     f(op, 4, 0);                                                        \
1355   }                                                                     \
1356   void NAME(Label &L, prfop op = PLDL1KEEP) {                           \
1357     wrap_label(L, op, &Assembler::NAME);                                \
1358   }
1359 
1360   INSN(prfm, 0b11, 0);
1361 
1362 #undef INSN
1363 
1364   // Load/store
1365   void ld_st1(int opc, int p1, int V, int L,
1366               Register Rt1, Register Rt2, Address adr, bool no_allocate) {
1367     starti;


1465   INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with
1466                           // writeback modes, but the assembler
1467                           // doesn't enfore that.
1468 
1469 #undef INSN
1470 
1471 #define INSN(NAME, size, op)                            \
1472   void NAME(FloatRegister Rt, const Address &adr) {     \
1473     ld_st2((Register)Rt, adr, size, op, 1);             \
1474   }
1475 
1476   INSN(strd, 0b11, 0b00);
1477   INSN(strs, 0b10, 0b00);
1478   INSN(ldrd, 0b11, 0b01);
1479   INSN(ldrs, 0b10, 0b01);
1480   INSN(strq, 0b00, 0b10);
1481   INSN(ldrq, 0x00, 0b11);
1482 
1483 #undef INSN
1484 
1485 /* SIMD extensions
1486  *
1487  * We just use FloatRegister in the following. They are exactly the same
1488  * as SIMD registers.
1489  */
1490 public:
1491 
1492   enum SIMD_Arrangement {
1493     T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
1494   };
1495 
1496   enum SIMD_RegVariant {
1497     B, H, S, D, Q
1498   };
1499 
1500   enum shift_kind { LSL, LSR, ASR, ROR };
1501 
1502   void op_shifted_reg(unsigned decode,
1503                       enum shift_kind kind, unsigned shift,
1504                       unsigned size, unsigned op) {
1505     f(size, 31);
1506     f(op, 30, 29);
1507     f(decode, 28, 24);
1508     f(shift, 15, 10);
1509     f(kind, 23, 22);
1510   }
1511 
1512   // Logical (shifted register)
1513 #define INSN(NAME, size, op, N)                                 \
1514   void NAME(Register Rd, Register Rn, Register Rm,              \
1515             enum shift_kind kind = LSL, unsigned shift = 0) {   \
1516     starti;                                                     \
1517     guarantee(size == 1 || shift < 32, "incorrect shift");      \
1518     f(N, 21);                                                   \
1519     zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0);                        \


1854   INSN(fcvts, 0b000, 0b00, 0b000101);   // Single-precision to double-precision
1855 
1856 private:
1857   INSN(i_fmovd, 0b000, 0b01, 0b000000);
1858 public:
1859   INSN(fabsd, 0b000, 0b01, 0b000001);
1860   INSN(fnegd, 0b000, 0b01, 0b000010);
1861   INSN(fsqrtd, 0b000, 0b01, 0b000011);
1862   INSN(fcvtd, 0b000, 0b01, 0b000100);   // Double-precision to single-precision
1863 
1864   void fmovd(FloatRegister Vd, FloatRegister Vn) {
1865     assert(Vd != Vn, "should be");
1866     i_fmovd(Vd, Vn);
1867   }
1868 
1869   void fmovs(FloatRegister Vd, FloatRegister Vn) {
1870     assert(Vd != Vn, "should be");
1871     i_fmovs(Vd, Vn);
1872   }
1873 
1874 private:
1875   void _fcvt_narrow_extend(FloatRegister Vd, SIMD_Arrangement Ta,
1876                            FloatRegister Vn, SIMD_Arrangement Tb, bool do_extend) {
1877     assert((do_extend && (Tb >> 1) + 1 == (Ta >> 1))
1878            || (!do_extend && (Ta >> 1) + 1 == (Tb >> 1)), "Incompatible arrangement");
1879     starti;
1880     int op30 = (do_extend ? Tb : Ta) & 1;
1881     int op22 = ((do_extend ? Ta : Tb) >> 1) & 1;
1882     f(0, 31), f(op30, 30), f(0b0011100, 29, 23), f(op22, 22);
1883     f(0b100001011, 21, 13), f(do_extend ? 1 : 0, 12), f(0b10, 11, 10);
1884     rf(Vn, 5), rf(Vd, 0);
1885   }
1886 
1887 public:
1888   void fcvtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb) {
1889     assert(Tb == T4H || Tb == T8H|| Tb == T2S || Tb == T4S, "invalid arrangement");
1890     _fcvt_narrow_extend(Vd, Ta, Vn, Tb, true);
1891   }
1892 
1893   void fcvtn(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb) {
1894     assert(Ta == T4H || Ta == T8H|| Ta == T2S || Ta == T4S, "invalid arrangement");
1895     _fcvt_narrow_extend(Vd, Ta, Vn, Tb, false);
1896   }
1897 
1898 #undef INSN
1899 
1900   // Floating-point data-processing (2 source)
1901   void data_processing(unsigned op31, unsigned type, unsigned opcode,
1902                        FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {
1903     starti;
1904     f(op31, 31, 29);
1905     f(0b11110, 28, 24);
1906     f(type, 23, 22), f(1, 21), f(opcode, 15, 12), f(0b10, 11, 10);
1907     rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);
1908   }
1909 
1910 #define INSN(NAME, op31, type, opcode)                  \
1911   void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {     \
1912     data_processing(op31, type, opcode, Vd, Vn, Vm);    \
1913   }
1914 
1915   INSN(fmuls, 0b000, 0b00, 0b0000);
1916   INSN(fdivs, 0b000, 0b00, 0b0001);
1917   INSN(fadds, 0b000, 0b00, 0b0010);


2014 
2015 #undef INSN
2016 
2017 #define INSN(NAME, op31, type, rmode, opcode)                           \
2018   void NAME(FloatRegister Vd, Register Rn) {                            \
2019     float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn);     \
2020   }
2021 
2022   INSN(fmovs, 0b000, 0b00, 0b00, 0b111);
2023   INSN(fmovd, 0b100, 0b01, 0b00, 0b111);
2024 
2025   INSN(scvtfws, 0b000, 0b00, 0b00, 0b010);
2026   INSN(scvtfs,  0b100, 0b00, 0b00, 0b010);
2027   INSN(scvtfwd, 0b000, 0b01, 0b00, 0b010);
2028   INSN(scvtfd,  0b100, 0b01, 0b00, 0b010);
2029 
2030   // INSN(fmovhid, 0b100, 0b10, 0b01, 0b111);
2031 
2032 #undef INSN
2033 
2034   enum sign_kind { SIGNED, UNSIGNED };
2035 
2036 private:
2037   void _xcvtf_scalar_integer(sign_kind sign, unsigned sz,
2038                              FloatRegister Rd, FloatRegister Rn) {
2039     starti;
2040     f(0b01, 31, 30), f(sign == SIGNED ? 0 : 1, 29);
2041     f(0b111100, 27, 23), f((sz >> 1) & 1, 22), f(0b100001110110, 21, 10);
2042     rf(Rn, 5), rf(Rd, 0);
2043   }
2044 
2045 public:
2046 #define INSN(NAME, sign, sz)                        \
2047   void NAME(FloatRegister Rd, FloatRegister Rn) {   \
2048     _xcvtf_scalar_integer(sign, sz, Rd, Rn);        \
2049   }
2050 
2051   INSN(scvtfs, SIGNED, 0);
2052   INSN(scvtfd, SIGNED, 1);
2053 
2054 #undef INSN
2055 
2056 private:
2057   void _xcvtf_vector_integer(sign_kind sign, SIMD_Arrangement T,
2058                              FloatRegister Rd, FloatRegister Rn) {
2059     assert(T == T2S || T == T4S || T == T2D, "invalid arrangement");
2060     starti;
2061     f(0, 31), f(T & 1, 30), f(sign == SIGNED ? 0 : 1, 29);
2062     f(0b011100, 28, 23), f((T >> 1) & 1, 22), f(0b100001110110, 21, 10);
2063     rf(Rn, 5), rf(Rd, 0);
2064   }
2065 
2066 public:
2067   void scvtfv(SIMD_Arrangement T, FloatRegister Rd, FloatRegister Rn) {
2068     _xcvtf_vector_integer(SIGNED, T, Rd, Rn);
2069   }
2070 
2071   // Floating-point compare
2072   void float_compare(unsigned op31, unsigned type,
2073                      unsigned op, unsigned op2,
2074                      FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) {
2075     starti;
2076     f(op31, 31, 29);
2077     f(0b11110, 28, 24);
2078     f(type, 23, 22), f(1, 21);
2079     f(op, 15, 14), f(0b1000, 13, 10), f(op2, 4, 0);
2080     rf(Vn, 5), rf(Vm, 16);
2081   }
2082 
2083 
2084 #define INSN(NAME, op31, type, op, op2)                 \
2085   void NAME(FloatRegister Vn, FloatRegister Vm) {       \
2086     float_compare(op31, type, op, op2, Vn, Vm);         \
2087   }
2088 
2089 #define INSN1(NAME, op31, type, op, op2)        \
2090   void NAME(FloatRegister Vn, double d) {       \


2165   INSN(frintxh, 0b11, 0b110);
2166   INSN(frintzh, 0b11, 0b011);
2167 
2168   INSN(frintas, 0b00, 0b100);
2169   INSN(frintis, 0b00, 0b111);
2170   INSN(frintms, 0b00, 0b010);
2171   INSN(frintns, 0b00, 0b000);
2172   INSN(frintps, 0b00, 0b001);
2173   INSN(frintxs, 0b00, 0b110);
2174   INSN(frintzs, 0b00, 0b011);
2175 
2176   INSN(frintad, 0b01, 0b100);
2177   INSN(frintid, 0b01, 0b111);
2178   INSN(frintmd, 0b01, 0b010);
2179   INSN(frintnd, 0b01, 0b000);
2180   INSN(frintpd, 0b01, 0b001);
2181   INSN(frintxd, 0b01, 0b110);
2182   INSN(frintzd, 0b01, 0b011);
2183 #undef INSN
2184 















2185 private:
2186   static short SIMD_Size_in_bytes[];
2187 
2188 public:
2189 #define INSN(NAME, op)                                            \
2190   void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) {   \
2191     ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
2192   }                                                                      \
2193 
2194   INSN(ldr, 1);
2195   INSN(str, 0);
2196 
2197 #undef INSN
2198 
2199  private:
2200 
2201   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) {
2202     starti;
2203     f(0,31), f((int)T & 1, 30);
2204     f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12);


2322   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2323     guarantee(T != T1Q && T != T1D, "incorrect arrangement");                           \
2324     if (!acceptT2D) guarantee(T != T2D, "incorrect arrangement");                       \
2325     starti;                                                                             \
2326     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2327     f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10);                      \
2328     rf(Vn, 5), rf(Vd, 0);                                                               \
2329   }
2330 
2331   INSN(addv,   0, 0b100001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2332   INSN(subv,   1, 0b100001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2333   INSN(mulv,   0, 0b100111, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2334   INSN(mlav,   0, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2335   INSN(mlsv,   1, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2336   INSN(sshl,   0, 0b010001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2337   INSN(ushl,   1, 0b010001, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2338   INSN(addpv,  0, 0b101111, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2339   INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2340   INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2341   INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2342   INSN(maxv,   0, 0b011001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2343   INSN(minv,   0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2344   INSN(cmeq,   1, 0b100011, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2345   INSN(cmgt,   0, 0b001101, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2346   INSN(cmge,   0, 0b001111, true);  // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2347 
2348 #undef INSN
2349 
2350 #define INSN(NAME, opc, opc2, accepted) \
2351   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                   \
2352     guarantee(T != T1Q && T != T1D, "incorrect arrangement");                           \
2353     if (accepted < 3) guarantee(T != T2D, "incorrect arrangement");                     \
2354     if (accepted < 2) guarantee(T != T2S, "incorrect arrangement");                     \
2355     if (accepted < 1) guarantee(T == T8B || T == T16B, "incorrect arrangement");        \
2356     starti;                                                                             \
2357     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2358     f((int)T >> 1, 23, 22), f(opc2, 21, 10);                                            \
2359     rf(Vn, 5), rf(Vd, 0);                                                               \
2360   }
2361 
2362   INSN(absr,   0, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2363   INSN(negr,   1, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2364   INSN(notr,   1, 0b100000010110, 0); // accepted arrangements: T8B, T16B
2365   INSN(addv,   0, 0b110001101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2366   INSN(smaxv,  0, 0b110000101010, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2367   INSN(sminv,  0, 0b110001101010, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2368   INSN(cls,    0, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2369   INSN(clz,    1, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2370   INSN(cnt,    0, 0b100000010110, 0); // accepted arrangements: T8B, T16B
2371   INSN(uaddlp, 1, 0b100000001010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
2372   INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2373 
2374 #undef INSN
2375 
2376 #define INSN(NAME, opc) \
2377   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                  \
2378     starti;                                                                            \
2379     assert(T == T4S, "arrangement must be T4S");                                       \
2380     f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24), f(opc, 23),                      \
2381     f(T == T4S ? 0 : 1, 22), f(0b110000111110, 21, 10); rf(Vn, 5), rf(Vd, 0);          \
2382   }
2383 
2384   INSN(fmaxv, 0);
2385   INSN(fminv, 1);
2386 
2387 #undef INSN


2412   INSN(bici, 1, 1);
2413 
2414 #undef INSN
2415 
2416 #define INSN(NAME, op1, op2, op3) \
2417   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2418     starti;                                                                             \
2419     assert(T == T2S || T == T4S || T == T2D, "invalid arrangement");                    \
2420     f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23);            \
2421     f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0);    \
2422   }
2423 
2424   INSN(fadd, 0, 0, 0b110101);
2425   INSN(fdiv, 1, 0, 0b111111);
2426   INSN(fmul, 1, 0, 0b110111);
2427   INSN(fsub, 0, 1, 0b110101);
2428   INSN(fmla, 0, 0, 0b110011);
2429   INSN(fmls, 0, 1, 0b110011);
2430   INSN(fmax, 0, 0, 0b111101);
2431   INSN(fmin, 0, 1, 0b111101);
2432   INSN(fcmeq, 0, 0, 0b111001);
2433   INSN(fcmgt, 1, 1, 0b111001);
2434   INSN(fcmge, 1, 0, 0b111001);
2435 
2436 #undef INSN
2437 
2438 #define INSN(NAME, opc)                                                                 \
2439   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2440     starti;                                                                             \
2441     assert(T == T4S, "arrangement must be T4S");                                        \
2442     f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0);         \
2443   }
2444 
2445   INSN(sha1c,     0b000000);
2446   INSN(sha1m,     0b001000);
2447   INSN(sha1p,     0b000100);
2448   INSN(sha1su0,   0b001100);
2449   INSN(sha256h2,  0b010100);
2450   INSN(sha256h,   0b010000);
2451   INSN(sha256su1, 0b011000);
2452 
2453 #undef INSN
2454 


2490   }
2491 
2492   // FMLA/FMLS - Vector - Scalar
2493   INSN(fmlavs, 0, 0b0001);
2494   INSN(fmlsvs, 0, 0b0101);
2495   // FMULX - Vector - Scalar
2496   INSN(fmulxvs, 1, 0b1001);
2497 
2498 #undef INSN
2499 
2500   // Floating-point Reciprocal Estimate
2501   void frecpe(FloatRegister Vd, FloatRegister Vn, SIMD_RegVariant type) {
2502     assert(type == D || type == S, "Wrong type for frecpe");
2503     starti;
2504     f(0b010111101, 31, 23);
2505     f(type == D ? 1 : 0, 22);
2506     f(0b100001110110, 21, 10);
2507     rf(Vn, 5), rf(Vd, 0);
2508   }
2509 
2510   // (long) {a, b} -> (a + b)
2511   void addpd(FloatRegister Vd, FloatRegister Vn) {
2512     starti;
2513     f(0b0101111011110001101110, 31, 10);
2514     rf(Vn, 5), rf(Vd, 0);
2515   }
2516 
2517   // (Floating-point) {a, b} -> (a + b)
2518   void faddp(FloatRegister Vd, FloatRegister Vn, SIMD_RegVariant type) {
2519     assert(type == D || type == S, "Wrong type for faddp");
2520     starti;
2521     f(0b011111100, 31, 23);
2522     f(type == D ? 1 : 0, 22);
2523     f(0b110000110110, 21, 10);
2524     rf(Vn, 5), rf(Vd, 0);
2525   }
2526 
2527   void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {
2528     starti;
2529     assert(T != Q, "invalid register variant");
2530     f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15);
2531     f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);
2532   }
2533 
2534   void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
2535     starti;
2536     f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
2537     f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);
2538     rf(Vn, 5), rf(Rd, 0);
2539   }
2540 
2541   void smov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
2542     starti;
2543     f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
2544     f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001011, 15, 10);
2545     rf(Vn, 5), rf(Rd, 0);
2546   }
2547 
2548 
2549 #define INSN(NAME, opc, opc2, isSHR)                                    \
2550   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
2551     starti;                                                             \
2552     /* The encodings for the immh:immb fields (bits 22:16) in *SHR are  \
2553      *   0001 xxx       8B/16B, shift = 16  - UInt(immh:immb)           \
2554      *   001x xxx       4H/8H,  shift = 32  - UInt(immh:immb)           \
2555      *   01xx xxx       2S/4S,  shift = 64  - UInt(immh:immb)           \
2556      *   1xxx xxx       1D/2D,  shift = 128 - UInt(immh:immb)           \
2557      *   (1D is RESERVED)                                               \
2558      * for SHL shift is calculated as:                                  \
2559      *   0001 xxx       8B/16B, shift = UInt(immh:immb) - 8             \
2560      *   001x xxx       4H/8H,  shift = UInt(immh:immb) - 16            \
2561      *   01xx xxx       2S/4S,  shift = UInt(immh:immb) - 32            \
2562      *   1xxx xxx       1D/2D,  shift = UInt(immh:immb) - 64            \
2563      *   (1D is RESERVED)                                               \
2564      */                                                                 \
2565     assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value");           \
2566     int cVal = (1 << (((T >> 1) + 3) + (isSHR ? 1 : 0)));               \
2567     int encodedShift = isSHR ? cVal - shift : cVal + shift;             \
2568     f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23),            \
2569     f(encodedShift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0);     \
2570   }
2571 
2572   INSN(shl,  0, 0b010101, /* isSHR = */ false);
2573   INSN(sshr, 0, 0b000001, /* isSHR = */ true);
2574   INSN(ushr, 1, 0b000001, /* isSHR = */ true);
2575 
2576 #undef INSN
2577 
2578 private:
2579   void _xshll(sign_kind sign, FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
2580     starti;
2581     /* The encodings for the immh:immb fields (bits 22:16) are
2582      *   0001 xxx       8H, 8B/16B shift = xxx
2583      *   001x xxx       4S, 4H/8H  shift = xxxx
2584      *   01xx xxx       2D, 2S/4S  shift = xxxxx
2585      *   1xxx xxx       RESERVED
2586      */
2587     assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement");
2588     assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value");
2589     f(0, 31), f(Tb & 1, 30), f(sign == SIGNED ? 0 : 1, 29), f(0b011110, 28, 23);
2590     f((1 << ((Tb>>1)+3))|shift, 22, 16);
2591     f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2592   }
2593 
2594 public:
2595   void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2596     assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement");
2597     _xshll(UNSIGNED, Vd, Ta, Vn, Tb, shift);
2598   }
2599 
2600   void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2601     assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement");
2602     _xshll(UNSIGNED, Vd, Ta, Vn, Tb, shift);
2603   }
2604 
2605   void uxtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb) {
2606     ushll(Vd, Ta, Vn, Tb, 0);
2607   }
2608 
2609   void sshll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2610     assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement");
2611     _xshll(SIGNED, Vd, Ta, Vn, Tb, shift);
2612   }
2613 
2614   void sshll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2615     assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement");
2616     _xshll(SIGNED, Vd, Ta, Vn, Tb, shift);
2617   }
2618 
2619   void sxtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb) {
2620     sshll(Vd, Ta, Vn, Tb, 0);
2621   }
2622 
2623   // Move from general purpose register
2624   //   mov  Vd.T[index], Rn
2625   void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) {
2626     starti;
2627     f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2628     f(0b000111, 15, 10), zrf(Xn, 5), rf(Vd, 0);
2629   }
2630 
2631   // Move to general purpose register
2632   //   mov  Rd, Vn.T[index]
2633   void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) {
2634     guarantee(T >= T2S && T < T1Q, "only D and S arrangements are supported");
2635     starti;
2636     f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21);
2637     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2638     f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0);
2639   }
2640 


2649   }
2650 
2651 public:
2652   void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2653     assert(Tb == T1D || Tb == T8B, "pmull assumes T1D or T8B as the second size specifier");
2654     _pmull(Vd, Ta, Vn, Vm, Tb);
2655   }
2656 
2657   void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2658     assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier");
2659     _pmull(Vd, Ta, Vn, Vm, Tb);
2660   }
2661 
2662   void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
2663     starti;
2664     int size_b = (int)Tb >> 1;
2665     int size_a = (int)Ta >> 1;
2666     assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");
2667     f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22);
2668     f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);
2669   }
2670 
2671   void xtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
2672     starti;
2673     int size_b = (int)Tb >> 1;
2674     int size_a = (int)Ta >> 1;
2675     assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");
2676     f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size_b, 23, 22);
2677     f(0b100001001010, 21, 10), rf(Vn, 5), rf(Vd, 0);
2678   }
2679 
2680   void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
2681   {
2682     starti;
2683     assert(T != T1D, "reserved encoding");
2684     f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2685     f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), zrf(Xs, 5), rf(Vd, 0);
2686   }
2687 
2688   void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)
2689   {
2690     starti;
2691     assert(T != T1D, "reserved encoding");
2692     f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2693     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2694     f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2695   }
2696 
2697   // AdvSIMD ZIP/UZP/TRN


< prev index next >