8328998: Encoding support for Intel APX extended general-purpose registers

Reviewed-by: kvn, sviswanathan, jbhateja
This commit is contained in:
steveatgh 2024-05-23 22:54:24 +00:00 committed by Sandhya Viswanathan
parent ddd73b4583
commit f8a3e4e428
5 changed files with 889 additions and 456 deletions

File diff suppressed because it is too large Load Diff

View File

@ -308,17 +308,29 @@ class Address {
private:
bool base_needs_rex() const {
return _base->is_valid() && _base->encoding() >= 8;
return _base->is_valid() && ((_base->encoding() & 8) == 8);
}
bool base_needs_rex2() const {
return _base->is_valid() && _base->encoding() >= 16;
}
bool index_needs_rex() const {
return _index->is_valid() &&_index->encoding() >= 8;
return _index->is_valid() && ((_index->encoding() & 8) == 8);
}
bool index_needs_rex2() const {
return _index->is_valid() &&_index->encoding() >= 16;
}
bool xmmindex_needs_rex() const {
return _xmmindex->is_valid() && ((_xmmindex->encoding() & 8) == 8);
}
bool xmmindex_needs_rex2() const {
return _xmmindex->is_valid() && _xmmindex->encoding() >= 16;
}
relocInfo::relocType reloc() const { return _rspec.type(); }
friend class Assembler;
@ -508,12 +520,26 @@ class Assembler : public AbstractAssembler {
REX_WRX = 0x4E,
REX_WRXB = 0x4F,
REX2 = 0xd5,
WREX2 = REX2 << 8,
VEX_3bytes = 0xC4,
VEX_2bytes = 0xC5,
EVEX_4bytes = 0x62,
Prefix_EMPTY = 0x0
};
enum PrefixBits {
REXBIT_B = 0x01,
REXBIT_X = 0x02,
REXBIT_R = 0x04,
REXBIT_W = 0x08,
REX2BIT_B4 = 0x10,
REX2BIT_X4 = 0x20,
REX2BIT_R4 = 0x40,
REX2BIT_M0 = 0x80
};
enum VexPrefix {
VEX_B = 0x20,
VEX_X = 0x40,
@ -525,10 +551,18 @@ class Assembler : public AbstractAssembler {
EVEX_F = 0x04,
EVEX_V = 0x08,
EVEX_Rb = 0x10,
EVEX_B = 0x20,
EVEX_X = 0x40,
EVEX_Z = 0x80
};
enum ExtEvexPrefix {
EEVEX_R = 0x10,
EEVEX_B = 0x08,
EEVEX_X = 0x04,
EEVEX_V = 0x08
};
enum EvexRoundPrefix {
EVEX_RNE = 0x0,
EVEX_RD = 0x1,
@ -540,7 +574,7 @@ class Assembler : public AbstractAssembler {
VEX_SIMD_NONE = 0x0,
VEX_SIMD_66 = 0x1,
VEX_SIMD_F3 = 0x2,
VEX_SIMD_F2 = 0x3
VEX_SIMD_F2 = 0x3,
};
enum VexOpcode {
@ -548,6 +582,7 @@ class Assembler : public AbstractAssembler {
VEX_OPCODE_0F = 0x1,
VEX_OPCODE_0F_38 = 0x2,
VEX_OPCODE_0F_3A = 0x3,
VEX_OPCODE_0F_3C = 0x4,
VEX_OPCODE_MASK = 0x1F
};
@ -572,7 +607,8 @@ class Assembler : public AbstractAssembler {
EVEX_OVM = 20,
EVEX_M128 = 21,
EVEX_DUP = 22,
EVEX_ETUP = 23
EVEX_NOSCALE = 23,
EVEX_ETUP = 24
};
enum EvexInputSizeInBits {
@ -686,33 +722,62 @@ private:
InstructionAttr *_attributes;
void set_attributes(InstructionAttr* attributes);
int get_base_prefix_bits(int enc);
int get_index_prefix_bits(int enc);
int get_base_prefix_bits(Register base);
int get_index_prefix_bits(Register index);
int get_reg_prefix_bits(int enc);
// 64bit prefixes
void prefix(Register reg);
void prefix(Register dst, Register src, Prefix p);
void prefix_rex2(Register dst, Register src);
void prefix(Register dst, Address adr, Prefix p);
void prefix_rex2(Register dst, Address adr);
void prefix(Address adr);
void prefix(Address adr, Register reg, bool byteinst = false);
// The is_map1 bool indicates an x86 map1 instruction which, when
// legacy encoded, uses a 0x0F opcode prefix. By specification, the
// opcode prefix is omitted when using rex2 encoding in support
// of APX extended GPRs.
void prefix(Address adr, bool is_map1 = false);
void prefix_rex2(Address adr, bool is_map1 = false);
void prefix(Address adr, Register reg, bool byteinst = false, bool is_map1 = false);
void prefix_rex2(Address adr, Register reg, bool byteinst = false, bool is_map1 = false);
void prefix(Address adr, XMMRegister reg);
void prefix_rex2(Address adr, XMMRegister reg);
int prefix_and_encode(int reg_enc, bool byteinst = false);
int prefix_and_encode(int dst_enc, int src_enc) {
return prefix_and_encode(dst_enc, false, src_enc, false);
int prefix_and_encode(int reg_enc, bool byteinst = false, bool is_map1 = false);
int prefix_and_encode_rex2(int reg_enc, bool is_map1 = false);
int prefix_and_encode(int dst_enc, int src_enc, bool is_map1 = false) {
return prefix_and_encode(dst_enc, false, src_enc, false, is_map1);
}
int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte);
int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte, bool is_map1 = false);
int prefix_and_encode_rex2(int dst_enc, int src_enc, int init_bits = 0);
// Some prefixq variants always emit exactly one prefix byte, so besides a
// prefix-emitting method we provide a method to get the prefix byte to emit,
// which can then be folded into a byte stream.
int8_t get_prefixq(Address adr);
int8_t get_prefixq(Address adr, Register reg);
int get_prefixq(Address adr, bool is_map1 = false);
int get_prefixq_rex2(Address adr, bool is_map1 = false);
int get_prefixq(Address adr, Register reg, bool is_map1 = false);
int get_prefixq_rex2(Address adr, Register reg, bool ismap1 = false);
void prefixq(Address adr);
void prefixq(Address adr, Register reg);
void prefixq(Address adr, Register reg, bool is_map1 = false);
void prefixq(Address adr, XMMRegister reg);
void prefixq_rex2(Address adr, XMMRegister src);
int prefixq_and_encode(int reg_enc);
int prefixq_and_encode(int dst_enc, int src_enc);
bool prefix_is_rex2(int prefix);
int prefixq_and_encode(int reg_enc, bool is_map1 = false);
int prefixq_and_encode_rex2(int reg_enc, bool is_map1 = false);
int prefixq_and_encode(int dst_enc, int src_enc, bool is_map1 = false);
int prefixq_and_encode_rex2(int dst_enc, int src_enc, bool is_map1 = false);
bool needs_rex2(Register reg1, Register reg2 = noreg, Register reg3 = noreg);
bool needs_eevex(Register reg1, Register reg2 = noreg, Register reg3 = noreg);
bool needs_eevex(int enc1, int enc2 = -1, int enc3 = -1);
void rex_prefix(Address adr, XMMRegister xreg,
VexSimdPrefix pre, VexOpcode opc, bool rex_w);
@ -721,22 +786,21 @@ private:
void vex_prefix(bool vex_r, bool vex_b, bool vex_x, int nds_enc, VexSimdPrefix pre, VexOpcode opc);
void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool evex_r, bool evex_v,
int nds_enc, VexSimdPrefix pre, VexOpcode opc);
void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool evex_v, bool evex_r, bool evex_b,
bool eevex_x, int nds_enc, VexSimdPrefix pre, VexOpcode opc);
void vex_prefix(Address adr, int nds_enc, int xreg_enc,
VexSimdPrefix pre, VexOpcode opc,
void vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
InstructionAttr *attributes);
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
VexSimdPrefix pre, VexOpcode opc,
InstructionAttr *attributes);
InstructionAttr *attributes, bool src_is_gpr = false);
void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, VexSimdPrefix pre,
VexOpcode opc, InstructionAttr *attributes);
int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, VexSimdPrefix pre,
VexOpcode opc, InstructionAttr *attributes);
VexOpcode opc, InstructionAttr *attributes, bool src_is_gpr = false);
// Helper functions for groups of instructions
void emit_arith_b(int op1, int op2, Register dst, int imm8);
@ -821,6 +885,10 @@ private:
void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
void emit_prefix_and_int8(int prefix, int b1);
void emit_opcode_prefix_and_encoding(int byte1, int ocp_and_encoding);
void emit_opcode_prefix_and_encoding(int byte1, int byte2, int ocp_and_encoding);
void emit_opcode_prefix_and_encoding(int byte1, int byte2, int ocp_and_encoding, int byte3);
bool always_reachable(AddressLiteral adr) NOT_LP64( { return true; } );
bool reachable(AddressLiteral adr) NOT_LP64( { return true; } );
@ -907,6 +975,8 @@ private:
// Instruction prefixes
void prefix(Prefix p);
void prefix16(int p);
public:
// Creation

View File

@ -30,23 +30,53 @@
#include "code/codeCache.hpp"
#ifndef _LP64
inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { return reg_enc; }
inline int Assembler::prefixq_and_encode(int reg_enc) { return reg_enc; }
inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst, bool is_map1)
{
int opc_prefix = is_map1 ? 0x0F00 : 0;
return opc_prefix | reg_enc;
}
inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) { return dst_enc << 3 | src_enc; }
inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { return dst_enc << 3 | src_enc; }
inline int Assembler::prefixq_and_encode(int reg_enc, bool is_map1) {
int opc_prefix = is_map1 ? 0xF00 : 0;
return opc_prefix | reg_enc;
}
inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte, bool is_map1) {
int opc_prefix = is_map1 ? 0xF00 : 0;
return opc_prefix | (dst_enc << 3 | src_enc);
}
inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc, bool is_map1) {
int opc_prefix = is_map1 ? 0xF00 : 0;
return opc_prefix | dst_enc << 3 | src_enc;
}
inline void Assembler::prefix(Register reg) {}
inline void Assembler::prefix(Register dst, Register src, Prefix p) {}
inline void Assembler::prefix(Register dst, Address adr, Prefix p) {}
inline void Assembler::prefix(Address adr) {}
inline void Assembler::prefix(Address adr, bool is_map1) {
if (is_map1) {
emit_int8(0x0F);
}
}
inline void Assembler::prefixq(Address adr) {}
inline void Assembler::prefix(Address adr, Register reg, bool byteinst) {}
inline void Assembler::prefixq(Address adr, Register reg) {}
inline void Assembler::prefix(Address adr, Register reg, bool byteinst, bool is_map1) {
if (is_map1) {
emit_int8(0x0F);
}
}
inline void Assembler::prefixq(Address adr, Register reg, bool is_map1) {
if (is_map1) {
emit_int8(0x0F);
}
}
inline void Assembler::prefix(Address adr, XMMRegister reg) {}
inline void Assembler::prefixq(Address adr, XMMRegister reg) {}
#endif // _LP64
#endif // CPU_X86_ASSEMBLER_X86_INLINE_HPP

View File

@ -232,8 +232,10 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
\
product(bool, IntelJccErratumMitigation, true, DIAGNOSTIC, \
"Turn off JVM mitigations related to Intel micro code " \
"mitigations for the Intel JCC erratum")
"mitigations for the Intel JCC erratum") \
\
product(bool, UseAPX, false, EXPERIMENTAL, \
"Use Advanced Performance Extensions on x86") \
// end of ARCH_FLAGS
#endif // CPU_X86_GLOBALS_X86_HPP

View File

@ -1002,6 +1002,14 @@ void VM_Version::get_processor_features() {
}
}
// APX support not enabled yet
if (UseAPX) {
if (!FLAG_IS_DEFAULT(UseAPX)) {
warning("APX is not supported on this CPU.");
}
FLAG_SET_DEFAULT(UseAPX, false);
}
if (FLAG_IS_DEFAULT(IntelJccErratumMitigation)) {
_has_intel_jcc_erratum = compute_has_intel_jcc_erratum();
} else {