< prev index next >
src/hotspot/cpu/x86/assembler_x86.cpp
Print this page
@@ -135,10 +135,12 @@
Address::Address(int disp, address loc, relocInfo::relocType rtype) {
_base = noreg;
_index = noreg;
_scale = no_scale;
_disp = disp;
+ _xmmindex = xnoreg;
+ _isxmmindex = false;
switch (rtype) {
case relocInfo::external_word_type:
_rspec = external_word_Relocation::spec(loc);
break;
case relocInfo::internal_word_type:
@@ -174,10 +176,12 @@
_base = noreg;
_index = noreg;
_scale = no_scale;
_disp = (intptr_t) loc;
_rspec = spec;
+ _xmmindex = xnoreg;
+ _isxmmindex = false;
}
#endif // _LP64
@@ -606,10 +610,25 @@
}
}
emit_operand((Register)reg, base, index, scale, disp, rspec);
}
+void Assembler::emit_operand(XMMRegister reg, Register base, XMMRegister index,
+ Address::ScaleFactor scale, int disp,
+ RelocationHolder const& rspec) {
+ if (UseAVX > 2) {
+ int xreg_enc = reg->encoding();
+ int xmmindex_enc = index->encoding();
+ XMMRegister new_reg = as_XMMRegister(xreg_enc & 0xf);
+ XMMRegister new_index = as_XMMRegister(xmmindex_enc & 0xf);
+ emit_operand((Register)new_reg, base, (Register)new_index, scale, disp, rspec);
+ } else {
+ emit_operand((Register)reg, base, (Register)index, scale, disp, rspec);
+ }
+}
+
+
// Secret local extension to Assembler::WhichOperand:
#define end_pc_operand (_WhichOperand_limit)
address Assembler::locate_operand(address inst, WhichOperand which) {
// Decode the given instruction, and return the address of
@@ -1106,12 +1125,16 @@
adr._rspec,
rip_relative_correction);
}
void Assembler::emit_operand(XMMRegister reg, Address adr) {
+ if (adr.isxmmindex()) {
+ emit_operand(reg, adr._base, adr._xmmindex, adr._scale, adr._disp, adr._rspec);
+ } else {
emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp,
adr._rspec);
+ }
}
// MMX operations
void Assembler::emit_operand(MMXRegister reg, Address adr) {
assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers");
@@ -3394,10 +3417,19 @@
emit_int8(0x06);
emit_int8(0xC0 | encode);
emit_int8(imm8);
}
+void Assembler::evpermi2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ attributes.set_is_evex_instruction();
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x76);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
void Assembler::pause() {
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)0x90);
}
@@ -3845,10 +3877,21 @@
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x30);
emit_operand(dst, src);
}
+void Assembler::vpmovzxbw(XMMRegister dst, XMMRegister src, int vector_len) {
+ assert(vector_len == AVX_128bit? VM_Version::supports_avx() :
+ vector_len == AVX_256bit? VM_Version::supports_avx2() :
+ vector_len == AVX_512bit? VM_Version::supports_avx512bw() : 0, "");
+ InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x30);
+ emit_int8((unsigned char) (0xC0 | encode));
+}
+
+
void Assembler::evpmovzxbw(XMMRegister dst, KRegister mask, Address src, int vector_len) {
assert(is_vector_masking(), "");
assert(VM_Version::supports_avx512vlbw(), "");
assert(dst != xnoreg, "sanity");
InstructionMark im(this);
@@ -3858,11 +3901,10 @@
attributes.set_is_evex_instruction();
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x30);
emit_operand(dst, src);
}
-
void Assembler::evpmovwb(Address dst, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx512vlbw(), "");
assert(src != xnoreg, "sanity");
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
@@ -3886,10 +3928,32 @@
vex_prefix(dst, 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x30);
emit_operand(src, dst);
}
+void Assembler::evpmovdb(Address dst, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ assert(src != xnoreg, "sanity");
+ InstructionMark im(this);
+ InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ attributes.set_address_attributes(/* tuple_type */ EVEX_QVM, /* input_size_in_bits */ EVEX_NObit);
+ attributes.set_is_evex_instruction();
+ vex_prefix(dst, 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x31);
+ emit_operand(src, dst);
+}
+
+void Assembler::vpmovzxwd(XMMRegister dst, XMMRegister src, int vector_len) {
+ assert(vector_len == AVX_128bit? VM_Version::supports_avx() :
+ vector_len == AVX_256bit? VM_Version::supports_avx2() :
+ vector_len == AVX_512bit? VM_Version::supports_evex() : 0, " ");
+ InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x33);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
// generic
void Assembler::pop(Register dst) {
int encode = prefix_and_encode(dst->encoding());
emit_int8(0x58 | encode);
}
@@ -6046,10 +6110,28 @@
int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0xD3);
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::evpsrlvw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_avx512bw(), "");
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ attributes.set_is_evex_instruction();
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x10);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::evpsllvw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_avx512bw(), "");
+ InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ attributes.set_is_evex_instruction();
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8(0x12);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
// Shift packed integers arithmetically right by specified number of bits.
void Assembler::psraw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
@@ -6147,10 +6229,19 @@
vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0xDB);
emit_operand(dst, src);
}
+void Assembler::vpandq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
+ emit_int8((unsigned char)0xDB);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+
void Assembler::pandn(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
attributes.set_rex_vex_w_reverted();
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
@@ -6182,10 +6273,19 @@
vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0xEB);
emit_operand(dst, src);
}
+void Assembler::vporq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
+ emit_int8((unsigned char)0xEB);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+
void Assembler::pxor(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0xEF);
@@ -6793,10 +6893,24 @@
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x7C);
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::evpgatherdd(XMMRegister dst, KRegister mask, Address src, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ assert(dst != xnoreg, "sanity");
+ InstructionMark im(this);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
+ attributes.reset_is_clear_context();
+ attributes.set_embedded_opmask_register_specifier(mask);
+ attributes.set_is_evex_instruction();
+ // swap src<->dst for encoding
+ vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0x90);
+ emit_operand(dst, src);
+}
// Carry-Less Multiplication Quadword
void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
assert(VM_Version::supports_clmul(), "");
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
@@ -7418,11 +7532,16 @@
}
void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc, InstructionAttr *attributes) {
bool vex_r = ((xreg_enc & 8) == 8) ? 1 : 0;
bool vex_b = adr.base_needs_rex();
- bool vex_x = adr.index_needs_rex();
+ bool vex_x;
+ if (adr.isxmmindex()) {
+ vex_x = adr.xmmindex_needs_rex();
+ } else {
+ vex_x = adr.index_needs_rex();
+ }
set_attributes(attributes);
attributes->set_current_assembler(this);
// if vector length is turned off, revert to AVX for vectors smaller than 512-bit
if (UseAVX > 2 && _legacy_mode_vl && attributes->uses_vl()) {
@@ -7455,11 +7574,17 @@
_is_managed = false;
if (UseAVX > 2 && !attributes->is_legacy_mode())
{
bool evex_r = (xreg_enc >= 16);
- bool evex_v = (nds_enc >= 16);
+ bool evex_v;
+ // EVEX.V' is set to true when VSIB is used as we may need to use higher order XMM registers (16-31)
+ if (adr.isxmmindex()) {
+ evex_v = ((adr._xmmindex->encoding() > 15) ? true : false);
+ } else {
+ evex_v = (nds_enc >= 16);
+ }
attributes->set_is_evex_instruction();
evex_prefix(vex_r, vex_b, vex_x, evex_r, evex_v, nds_enc, pre, opc);
} else {
if (UseAVX > 2 && attributes->is_rex_vex_w_reverted()) {
attributes->set_rex_vex_w(false);
< prev index next >