< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page
rev 61868 : manual merge with default

*** 1328,1337 **** --- 1328,1352 ---- INSN(ldrd, 0b01, 1); INSN(ldrq, 0b10, 1); #undef INSN + #define INSN(NAME, size, opc) \ + void NAME(FloatRegister Rt, Register Rn) { \ + starti; \ + f(size, 31, 30), f(0b111100, 29, 24), f(opc, 23, 22), f(0, 21); \ + f(0, 20, 12), f(0b01, 11, 10); \ + rf(Rn, 5), rf((Register)Rt, 0); \ + } + + INSN(ldrs, 0b10, 0b01); + INSN(ldrd, 0b11, 0b01); + INSN(ldrq, 0b00, 0b11); + + #undef INSN + + #define INSN(NAME, opc, V) \ void NAME(address dest, prfop op = PLDL1KEEP) { \ long offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \
*** 1465,1474 **** --- 1480,1504 ---- INSN(strq, 0b00, 0b10); INSN(ldrq, 0x00, 0b11); #undef INSN + /* SIMD extensions + * + * We just use FloatRegister in the following. They are exactly the same + * as SIMD registers. + */ + public: + + enum SIMD_Arrangement { + T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q + }; + + enum SIMD_RegVariant { + B, H, S, D, Q + }; + enum shift_kind { LSL, LSR, ASR, ROR }; void op_shifted_reg(unsigned decode, enum shift_kind kind, unsigned shift, unsigned size, unsigned op) {
*** 1839,1848 **** --- 1869,1902 ---- void fmovs(FloatRegister Vd, FloatRegister Vn) { assert(Vd != Vn, "should be"); i_fmovs(Vd, Vn); } + private: + void _fcvt_narrow_extend(FloatRegister Vd, SIMD_Arrangement Ta, + FloatRegister Vn, SIMD_Arrangement Tb, bool do_extend) { + assert((do_extend && (Tb >> 1) + 1 == (Ta >> 1)) + || (!do_extend && (Ta >> 1) + 1 == (Tb >> 1)), "Incompatible arrangement"); + starti; + int op30 = (do_extend ? Tb : Ta) & 1; + int op22 = ((do_extend ? Ta : Tb) >> 1) & 1; + f(0, 31), f(op30, 30), f(0b0011100, 29, 23), f(op22, 22); + f(0b100001011, 21, 13), f(do_extend ? 1 : 0, 12), f(0b10, 11, 10); + rf(Vn, 5), rf(Vd, 0); + } + + public: + void fcvtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb) { + assert(Tb == T4H || Tb == T8H|| Tb == T2S || Tb == T4S, "invalid arrangement"); + _fcvt_narrow_extend(Vd, Ta, Vn, Tb, true); + } + + void fcvtn(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb) { + assert(Ta == T4H || Ta == T8H|| Ta == T2S || Ta == T4S, "invalid arrangement"); + _fcvt_narrow_extend(Vd, Ta, Vn, Tb, false); + } + #undef INSN // Floating-point data-processing (2 source) void data_processing(unsigned op31, unsigned type, unsigned opcode, FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {
*** 1975,1984 **** --- 2029,2075 ---- // INSN(fmovhid, 0b100, 0b10, 0b01, 0b111); #undef INSN + enum sign_kind { SIGNED, UNSIGNED }; + + private: + void _xcvtf_scalar_integer(sign_kind sign, unsigned sz, + FloatRegister Rd, FloatRegister Rn) { + starti; + f(0b01, 31, 30), f(sign == SIGNED ? 0 : 1, 29); + f(0b111100, 27, 23), f((sz >> 1) & 1, 22), f(0b100001110110, 21, 10); + rf(Rn, 5), rf(Rd, 0); + } + + public: + #define INSN(NAME, sign, sz) \ + void NAME(FloatRegister Rd, FloatRegister Rn) { \ + _xcvtf_scalar_integer(sign, sz, Rd, Rn); \ + } + + INSN(scvtfs, SIGNED, 0); + INSN(scvtfd, SIGNED, 1); + + #undef INSN + + private: + void _xcvtf_vector_integer(sign_kind sign, SIMD_Arrangement T, + FloatRegister Rd, FloatRegister Rn) { + assert(T == T2S || T == T4S || T == T2D, "invalid arrangement"); + starti; + f(0, 31), f(T & 1, 30), f(sign == SIGNED ? 0 : 1, 29); + f(0b011100, 28, 23), f((T >> 1) & 1, 22), f(0b100001110110, 21, 10); + rf(Rn, 5), rf(Rd, 0); + } + + public: + void scvtfv(SIMD_Arrangement T, FloatRegister Rd, FloatRegister Rn) { + _xcvtf_vector_integer(SIGNED, T, Rd, Rn); + } + // Floating-point compare void float_compare(unsigned op31, unsigned type, unsigned op, unsigned op2, FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) { starti;
*** 2089,2113 **** INSN(frintpd, 0b01, 0b001); INSN(frintxd, 0b01, 0b110); INSN(frintzd, 0b01, 0b011); #undef INSN - /* SIMD extensions - * - * We just use FloatRegister in the following. They are exactly the same - * as SIMD registers. - */ - public: - - enum SIMD_Arrangement { - T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q - }; - - enum SIMD_RegVariant { - B, H, S, D, Q - }; - private: static short SIMD_Size_in_bytes[]; public: #define INSN(NAME, op) \ --- 2180,2189 ----
*** 2261,2270 **** --- 2337,2351 ---- INSN(ushl, 1, 0b010001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(addpv, 0, 0b101111, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(maxv, 0, 0b011001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(minv, 0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(cmeq, 1, 0b100011, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmgt, 0, 0b001101, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmge, 0, 0b001111, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D #undef INSN #define INSN(NAME, opc, opc2, accepted) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
*** 2280,2289 **** --- 2361,2372 ---- INSN(absr, 0, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(negr, 1, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(notr, 1, 0b100000010110, 0); // accepted arrangements: T8B, T16B INSN(addv, 0, 0b110001101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S + INSN(smaxv, 0, 0b110000101010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S + INSN(sminv, 0, 0b110001101010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S INSN(cls, 0, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(clz, 1, 0b100000010010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(cnt, 0, 0b100000010110, 0); // accepted arrangements: T8B, T16B INSN(uaddlp, 1, 0b100000001010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
*** 2344,2353 **** --- 2427,2439 ---- INSN(fsub, 0, 1, 0b110101); INSN(fmla, 0, 0, 0b110011); INSN(fmls, 0, 1, 0b110011); INSN(fmax, 0, 0, 0b111101); INSN(fmin, 0, 1, 0b111101); + INSN(fcmeq, 0, 0, 0b111001); + INSN(fcmgt, 1, 1, 0b111001); + INSN(fcmge, 1, 0, 0b111001); #undef INSN #define INSN(NAME, opc) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
*** 2419,2432 **** f(type == D ? 1 : 0, 22); f(0b100001110110, 21, 10); rf(Vn, 5), rf(Vd, 0); } ! // (double) {a, b} -> (a + b) ! void faddpd(FloatRegister Vd, FloatRegister Vn) { starti; ! f(0b0111111001110000110110, 31, 10); rf(Vn, 5), rf(Vd, 0); } void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) { starti; --- 2505,2528 ---- f(type == D ? 1 : 0, 22); f(0b100001110110, 21, 10); rf(Vn, 5), rf(Vd, 0); } ! // (long) {a, b} -> (a + b) ! void addpd(FloatRegister Vd, FloatRegister Vn) { starti; ! f(0b0101111011110001101110, 31, 10); ! rf(Vn, 5), rf(Vd, 0); ! } ! ! // (Floating-point) {a, b} -> (a + b) ! void faddp(FloatRegister Vd, FloatRegister Vn, SIMD_RegVariant type) { ! assert(type == D || type == S, "Wrong type for faddp"); ! starti; ! f(0b011111100, 31, 23); ! f(type == D ? 1 : 0, 22); ! f(0b110000110110, 21, 10); rf(Vn, 5), rf(Vd, 0); } void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) { starti;
*** 2440,2449 **** --- 2536,2553 ---- f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21); f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10); rf(Vn, 5), rf(Rd, 0); } + void smov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) { + starti; + f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21); + f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001011, 15, 10); + rf(Vn, 5), rf(Rd, 0); + } + + #define INSN(NAME, opc, opc2, isSHR) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \ starti; \ /* The encodings for the immh:immb fields (bits 22:16) in *SHR are \ * 0001 xxx 8B/16B, shift = 16 - UInt(immh:immb) \
*** 2470,2502 **** INSN(ushr, 1, 0b000001, /* isSHR = */ true); #undef INSN private: ! void _ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { starti; /* The encodings for the immh:immb fields (bits 22:16) are ! * 0001 xxx 8H, 8B/16b shift = xxx * 001x xxx 4S, 4H/8H shift = xxxx * 01xx xxx 2D, 2S/4S shift = xxxxx * 1xxx xxx RESERVED */ assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement"); assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value"); ! f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16); f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0); } public: void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement"); ! _ushll(Vd, Ta, Vn, Tb, shift); } void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement"); ! _ushll(Vd, Ta, Vn, Tb, shift); } // Move from general purpose register // mov Vd.T[index], Rn void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) { --- 2574,2625 ---- INSN(ushr, 1, 0b000001, /* isSHR = */ true); #undef INSN private: ! void _xshll(sign_kind sign, FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { starti; /* The encodings for the immh:immb fields (bits 22:16) are ! * 0001 xxx 8H, 8B/16B shift = xxx * 001x xxx 4S, 4H/8H shift = xxxx * 01xx xxx 2D, 2S/4S shift = xxxxx * 1xxx xxx RESERVED */ assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement"); assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value"); ! f(0, 31), f(Tb & 1, 30), f(sign == SIGNED ? 0 : 1, 29), f(0b011110, 28, 23); ! f((1 << ((Tb>>1)+3))|shift, 22, 16); f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0); } public: void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement"); ! _xshll(UNSIGNED, Vd, Ta, Vn, Tb, shift); } void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement"); ! _xshll(UNSIGNED, Vd, Ta, Vn, Tb, shift); ! } ! ! void uxtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb) { ! ushll(Vd, Ta, Vn, Tb, 0); ! } ! ! void sshll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { ! assert(Tb == T8B || Tb == T4H || Tb == T2S, "invalid arrangement"); ! _xshll(SIGNED, Vd, Ta, Vn, Tb, shift); ! } ! ! void sshll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { ! assert(Tb == T16B || Tb == T8H || Tb == T4S, "invalid arrangement"); ! _xshll(SIGNED, Vd, Ta, Vn, Tb, shift); ! } ! ! void sxtl(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb) { ! sshll(Vd, Ta, Vn, Tb, 0); } // Move from general purpose register // mov Vd.T[index], Rn void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) {
*** 2543,2552 **** --- 2666,2684 ---- assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier"); f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22); f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0); } + void xtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) { + starti; + int size_b = (int)Tb >> 1; + int size_a = (int)Ta >> 1; + assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier"); + f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size_b, 23, 22); + f(0b100001001010, 21, 10), rf(Vn, 5), rf(Vd, 0); + } + void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs) { starti; assert(T != T1D, "reserved encoding"); f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
< prev index next >