< prev index next >

src/cpu/aarch64/vm/assembler_aarch64.hpp

Print this page
rev 8393 : 8079565: aarch64: Add vectorization support for aarch64
Summary: Add vectorization support
Reviewed-by: duke


 449     return _offset;
 450   }
 451   Register index() const {
 452     return _index;
 453   }
 454   mode getMode() const {
 455     return _mode;
 456   }
 457   bool uses(Register reg) const { return _base == reg || _index == reg; }
 458   address target() const { return _target; }
 459   const RelocationHolder& rspec() const { return _rspec; }
 460 
 461   void encode(Instruction_aarch64 *i) const {
 462     i->f(0b111, 29, 27);
 463     i->srf(_base, 5);
 464 
 465     switch(_mode) {
 466     case base_plus_offset:
 467       {
 468         unsigned size = i->get(31, 30);





 469         unsigned mask = (1 << size) - 1;
 470         if (_offset < 0 || _offset & mask)
 471           {
 472             i->f(0b00, 25, 24);
 473             i->f(0, 21), i->f(0b00, 11, 10);
 474             i->sf(_offset, 20, 12);
 475           } else {
 476             i->f(0b01, 25, 24);
 477             i->f(_offset >> size, 21, 10);
 478           }
 479       }
 480       break;
 481 
 482     case base_plus_offset_reg:
 483       {
 484         i->f(0b00, 25, 24);
 485         i->f(1, 21);
 486         i->rf(_index, 16);
 487         i->f(_ext.option(), 15, 13);
 488         unsigned size = i->get(31, 30);


1871   }
1872   void fmovd(FloatRegister Vn, double value) {
1873     if (value)
1874       fmov_imm(Vn, value, 0b01);
1875     else
1876       fmovd(Vn, zr);
1877   }
1878 
1879 /* SIMD extensions
1880  *
1881  * We just use FloatRegister in the following. They are exactly the same
1882  * as SIMD registers.
1883  */
1884  public:
1885 
1886   enum SIMD_Arrangement {
1887        T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D
1888   };
1889 
1890   enum SIMD_RegVariant {
1891        S32, D64, Q128
1892   };
1893 









1894 
1895  private:
1896 
1897   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) {
1898     starti;
1899     f(0,31), f((int)T & 1, 30);
1900     f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12);
1901     f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);
1902   }
1903   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
1904              int imm, int op1, int op2) {
1905     starti;
1906     f(0,31), f((int)T & 1, 30);
1907     f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);
1908     f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);
1909   }
1910   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
1911              Register Xm, int op1, int op2) {
1912     starti;
1913     f(0,31), f((int)T & 1, 30);


1991 
1992 #define INSN(NAME, opc)                                                                 \
1993   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
1994     starti;                                                                             \
1995     assert(T == T8B || T == T16B, "must be T8B or T16B");                               \
1996     f(0, 31), f((int)T & 1, 30), f(opc, 29, 21);                                        \
1997     rf(Vm, 16), f(0b000111, 15, 10), rf(Vn, 5), rf(Vd, 0);                              \
1998   }
1999 
2000   INSN(eor, 0b101110001);
2001   INSN(orr, 0b001110101);
2002   INSN(andr, 0b001110001);
2003   INSN(bic, 0b001110011);
2004   INSN(bif, 0b101110111);
2005   INSN(bit, 0b101110101);
2006   INSN(bsl, 0b101110011);
2007   INSN(orn, 0b001110111);
2008 
2009 #undef INSN
2010 
2011 #define INSN(NAME, opc)                                                                 \
2012   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2013     starti;                                                                             \
2014     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2015     f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(0b100001, 15, 10);                  \
2016     rf(Vn, 5), rf(Vd, 0);                                                               \
2017   }
2018 
2019   INSN(addv, 0);
2020   INSN(subv, 1);




























































2021 
2022 #undef INSN
2023 
2024 #define INSN(NAME, opc)                                                                 \
2025   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2026     starti;                                                                             \
2027     assert(T == T4S, "arrangement must be T4S");                                        \
2028     f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0);         \
2029   }
2030 
2031   INSN(sha1c,     0b000000);
2032   INSN(sha1m,     0b001000);
2033   INSN(sha1p,     0b000100);
2034   INSN(sha1su0,   0b001100);
2035   INSN(sha256h2,  0b010100);
2036   INSN(sha256h,   0b010000);
2037   INSN(sha256su1, 0b011000);
2038 
2039 #undef INSN
2040 


2047 
2048   INSN(sha1h,     0b000010);
2049   INSN(sha1su1,   0b000110);
2050   INSN(sha256su0, 0b001010);
2051 
2052 #undef INSN
2053 
2054 #define INSN(NAME, opc)                           \
2055   void NAME(FloatRegister Vd, FloatRegister Vn) { \
2056     starti;                                       \
2057     f(opc, 31, 10), rf(Vn, 5), rf(Vd, 0);         \
2058   }
2059 
2060   INSN(aese, 0b0100111000101000010010);
2061   INSN(aesd, 0b0100111000101000010110);
2062   INSN(aesmc, 0b0100111000101000011010);
2063   INSN(aesimc, 0b0100111000101000011110);
2064 
2065 #undef INSN
2066 
2067   void shl(FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement T, int shift){
2068     starti;
2069     /* The encodings for the immh:immb fields (bits 22:16) are
2070      *   0001 xxx       8B/16B, shift = xxx
2071      *   001x xxx       4H/8H,  shift = xxxx
2072      *   01xx xxx       2S/4S,  shift = xxxxx
2073      *   1xxx xxx       1D/2D,  shift = xxxxxx (1D is RESERVED)
2074      */
2075     assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value");
2076     f(0, 31), f(T & 1, 30), f(0b0011110, 29, 23), f((1 << ((T>>1)+3))|shift, 22, 16);
2077     f(0b010101, 15, 10), rf(Vn, 5), rf(Vd, 0);















2078   }
2079 






2080   void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
2081     starti;
2082     /* The encodings for the immh:immb fields (bits 22:16) are
2083      *   0001 xxx       8H, 8B/16b shift = xxx
2084      *   001x xxx       4S, 4H/8H  shift = xxxx
2085      *   01xx xxx       2D, 2S/4S  shift = xxxxx
2086      *   1xxx xxx       RESERVED
2087      */
2088     assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement");
2089     assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value");
2090     f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16);
2091     f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2092   }
2093   void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2094     ushll(Vd, Ta, Vn, Tb, shift);
2095   }
2096 
2097   void uzp1(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm,  SIMD_Arrangement T, int op = 0){
2098     starti;
2099     f(0, 31), f((T & 0x1), 30), f(0b001110, 29, 24), f((T >> 1), 23, 22), f(0, 21);


2130   void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2131     pmull(Vd, Ta, Vn, Vm, Tb);
2132   }
2133 
2134   void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
2135     starti;
2136     int size_b = (int)Tb >> 1;
2137     int size_a = (int)Ta >> 1;
2138     assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");
2139     f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22);
2140     f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);
2141   }
2142 
2143   void rev32(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn)
2144   {
2145     starti;
2146     assert(T <= T8H, "must be one of T8B, T16B, T4H, T8H");
2147     f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24);
2148     f(T <= T16B ? 0b00 : 0b01, 23, 22), f(0b100000000010, 21, 10);
2149     rf(Vn, 5), rf(Vd, 0);

















2150   }
2151 
2152   // CRC32 instructions
2153 #define INSN(NAME, sf, sz)                                                \
2154   void NAME(Register Rd, Register Rn, Register Rm) {                      \
2155     starti;                                                               \
2156     f(sf, 31), f(0b0011010110, 30, 21), f(0b0100, 15, 12), f(sz, 11, 10); \
2157     rf(Rm, 16), rf(Rn, 5), rf(Rd, 0);                                     \
2158   }
2159 
2160   INSN(crc32b, 0, 0b00);
2161   INSN(crc32h, 0, 0b01);
2162   INSN(crc32w, 0, 0b10);
2163   INSN(crc32x, 1, 0b11);
2164 
2165 #undef INSN
2166 
2167 
2168 /* Simulator extensions to the ISA
2169 




 449     return _offset;
 450   }
 451   Register index() const {
 452     return _index;
 453   }
 454   mode getMode() const {
 455     return _mode;
 456   }
 457   bool uses(Register reg) const { return _base == reg || _index == reg; }
 458   address target() const { return _target; }
 459   const RelocationHolder& rspec() const { return _rspec; }
 460 
 461   void encode(Instruction_aarch64 *i) const {
 462     i->f(0b111, 29, 27);
 463     i->srf(_base, 5);
 464 
 465     switch(_mode) {
 466     case base_plus_offset:
 467       {
 468         unsigned size = i->get(31, 30);
 469         if (i->get(26, 26) && i->get(23, 23)) {
 470           // SIMD Q Type - Size = 128 bits
 471           assert(size == 0, "bad size");
 472           size = 0b100;
 473         }
 474         unsigned mask = (1 << size) - 1;
 475         if (_offset < 0 || _offset & mask)
 476           {
 477             i->f(0b00, 25, 24);
 478             i->f(0, 21), i->f(0b00, 11, 10);
 479             i->sf(_offset, 20, 12);
 480           } else {
 481             i->f(0b01, 25, 24);
 482             i->f(_offset >> size, 21, 10);
 483           }
 484       }
 485       break;
 486 
 487     case base_plus_offset_reg:
 488       {
 489         i->f(0b00, 25, 24);
 490         i->f(1, 21);
 491         i->rf(_index, 16);
 492         i->f(_ext.option(), 15, 13);
 493         unsigned size = i->get(31, 30);


1876   }
1877   void fmovd(FloatRegister Vn, double value) {
1878     if (value)
1879       fmov_imm(Vn, value, 0b01);
1880     else
1881       fmovd(Vn, zr);
1882   }
1883 
1884 /* SIMD extensions
1885  *
1886  * We just use FloatRegister in the following. They are exactly the same
1887  * as SIMD registers.
1888  */
1889  public:
1890 
1891   enum SIMD_Arrangement {
1892        T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D
1893   };
1894 
1895   enum SIMD_RegVariant {
1896        B, H, S, D, Q
1897   };
1898 
1899 #define INSN(NAME, op)                                            \
1900   void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) {   \
1901     ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
1902   }                                                                      \
1903 
1904   INSN(ldr, 1);
1905   INSN(str, 0);
1906 
1907 #undef INSN
1908 
1909  private:
1910 
1911   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) {
1912     starti;
1913     f(0,31), f((int)T & 1, 30);
1914     f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12);
1915     f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);
1916   }
1917   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
1918              int imm, int op1, int op2) {
1919     starti;
1920     f(0,31), f((int)T & 1, 30);
1921     f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);
1922     f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);
1923   }
1924   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
1925              Register Xm, int op1, int op2) {
1926     starti;
1927     f(0,31), f((int)T & 1, 30);


2005 
2006 #define INSN(NAME, opc)                                                                 \
2007   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2008     starti;                                                                             \
2009     assert(T == T8B || T == T16B, "must be T8B or T16B");                               \
2010     f(0, 31), f((int)T & 1, 30), f(opc, 29, 21);                                        \
2011     rf(Vm, 16), f(0b000111, 15, 10), rf(Vn, 5), rf(Vd, 0);                              \
2012   }
2013 
2014   INSN(eor,  0b101110001);
2015   INSN(orr,  0b001110101);
2016   INSN(andr, 0b001110001);
2017   INSN(bic,  0b001110011);
2018   INSN(bif,  0b101110111);
2019   INSN(bit,  0b101110101);
2020   INSN(bsl,  0b101110011);
2021   INSN(orn,  0b001110111);
2022 
2023 #undef INSN
2024 
2025 #define INSN(NAME, opc, opc2)                                                                 \
2026   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2027     starti;                                                                             \
2028     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2029     f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10);                      \
2030     rf(Vn, 5), rf(Vd, 0);                                                               \
2031   }
2032 
2033   INSN(addv, 0, 0b100001);
2034   INSN(subv, 1, 0b100001);
2035   INSN(mulv, 0, 0b100111);
2036   INSN(sshl, 0, 0b010001);
2037   INSN(ushl, 1, 0b010001);
2038 
2039 #undef INSN
2040 
2041 #define INSN(NAME, opc, opc2) \
2042   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {                   \
2043     starti;                                                                             \
2044     f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24);                        \
2045     f((int)T >> 1, 23, 22), f(opc2, 21, 10);                                            \
2046     rf(Vn, 5), rf(Vd, 0);                                                               \
2047   }
2048 
2049   INSN(absr,  0, 0b100000101110);
2050   INSN(negr,  1, 0b100000101110);
2051   INSN(notr,  1, 0b100000010110);
2052   INSN(addv,  0, 0b110001101110);
2053 
2054 #undef INSN
2055 
2056 #define INSN(NAME, op0, cmode0) \
2057   void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) {   \
2058     unsigned cmode = cmode0;                                                           \
2059     unsigned op = op0;                                                                 \
2060     starti;                                                                            \
2061     assert(lsl == 0 ||                                                                 \
2062            ((T == T4H || T == T8H) && lsl == 8) ||                                     \
2063            ((T == T2S || T == T4S) && ((lsl >> 3) < 4)), "invalid shift");             \
2064     cmode |= lsl >> 2;                                                                 \
2065     if (T == T4H || T == T8H) cmode |= 0b1000;                                         \
2066     if (!(T == T4H || T == T8H || T == T2S || T == T4S)) {                             \
2067       assert(op == 0 && cmode0 == 0, "must be MOVI");                                  \
2068       cmode = 0b1110;                                                                  \
2069       if (T == T1D || T == T2D) op = 1;                                                \
2070     }                                                                                  \
2071     f(0, 31), f((int)T & 1, 30), f(op, 29), f(0b0111100000, 28, 19);                   \
2072     f(imm8 >> 5, 18, 16), f(cmode, 15, 12), f(0x01, 11, 10), f(imm8 & 0b11111, 9, 5);  \
2073     rf(Vd, 0);                                                                         \
2074   }
2075 
2076   INSN(movi, 0, 0);
2077   INSN(orri, 0, 1);
2078   INSN(mvni, 1, 0);
2079   INSN(bici, 1, 1);
2080 
2081 #undef INSN
2082 
2083 #define INSN(NAME, op1, op2, op3) \
2084   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2085     starti;                                                                             \
2086     assert(T == T2S || T == T4S || T == T2D, "invalid arrangement");                    \
2087     f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23);            \
2088     f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0);    \
2089   }
2090 
2091   INSN(fadd, 0, 0, 0b110101);
2092   INSN(fdiv, 1, 0, 0b111111);
2093   INSN(fmul, 1, 0, 0b110111);
2094   INSN(fsub, 0, 1, 0b110101);
2095 
2096 #undef INSN
2097 
2098 #define INSN(NAME, opc)                                                                 \
2099   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
2100     starti;                                                                             \
2101     assert(T == T4S, "arrangement must be T4S");                                        \
2102     f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0);         \
2103   }
2104 
2105   INSN(sha1c,     0b000000);
2106   INSN(sha1m,     0b001000);
2107   INSN(sha1p,     0b000100);
2108   INSN(sha1su0,   0b001100);
2109   INSN(sha256h2,  0b010100);
2110   INSN(sha256h,   0b010000);
2111   INSN(sha256su1, 0b011000);
2112 
2113 #undef INSN
2114 


2121 
2122   INSN(sha1h,     0b000010);
2123   INSN(sha1su1,   0b000110);
2124   INSN(sha256su0, 0b001010);
2125 
2126 #undef INSN
2127 
2128 #define INSN(NAME, opc)                           \
2129   void NAME(FloatRegister Vd, FloatRegister Vn) { \
2130     starti;                                       \
2131     f(opc, 31, 10), rf(Vn, 5), rf(Vd, 0);         \
2132   }
2133 
2134   INSN(aese, 0b0100111000101000010010);
2135   INSN(aesd, 0b0100111000101000010110);
2136   INSN(aesmc, 0b0100111000101000011010);
2137   INSN(aesimc, 0b0100111000101000011110);
2138 
2139 #undef INSN
2140 
2141   void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {
2142     starti;
2143     assert(T != Q, "invalid register variant");
2144     f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15);
2145     f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);
2146   }
2147 
2148   void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
2149     starti;
2150     f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
2151     f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);
2152     rf(Vn, 5), rf(Rd, 0);
2153   }
2154 
2155 #define INSN(NAME, opc, opc2) \
2156   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){         \
2157     starti;                                                                             \
2158     /* The encodings for the immh:immb fields (bits 22:16) are                          \
2159      *   0001 xxx       8B/16B, shift = xxx                                             \
2160      *   001x xxx       4H/8H,  shift = xxxx                                            \
2161      *   01xx xxx       2S/4S,  shift = xxxxx                                           \
2162      *   1xxx xxx       1D/2D,  shift = xxxxxx (1D is RESERVED)                         \
2163      */                                                                                 \
2164     assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value");                           \
2165     f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23),                            \
2166     f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0);          \
2167   }
2168 
2169   INSN(shl,  0, 0b010101);
2170   INSN(sshr, 0, 0b000001);
2171   INSN(ushr, 1, 0b000001);
2172 
2173 #undef INSN
2174 
2175   void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
2176     starti;
2177     /* The encodings for the immh:immb fields (bits 22:16) are
2178      *   0001 xxx       8H, 8B/16b shift = xxx
2179      *   001x xxx       4S, 4H/8H  shift = xxxx
2180      *   01xx xxx       2D, 2S/4S  shift = xxxxx
2181      *   1xxx xxx       RESERVED
2182      */
2183     assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement");
2184     assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value");
2185     f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16);
2186     f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2187   }
2188   void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,  SIMD_Arrangement Tb, int shift) {
2189     ushll(Vd, Ta, Vn, Tb, shift);
2190   }
2191 
2192   void uzp1(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm,  SIMD_Arrangement T, int op = 0){
2193     starti;
2194     f(0, 31), f((T & 0x1), 30), f(0b001110, 29, 24), f((T >> 1), 23, 22), f(0, 21);


2225   void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
2226     pmull(Vd, Ta, Vn, Vm, Tb);
2227   }
2228 
2229   void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
2230     starti;
2231     int size_b = (int)Tb >> 1;
2232     int size_a = (int)Ta >> 1;
2233     assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");
2234     f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22);
2235     f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);
2236   }
2237 
2238   void rev32(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn)
2239   {
2240     starti;
2241     assert(T <= T8H, "must be one of T8B, T16B, T4H, T8H");
2242     f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24);
2243     f(T <= T16B ? 0b00 : 0b01, 23, 22), f(0b100000000010, 21, 10);
2244     rf(Vn, 5), rf(Vd, 0);
2245   }
2246 
2247   void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
2248   {
2249     starti;
2250     assert(T != T1D, "reserved encoding");
2251     f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2252     f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), rf(Xs, 5), rf(Vd, 0);
2253   }
2254 
2255   void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)
2256   {
2257     starti;
2258     assert(T != T1D, "reserved encoding");
2259     f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);
2260     f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
2261     f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);
2262   }
2263 
2264   // CRC32 instructions
2265 #define INSN(NAME, sf, sz)                                                \
2266   void NAME(Register Rd, Register Rn, Register Rm) {                      \
2267     starti;                                                               \
2268     f(sf, 31), f(0b0011010110, 30, 21), f(0b0100, 15, 12), f(sz, 11, 10); \
2269     rf(Rm, 16), rf(Rn, 5), rf(Rd, 0);                                     \
2270   }
2271 
2272   INSN(crc32b, 0, 0b00);
2273   INSN(crc32h, 0, 0b01);
2274   INSN(crc32w, 0, 0b10);
2275   INSN(crc32x, 1, 0b11);
2276 
2277 #undef INSN
2278 
2279 
2280 /* Simulator extensions to the ISA
2281 


< prev index next >