< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page
rev 60010 : 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 < 2) guarantee(T != T2S && T != T2D, "incorrect arrangement");         \

2273     if (accepted == 0) guarantee(T == T8B || T == T16B, "incorrect arrangement");       \
2274     starti;                                                                             \
2275     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2276     f((int)T >> 1, 23, 22), f(opc2, 21, 10);                                            \
2277     rf(Vn, 5), rf(Vd, 0);                                                               \
2278   }
2279 
2280   INSN(absr,   0, 0b100000101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2281   INSN(negr,   1, 0b100000101110, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
2282   INSN(notr,   1, 0b100000010110, 0); // accepted arrangements: T8B, T16B
2283   INSN(addv,   0, 0b110001101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2284   INSN(cls,    0, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2285   INSN(clz,    1, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S


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


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



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


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










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








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

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


















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


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









2544   }
2545 
2546   void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
2547   {
2548     starti;
2549     assert(T != T1D, "reserved encoding");
2550     f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2551     f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), zrf(Xs, 5), rf(Vd, 0);
2552   }
2553 
2554   void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)
2555   {
2556     starti;
2557     assert(T != T1D, "reserved encoding");
2558     f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2559     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2560     f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2561   }
2562 
2563   // 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 == 2) guarantee(T != T2D, "incorrect arrangement");                    \
2354     if (accepted == 1) guarantee(T != T2S && T != T2D, "incorrect arrangement");        \
2355     if (accepted == 0) 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(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H,      T4S
2372 
2373 #undef INSN
2374 
2375 #define INSN(NAME, opc) \
2376   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                  \
2377     starti;                                                                            \
2378     assert(T == T4S, "arrangement must be T4S");                                       \
2379     f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24), f(opc, 23),                      \
2380     f(T == T4S ? 0 : 1, 22), f(0b110000111110, 21, 10); rf(Vn, 5), rf(Vd, 0);          \
2381   }
2382 
2383   INSN(fmaxv, 0);
2384   INSN(fminv, 1);
2385 
2386 #undef INSN
2387 
2388 #define INSN(NAME, op0, cmode0) \
2389   void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) {   \


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


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


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


< prev index next >