< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page

        

*** 274,284 **** } unsigned get(int msb = 31, int lsb = 0) { int nbits = msb - lsb + 1; unsigned mask = ((1U << nbits) - 1) << lsb; ! assert_cond((bits & mask) == mask); return (insn & mask) >> lsb; } void fixed(unsigned value, unsigned mask) { assert_cond ((mask & bits) == 0); --- 274,284 ---- } unsigned get(int msb = 31, int lsb = 0) { int nbits = msb - lsb + 1; unsigned mask = ((1U << nbits) - 1) << lsb; ! assert_cond(bits & mask == mask); return (insn & mask) >> lsb; } void fixed(unsigned value, unsigned mask) { assert_cond ((mask & bits) == 0);
*** 304,319 **** public: Pre(Register reg, int o) : PrePost(reg, o) { } }; class Post : public PrePost { Register _idx; - bool _is_postreg; public: ! Post(Register reg, int o) : PrePost(reg, o) { _idx = NULL; _is_postreg = false; } ! Post(Register reg, Register idx) : PrePost(reg, 0) { _idx = idx; _is_postreg = true; } Register idx_reg() { return _idx; } - bool is_postreg() {return _is_postreg; } }; namespace ext { enum operation { uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx }; --- 304,317 ---- public: Pre(Register reg, int o) : PrePost(reg, o) { } }; class Post : public PrePost { Register _idx; public: ! Post(Register reg, int o) : PrePost(reg, o) { _idx = NULL; } ! Post(Register reg, Register idx) : PrePost(reg, 0) { _idx = idx; } Register idx_reg() { return _idx; } }; namespace ext { enum operation { uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx };
*** 393,403 **** _ext(ext), _target(0) { } Address(Pre p) : _base(p.reg()), _offset(p.offset()), _mode(pre) { } Address(Post p) : _base(p.reg()), _index(p.idx_reg()), _offset(p.offset()), ! _mode(p.is_postreg() ? post_reg : post), _target(0) { } Address(address target, RelocationHolder const& rspec) : _mode(literal), _rspec(rspec), _is_lval(false), _target(target) { } --- 391,401 ---- _ext(ext), _target(0) { } Address(Pre p) : _base(p.reg()), _offset(p.offset()), _mode(pre) { } Address(Post p) : _base(p.reg()), _index(p.idx_reg()), _offset(p.offset()), ! _mode(p.idx_reg() == NULL ? post : post_reg), _target(0) { } Address(address target, RelocationHolder const& rspec) : _mode(literal), _rspec(rspec), _is_lval(false), _target(target) { }
*** 807,844 **** INSN(movk, 0b111); #undef INSN // Bitfield ! #define INSN(NAME, opcode, size) \ void NAME(Register Rd, Register Rn, unsigned immr, unsigned imms) { \ starti; \ - guarantee(size == 1 || (immr < 32 && imms < 32), "incorrect immr/imms");\ f(opcode, 31, 22), f(immr, 21, 16), f(imms, 15, 10); \ zrf(Rn, 5), rf(Rd, 0); \ } ! INSN(sbfmw, 0b0001001100, 0); ! INSN(bfmw, 0b0011001100, 0); ! INSN(ubfmw, 0b0101001100, 0); ! INSN(sbfm, 0b1001001101, 1); ! INSN(bfm, 0b1011001101, 1); ! INSN(ubfm, 0b1101001101, 1); #undef INSN // Extract ! #define INSN(NAME, opcode, size) \ void NAME(Register Rd, Register Rn, Register Rm, unsigned imms) { \ starti; \ - guarantee(size == 1 || imms < 32, "incorrect imms"); \ f(opcode, 31, 21), f(imms, 15, 10); \ ! zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \ } ! INSN(extrw, 0b00010011100, 0); ! INSN(extr, 0b10010011110, 1); #undef INSN // The maximum range of a branch is fixed for the AArch64 // architecture. In debug mode we shrink it in order to test --- 805,840 ---- INSN(movk, 0b111); #undef INSN // Bitfield ! #define INSN(NAME, opcode) \ void NAME(Register Rd, Register Rn, unsigned immr, unsigned imms) { \ starti; \ f(opcode, 31, 22), f(immr, 21, 16), f(imms, 15, 10); \ zrf(Rn, 5), rf(Rd, 0); \ } ! INSN(sbfmw, 0b0001001100); ! INSN(bfmw, 0b0011001100); ! INSN(ubfmw, 0b0101001100); ! INSN(sbfm, 0b1001001101); ! INSN(bfm, 0b1011001101); ! INSN(ubfm, 0b1101001101); #undef INSN // Extract ! #define INSN(NAME, opcode) \ void NAME(Register Rd, Register Rn, Register Rm, unsigned imms) { \ starti; \ f(opcode, 31, 21), f(imms, 15, 10); \ ! rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ } ! INSN(extrw, 0b00010011100); ! INSN(extr, 0b10010011110); #undef INSN // The maximum range of a branch is fixed for the AArch64 // architecture. In debug mode we shrink it in order to test
*** 1128,1138 **** void load_store_exclusive(Register Rs, Register Rt1, Register Rt2, Register Rn, enum operand_size sz, int op, bool ordered) { starti; f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21); ! rf(Rs, 16), f(ordered, 15), zrf(Rt2, 10), srf(Rn, 5), zrf(Rt1, 0); } void load_exclusive(Register dst, Register addr, enum operand_size sz, bool ordered) { load_store_exclusive(dummy_reg, dst, dummy_reg, addr, --- 1124,1134 ---- void load_store_exclusive(Register Rs, Register Rt1, Register Rt2, Register Rn, enum operand_size sz, int op, bool ordered) { starti; f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21); ! rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), srf(Rn, 5), zrf(Rt1, 0); } void load_exclusive(Register dst, Register addr, enum operand_size sz, bool ordered) { load_store_exclusive(dummy_reg, dst, dummy_reg, addr,
*** 1257,1267 **** // 8.1 Atomic operations void lse_atomic(Register Rs, Register Rt, Register Rn, enum operand_size sz, int op1, int op2, bool a, bool r) { starti; f(sz, 31, 30), f(0b111000, 29, 24), f(a, 23), f(r, 22), f(1, 21); ! zrf(Rs, 16), f(op1, 15), f(op2, 14, 12), f(0, 11, 10), srf(Rn, 5), zrf(Rt, 0); } #define INSN(NAME, NAME_A, NAME_L, NAME_AL, op1, op2) \ void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \ lse_atomic(Rs, Rt, Rn, sz, op1, op2, false, false); \ --- 1253,1263 ---- // 8.1 Atomic operations void lse_atomic(Register Rs, Register Rt, Register Rn, enum operand_size sz, int op1, int op2, bool a, bool r) { starti; f(sz, 31, 30), f(0b111000, 29, 24), f(a, 23), f(r, 22), f(1, 21); ! rf(Rs, 16), f(op1, 15), f(op2, 14, 12), f(0, 11, 10), srf(Rn, 5), zrf(Rt, 0); } #define INSN(NAME, NAME_A, NAME_L, NAME_AL, op1, op2) \ void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \ lse_atomic(Rs, Rt, Rn, sz, op1, op2, false, false); \
*** 1479,1489 **** // Logical (shifted register) #define INSN(NAME, size, op, N) \ void NAME(Register Rd, Register Rn, Register Rm, \ enum shift_kind kind = LSL, unsigned shift = 0) { \ starti; \ - guarantee(size == 1 || shift < 32, "incorrect shift"); \ f(N, 21); \ zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \ op_shifted_reg(0b01010, kind, shift, size, op); \ } --- 1475,1484 ----
*** 1542,1552 **** void NAME(Register Rd, Register Rn, Register Rm, \ enum shift_kind kind, unsigned shift = 0) { \ starti; \ f(0, 21); \ assert_cond(kind != ROR); \ - guarantee(size == 1 || shift < 32, "incorrect shift");\ zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16); \ op_shifted_reg(0b01011, kind, shift, size, op); \ } INSN(add, 1, 0b000); --- 1537,1546 ----
*** 1571,1581 **** } void add_sub_extended_reg(unsigned op, unsigned decode, Register Rd, Register Rn, Register Rm, unsigned opt, ext::operation option, unsigned imm) { ! guarantee(imm <= 4, "shift amount must be <= 4"); f(op, 31, 29), f(decode, 28, 24), f(opt, 23, 22), f(1, 21); f(option, 15, 13), f(imm, 12, 10); } INSN(addw, 0b000); --- 1565,1575 ---- } void add_sub_extended_reg(unsigned op, unsigned decode, Register Rd, Register Rn, Register Rm, unsigned opt, ext::operation option, unsigned imm) { ! guarantee(imm <= 4, "shift amount must be < 4"); f(op, 31, 29), f(decode, 28, 24), f(opt, 23, 22), f(1, 21); f(option, 15, 13), f(imm, 12, 10); } INSN(addw, 0b000);
*** 1656,1666 **** f(cond, 15, 12); f(o1, 11); f(o2, 10); f(o3, 4); f(nzcv, 3, 0); ! f(imm5, 20, 16), zrf(Rn, 5); } #define INSN(NAME, op) \ void NAME(Register Rn, Register Rm, int imm, Condition cond) { \ int regNumber = (Rm == zr ? 31 : (uintptr_t)Rm); \ --- 1650,1660 ---- f(cond, 15, 12); f(o1, 11); f(o2, 10); f(o3, 4); f(nzcv, 3, 0); ! f(imm5, 20, 16), rf(Rn, 5); } #define INSN(NAME, op) \ void NAME(Register Rn, Register Rm, int imm, Condition cond) { \ int regNumber = (Rm == zr ? 31 : (uintptr_t)Rm); \
*** 2125,2140 **** f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12); f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0); } void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int imm, int op1, int op2, int regs) { ! ! bool replicate = op2 >> 2 == 3; ! // post-index value (imm) is formed differently for replicate/non-replicate ld* instructions ! int expectedImmediate = replicate ? regs * (1 << (T >> 1)) : SIMD_Size_in_bytes[T] * regs; ! guarantee(T < T1Q , "incorrect arrangement"); ! guarantee(imm == expectedImmediate, "bad offset"); starti; f(0,31), f((int)T & 1, 30); f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12); f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0); } --- 2119,2129 ---- f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12); f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0); } void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int imm, int op1, int op2, int regs) { ! guarantee(T <= T1Q && imm == SIMD_Size_in_bytes[T] * regs, "bad offset"); starti; f(0,31), f((int)T & 1, 30); f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12); f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0); }
*** 2237,2287 **** INSN(bsl, 0b101110011); INSN(orn, 0b001110111); #undef INSN ! #define INSN(NAME, opc, opc2, acceptT2D) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ - guarantee(T != T1Q && T != T1D, "incorrect arrangement"); \ - if (!acceptT2D) guarantee(T != T2D, "incorrect arrangement"); \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \ rf(Vn, 5), rf(Vd, 0); \ } ! INSN(addv, 0, 0b100001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D ! INSN(subv, 1, 0b100001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D ! INSN(mulv, 0, 0b100111, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S ! INSN(mlav, 0, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S ! INSN(mlsv, 1, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S ! INSN(sshl, 0, 0b010001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D ! INSN(ushl, 1, 0b010001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D ! 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 #undef INSN ! #define INSN(NAME, opc, opc2, accepted) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ - guarantee(T != T1Q && T != T1D, "incorrect arrangement"); \ - if (accepted < 2) guarantee(T != T2S && T != T2D, "incorrect arrangement"); \ - if (accepted == 0) guarantee(T == T8B || T == T16B, "incorrect arrangement"); \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(opc2, 21, 10); \ rf(Vn, 5), rf(Vd, 0); \ } ! INSN(absr, 0, 0b100000101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S ! INSN(negr, 1, 0b100000101110, 2); // 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(cls, 0, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S ! INSN(clz, 1, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S ! INSN(cnt, 0, 0b100000010110, 0); // accepted arrangements: T8B, T16B ! INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S #undef INSN #define INSN(NAME, opc) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ --- 2226,2271 ---- INSN(bsl, 0b101110011); INSN(orn, 0b001110111); #undef INSN ! #define INSN(NAME, opc, opc2) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \ rf(Vn, 5), rf(Vd, 0); \ } ! INSN(addv, 0, 0b100001); ! INSN(subv, 1, 0b100001); ! INSN(mulv, 0, 0b100111); ! INSN(mlav, 0, 0b100101); ! INSN(mlsv, 1, 0b100101); ! INSN(sshl, 0, 0b010001); ! INSN(ushl, 1, 0b010001); ! INSN(umullv, 1, 0b110000); ! INSN(umlalv, 1, 0b100000); #undef INSN ! #define INSN(NAME, opc, opc2) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(opc2, 21, 10); \ rf(Vn, 5), rf(Vd, 0); \ } ! INSN(absr, 0, 0b100000101110); ! INSN(negr, 1, 0b100000101110); ! INSN(notr, 1, 0b100000010110); ! INSN(addv, 0, 0b110001101110); ! INSN(cls, 0, 0b100000010010); ! INSN(clz, 1, 0b100000010010); ! INSN(cnt, 0, 0b100000010110); ! INSN(uaddlv, 1, 0b110000001110); #undef INSN #define INSN(NAME, opc) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
*** 2301,2311 **** unsigned cmode = cmode0; \ unsigned op = op0; \ starti; \ assert(lsl == 0 || \ ((T == T4H || T == T8H) && lsl == 8) || \ ! ((T == T2S || T == T4S) && ((lsl >> 3) < 4) && ((lsl & 7) == 0)), "invalid shift");\ cmode |= lsl >> 2; \ if (T == T4H || T == T8H) cmode |= 0b1000; \ if (!(T == T4H || T == T8H || T == T2S || T == T4S)) { \ assert(op == 0 && cmode0 == 0, "must be MOVI"); \ cmode = 0b1110; \ --- 2285,2295 ---- unsigned cmode = cmode0; \ unsigned op = op0; \ starti; \ assert(lsl == 0 || \ ((T == T4H || T == T8H) && lsl == 8) || \ ! ((T == T2S || T == T4S) && ((lsl >> 3) < 4)), "invalid shift"); \ cmode |= lsl >> 2; \ if (T == T4H || T == T8H) cmode |= 0b1000; \ if (!(T == T4H || T == T8H || T == T2S || T == T4S)) { \ assert(op == 0 && cmode0 == 0, "must be MOVI"); \ cmode = 0b1110; \
*** 2462,2473 **** INSN(sshr, 0, 0b000001, /* isSHR = */ true); 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 --- 2446,2456 ---- INSN(sshr, 0, 0b000001, /* isSHR = */ true); INSN(ushr, 1, 0b000001, /* isSHR = */ true); #undef INSN ! 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
*** 2476,2534 **** 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) { starti; f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); ! f(0b000111, 15, 10), zrf(Xn, 5), rf(Vd, 0); } // Move to general purpose register // mov Rd, Vn.T[index] void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) { - guarantee(T >= T2S && T < T1Q, "only D and S arrangements are supported"); starti; f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21); f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0); } ! private: ! void _pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { starti; assert((Ta == T1Q && (Tb == T1D || Tb == T2D)) || (Ta == T8H && (Tb == T8B || Tb == T16B)), "Invalid Size specifier"); int size = (Ta == T1Q) ? 0b11 : 0b00; f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size, 23, 22); f(1, 21), rf(Vm, 16), f(0b111000, 15, 10), rf(Vn, 5), rf(Vd, 0); } - - public: - void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { - assert(Tb == T1D || Tb == T8B, "pmull assumes T1D or T8B as the second size specifier"); - _pmull(Vd, Ta, Vn, Vm, Tb); - } - void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier"); ! _pmull(Vd, Ta, Vn, Vm, Tb); } void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) { starti; int size_b = (int)Tb >> 1; --- 2459,2500 ---- 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); } void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { ! 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) { starti; f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); ! f(0b000111, 15, 10), rf(Xn, 5), rf(Vd, 0); } // Move to general purpose register // mov Rd, Vn.T[index] void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) { starti; f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21); f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0); } ! void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { starti; assert((Ta == T1Q && (Tb == T1D || Tb == T2D)) || (Ta == T8H && (Tb == T8B || Tb == T16B)), "Invalid Size specifier"); int size = (Ta == T1Q) ? 0b11 : 0b00; f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size, 23, 22); f(1, 21), rf(Vm, 16), f(0b111000, 15, 10), rf(Vn, 5), rf(Vd, 0); } void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier"); ! pmull(Vd, Ta, Vn, Vm, Tb); } void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) { starti; int size_b = (int)Tb >> 1;
*** 2541,2551 **** 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); ! f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), zrf(Xs, 5), rf(Vd, 0); } void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0) { starti; --- 2507,2517 ---- 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); ! f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), rf(Xs, 5), rf(Vd, 0); } void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0) { starti;
*** 2556,2566 **** } // AdvSIMD ZIP/UZP/TRN #define INSN(NAME, opcode) \ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ - guarantee(T != T1D && T != T1Q, "invalid arrangement"); \ starti; \ f(0, 31), f(0b001110, 29, 24), f(0, 21), f(0, 15); \ f(opcode, 14, 12), f(0b10, 11, 10); \ rf(Vm, 16), rf(Vn, 5), rf(Vd, 0); \ f(T & 1, 30), f(T >> 1, 23, 22); \ --- 2522,2531 ----
*** 2642,2652 **** #define ASSERTION (T == T8B || T == T16B) INSN(rev16, 0, 0b00001); // RBIT only allows T8B and T16B but encodes them oddly. Argh... void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { assert((ASSERTION), MSG); ! _rbit(Vd, SIMD_Arrangement((T & 1) | 0b010), Vn); } #undef ASSERTION #undef MSG --- 2607,2617 ---- #define ASSERTION (T == T8B || T == T16B) INSN(rev16, 0, 0b00001); // RBIT only allows T8B and T16B but encodes them oddly. Argh... void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { assert((ASSERTION), MSG); ! _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn); } #undef ASSERTION #undef MSG
< prev index next >