Skip to content

Commit

Permalink
8343214: Fix encoding errors in APX New Data Destination Instructions…
Browse files Browse the repository at this point in the history
… Support

Reviewed-by: jbhateja, sviswanathan
  • Loading branch information
Srinivas Vamsi Parasa authored and Sandhya Viswanathan committed Nov 6, 2024
1 parent 0be7118 commit c0e6c3b
Showing 1 changed file with 71 additions and 44 deletions.
115 changes: 71 additions & 44 deletions src/hotspot/cpu/x86/assembler_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1488,9 +1488,10 @@ void Assembler::addl(Register dst, Register src) {

void Assembler::eaddl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x01, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void)evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x03, 0xC0, src1, src2);
}

void Assembler::addr_nop_4() {
Expand Down Expand Up @@ -1728,9 +1729,10 @@ void Assembler::andl(Register dst, Register src) {

void Assembler::eandl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x21, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x23, 0xC0, src1, src2);
}

void Assembler::andnl(Register dst, Register src1, Register src2) {
Expand Down Expand Up @@ -2637,7 +2639,7 @@ void Assembler::eimull(Register dst, Address src, int32_t value, bool no_flags)
InstructionMark im(this);
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
evex_prefix_ndd(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
evex_prefix_nf(src, 0, dst->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
if (is8bit(value)) {
emit_int8((unsigned char)0x6B);
emit_operand(dst, src, 1);
Expand Down Expand Up @@ -4467,7 +4469,9 @@ void Assembler::enotl(Register dst, Register src) {

void Assembler::eorw(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_66, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x0B, 0xC0, src1, src2);
}

Expand Down Expand Up @@ -4519,9 +4523,10 @@ void Assembler::orl(Register dst, Register src) {

void Assembler::eorl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x09, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x0B, 0xC0, src1, src2);
}

void Assembler::orl(Address dst, Register src) {
Expand Down Expand Up @@ -6938,7 +6943,9 @@ void Assembler::shldl(Register dst, Register src) {

void Assembler::eshldl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int16(0xA5, (0xC0 | encode));
}

Expand All @@ -6949,7 +6956,9 @@ void Assembler::shldl(Register dst, Register src, int8_t imm8) {

void Assembler::eshldl(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int24(0x24, (0xC0 | encode), imm8);
}

Expand All @@ -6960,7 +6969,9 @@ void Assembler::shrdl(Register dst, Register src) {

void Assembler::eshrdl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int16(0xAD, (0xC0 | encode));
}

Expand All @@ -6971,7 +6982,9 @@ void Assembler::shrdl(Register dst, Register src, int8_t imm8) {

void Assembler::eshrdl(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int24(0x2C, (0xC0 | encode), imm8);
}

Expand All @@ -6983,7 +6996,9 @@ void Assembler::shldq(Register dst, Register src, int8_t imm8) {

void Assembler::eshldq(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int24(0x24, (0xC0 | encode), imm8);
}

Expand All @@ -6994,7 +7009,9 @@ void Assembler::shrdq(Register dst, Register src, int8_t imm8) {

void Assembler::eshrdq(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int24(0x2C, (0xC0 | encode), imm8);
}
#endif
Expand Down Expand Up @@ -7155,11 +7172,12 @@ void Assembler::subl(Register dst, Register src) {
emit_arith(0x2B, 0xC0, dst, src);
}

void Assembler::esubl(Register dst, Register src2, Register src1, bool no_flags) {
void Assembler::esubl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x29, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x2B, 0xC0, src1, src2);
}

void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Expand Down Expand Up @@ -7485,9 +7503,10 @@ void Assembler::xorl(Register dst, Register src) {

void Assembler::exorl(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x31, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x33, 0xC0, src1, src2);
}

void Assembler::xorl(Address dst, Register src) {
Expand Down Expand Up @@ -7548,10 +7567,11 @@ void Assembler::xorw(Register dst, Address src) {

void Assembler::exorw(Register dst, Register src1, Address src2, bool no_flags) {
InstructionMark im(this);
emit_int8(0x66);
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
evex_prefix_ndd(src2, dst->encoding(), src1->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3C, &attributes, no_flags);
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_16bit);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
evex_prefix_ndd(src2, dst->encoding(), src1->encoding(), VEX_SIMD_66, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_int8(0x33);
emit_operand(src1, src2, 0);
}
Expand Down Expand Up @@ -15064,9 +15084,10 @@ void Assembler::addq(Register dst, Register src) {

void Assembler::eaddq(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x01, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x03, 0xC0, src1, src2);
}

void Assembler::adcxq(Register dst, Register src) {
Expand Down Expand Up @@ -15160,9 +15181,10 @@ void Assembler::andq(Register dst, Register src) {

void Assembler::eandq(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x21, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x23, 0xC0, src1, src2);
}

void Assembler::andq(Address dst, Register src) {
Expand Down Expand Up @@ -15591,7 +15613,7 @@ void Assembler::imulq(Register dst, Register src, int value) {

void Assembler::eimulq(Register dst, Register src, int value, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, /* src_is_gpr */ true, /* nds_is_ndd */ false, no_flags);
int encode = evex_prefix_and_encode_nf(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
if (is8bit(value)) {
emit_int24(0x6B, (0xC0 | encode), (value & 0xFF));
} else {
Expand All @@ -15610,7 +15632,9 @@ void Assembler::imulq(Register dst, Address src) {
void Assembler::eimulq(Register dst, Address src, bool no_flags) {
InstructionMark im(this);
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes, /* nds_is_ndd */ false, no_flags);
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
evex_prefix_nf(src, 0, dst->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);

emit_int8((unsigned char)0xAF);
emit_operand(dst, src, 0);
}
Expand Down Expand Up @@ -16055,9 +16079,10 @@ void Assembler::orq(Register dst, Register src) {

void Assembler::eorq(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x09, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x0B, 0xC0, src1, src2);
}

void Assembler::popcntq(Register dst, Address src) {
Expand Down Expand Up @@ -16743,9 +16768,10 @@ void Assembler::subq(Register dst, Register src) {

void Assembler::esubq(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x29, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x2B, 0xC0, src1, src2);
}

void Assembler::testq(Address dst, int32_t imm32) {
Expand Down Expand Up @@ -16807,9 +16833,10 @@ void Assembler::xorq(Register dst, Register src) {

void Assembler::exorq(Register dst, Register src1, Register src2, bool no_flags) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags);
// opcode matches gcc
emit_arith(0x31, 0xC0, src1, src2);
// NDD shares its encoding bits with NDS bits for regular EVEX instruction.
// Therefore, DST is passed as the second argument to minimize changes in the leaf level routine.
(void) evex_prefix_and_encode_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags);
emit_arith(0x33, 0xC0, src1, src2);
}

void Assembler::xorq(Register dst, Address src) {
Expand Down

0 comments on commit c0e6c3b

Please sign in to comment.