mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8134553: CRC32C implementations for x86/x64 targets
Reviewed-by: kvn
This commit is contained in:
parent
d49d1ea740
commit
61b77b8590
24 changed files with 1092 additions and 19 deletions
|
@ -1604,6 +1604,85 @@ void Assembler::cpuid() {
|
|||
emit_int8((unsigned char)0xA2);
|
||||
}
|
||||
|
||||
// Opcode / Instruction Op / En 64 - Bit Mode Compat / Leg Mode Description Implemented
|
||||
// F2 0F 38 F0 / r CRC32 r32, r / m8 RM Valid Valid Accumulate CRC32 on r / m8. v
|
||||
// F2 REX 0F 38 F0 / r CRC32 r32, r / m8* RM Valid N.E. Accumulate CRC32 on r / m8. -
|
||||
// F2 REX.W 0F 38 F0 / r CRC32 r64, r / m8 RM Valid N.E. Accumulate CRC32 on r / m8. -
|
||||
//
|
||||
// F2 0F 38 F1 / r CRC32 r32, r / m16 RM Valid Valid Accumulate CRC32 on r / m16. v
|
||||
//
|
||||
// F2 0F 38 F1 / r CRC32 r32, r / m32 RM Valid Valid Accumulate CRC32 on r / m32. v
|
||||
//
|
||||
// F2 REX.W 0F 38 F1 / r CRC32 r64, r / m64 RM Valid N.E. Accumulate CRC32 on r / m64. v
|
||||
void Assembler::crc32(Register crc, Register v, int8_t sizeInBytes) {
|
||||
assert(VM_Version::supports_sse4_2(), "");
|
||||
int8_t w = 0x01;
|
||||
Prefix p = Prefix_EMPTY;
|
||||
|
||||
emit_int8((int8_t)0xF2);
|
||||
switch (sizeInBytes) {
|
||||
case 1:
|
||||
w = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
break;
|
||||
LP64_ONLY(case 8:)
|
||||
// This instruction is not valid in 32 bits
|
||||
// Note:
|
||||
// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
|
||||
//
|
||||
// Page B - 72 Vol. 2C says
|
||||
// qwreg2 to qwreg 1111 0010 : 0100 1R0B : 0000 1111 : 0011 1000 : 1111 0000 : 11 qwreg1 qwreg2
|
||||
// mem64 to qwreg 1111 0010 : 0100 1R0B : 0000 1111 : 0011 1000 : 1111 0000 : mod qwreg r / m
|
||||
// F0!!!
|
||||
// while 3 - 208 Vol. 2A
|
||||
// F2 REX.W 0F 38 F1 / r CRC32 r64, r / m64 RM Valid N.E.Accumulate CRC32 on r / m64.
|
||||
//
|
||||
// the 0 on a last bit is reserved for a different flavor of this instruction :
|
||||
// F2 REX.W 0F 38 F0 / r CRC32 r64, r / m8 RM Valid N.E.Accumulate CRC32 on r / m8.
|
||||
p = REX_W;
|
||||
break;
|
||||
default:
|
||||
assert(0, "Unsupported value for a sizeInBytes argument");
|
||||
break;
|
||||
}
|
||||
LP64_ONLY(prefix(crc, v, p);)
|
||||
emit_int8((int8_t)0x0F);
|
||||
emit_int8(0x38);
|
||||
emit_int8((int8_t)(0xF0 | w));
|
||||
emit_int8(0xC0 | ((crc->encoding() & 0x7) << 3) | (v->encoding() & 7));
|
||||
}
|
||||
|
||||
void Assembler::crc32(Register crc, Address adr, int8_t sizeInBytes) {
|
||||
assert(VM_Version::supports_sse4_2(), "");
|
||||
InstructionMark im(this);
|
||||
int8_t w = 0x01;
|
||||
Prefix p = Prefix_EMPTY;
|
||||
|
||||
emit_int8((int8_t)0xF2);
|
||||
switch (sizeInBytes) {
|
||||
case 1:
|
||||
w = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
break;
|
||||
LP64_ONLY(case 8:)
|
||||
// This instruction is not valid in 32 bits
|
||||
p = REX_W;
|
||||
break;
|
||||
default:
|
||||
assert(0, "Unsupported value for a sizeInBytes argument");
|
||||
break;
|
||||
}
|
||||
LP64_ONLY(prefix(crc, adr, p);)
|
||||
emit_int8((int8_t)0x0F);
|
||||
emit_int8(0x38);
|
||||
emit_int8((int8_t)(0xF0 | w));
|
||||
emit_operand(crc, adr);
|
||||
}
|
||||
|
||||
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, /* legacy_mode */ true);
|
||||
|
@ -6223,6 +6302,14 @@ void Assembler::shldl(Register dst, Register src) {
|
|||
emit_int8((unsigned char)(0xC0 | src->encoding() << 3 | dst->encoding()));
|
||||
}
|
||||
|
||||
// 0F A4 / r ib
|
||||
void Assembler::shldl(Register dst, Register src, int8_t imm8) {
|
||||
emit_int8(0x0F);
|
||||
emit_int8((unsigned char)0xA4);
|
||||
emit_int8((unsigned char)(0xC0 | src->encoding() << 3 | dst->encoding()));
|
||||
emit_int8(imm8);
|
||||
}
|
||||
|
||||
void Assembler::shrdl(Register dst, Register src) {
|
||||
emit_int8(0x0F);
|
||||
emit_int8((unsigned char)0xAD);
|
||||
|
@ -6408,6 +6495,40 @@ void Assembler::prefix(Register reg) {
|
|||
}
|
||||
}
|
||||
|
||||
void Assembler::prefix(Register dst, Register src, Prefix p) {
|
||||
if (src->encoding() >= 8) {
|
||||
p = (Prefix)(p | REX_B);
|
||||
}
|
||||
if (dst->encoding() >= 8) {
|
||||
p = (Prefix)( p | REX_R);
|
||||
}
|
||||
if (p != Prefix_EMPTY) {
|
||||
// do not generate an empty prefix
|
||||
prefix(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::prefix(Register dst, Address adr, Prefix p) {
|
||||
if (adr.base_needs_rex()) {
|
||||
if (adr.index_needs_rex()) {
|
||||
assert(false, "prefix(Register dst, Address adr, Prefix p) does not support handling of an X");
|
||||
} else {
|
||||
prefix(REX_B);
|
||||
}
|
||||
} else {
|
||||
if (adr.index_needs_rex()) {
|
||||
assert(false, "prefix(Register dst, Address adr, Prefix p) does not support handling of an X");
|
||||
}
|
||||
}
|
||||
if (dst->encoding() >= 8) {
|
||||
p = (Prefix)(p | REX_R);
|
||||
}
|
||||
if (p != Prefix_EMPTY) {
|
||||
// do not generate an empty prefix
|
||||
prefix(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::prefix(Address adr) {
|
||||
if (adr.base_needs_rex()) {
|
||||
if (adr.index_needs_rex()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue