< prev index next >
src/hotspot/cpu/aarch64/assembler_aarch64.hpp
Print this page
rev 61868 : manual merge with default
@@ -1328,10 +1328,25 @@
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,10 +1480,25 @@
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,10 +1869,34 @@
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,10 +2029,47 @@
// 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,25 +2180,10 @@
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) \
@@ -2261,10 +2337,15 @@
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,10 +2361,12 @@
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,10 +2427,13 @@
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,14 +2505,24 @@
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) {
+ // (long) {a, b} -> (a + b)
+ void addpd(FloatRegister Vd, FloatRegister Vn) {
starti;
- f(0b0111111001110000110110, 31, 10);
+ 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,10 +2536,18 @@
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,33 +2574,52 @@
INSN(ushr, 1, 0b000001, /* isSHR = */ true);
#undef INSN
private:
- void _ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
+ 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
+ * 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(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");
- _ushll(Vd, Ta, Vn, Tb, shift);
+ _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");
- _ushll(Vd, Ta, Vn, Tb, shift);
+ _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,10 +2666,19 @@
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 >