# HG changeset patch # User kvn # Date 1323903278 28800 # Node ID 127b3692c168219cb69c0ebf5c9c1f1b17a0f82a # Parent d725f0affb1af0446acdfc400d5e92b20bf2f89a 7116452: Add support for AVX instructions Summary: Added support for AVX extension to the x86 instruction set. Reviewed-by: never diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/assembler_x86.cpp Wed Dec 14 14:54:38 2011 -0800 @@ -533,6 +533,19 @@ case 0x0F: // movx..., etc. switch (0xFF & *ip++) { + case 0x3A: // pcmpestri + tail_size = 1; + case 0x38: // ptest, pmovzxbw + ip++; // skip opcode + debug_only(has_disp32 = true); // has both kinds of operands! + break; + + case 0x70: // pshufd r, r/a, #8 + debug_only(has_disp32 = true); // has both kinds of operands! + case 0x73: // psrldq r, #8 + tail_size = 1; + break; + case 0x12: // movlps case 0x28: // movaps case 0x2E: // ucomiss @@ -543,9 +556,7 @@ case 0x57: // xorps case 0x6E: // movd case 0x7E: // movd - case 0xAE: // ldmxcsr a - // 64bit side says it these have both operands but that doesn't - // appear to be true + case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush debug_only(has_disp32 = true); break; @@ -565,6 +576,12 @@ // fall out of the switch to decode the address break; + case 0xC4: // pinsrw r, a, #8 + debug_only(has_disp32 = true); + case 0xC5: // pextrw r, r, #8 + tail_size = 1; // the imm8 + break; + case 0xAC: // shrd r, a, #8 debug_only(has_disp32 = true); tail_size = 1; // the imm8 @@ -625,11 +642,44 @@ tail_size = 1; // the imm8 break; - case 0xE8: // call rdisp32 - case 0xE9: // jmp rdisp32 - if (which == end_pc_operand) return ip + 4; - assert(which == call32_operand, "call has no disp32 or imm"); - return ip; + case 0xC4: // VEX_3bytes + case 0xC5: // VEX_2bytes + assert((UseAVX > 0), "shouldn't have VEX prefix"); + assert(ip == inst+1, "no prefixes allowed"); + // C4 and C5 are also used as opcodes for PINSRW and PEXTRW instructions + // but they have prefix 0x0F and processed when 0x0F processed above. + // + // In 32-bit mode the VEX first byte C4 and C5 alias onto LDS and LES + // instructions (these instructions are not supported in 64-bit mode). + // To distinguish them bits [7:6] are set in the VEX second byte since + // ModRM byte can not be of the form 11xxxxxx in 32-bit mode. To set + // those VEX bits REX and vvvv bits are inverted. + // + // Fortunately C2 doesn't generate these instructions so we don't need + // to check for them in product version. + + // Check second byte + NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions")); + + // First byte + if ((0xFF & *inst) == VEX_3bytes) { + ip++; // third byte + is_64bit = ((VEX_W & *ip) == VEX_W); + } + ip++; // opcode + // To find the end of instruction (which == end_pc_operand). + switch (0xFF & *ip) { + case 0x61: // pcmpestri r, r/a, #8 + case 0x70: // pshufd r, r/a, #8 + case 0x73: // psrldq r, #8 + tail_size = 1; // the imm8 + break; + default: + break; + } + ip++; // skip opcode + debug_only(has_disp32 = true); // has both kinds of operands! + break; case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1 case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl @@ -643,6 +693,12 @@ debug_only(has_disp32 = true); break; + case 0xE8: // call rdisp32 + case 0xE9: // jmp rdisp32 + if (which == end_pc_operand) return ip + 4; + assert(which == call32_operand, "call has no disp32 or imm"); + return ip; + case 0xF0: // Lock assert(os::is_MP(), "only on MP"); goto again_after_prefix; @@ -918,9 +974,7 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x58); emit_byte(0xC0 | encode); } @@ -928,18 +982,14 @@ void Assembler::addsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F2); emit_byte(0x58); emit_operand(dst, src); } void Assembler::addss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x58); emit_byte(0xC0 | encode); } @@ -947,13 +997,19 @@ void Assembler::addss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F3); emit_byte(0x58); emit_operand(dst, src); } +void Assembler::andl(Address dst, int32_t imm32) { + InstructionMark im(this); + prefix(dst); + emit_byte(0x81); + emit_operand(rsp, dst, 4); + emit_long(imm32); +} + void Assembler::andl(Register dst, int32_t imm32) { prefix(dst); emit_arith(0x81, 0xE0, dst, imm32); @@ -974,13 +1030,33 @@ void Assembler::andpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_66); emit_byte(0x54); emit_operand(dst, src); } +void Assembler::andpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); + emit_byte(0x54); + emit_byte(0xC0 | encode); +} + +void Assembler::andps(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_NONE); + emit_byte(0x54); + emit_operand(dst, src); +} + +void Assembler::andps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_NONE); + emit_byte(0x54); + emit_byte(0xC0 | encode); +} + void Assembler::bsfl(Register dst, Register src) { int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); @@ -1025,19 +1101,7 @@ } void Assembler::call(Register dst) { - // This was originally using a 32bit register encoding - // and surely we want 64bit! - // this is a 32bit encoding but in 64bit mode the default - // operand size is 64bit so there is no need for the - // wide prefix. So prefix only happens if we use the - // new registers. Much like push/pop. - int x = offset(); - // this may be true but dbx disassembles it as if it - // were 32bits... - // int encode = prefix_and_encode(dst->encoding()); - // if (offset() != x) assert(dst->encoding() >= 8, "what?"); - int encode = prefixq_and_encode(dst->encoding()); - + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xFF); emit_byte(0xD0 | encode); } @@ -1157,87 +1221,119 @@ // NOTE: dbx seems to decode this as comiss even though the // 0x66 is there. Strangly ucomisd comes out correct NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - comiss(dst, src); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66); + emit_byte(0x2F); + emit_operand(dst, src); +} + +void Assembler::comisd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); + emit_byte(0x2F); + emit_byte(0xC0 | encode); } void Assembler::comiss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - - InstructionMark im(this); - prefix(src, dst); - emit_byte(0x0F); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_NONE); emit_byte(0x2F); emit_operand(dst, src); } +void Assembler::comiss(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); + emit_byte(0x2F); + emit_byte(0xC0 | encode); +} + void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); emit_byte(0xE6); emit_byte(0xC0 | encode); } void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); emit_byte(0x5B); emit_byte(0xC0 | encode); } void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x5A); emit_byte(0xC0 | encode); } +void Assembler::cvtsd2ss(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_F2); + emit_byte(0x5A); + emit_operand(dst, src); +} + void Assembler::cvtsi2sdl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x2A); emit_byte(0xC0 | encode); } +void Assembler::cvtsi2sdl(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_F2); + emit_byte(0x2A); + emit_operand(dst, src); +} + void Assembler::cvtsi2ssl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x2A); emit_byte(0xC0 | encode); } +void Assembler::cvtsi2ssl(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_F3); + emit_byte(0x2A); + emit_operand(dst, src); +} + void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x5A); emit_byte(0xC0 | encode); } +void Assembler::cvtss2sd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_F3); + emit_byte(0x5A); + emit_operand(dst, src); +} + + void Assembler::cvttsd2sil(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2); emit_byte(0x2C); emit_byte(0xC0 | encode); } void Assembler::cvttss2sil(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); emit_byte(0x2C); emit_byte(0xC0 | encode); } @@ -1253,18 +1349,14 @@ void Assembler::divsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F2); emit_byte(0x5E); emit_operand(dst, src); } void Assembler::divsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x5E); emit_byte(0xC0 | encode); } @@ -1272,18 +1364,14 @@ void Assembler::divss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F3); emit_byte(0x5E); emit_operand(dst, src); } void Assembler::divss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x5E); emit_byte(0xC0 | encode); } @@ -1509,49 +1597,16 @@ void Assembler::movapd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - emit_byte(0x66); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); emit_byte(0x28); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); } void Assembler::movaps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); emit_byte(0x28); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); } void Assembler::movb(Register dst, Address src) { @@ -1582,19 +1637,15 @@ void Assembler::movdl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); emit_byte(0x6E); emit_byte(0xC0 | encode); } void Assembler::movdl(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); // swap src/dst to get correct prefix - int encode = prefix_and_encode(src->encoding(), dst->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66); emit_byte(0x7E); emit_byte(0xC0 | encode); } @@ -1602,58 +1653,29 @@ void Assembler::movdl(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_66); emit_byte(0x6E); emit_operand(dst, src); } - -void Assembler::movdqa(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); - emit_byte(0x6F); - emit_operand(dst, src); -} - void Assembler::movdqa(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); emit_byte(0x6F); emit_byte(0xC0 | encode); } -void Assembler::movdqa(Address dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0x66); - prefix(dst, src); - emit_byte(0x0F); - emit_byte(0x7F); - emit_operand(src, dst); -} - void Assembler::movdqu(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F3); emit_byte(0x6F); emit_operand(dst, src); } void Assembler::movdqu(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF3); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); emit_byte(0x6F); emit_byte(0xC0 | encode); } @@ -1661,9 +1683,7 @@ void Assembler::movdqu(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(dst, src); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F3); emit_byte(0x7F); emit_operand(src, dst); } @@ -1710,9 +1730,7 @@ void Assembler::movlpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_66); emit_byte(0x12); emit_operand(dst, src); } @@ -1740,9 +1758,7 @@ void Assembler::movq(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F3); emit_byte(0x7E); emit_operand(dst, src); } @@ -1750,9 +1766,7 @@ void Assembler::movq(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0x66); - prefix(dst, src); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_66); emit_byte(0xD6); emit_operand(src, dst); } @@ -1775,9 +1789,7 @@ void Assembler::movsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x10); emit_byte(0xC0 | encode); } @@ -1785,9 +1797,7 @@ void Assembler::movsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F2); emit_byte(0x10); emit_operand(dst, src); } @@ -1795,18 +1805,14 @@ void Assembler::movsd(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(dst, src); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F2); emit_byte(0x11); emit_operand(src, dst); } void Assembler::movss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x10); emit_byte(0xC0 | encode); } @@ -1814,9 +1820,7 @@ void Assembler::movss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F3); emit_byte(0x10); emit_operand(dst, src); } @@ -1824,9 +1828,7 @@ void Assembler::movss(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(dst, src); - emit_byte(0x0F); + simd_prefix(dst, src, VEX_SIMD_F3); emit_byte(0x11); emit_operand(src, dst); } @@ -1919,18 +1921,14 @@ void Assembler::mulsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F2); emit_byte(0x59); emit_operand(dst, src); } void Assembler::mulsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x59); emit_byte(0xC0 | encode); } @@ -1938,18 +1936,14 @@ void Assembler::mulss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F3); emit_byte(0x59); emit_operand(dst, src); } void Assembler::mulss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x59); emit_byte(0xC0 | encode); } @@ -2237,14 +2231,26 @@ emit_arith(0x0B, 0xC0, dst, src); } +void Assembler::packuswb(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66); + emit_byte(0x67); + emit_operand(dst, src); +} + +void Assembler::packuswb(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); + emit_byte(0x67); + emit_byte(0xC0 | encode); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); - - InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); - emit_byte(0x3A); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); emit_byte(0x61); emit_operand(dst, src); emit_byte(imm8); @@ -2252,16 +2258,27 @@ void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); - - emit_byte(0x66); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); - emit_byte(0x3A); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); emit_byte(0x61); emit_byte(0xC0 | encode); emit_byte(imm8); } +void Assembler::pmovzxbw(XMMRegister dst, Address src) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + emit_byte(0x30); + emit_operand(dst, src); +} + +void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sse4_1(), ""); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + emit_byte(0x30); + emit_byte(0xC0 | encode); +} + // generic void Assembler::pop(Register dst) { int encode = prefix_and_encode(dst->encoding()); @@ -2360,22 +2377,24 @@ void Assembler::por(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - emit_byte(0x66); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); - + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); emit_byte(0xEB); emit_byte(0xC0 | encode); } +void Assembler::por(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66); + emit_byte(0xEB); + emit_operand(dst, src); +} + void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - emit_byte(0x66); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); emit_byte(0x70); emit_byte(0xC0 | encode); emit_byte(mode & 0xFF); @@ -2385,11 +2404,9 @@ void Assembler::pshufd(XMMRegister dst, Address src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66); emit_byte(0x70); emit_operand(dst, src); emit_byte(mode & 0xFF); @@ -2398,10 +2415,7 @@ void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2); emit_byte(0x70); emit_byte(0xC0 | encode); emit_byte(mode & 0xFF); @@ -2410,11 +2424,9 @@ void Assembler::pshuflw(XMMRegister dst, Address src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); // QQ new - emit_byte(0x0F); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_F2); emit_byte(0x70); emit_operand(dst, src); emit_byte(mode & 0xFF); @@ -2425,11 +2437,8 @@ // HMM Table D-1 says sse2 or mmx. // Do not confuse it with psrldq SSE2 instruction which // shifts 128 bit value in xmm register by number of bytes. - NOT_LP64(assert(VM_Version::supports_sse(), "")); - - int encode = prefixq_and_encode(xmm2->encoding(), dst->encoding()); - emit_byte(0x66); - emit_byte(0x0F); + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); emit_byte(0x73); emit_byte(0xC0 | encode); emit_byte(shift); @@ -2438,10 +2447,7 @@ void Assembler::psrldq(XMMRegister dst, int shift) { // Shift 128 bit value in xmm register by number of bytes. NOT_LP64(assert(VM_Version::supports_sse2(), "")); - - int encode = prefixq_and_encode(xmm3->encoding(), dst->encoding()); - emit_byte(0x66); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66); emit_byte(0x73); emit_byte(0xC0 | encode); emit_byte(shift); @@ -2449,36 +2455,52 @@ void Assembler::ptest(XMMRegister dst, Address src) { assert(VM_Version::supports_sse4_1(), ""); - - InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); - emit_byte(0x38); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); emit_byte(0x17); emit_operand(dst, src); } void Assembler::ptest(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - - emit_byte(0x66); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); - emit_byte(0x38); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); emit_byte(0x17); emit_byte(0xC0 | encode); } +void Assembler::punpcklbw(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66); + emit_byte(0x60); + emit_operand(dst, src); +} + void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); emit_byte(0x60); emit_byte(0xC0 | encode); } +void Assembler::punpckldq(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66); + emit_byte(0x62); + emit_operand(dst, src); +} + +void Assembler::punpckldq(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); + emit_byte(0x62); + emit_byte(0xC0 | encode); +} + void Assembler::push(int32_t imm32) { // in 64bits we push 64bits onto the stack but only // take a 32bit immediate @@ -2508,20 +2530,16 @@ void Assembler::pxor(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66); emit_byte(0xEF); emit_operand(dst, src); } void Assembler::pxor(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0x66); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); emit_byte(0xEF); emit_byte(0xC0 | encode); } @@ -2683,12 +2701,8 @@ } void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { - // HMM Table D-1 says sse2 - // NOT_LP64(assert(VM_Version::supports_sse(), "")); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x51); emit_byte(0xC0 | encode); } @@ -2696,30 +2710,22 @@ void Assembler::sqrtsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F2); emit_byte(0x51); emit_operand(dst, src); } void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { - // HMM Table D-1 says sse2 - // NOT_LP64(assert(VM_Version::supports_sse(), "")); - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + NOT_LP64(assert(VM_Version::supports_sse(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x51); emit_byte(0xC0 | encode); } void Assembler::sqrtss(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_F3); emit_byte(0x51); emit_operand(dst, src); } @@ -2765,9 +2771,7 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); emit_byte(0x5C); emit_byte(0xC0 | encode); } @@ -2775,18 +2779,14 @@ void Assembler::subsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F2); emit_byte(0x5C); emit_operand(dst, src); } void Assembler::subss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); emit_byte(0x5C); emit_byte(0xC0 | encode); } @@ -2794,9 +2794,7 @@ void Assembler::subss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - emit_byte(0xF3); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_F3); emit_byte(0x5C); emit_operand(dst, src); } @@ -2836,30 +2834,30 @@ void Assembler::ucomisd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - ucomiss(dst, src); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66); + emit_byte(0x2E); + emit_operand(dst, src); } void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - ucomiss(dst, src); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); + emit_byte(0x2E); + emit_byte(0xC0 | encode); } void Assembler::ucomiss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - - InstructionMark im(this); - prefix(src, dst); - emit_byte(0x0F); + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_NONE); emit_byte(0x2E); emit_operand(dst, src); } void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); emit_byte(0x2E); emit_byte(0xC0 | encode); } @@ -2905,16 +2903,15 @@ void Assembler::xorpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0x66); - xorps(dst, src); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); + emit_byte(0x57); + emit_byte(0xC0 | encode); } void Assembler::xorpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - emit_byte(0x66); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_66); emit_byte(0x57); emit_operand(dst, src); } @@ -2922,8 +2919,7 @@ void Assembler::xorps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = prefix_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_NONE); emit_byte(0x57); emit_byte(0xC0 | encode); } @@ -2931,8 +2927,7 @@ void Assembler::xorps(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - prefix(src, dst); - emit_byte(0x0F); + simd_prefix(dst, dst, src, VEX_SIMD_NONE); emit_byte(0x57); emit_operand(dst, src); } @@ -3394,12 +3389,114 @@ emit_byte(0xF1); } +// SSE SIMD prefix byte values corresponding to VexSimdPrefix encoding. +static int simd_pre[4] = { 0, 0x66, 0xF3, 0xF2 }; +// SSE opcode second byte values (first is 0x0F) corresponding to VexOpcode encoding. +static int simd_opc[4] = { 0, 0, 0x38, 0x3A }; + +// Generate SSE legacy REX prefix and SIMD opcode based on VEX encoding. +void Assembler::rex_prefix(Address adr, XMMRegister xreg, VexSimdPrefix pre, VexOpcode opc, bool rex_w) { + if (pre > 0) { + emit_byte(simd_pre[pre]); + } + if (rex_w) { + prefixq(adr, xreg); + } else { + prefix(adr, xreg); + } + if (opc > 0) { + emit_byte(0x0F); + int opc2 = simd_opc[opc]; + if (opc2 > 0) { + emit_byte(opc2); + } + } +} + +int Assembler::rex_prefix_and_encode(int dst_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, bool rex_w) { + if (pre > 0) { + emit_byte(simd_pre[pre]); + } + int encode = (rex_w) ? prefixq_and_encode(dst_enc, src_enc) : + prefix_and_encode(dst_enc, src_enc); + if (opc > 0) { + emit_byte(0x0F); + int opc2 = simd_opc[opc]; + if (opc2 > 0) { + emit_byte(opc2); + } + } + return encode; +} + + +void Assembler::vex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, int nds_enc, VexSimdPrefix pre, VexOpcode opc, bool vector256) { + if (vex_b || vex_x || vex_w || (opc == VEX_OPCODE_0F_38) || (opc == VEX_OPCODE_0F_3A)) { + prefix(VEX_3bytes); + + int byte1 = (vex_r ? VEX_R : 0) | (vex_x ? VEX_X : 0) | (vex_b ? VEX_B : 0); + byte1 = (~byte1) & 0xE0; + byte1 |= opc; + a_byte(byte1); + + int byte2 = ((~nds_enc) & 0xf) << 3; + byte2 |= (vex_w ? VEX_W : 0) | (vector256 ? 4 : 0) | pre; + emit_byte(byte2); + } else { + prefix(VEX_2bytes); + + int byte1 = vex_r ? VEX_R : 0; + byte1 = (~byte1) & 0x80; + byte1 |= ((~nds_enc) & 0xf) << 3; + byte1 |= (vector256 ? 4 : 0) | pre; + emit_byte(byte1); + } +} + +void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc, bool vex_w, bool vector256){ + bool vex_r = (xreg_enc >= 8); + bool vex_b = adr.base_needs_rex(); + bool vex_x = adr.index_needs_rex(); + vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector256); +} + +int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, bool vex_w, bool vector256) { + bool vex_r = (dst_enc >= 8); + bool vex_b = (src_enc >= 8); + bool vex_x = false; + vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector256); + return (((dst_enc & 7) << 3) | (src_enc & 7)); +} + + +void Assembler::simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, VexSimdPrefix pre, VexOpcode opc, bool rex_w, bool vector256) { + if (UseAVX > 0) { + int xreg_enc = xreg->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + vex_prefix(adr, nds_enc, xreg_enc, pre, opc, rex_w, vector256); + } else { + assert((nds == xreg) || (nds == xnoreg), "wrong sse encoding"); + rex_prefix(adr, xreg, pre, opc, rex_w); + } +} + +int Assembler::simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, VexSimdPrefix pre, VexOpcode opc, bool rex_w, bool vector256) { + int dst_enc = dst->encoding(); + int src_enc = src->encoding(); + if (UseAVX > 0) { + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + return vex_prefix_and_encode(dst_enc, nds_enc, src_enc, pre, opc, rex_w, vector256); + } else { + assert((nds == dst) || (nds == src) || (nds == xnoreg), "wrong sse encoding"); + return rex_prefix_and_encode(dst_enc, src_enc, pre, opc, rex_w); + } +} #ifndef _LP64 void Assembler::incl(Register dst) { // Don't use it directly. Use MacroAssembler::incrementl() instead. - emit_byte(0x40 | dst->encoding()); + emit_byte(0x40 | dst->encoding()); } void Assembler::lea(Register dst, Address src) { @@ -3756,6 +3853,38 @@ } } +void Assembler::prefixq(Address adr, XMMRegister src) { + if (src->encoding() < 8) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_WXB); + } else { + prefix(REX_WB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_WX); + } else { + prefix(REX_W); + } + } + } else { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_WRXB); + } else { + prefix(REX_WRB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_WRX); + } else { + prefix(REX_WR); + } + } + } +} + void Assembler::adcq(Register dst, int32_t imm32) { (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xD0, dst, imm32); @@ -3918,36 +4047,44 @@ void Assembler::cvtsi2sdq(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2); emit_byte(0x2A); emit_byte(0xC0 | encode); } +void Assembler::cvtsi2sdq(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + simd_prefix_q(dst, dst, src, VEX_SIMD_F2); + emit_byte(0x2A); + emit_operand(dst, src); +} + void Assembler::cvtsi2ssq(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F3); emit_byte(0x2A); emit_byte(0xC0 | encode); } +void Assembler::cvtsi2ssq(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + simd_prefix_q(dst, dst, src, VEX_SIMD_F3); + emit_byte(0x2A); + emit_operand(dst, src); +} + void Assembler::cvttsd2siq(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_byte(0xF2); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F2); emit_byte(0x2C); emit_byte(0xC0 | encode); } void Assembler::cvttss2siq(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_byte(0xF3); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F3); emit_byte(0x2C); emit_byte(0xC0 | encode); } @@ -4107,21 +4244,17 @@ void Assembler::movdq(XMMRegister dst, Register src) { // table D-1 says MMX/SSE2 - NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); - emit_byte(0x66); - int encode = prefixq_and_encode(dst->encoding(), src->encoding()); - emit_byte(0x0F); + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_66); emit_byte(0x6E); emit_byte(0xC0 | encode); } void Assembler::movdq(Register dst, XMMRegister src) { // table D-1 says MMX/SSE2 - NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); - emit_byte(0x66); + NOT_LP64(assert(VM_Version::supports_sse2(), "")); // swap src/dst to get correct prefix - int encode = prefixq_and_encode(src->encoding(), dst->encoding()); - emit_byte(0x0F); + int encode = simd_prefix_and_encode_q(src, dst, VEX_SIMD_66); emit_byte(0x7E); emit_byte(0xC0 | encode); } @@ -5680,6 +5813,24 @@ LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); } +void MacroAssembler::addsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::addsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::addsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::addss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + addss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + addss(dst, Address(rscratch1, 0)); + } +} + void MacroAssembler::align(int modulus) { if (offset() % modulus != 0) { nop(modulus - (offset() % modulus)); @@ -5687,11 +5838,24 @@ } void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { + // Used in sign-masking with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { - andpd(dst, as_Address(src)); + Assembler::andpd(dst, as_Address(src)); } else { lea(rscratch1, src); - andpd(dst, Address(rscratch1, 0)); + Assembler::andpd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::andps(XMMRegister dst, AddressLiteral src) { + // Used in sign-masking with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::andps(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::andps(dst, Address(rscratch1, 0)); } } @@ -6268,19 +6432,19 @@ void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { - comisd(dst, as_Address(src)); + Assembler::comisd(dst, as_Address(src)); } else { lea(rscratch1, src); - comisd(dst, Address(rscratch1, 0)); + Assembler::comisd(dst, Address(rscratch1, 0)); } } void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { - comiss(dst, as_Address(src)); + Assembler::comiss(dst, as_Address(src)); } else { lea(rscratch1, src); - comiss(dst, Address(rscratch1, 0)); + Assembler::comiss(dst, Address(rscratch1, 0)); } } @@ -6364,6 +6528,24 @@ sarl(reg, shift_value); } +void MacroAssembler::divsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::divsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::divsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::divss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::divss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::divss(dst, Address(rscratch1, 0)); + } +} + // !defined(COMPILER2) is because of stupid core builds #if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) void MacroAssembler::empty_FPU_stack() { @@ -6803,12 +6985,39 @@ LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); } +void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::movsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::movsd(dst, Address(rscratch1, 0)); + } +} + void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { - movss(dst, as_Address(src)); + Assembler::movss(dst, as_Address(src)); } else { lea(rscratch1, src); - movss(dst, Address(rscratch1, 0)); + Assembler::movss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::mulsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::mulsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::mulsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::mulss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::mulss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::mulss(dst, Address(rscratch1, 0)); } } @@ -6990,6 +7199,42 @@ testl(dst, as_Address(src)); } +void MacroAssembler::sqrtsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::sqrtsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::sqrtsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::sqrtss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::sqrtss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::sqrtss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::subsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::subsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::subsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::subss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::subss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::subss(dst, Address(rscratch1, 0)); + } +} + ////////////////////////////////////////////////////////////////////////////////// #ifndef SERIALGC @@ -7875,28 +8120,42 @@ void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { - ucomisd(dst, as_Address(src)); + if (reachable(src)) { + Assembler::ucomisd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ucomisd(dst, Address(rscratch1, 0)); + } } void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { - ucomiss(dst, as_Address(src)); + if (reachable(src)) { + Assembler::ucomiss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ucomiss(dst, Address(rscratch1, 0)); + } } void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { + // Used in sign-bit flipping with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { - xorpd(dst, as_Address(src)); + Assembler::xorpd(dst, as_Address(src)); } else { lea(rscratch1, src); - xorpd(dst, Address(rscratch1, 0)); + Assembler::xorpd(dst, Address(rscratch1, 0)); } } void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { + // Used in sign-bit flipping with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { - xorps(dst, as_Address(src)); + Assembler::xorps(dst, as_Address(src)); } else { lea(rscratch1, src); - xorps(dst, Address(rscratch1, 0)); + Assembler::xorps(dst, Address(rscratch1, 0)); } } diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/assembler_x86.hpp Wed Dec 14 14:54:38 2011 -0800 @@ -503,7 +503,31 @@ REX_WR = 0x4C, REX_WRB = 0x4D, REX_WRX = 0x4E, - REX_WRXB = 0x4F + REX_WRXB = 0x4F, + + VEX_3bytes = 0xC4, + VEX_2bytes = 0xC5 + }; + + enum VexPrefix { + VEX_B = 0x20, + VEX_X = 0x40, + VEX_R = 0x80, + VEX_W = 0x80 + }; + + enum VexSimdPrefix { + VEX_SIMD_NONE = 0x0, + VEX_SIMD_66 = 0x1, + VEX_SIMD_F3 = 0x2, + VEX_SIMD_F2 = 0x3 + }; + + enum VexOpcode { + VEX_OPCODE_NONE = 0x0, + VEX_OPCODE_0F = 0x1, + VEX_OPCODE_0F_38 = 0x2, + VEX_OPCODE_0F_3A = 0x3 }; enum WhichOperand { @@ -546,12 +570,88 @@ void prefixq(Address adr); void prefix(Address adr, Register reg, bool byteinst = false); + void prefix(Address adr, XMMRegister reg); void prefixq(Address adr, Register reg); - - void prefix(Address adr, XMMRegister reg); + void prefixq(Address adr, XMMRegister reg); void prefetch_prefix(Address src); + void rex_prefix(Address adr, XMMRegister xreg, + VexSimdPrefix pre, VexOpcode opc, bool rex_w); + int rex_prefix_and_encode(int dst_enc, int src_enc, + VexSimdPrefix pre, VexOpcode opc, bool rex_w); + + void vex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, + int nds_enc, VexSimdPrefix pre, VexOpcode opc, + bool vector256); + + void vex_prefix(Address adr, int nds_enc, int xreg_enc, + VexSimdPrefix pre, VexOpcode opc, + bool vex_w, bool vector256); + + int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, + VexSimdPrefix pre, VexOpcode opc, + bool vex_w, bool vector256); + + + void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F, + bool rex_w = false, bool vector256 = false); + + void simd_prefix(XMMRegister dst, Address src, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { + simd_prefix(dst, xnoreg, src, pre, opc); + } + void simd_prefix(Address dst, XMMRegister src, VexSimdPrefix pre) { + simd_prefix(src, dst, pre); + } + void simd_prefix_q(XMMRegister dst, XMMRegister nds, Address src, + VexSimdPrefix pre) { + bool rex_w = true; + simd_prefix(dst, nds, src, pre, VEX_OPCODE_0F, rex_w); + } + + + int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F, + bool rex_w = false, bool vector256 = false); + + int simd_prefix_and_encode(XMMRegister dst, XMMRegister src, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { + return simd_prefix_and_encode(dst, xnoreg, src, pre, opc); + } + + // Move/convert 32-bit integer value. + int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, Register src, + VexSimdPrefix pre) { + // It is OK to cast from Register to XMMRegister to pass argument here + // since only encoding is used in simd_prefix_and_encode() and number of + // Gen and Xmm registers are the same. + return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre); + } + int simd_prefix_and_encode(XMMRegister dst, Register src, VexSimdPrefix pre) { + return simd_prefix_and_encode(dst, xnoreg, src, pre); + } + int simd_prefix_and_encode(Register dst, XMMRegister src, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { + return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, opc); + } + + // Move/convert 64-bit integer value. + int simd_prefix_and_encode_q(XMMRegister dst, XMMRegister nds, Register src, + VexSimdPrefix pre) { + bool rex_w = true; + return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, VEX_OPCODE_0F, rex_w); + } + int simd_prefix_and_encode_q(XMMRegister dst, Register src, VexSimdPrefix pre) { + return simd_prefix_and_encode_q(dst, xnoreg, src, pre); + } + int simd_prefix_and_encode_q(Register dst, XMMRegister src, + VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { + bool rex_w = true; + return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, opc, rex_w); + } + // Helper functions for groups of instructions void emit_arith_b(int op1, int op2, Register dst, int imm8); @@ -764,6 +864,7 @@ void addss(XMMRegister dst, Address src); void addss(XMMRegister dst, XMMRegister src); + void andl(Address dst, int32_t imm32); void andl(Register dst, int32_t imm32); void andl(Register dst, Address src); void andl(Register dst, Register src); @@ -774,9 +875,11 @@ void andq(Register dst, Register src); // Bitwise Logical AND of Packed Double-Precision Floating-Point Values - void andpd(XMMRegister dst, Address src); void andpd(XMMRegister dst, XMMRegister src); + // Bitwise Logical AND of Packed Single-Precision Floating-Point Values + void andps(XMMRegister dst, XMMRegister src); + void bsfl(Register dst, Register src); void bsrl(Register dst, Register src); @@ -837,9 +940,11 @@ // Ordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS void comisd(XMMRegister dst, Address src); + void comisd(XMMRegister dst, XMMRegister src); // Ordered Compare Scalar Single-Precision Floating-Point Values and set EFLAGS void comiss(XMMRegister dst, Address src); + void comiss(XMMRegister dst, XMMRegister src); // Identify processor type and features void cpuid() { @@ -849,14 +954,19 @@ // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value void cvtsd2ss(XMMRegister dst, XMMRegister src); + void cvtsd2ss(XMMRegister dst, Address src); // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value void cvtsi2sdl(XMMRegister dst, Register src); + void cvtsi2sdl(XMMRegister dst, Address src); void cvtsi2sdq(XMMRegister dst, Register src); + void cvtsi2sdq(XMMRegister dst, Address src); // Convert Doubleword Integer to Scalar Single-Precision Floating-Point Value void cvtsi2ssl(XMMRegister dst, Register src); + void cvtsi2ssl(XMMRegister dst, Address src); void cvtsi2ssq(XMMRegister dst, Register src); + void cvtsi2ssq(XMMRegister dst, Address src); // Convert Packed Signed Doubleword Integers to Packed Double-Precision Floating-Point Value void cvtdq2pd(XMMRegister dst, XMMRegister src); @@ -866,6 +976,7 @@ // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value void cvtss2sd(XMMRegister dst, XMMRegister src); + void cvtss2sd(XMMRegister dst, Address src); // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer void cvttsd2sil(Register dst, Address src); @@ -1140,8 +1251,6 @@ void movdq(Register dst, XMMRegister src); // Move Aligned Double Quadword - void movdqa(Address dst, XMMRegister src); - void movdqa(XMMRegister dst, Address src); void movdqa(XMMRegister dst, XMMRegister src); // Move Unaligned Double Quadword @@ -1261,10 +1370,18 @@ void orq(Register dst, Address src); void orq(Register dst, Register src); + // Pack with unsigned saturation + void packuswb(XMMRegister dst, XMMRegister src); + void packuswb(XMMRegister dst, Address src); + // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); + // SSE4.1 packed move + void pmovzxbw(XMMRegister dst, XMMRegister src); + void pmovzxbw(XMMRegister dst, Address src); + #ifndef _LP64 // no 32bit push/pop on amd64 void popl(Address dst); #endif @@ -1292,6 +1409,7 @@ // POR - Bitwise logical OR void por(XMMRegister dst, XMMRegister src); + void por(XMMRegister dst, Address src); // Shuffle Packed Doublewords void pshufd(XMMRegister dst, XMMRegister src, int mode); @@ -1313,6 +1431,11 @@ // Interleave Low Bytes void punpcklbw(XMMRegister dst, XMMRegister src); + void punpcklbw(XMMRegister dst, Address src); + + // Interleave Low Doublewords + void punpckldq(XMMRegister dst, XMMRegister src); + void punpckldq(XMMRegister dst, Address src); #ifndef _LP64 // no 32bit push/pop on amd64 void pushl(Address src); @@ -1429,6 +1552,13 @@ void xchgq(Register reg, Address adr); void xchgq(Register dst, Register src); + // Get Value of Extended Control Register + void xgetbv() { + emit_byte(0x0F); + emit_byte(0x01); + emit_byte(0xD0); + } + void xorl(Register dst, int32_t imm32); void xorl(Register dst, Address src); void xorl(Register dst, Register src); @@ -1437,14 +1567,21 @@ void xorq(Register dst, Register src); // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values - void xorpd(XMMRegister dst, Address src); void xorpd(XMMRegister dst, XMMRegister src); // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values - void xorps(XMMRegister dst, Address src); void xorps(XMMRegister dst, XMMRegister src); void set_byte_if_not_zero(Register dst); // sets reg to 1 if not zero, otherwise 0 + + protected: + // Next instructions require address alignment 16 bytes SSE mode. + // They should be called only from corresponding MacroAssembler instructions. + void andpd(XMMRegister dst, Address src); + void andps(XMMRegister dst, Address src); + void xorpd(XMMRegister dst, Address src); + void xorps(XMMRegister dst, Address src); + }; @@ -2175,9 +2312,15 @@ void andpd(XMMRegister dst, Address src) { Assembler::andpd(dst, src); } void andpd(XMMRegister dst, AddressLiteral src); + void andps(XMMRegister dst, XMMRegister src) { Assembler::andps(dst, src); } + void andps(XMMRegister dst, Address src) { Assembler::andps(dst, src); } + void andps(XMMRegister dst, AddressLiteral src); + + void comiss(XMMRegister dst, XMMRegister src) { Assembler::comiss(dst, src); } void comiss(XMMRegister dst, Address src) { Assembler::comiss(dst, src); } void comiss(XMMRegister dst, AddressLiteral src); + void comisd(XMMRegister dst, XMMRegister src) { Assembler::comisd(dst, src); } void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); } void comisd(XMMRegister dst, AddressLiteral src); @@ -2211,62 +2354,62 @@ void movss(XMMRegister dst, Address src) { Assembler::movss(dst, src); } void movss(XMMRegister dst, AddressLiteral src); - void movlpd(XMMRegister dst, Address src) {Assembler::movlpd(dst, src); } + void movlpd(XMMRegister dst, Address src) {Assembler::movlpd(dst, src); } void movlpd(XMMRegister dst, AddressLiteral src); public: void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); } void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); } - void addsd(XMMRegister dst, AddressLiteral src) { Assembler::addsd(dst, as_Address(src)); } + void addsd(XMMRegister dst, AddressLiteral src); void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); } void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); } - void addss(XMMRegister dst, AddressLiteral src) { Assembler::addss(dst, as_Address(src)); } + void addss(XMMRegister dst, AddressLiteral src); void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); } void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); } - void divsd(XMMRegister dst, AddressLiteral src) { Assembler::divsd(dst, as_Address(src)); } + void divsd(XMMRegister dst, AddressLiteral src); void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); } void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); } - void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); } + void divss(XMMRegister dst, AddressLiteral src); void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); } + void movsd(XMMRegister dst, AddressLiteral src); void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); } void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); } - void mulsd(XMMRegister dst, AddressLiteral src) { Assembler::mulsd(dst, as_Address(src)); } + void mulsd(XMMRegister dst, AddressLiteral src); void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); } void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } - void mulss(XMMRegister dst, AddressLiteral src) { Assembler::mulss(dst, as_Address(src)); } + void mulss(XMMRegister dst, AddressLiteral src); void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); } - void sqrtsd(XMMRegister dst, AddressLiteral src) { Assembler::sqrtsd(dst, as_Address(src)); } + void sqrtsd(XMMRegister dst, AddressLiteral src); void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); } void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); } - void sqrtss(XMMRegister dst, AddressLiteral src) { Assembler::sqrtss(dst, as_Address(src)); } + void sqrtss(XMMRegister dst, AddressLiteral src); void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); } void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); } - void subsd(XMMRegister dst, AddressLiteral src) { Assembler::subsd(dst, as_Address(src)); } + void subsd(XMMRegister dst, AddressLiteral src); void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); } void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); } - void subss(XMMRegister dst, AddressLiteral src) { Assembler::subss(dst, as_Address(src)); } + void subss(XMMRegister dst, AddressLiteral src); void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } - void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } + void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } void ucomiss(XMMRegister dst, AddressLiteral src); void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); } - void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } + void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } void ucomisd(XMMRegister dst, AddressLiteral src); // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/assembler_x86.inline.hpp --- a/src/cpu/x86/vm/assembler_x86.inline.hpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/assembler_x86.inline.hpp Wed Dec 14 14:54:38 2011 -0800 @@ -86,6 +86,7 @@ inline void Assembler::prefixq(Address adr, Register reg) {} inline void Assembler::prefix(Address adr, XMMRegister reg) {} +inline void Assembler::prefixq(Address adr, XMMRegister reg) {} #else inline void Assembler::emit_long64(jlong x) { *(jlong*) _code_pos = x; diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/nativeInst_x86.cpp --- a/src/cpu/x86/vm/nativeInst_x86.cpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/nativeInst_x86.cpp Wed Dec 14 14:54:38 2011 -0800 @@ -237,9 +237,21 @@ int off = 0; u_char instr_0 = ubyte_at(off); + // See comment in Assembler::locate_operand() about VEX prefixes. + if (instr_0 == instruction_VEX_prefix_2bytes) { + assert((UseAVX > 0), "shouldn't have VEX prefix"); + NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions")); + return 2; + } + if (instr_0 == instruction_VEX_prefix_3bytes) { + assert((UseAVX > 0), "shouldn't have VEX prefix"); + NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions")); + return 3; + } + // First check to see if we have a (prefixed or not) xor - if ( instr_0 >= instruction_prefix_wide_lo && // 0x40 - instr_0 <= instruction_prefix_wide_hi) { // 0x4f + if (instr_0 >= instruction_prefix_wide_lo && // 0x40 + instr_0 <= instruction_prefix_wide_hi) { // 0x4f off++; instr_0 = ubyte_at(off); } @@ -256,13 +268,13 @@ instr_0 = ubyte_at(off); } - if ( instr_0 == instruction_code_xmm_ss_prefix || // 0xf3 + if ( instr_0 == instruction_code_xmm_ss_prefix || // 0xf3 instr_0 == instruction_code_xmm_sd_prefix) { // 0xf2 off++; instr_0 = ubyte_at(off); } - if ( instr_0 >= instruction_prefix_wide_lo && // 0x40 + if ( instr_0 >= instruction_prefix_wide_lo && // 0x40 instr_0 <= instruction_prefix_wide_hi) { // 0x4f off++; instr_0 = ubyte_at(off); diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/nativeInst_x86.hpp --- a/src/cpu/x86/vm/nativeInst_x86.hpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp Wed Dec 14 14:54:38 2011 -0800 @@ -287,6 +287,9 @@ instruction_code_xmm_store = 0x11, instruction_code_xmm_lpd = 0x12, + instruction_VEX_prefix_2bytes = Assembler::VEX_2bytes, + instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes, + instruction_size = 4, instruction_offset = 0, data_offset = 2, diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/register_definitions_x86.cpp --- a/src/cpu/x86/vm/register_definitions_x86.cpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/register_definitions_x86.cpp Wed Dec 14 14:54:38 2011 -0800 @@ -53,6 +53,7 @@ REGISTER_DEFINITION(Register, r15); #endif // AMD64 +REGISTER_DEFINITION(XMMRegister, xnoreg); REGISTER_DEFINITION(XMMRegister, xmm0 ); REGISTER_DEFINITION(XMMRegister, xmm1 ); REGISTER_DEFINITION(XMMRegister, xmm2 ); @@ -115,6 +116,7 @@ REGISTER_DEFINITION(Register, r15_thread); #endif // AMD64 +REGISTER_DEFINITION(MMXRegister, mnoreg ); REGISTER_DEFINITION(MMXRegister, mmx0 ); REGISTER_DEFINITION(MMXRegister, mmx1 ); REGISTER_DEFINITION(MMXRegister, mmx2 ); diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Wed Dec 14 14:54:38 2011 -0800 @@ -50,7 +50,7 @@ VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; static BufferBlob* stub_blob; -static const int stub_size = 400; +static const int stub_size = 500; extern "C" { typedef void (*getPsrInfo_stub_t)(void*); @@ -73,7 +73,7 @@ const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; - Label ext_cpuid1, ext_cpuid5, done; + Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, done; StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); # define __ _masm-> @@ -229,6 +229,41 @@ __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); + // + // Check if OS has enabled XGETBV instruction to access XCR0 + // (OSXSAVE feature flag) and CPU supports AVX + // + __ andl(rcx, 0x18000000); + __ cmpl(rcx, 0x18000000); + __ jccb(Assembler::notEqual, sef_cpuid); + + // + // XCR0, XFEATURE_ENABLED_MASK register + // + __ xorl(rcx, rcx); // zero for XCR0 register + __ xgetbv(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rdx); + + // + // cpuid(0x7) Structured Extended Features + // + __ bind(sef_cpuid); + __ movl(rax, 7); + __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x7) supported? + __ jccb(Assembler::greater, ext_cpuid); + + __ xorl(rcx, rcx); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + + // + // Extended cpuid(0x80000000) + // + __ bind(ext_cpuid); __ movl(rax, 0x80000000); __ cpuid(); __ cmpl(rax, 0x80000000); // Is cpuid(0x80000001) supported? @@ -359,13 +394,19 @@ if (UseSSE < 1) _cpuFeatures &= ~CPU_SSE; + if (UseAVX < 2) + _cpuFeatures &= ~CPU_AVX2; + + if (UseAVX < 1) + _cpuFeatures &= ~CPU_AVX; + if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. _cpuFeatures &= ~CPU_HT; } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -379,6 +420,8 @@ (supports_sse4_1() ? ", sse4.1" : ""), (supports_sse4_2() ? ", sse4.2" : ""), (supports_popcnt() ? ", popcnt" : ""), + (supports_avx() ? ", avx" : ""), + (supports_avx2() ? ", avx2" : ""), (supports_mmx_ext() ? ", mmxext" : ""), (supports_3dnow_prefetch() ? ", 3dnowpref" : ""), (supports_lzcnt() ? ", lzcnt": ""), @@ -389,17 +432,24 @@ // UseSSE is set to the smaller of what hardware supports and what // the command line requires. I.e., you cannot set UseSSE to 2 on // older Pentiums which do not support it. - if( UseSSE > 4 ) UseSSE=4; - if( UseSSE < 0 ) UseSSE=0; - if( !supports_sse4_1() ) // Drop to 3 if no SSE4 support + if (UseSSE > 4) UseSSE=4; + if (UseSSE < 0) UseSSE=0; + if (!supports_sse4_1()) // Drop to 3 if no SSE4 support UseSSE = MIN2((intx)3,UseSSE); - if( !supports_sse3() ) // Drop to 2 if no SSE3 support + if (!supports_sse3()) // Drop to 2 if no SSE3 support UseSSE = MIN2((intx)2,UseSSE); - if( !supports_sse2() ) // Drop to 1 if no SSE2 support + if (!supports_sse2()) // Drop to 1 if no SSE2 support UseSSE = MIN2((intx)1,UseSSE); - if( !supports_sse () ) // Drop to 0 if no SSE support + if (!supports_sse ()) // Drop to 0 if no SSE support UseSSE = 0; + if (UseAVX > 2) UseAVX=2; + if (UseAVX < 0) UseAVX=0; + if (!supports_avx2()) // Drop to 1 if no AVX2 support + UseAVX = MIN2((intx)1,UseAVX); + if (!supports_avx ()) // Drop to 0 if no AVX support + UseAVX = 0; + // On new cpus instructions which update whole XMM register should be used // to prevent partial register stall due to dependencies on high half. // @@ -534,6 +584,9 @@ if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { UsePopCountInstruction = true; } + } else if (UsePopCountInstruction) { + warning("POPCNT instruction is not available on this CPU"); + FLAG_SET_DEFAULT(UsePopCountInstruction, false); } #ifdef COMPILER2 @@ -605,7 +658,11 @@ if (PrintMiscellaneous && Verbose) { tty->print_cr("Logical CPUs per core: %u", logical_processors_per_package()); - tty->print_cr("UseSSE=%d",UseSSE); + tty->print("UseSSE=%d",UseSSE); + if (UseAVX > 0) { + tty->print(" UseAVX=%d",UseAVX); + } + tty->cr(); tty->print("Allocation"); if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { tty->print_cr(": no prefetching"); diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/vm_version_x86.hpp --- a/src/cpu/x86/vm/vm_version_x86.hpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Wed Dec 14 14:54:38 2011 -0800 @@ -78,7 +78,10 @@ sse4_2 : 1, : 2, popcnt : 1, - : 8; + : 3, + osxsave : 1, + avx : 1, + : 3; } bits; }; @@ -176,6 +179,34 @@ } bits; }; + union SefCpuid7Eax { + uint32_t value; + }; + + union SefCpuid7Ebx { + uint32_t value; + struct { + uint32_t fsgsbase : 1, + : 2, + bmi1 : 1, + : 1, + avx2 : 1, + : 2, + bmi2 : 1, + : 23; + } bits; + }; + + union XemXcr0Eax { + uint32_t value; + struct { + uint32_t x87 : 1, + sse : 1, + ymm : 1, + : 29; + } bits; + }; + protected: static int _cpu; static int _model; @@ -200,7 +231,9 @@ CPU_SSE4_1 = (1 << 11), CPU_SSE4_2 = (1 << 12), CPU_POPCNT = (1 << 13), - CPU_LZCNT = (1 << 14) + CPU_LZCNT = (1 << 14), + CPU_AVX = (1 << 15), + CPU_AVX2 = (1 << 16) } cpuFeatureFlags; // cpuid information block. All info derived from executing cpuid with @@ -228,6 +261,12 @@ uint32_t dcp_cpuid4_ecx; // unused currently uint32_t dcp_cpuid4_edx; // unused currently + // cpuid function 7 (structured extended features) + SefCpuid7Eax sef_cpuid7_eax; + SefCpuid7Ebx sef_cpuid7_ebx; + uint32_t sef_cpuid7_ecx; // unused currently + uint32_t sef_cpuid7_edx; // unused currently + // cpuid function 0xB (processor topology) // ecx = 0 uint32_t tpl_cpuidB0_eax; @@ -275,6 +314,10 @@ uint32_t ext_cpuid8_ebx; // reserved ExtCpuid8Ecx ext_cpuid8_ecx; uint32_t ext_cpuid8_edx; // reserved + + // extended control register XCR0 (the XFEATURE_ENABLED_MASK register) + XemXcr0Eax xem_xcr0_eax; + uint32_t xem_xcr0_edx; // reserved }; // The actual cpuid info block @@ -328,6 +371,14 @@ result |= CPU_SSE4_2; if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) result |= CPU_POPCNT; + if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 && + _cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 && + _cpuid_info.xem_xcr0_eax.bits.sse != 0 && + _cpuid_info.xem_xcr0_eax.bits.ymm != 0) { + result |= CPU_AVX; + if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0) + result |= CPU_AVX2; + } // AMD features. if (is_amd()) { @@ -350,12 +401,14 @@ static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } + static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); } static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); } static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); } static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); } static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); } static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); } + static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); } // Initialization static void initialize(); @@ -447,6 +500,8 @@ static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } + static bool supports_avx() { return (_cpuFeatures & CPU_AVX) != 0; } + static bool supports_avx2() { return (_cpuFeatures & CPU_AVX2) != 0; } // // AMD features // diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/x86_32.ad Wed Dec 14 14:54:38 2011 -0800 @@ -281,7 +281,7 @@ } static int preserve_SP_size() { - return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) + return 2; // op, rm(reg/reg) } // !!!!! Special hack to get all type of calls to specify the byte offset @@ -495,14 +495,34 @@ } } -void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) { - if( dst_encoding == src_encoding ) { - // reg-reg copy, use an empty encoding - } else { - MacroAssembler _masm(&cbuf); - - __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding)); - } +void emit_cmpfp_fixup(MacroAssembler& _masm) { + Label exit; + __ jccb(Assembler::noParity, exit); + __ pushf(); + // + // comiss/ucomiss instructions set ZF,PF,CF flags and + // zero OF,AF,SF for NaN values. + // Fixup flags by zeroing ZF,PF so that compare of NaN + // values returns 'less than' result (CF is set). + // Leave the rest of flags unchanged. + // + // 7 6 5 4 3 2 1 0 + // |S|Z|r|A|r|P|r|C| (r - reserved bit) + // 0 0 1 0 1 0 1 1 (0x2B) + // + __ andl(Address(rsp, 0), 0xffffff2b); + __ popf(); + __ bind(exit); +} + +void emit_cmpfp3(MacroAssembler& _masm, Register dst) { + Label done; + __ movl(dst, -1); + __ jcc(Assembler::parity, done); + __ jcc(Assembler::below, done); + __ setb(Assembler::notEqual, dst); + __ movzbl(dst, dst); + __ bind(done); } @@ -792,92 +812,88 @@ // Helper for XMM registers. Extra opcode bits, limited syntax. static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg_lo, int reg_hi, int size, outputStream* st ) { - if( cbuf ) { - if( reg_lo+1 == reg_hi ) { // double move? - if( is_load && !UseXmmLoadAndClearUpper ) - emit_opcode(*cbuf, 0x66 ); // use 'movlpd' for load - else - emit_opcode(*cbuf, 0xF2 ); // use 'movsd' otherwise + if (cbuf) { + MacroAssembler _masm(cbuf); + if (reg_lo+1 == reg_hi) { // double move? + if (is_load) { + __ movdbl(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset)); + } else { + __ movdbl(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo])); + } } else { - emit_opcode(*cbuf, 0xF3 ); + if (is_load) { + __ movflt(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset)); + } else { + __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo])); + } } - emit_opcode(*cbuf, 0x0F ); - if( reg_lo+1 == reg_hi && is_load && !UseXmmLoadAndClearUpper ) - emit_opcode(*cbuf, 0x12 ); // use 'movlpd' for load - else - emit_opcode(*cbuf, is_load ? 0x10 : 0x11 ); - encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - if( reg_lo+1 == reg_hi ) { // double move? - if( is_load ) st->print("%s %s,[ESP + #%d]", - UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", - Matcher::regName[reg_lo], offset); - else st->print("MOVSD [ESP + #%d],%s", - offset, Matcher::regName[reg_lo]); + } else if (!do_size) { + if (size != 0) st->print("\n\t"); + if (reg_lo+1 == reg_hi) { // double move? + if (is_load) st->print("%s %s,[ESP + #%d]", + UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", + Matcher::regName[reg_lo], offset); + else st->print("MOVSD [ESP + #%d],%s", + offset, Matcher::regName[reg_lo]); } else { - if( is_load ) st->print("MOVSS %s,[ESP + #%d]", - Matcher::regName[reg_lo], offset); - else st->print("MOVSS [ESP + #%d],%s", - offset, Matcher::regName[reg_lo]); + if (is_load) st->print("MOVSS %s,[ESP + #%d]", + Matcher::regName[reg_lo], offset); + else st->print("MOVSS [ESP + #%d],%s", + offset, Matcher::regName[reg_lo]); } #endif } int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4); + // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes. return size+5+offset_size; } static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, int src_hi, int dst_hi, int size, outputStream* st ) { - if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers - if( cbuf ) { - if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { - emit_opcode(*cbuf, 0x66 ); - } - emit_opcode(*cbuf, 0x0F ); - emit_opcode(*cbuf, 0x28 ); - emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); + if (cbuf) { + MacroAssembler _masm(cbuf); + if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move? + __ movdbl(as_XMMRegister(Matcher::_regEncode[dst_lo]), + as_XMMRegister(Matcher::_regEncode[src_lo])); + } else { + __ movflt(as_XMMRegister(Matcher::_regEncode[dst_lo]), + as_XMMRegister(Matcher::_regEncode[src_lo])); + } #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? + } else if (!do_size) { + if (size != 0) st->print("\n\t"); + if (UseXmmRegToRegMoveAll) {//Use movaps,movapd to move between xmm registers + if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move? st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } -#endif - } - return size + ((src_lo+1 == src_hi && dst_lo+1 == dst_hi) ? 4 : 3); - } else { - if( cbuf ) { - emit_opcode(*cbuf, (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ? 0xF2 : 0xF3 ); - emit_opcode(*cbuf, 0x0F ); - emit_opcode(*cbuf, 0x10 ); - emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); -#ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); + } else { if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } + } #endif - } - return size+4; } + // VEX_2bytes prefix is used if UseAVX > 0, and it takes the same 2 bytes. + // Only MOVAPS SSE prefix uses 1 byte. + int sz = 4; + if (!(src_lo+1 == src_hi && dst_lo+1 == dst_hi) && + UseXmmRegToRegMoveAll && (UseAVX == 0)) sz = 3; + return size + sz; } static int impl_movgpr2x_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, int src_hi, int dst_hi, int size, outputStream* st ) { // 32-bit if (cbuf) { - emit_opcode(*cbuf, 0x66); - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x6E); - emit_rm(*cbuf, 0x3, Matcher::_regEncode[dst_lo] & 7, Matcher::_regEncode[src_lo] & 7); + MacroAssembler _masm(cbuf); + __ movdl(as_XMMRegister(Matcher::_regEncode[dst_lo]), + as_Register(Matcher::_regEncode[src_lo])); #ifndef PRODUCT } else if (!do_size) { st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]); @@ -891,10 +907,9 @@ int src_hi, int dst_hi, int size, outputStream* st ) { // 32-bit if (cbuf) { - emit_opcode(*cbuf, 0x66); - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x7E); - emit_rm(*cbuf, 0x3, Matcher::_regEncode[src_lo] & 7, Matcher::_regEncode[dst_lo] & 7); + MacroAssembler _masm(cbuf); + __ movdl(as_Register(Matcher::_regEncode[dst_lo]), + as_XMMRegister(Matcher::_regEncode[src_lo])); #ifndef PRODUCT } else if (!do_size) { st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]); @@ -1931,11 +1946,6 @@ %} - enc_class Xor_Reg (eRegI dst) %{ - emit_opcode(cbuf, 0x33); - emit_rm(cbuf, 0x3, $dst$$reg, $dst$$reg); - %} - // Following encoding is no longer used, but may be restored if calling // convention changes significantly. // Became: Xor_Reg(EBP), Java_To_Runtime( labl ) @@ -2013,64 +2023,6 @@ %} - enc_class MovI2X_reg(regX dst, eRegI src) %{ - emit_opcode(cbuf, 0x66 ); // MOVD dst,src - emit_opcode(cbuf, 0x0F ); - emit_opcode(cbuf, 0x6E ); - emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg); - %} - - enc_class MovX2I_reg(eRegI dst, regX src) %{ - emit_opcode(cbuf, 0x66 ); // MOVD dst,src - emit_opcode(cbuf, 0x0F ); - emit_opcode(cbuf, 0x7E ); - emit_rm(cbuf, 0x3, $src$$reg, $dst$$reg); - %} - - enc_class MovL2XD_reg(regXD dst, eRegL src, regXD tmp) %{ - { // MOVD $dst,$src.lo - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x6E); - emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg); - } - { // MOVD $tmp,$src.hi - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x6E); - emit_rm(cbuf, 0x3, $tmp$$reg, HIGH_FROM_LOW($src$$reg)); - } - { // PUNPCKLDQ $dst,$tmp - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x62); - emit_rm(cbuf, 0x3, $dst$$reg, $tmp$$reg); - } - %} - - enc_class MovXD2L_reg(eRegL dst, regXD src, regXD tmp) %{ - { // MOVD $dst.lo,$src - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x7E); - emit_rm(cbuf, 0x3, $src$$reg, $dst$$reg); - } - { // PSHUFLW $tmp,$src,0x4E (01001110b) - emit_opcode(cbuf,0xF2); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x70); - emit_rm(cbuf, 0x3, $tmp$$reg, $src$$reg); - emit_d8(cbuf, 0x4E); - } - { // MOVD $dst.hi,$tmp - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x7E); - emit_rm(cbuf, 0x3, $tmp$$reg, HIGH_FROM_LOW($dst$$reg)); - } - %} - - // Encode a reg-reg copy. If it is useless, then empty encoding. enc_class enc_Copy( eRegI dst, eRegI src ) %{ encode_Copy( cbuf, $dst$$reg, $src$$reg ); @@ -2080,11 +2032,6 @@ encode_Copy( cbuf, $dst$$reg, $src$$reg ); %} - // Encode xmm reg-reg copy. If it is useless, then empty encoding. - enc_class enc_CopyXD( RegXD dst, RegXD src ) %{ - encode_CopyXD( cbuf, $dst$$reg, $src$$reg ); - %} - enc_class RegReg (eRegI dst, eRegI src) %{ // RegReg(Many) emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg); %} @@ -2634,116 +2581,59 @@ } %} - enc_class Push_ModD_encoding( regXD src0, regXD src1) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x08); - - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], src1 - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src1$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], src0 - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src0$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - %} - - enc_class Push_ModX_encoding( regX src0, regX src1) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,4 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x04); - - emit_opcode (cbuf, 0xF3 ); // MOVSS [ESP], src1 - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src1$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9 ); // FLD [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode (cbuf, 0xF3 ); // MOVSS [ESP], src0 - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src0$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9 ); // FLD [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - + enc_class Push_ModD_encoding(regXD src0, regXD src1) %{ + MacroAssembler _masm(&cbuf); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src1$$XMMRegister); + __ fld_d(Address(rsp, 0)); + __ movdbl(Address(rsp, 0), $src0$$XMMRegister); + __ fld_d(Address(rsp, 0)); + %} + + enc_class Push_ModX_encoding(regX src0, regX src1) %{ + MacroAssembler _masm(&cbuf); + __ subptr(rsp, 4); + __ movflt(Address(rsp, 0), $src1$$XMMRegister); + __ fld_s(Address(rsp, 0)); + __ movflt(Address(rsp, 0), $src0$$XMMRegister); + __ fld_s(Address(rsp, 0)); %} enc_class Push_ResultXD(regXD dst) %{ - store_to_stackslot( cbuf, 0xDD, 0x03, 0 ); //FSTP [ESP] - - // UseXmmLoadAndClearUpper ? movsd dst,[esp] : movlpd dst,[esp] - emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12); - encode_RegMem(cbuf, $dst$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,8 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,0x08); + MacroAssembler _masm(&cbuf); + __ fstp_d(Address(rsp, 0)); + __ movdbl($dst$$XMMRegister, Address(rsp, 0)); + __ addptr(rsp, 8); %} enc_class Push_ResultX(regX dst, immI d8) %{ - store_to_stackslot( cbuf, 0xD9, 0x03, 0 ); //FSTP_S [ESP] - - emit_opcode (cbuf, 0xF3 ); // MOVSS dst(xmm), [ESP] - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x10 ); - encode_RegMem(cbuf, $dst$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,d8 (4 or 8) - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,$d8$$constant); + MacroAssembler _masm(&cbuf); + __ fstp_s(Address(rsp, 0)); + __ movflt($dst$$XMMRegister, Address(rsp, 0)); + __ addptr(rsp, $d8$$constant); %} enc_class Push_SrcXD(regXD src) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x08); - - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); + MacroAssembler _masm(&cbuf); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); %} enc_class push_stack_temp_qword() %{ - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8 (cbuf,0x08); + MacroAssembler _masm(&cbuf); + __ subptr(rsp, 8); %} enc_class pop_stack_temp_qword() %{ - emit_opcode(cbuf,0x83); // ADD ESP,8 - emit_opcode(cbuf,0xC4); - emit_d8 (cbuf,0x08); - %} - - enc_class push_xmm_to_fpr1( regXD xmm_src ) %{ - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], xmm_src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $xmm_src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); + MacroAssembler _masm(&cbuf); + __ addptr(rsp, 8); + %} + + enc_class push_xmm_to_fpr1(regXD src) %{ + MacroAssembler _masm(&cbuf); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); %} // Compute X^Y using Intel's fast hardware instructions, if possible. @@ -2922,24 +2812,6 @@ %} - // XMM version of CmpF_Result. Because the XMM compare - // instructions set the EFLAGS directly. It becomes simpler than - // the float version above. - enc_class CmpX_Result(eRegI dst) %{ - MacroAssembler _masm(&cbuf); - Label nan, inc, done; - - __ jccb(Assembler::parity, nan); - __ jccb(Assembler::equal, done); - __ jccb(Assembler::above, inc); - __ bind(nan); - __ decrement(as_Register($dst$$reg)); // NO L qqq - __ jmpb(done); - __ bind(inc); - __ increment(as_Register($dst$$reg)); // NO L qqq - __ bind(done); - %} - // Compare the longs and set flags // BROKEN! Do Not use as-is enc_class cmpl_test( eRegL src1, eRegL src2 ) %{ @@ -3162,48 +3034,6 @@ emit_d8 (cbuf,0 ); %} - enc_class movq_ld(regXD dst, memory mem) %{ - MacroAssembler _masm(&cbuf); - __ movq($dst$$XMMRegister, $mem$$Address); - %} - - enc_class movq_st(memory mem, regXD src) %{ - MacroAssembler _masm(&cbuf); - __ movq($mem$$Address, $src$$XMMRegister); - %} - - enc_class pshufd_8x8(regX dst, regX src) %{ - MacroAssembler _masm(&cbuf); - - encode_CopyXD(cbuf, $dst$$reg, $src$$reg); - __ punpcklbw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg)); - __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg), 0x00); - %} - - enc_class pshufd_4x16(regX dst, regX src) %{ - MacroAssembler _masm(&cbuf); - - __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), 0x00); - %} - - enc_class pshufd(regXD dst, regXD src, int mode) %{ - MacroAssembler _masm(&cbuf); - - __ pshufd(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), $mode); - %} - - enc_class pxor(regXD dst, regXD src) %{ - MacroAssembler _masm(&cbuf); - - __ pxor(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg)); - %} - - enc_class mov_i2x(regXD dst, eRegI src) %{ - MacroAssembler _masm(&cbuf); - - __ movdl(as_XMMRegister($dst$$reg), as_Register($src$$reg)); - %} - // Because the transitions from emitted code to the runtime // monitorenter/exit helper stubs are so slow it's critical that @@ -3842,273 +3672,6 @@ // Carry on here... %} - enc_class X2L_encoding( regX src ) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x08); - - emit_opcode (cbuf, 0xF3 ); // MOVSS [ESP], src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9 ); // FLD_S [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9); // FLDCW trunc - emit_opcode(cbuf,0x2D); - emit_d32(cbuf,(int)StubRoutines::addr_fpu_cntrl_wrd_trunc()); - - // Encoding assumes a double has been pushed into FPR0. - // Store down the double as a long, popping the FPU stack - emit_opcode(cbuf,0xDF); // FISTP [ESP] - emit_opcode(cbuf,0x3C); - emit_d8(cbuf,0x24); - - // Restore the rounding mode; mask the exception - emit_opcode(cbuf,0xD9); // FLDCW std/24-bit mode - emit_opcode(cbuf,0x2D); - emit_d32( cbuf, Compile::current()->in_24_bit_fp_mode() - ? (int)StubRoutines::addr_fpu_cntrl_wrd_24() - : (int)StubRoutines::addr_fpu_cntrl_wrd_std()); - - // Load the converted int; adjust CPU stack - emit_opcode(cbuf,0x58); // POP EAX - - emit_opcode(cbuf,0x5A); // POP EDX - - emit_opcode(cbuf,0x81); // CMP EDX,imm - emit_d8 (cbuf,0xFA); // rdx - emit_d32 (cbuf,0x80000000);// 0x80000000 - - emit_opcode(cbuf,0x75); // JNE around_slow_call - emit_d8 (cbuf,0x13+4); // Size of slow_call - - emit_opcode(cbuf,0x85); // TEST EAX,EAX - emit_opcode(cbuf,0xC0); // 2/rax,/rax, - - emit_opcode(cbuf,0x75); // JNE around_slow_call - emit_d8 (cbuf,0x13); // Size of slow_call - - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,4 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x04); - - emit_opcode (cbuf, 0xF3 ); // MOVSS [ESP], src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9 ); // FLD_S [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,4 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,0x04); - - // CALL directly to the runtime - cbuf.set_insts_mark(); - emit_opcode(cbuf,0xE8); // Call into runtime - emit_d32_reloc(cbuf, (StubRoutines::d2l_wrapper() - cbuf.insts_end()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 ); - // Carry on here... - %} - - enc_class XD2L_encoding( regXD src ) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x08); - - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9); // FLDCW trunc - emit_opcode(cbuf,0x2D); - emit_d32(cbuf,(int)StubRoutines::addr_fpu_cntrl_wrd_trunc()); - - // Encoding assumes a double has been pushed into FPR0. - // Store down the double as a long, popping the FPU stack - emit_opcode(cbuf,0xDF); // FISTP [ESP] - emit_opcode(cbuf,0x3C); - emit_d8(cbuf,0x24); - - // Restore the rounding mode; mask the exception - emit_opcode(cbuf,0xD9); // FLDCW std/24-bit mode - emit_opcode(cbuf,0x2D); - emit_d32( cbuf, Compile::current()->in_24_bit_fp_mode() - ? (int)StubRoutines::addr_fpu_cntrl_wrd_24() - : (int)StubRoutines::addr_fpu_cntrl_wrd_std()); - - // Load the converted int; adjust CPU stack - emit_opcode(cbuf,0x58); // POP EAX - - emit_opcode(cbuf,0x5A); // POP EDX - - emit_opcode(cbuf,0x81); // CMP EDX,imm - emit_d8 (cbuf,0xFA); // rdx - emit_d32 (cbuf,0x80000000); // 0x80000000 - - emit_opcode(cbuf,0x75); // JNE around_slow_call - emit_d8 (cbuf,0x13+4); // Size of slow_call - - emit_opcode(cbuf,0x85); // TEST EAX,EAX - emit_opcode(cbuf,0xC0); // 2/rax,/rax, - - emit_opcode(cbuf,0x75); // JNE around_slow_call - emit_d8 (cbuf,0x13); // Size of slow_call - - // Push src onto stack slow-path - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,8 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x08); - - emit_opcode (cbuf, 0xF2 ); // MOVSD [ESP], src - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xDD ); // FLD_D [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,8 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,0x08); - - // CALL directly to the runtime - cbuf.set_insts_mark(); - emit_opcode(cbuf,0xE8); // Call into runtime - emit_d32_reloc(cbuf, (StubRoutines::d2l_wrapper() - cbuf.insts_end()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 ); - // Carry on here... - %} - - enc_class D2X_encoding( regX dst, regD src ) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,4 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x04); - int pop = 0x02; - if ($src$$reg != FPR1L_enc) { - emit_opcode( cbuf, 0xD9 ); // FLD ST(i-1) - emit_d8( cbuf, 0xC0-1+$src$$reg ); - pop = 0x03; - } - store_to_stackslot( cbuf, 0xD9, pop, 0 ); // FST

_S [ESP] - - emit_opcode (cbuf, 0xF3 ); // MOVSS dst(xmm), [ESP] - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x10 ); - encode_RegMem(cbuf, $dst$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,4 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,0x04); - // Carry on here... - %} - - enc_class FX2I_encoding( regX src, eRegI dst ) %{ - emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg); - - // Compare the result to see if we need to go to the slow path - emit_opcode(cbuf,0x81); // CMP dst,imm - emit_rm (cbuf,0x3,0x7,$dst$$reg); - emit_d32 (cbuf,0x80000000); // 0x80000000 - - emit_opcode(cbuf,0x75); // JNE around_slow_call - emit_d8 (cbuf,0x13); // Size of slow_call - // Store xmm to a temp memory - // location and push it onto stack. - - emit_opcode(cbuf,0x83); // SUB ESP,4 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf, $primary ? 0x8 : 0x4); - - emit_opcode (cbuf, $primary ? 0xF2 : 0xF3 ); // MOVSS [ESP], xmm - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf, $primary ? 0xDD : 0xD9 ); // FLD [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,4 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf, $primary ? 0x8 : 0x4); - - // CALL directly to the runtime - cbuf.set_insts_mark(); - emit_opcode(cbuf,0xE8); // Call into runtime - emit_d32_reloc(cbuf, (StubRoutines::d2i_wrapper() - cbuf.insts_end()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 ); - - // Carry on here... - %} - - enc_class X2D_encoding( regD dst, regX src ) %{ - // Allocate a word - emit_opcode(cbuf,0x83); // SUB ESP,4 - emit_opcode(cbuf,0xEC); - emit_d8(cbuf,0x04); - - emit_opcode (cbuf, 0xF3 ); // MOVSS [ESP], xmm - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, 0x11 ); - encode_RegMem(cbuf, $src$$reg, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0xD9 ); // FLD_S [ESP] - encode_RegMem(cbuf, 0x0, ESP_enc, 0x4, 0, 0, false); - - emit_opcode(cbuf,0x83); // ADD ESP,4 - emit_opcode(cbuf,0xC4); - emit_d8(cbuf,0x04); - - // Carry on here... - %} - - enc_class AbsXF_encoding(regX dst) %{ - address signmask_address=(address)float_signmask_pool; - // andpd:\tANDPS $dst,[signconst] - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x54); - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_d32(cbuf, (int)signmask_address); - %} - - enc_class AbsXD_encoding(regXD dst) %{ - address signmask_address=(address)double_signmask_pool; - // andpd:\tANDPD $dst,[signconst] - emit_opcode(cbuf, 0x66); - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x54); - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_d32(cbuf, (int)signmask_address); - %} - - enc_class NegXF_encoding(regX dst) %{ - address signmask_address=(address)float_signflip_pool; - // andpd:\tXORPS $dst,[signconst] - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x57); - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_d32(cbuf, (int)signmask_address); - %} - - enc_class NegXD_encoding(regXD dst) %{ - address signmask_address=(address)double_signflip_pool; - // andpd:\tXORPD $dst,[signconst] - emit_opcode(cbuf, 0x66); - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x57); - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_d32(cbuf, (int)signmask_address); - %} - enc_class FMul_ST_reg( eRegF src1 ) %{ // Operand was loaded from memory into fp ST (stack top) // FMUL ST,$src /* D8 C8+i */ @@ -4176,66 +3739,6 @@ store_to_stackslot( cbuf, 0x0DF, 0x07, $dst$$disp ); %} - enc_class enc_loadLX_volatile( memory mem, stackSlotL dst, regXD tmp ) %{ - { // Atomic long load - // UseXmmLoadAndClearUpper ? movsd $tmp,$mem : movlpd $tmp,$mem - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0x10 : 0x12); - int base = $mem$$base; - int index = $mem$$index; - int scale = $mem$$scale; - int displace = $mem$$disp; - bool disp_is_oop = $mem->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - { // MOVSD $dst,$tmp ! atomic long store - emit_opcode(cbuf,0xF2); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x11); - int base = $dst$$base; - int index = $dst$$index; - int scale = $dst$$scale; - int displace = $dst$$disp; - bool disp_is_oop = $dst->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - %} - - enc_class enc_loadLX_reg_volatile( memory mem, eRegL dst, regXD tmp ) %{ - { // Atomic long load - // UseXmmLoadAndClearUpper ? movsd $tmp,$mem : movlpd $tmp,$mem - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0x10 : 0x12); - int base = $mem$$base; - int index = $mem$$index; - int scale = $mem$$scale; - int displace = $mem$$disp; - bool disp_is_oop = $mem->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - { // MOVD $dst.lo,$tmp - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x7E); - emit_rm(cbuf, 0x3, $tmp$$reg, $dst$$reg); - } - { // PSRLQ $tmp,32 - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x73); - emit_rm(cbuf, 0x3, 0x02, $tmp$$reg); - emit_d8(cbuf, 0x20); - } - { // MOVD $dst.hi,$tmp - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x7E); - emit_rm(cbuf, 0x3, $tmp$$reg, HIGH_FROM_LOW($dst$$reg)); - } - %} - // Volatile Store Long. Must be atomic, so move it into // the FP TOS and then do a 64-bit FIST. Has to probe the // target address before the store (for null-ptr checks) @@ -4253,66 +3756,6 @@ encode_RegMem(cbuf, rm_byte_opcode, base, index, scale, displace, disp_is_oop); %} - enc_class enc_storeLX_volatile( memory mem, stackSlotL src, regXD tmp) %{ - { // Atomic long load - // UseXmmLoadAndClearUpper ? movsd $tmp,[$src] : movlpd $tmp,[$src] - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,UseXmmLoadAndClearUpper ? 0x10 : 0x12); - int base = $src$$base; - int index = $src$$index; - int scale = $src$$scale; - int displace = $src$$disp; - bool disp_is_oop = $src->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - cbuf.set_insts_mark(); // Mark start of MOVSD in case $mem has an oop - { // MOVSD $mem,$tmp ! atomic long store - emit_opcode(cbuf,0xF2); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x11); - int base = $mem$$base; - int index = $mem$$index; - int scale = $mem$$scale; - int displace = $mem$$disp; - bool disp_is_oop = $mem->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - %} - - enc_class enc_storeLX_reg_volatile( memory mem, eRegL src, regXD tmp, regXD tmp2) %{ - { // MOVD $tmp,$src.lo - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x6E); - emit_rm(cbuf, 0x3, $tmp$$reg, $src$$reg); - } - { // MOVD $tmp2,$src.hi - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x6E); - emit_rm(cbuf, 0x3, $tmp2$$reg, HIGH_FROM_LOW($src$$reg)); - } - { // PUNPCKLDQ $tmp,$tmp2 - emit_opcode(cbuf,0x66); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x62); - emit_rm(cbuf, 0x3, $tmp$$reg, $tmp2$$reg); - } - cbuf.set_insts_mark(); // Mark start of MOVSD in case $mem has an oop - { // MOVSD $mem,$tmp ! atomic long store - emit_opcode(cbuf,0xF2); - emit_opcode(cbuf,0x0F); - emit_opcode(cbuf,0x11); - int base = $mem$$base; - int index = $mem$$index; - int scale = $mem$$scale; - int displace = $mem$$disp; - bool disp_is_oop = $mem->disp_is_oop(); // disp-as-oop when working with static globals - encode_RegMem(cbuf, $tmp$$reg, base, index, scale, displace, disp_is_oop); - } - %} - // Safepoint Poll. This polls the safepoint page, and causes an // exception if it is not readable. Unfortunately, it kills the condition code // in the process @@ -6877,7 +6320,10 @@ ins_cost(180); format %{ "MOVSD $tmp,$mem\t# Atomic volatile long load\n\t" "MOVSD $dst,$tmp" %} - ins_encode(enc_loadLX_volatile(mem, dst, tmp)); + ins_encode %{ + __ movdbl($tmp$$XMMRegister, $mem$$Address); + __ movdbl(Address(rsp, $dst$$disp), $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -6890,7 +6336,12 @@ "MOVD $dst.lo,$tmp\n\t" "PSRLQ $tmp,32\n\t" "MOVD $dst.hi,$tmp" %} - ins_encode(enc_loadLX_reg_volatile(mem, dst, tmp)); + ins_encode %{ + __ movdbl($tmp$$XMMRegister, $mem$$Address); + __ movdl($dst$$Register, $tmp$$XMMRegister); + __ psrlq($tmp$$XMMRegister, 32); + __ movdl(HIGH_FROM_LOW($dst$$Register), $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -6948,7 +6399,9 @@ match(Set dst (LoadD mem)); ins_cost(145); format %{ "MOVSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x10), RegMem(dst,mem)); + ins_encode %{ + __ movdbl ($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6957,7 +6410,9 @@ match(Set dst (LoadD mem)); ins_cost(145); format %{ "MOVLPD $dst,$mem" %} - ins_encode( Opcode(0x66), Opcode(0x0F), Opcode(0x12), RegMem(dst,mem)); + ins_encode %{ + __ movdbl ($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6968,7 +6423,9 @@ match(Set dst (LoadF mem)); ins_cost(145); format %{ "MOVSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), RegMem(dst,mem)); + ins_encode %{ + __ movflt ($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6992,7 +6449,9 @@ match(Set dst (Load8B mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed8B" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -7002,7 +6461,9 @@ match(Set dst (Load4S mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed4S" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -7012,7 +6473,9 @@ match(Set dst (Load4C mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed4C" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -7022,7 +6485,9 @@ match(Set dst (Load2I mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed2I" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -7032,7 +6497,9 @@ match(Set dst (Load2F mem)); ins_cost(145); format %{ "MOVQ $dst,$mem\t! packed2F" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -7258,7 +6725,9 @@ match(Set dst src); ins_cost(100); format %{ "XORPD $dst,$dst\t# double 0.0" %} - ins_encode( Opcode(0x66), Opcode(0x0F), Opcode(0x57), RegReg(dst,dst)); + ins_encode %{ + __ xorpd ($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7560,8 +7029,11 @@ format %{ "CMP $mem,EAX\t# Probe address for implicit null check\n\t" "MOVSD $tmp,$src\n\t" "MOVSD $mem,$tmp\t # 64-bit atomic volatile long store" %} - opcode(0x3B); - ins_encode( OpcP, RegMem( EAX, mem ), enc_storeLX_volatile(mem, src, tmp)); + ins_encode %{ + __ cmpl(rax, $mem$$Address); + __ movdbl($tmp$$XMMRegister, Address(rsp, $src$$disp)); + __ movdbl($mem$$Address, $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7575,8 +7047,13 @@ "MOVD $tmp2,$src.hi\n\t" "PUNPCKLDQ $tmp,$tmp2\n\t" "MOVSD $mem,$tmp\t # 64-bit atomic volatile long store" %} - opcode(0x3B); - ins_encode( OpcP, RegMem( EAX, mem ), enc_storeLX_reg_volatile(mem, src, tmp, tmp2)); + ins_encode %{ + __ cmpl(rax, $mem$$Address); + __ movdl($tmp$$XMMRegister, $src$$Register); + __ movdl($tmp2$$XMMRegister, HIGH_FROM_LOW($src$$Register)); + __ punpckldq($tmp$$XMMRegister, $tmp2$$XMMRegister); + __ movdbl($mem$$Address, $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7643,7 +7120,9 @@ match(Set mem (Store8B mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed8B" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7653,7 +7132,9 @@ match(Set mem (Store4C mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed4C" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7663,7 +7144,9 @@ match(Set mem (Store2I mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed2I" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7709,7 +7192,9 @@ match(Set mem (StoreD mem src)); ins_cost(95); format %{ "MOVSD $mem,$src" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x11), RegMem(src, mem)); + ins_encode %{ + __ movdbl($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7720,7 +7205,9 @@ match(Set mem (StoreF mem src)); ins_cost(95); format %{ "MOVSS $mem,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x11), RegMem(src, mem)); + ins_encode %{ + __ movflt($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7730,7 +7217,9 @@ match(Set mem (Store2F mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed2F" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -8440,7 +7929,7 @@ %} // LoadLong-locked - same as a volatile long load when used with compare-swap -instruct loadLLocked(stackSlotL dst, load_long_memory mem) %{ +instruct loadLLocked(stackSlotL dst, memory mem) %{ predicate(UseSSE<=1); match(Set dst (LoadLLocked mem)); @@ -8451,18 +7940,21 @@ ins_pipe( fpu_reg_mem ); %} -instruct loadLX_Locked(stackSlotL dst, load_long_memory mem, regXD tmp) %{ +instruct loadLX_Locked(stackSlotL dst, memory mem, regXD tmp) %{ predicate(UseSSE>=2); match(Set dst (LoadLLocked mem)); effect(TEMP tmp); ins_cost(180); format %{ "MOVSD $tmp,$mem\t# Atomic volatile long load\n\t" "MOVSD $dst,$tmp" %} - ins_encode(enc_loadLX_volatile(mem, dst, tmp)); - ins_pipe( pipe_slow ); -%} - -instruct loadLX_reg_Locked(eRegL dst, load_long_memory mem, regXD tmp) %{ + ins_encode %{ + __ movdbl($tmp$$XMMRegister, $mem$$Address); + __ movdbl(Address(rsp, $dst$$disp), $tmp$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct loadLX_reg_Locked(eRegL dst, memory mem, regXD tmp) %{ predicate(UseSSE>=2); match(Set dst (LoadLLocked mem)); effect(TEMP tmp); @@ -8471,7 +7963,12 @@ "MOVD $dst.lo,$tmp\n\t" "PSRLQ $tmp,32\n\t" "MOVD $dst.hi,$tmp" %} - ins_encode(enc_loadLX_reg_volatile(mem, dst, tmp)); + ins_encode %{ + __ movdbl($tmp$$XMMRegister, $mem$$Address); + __ movdl($dst$$Register, $tmp$$XMMRegister); + __ psrlq($tmp$$XMMRegister, 32); + __ movdl(HIGH_FROM_LOW($dst$$Register), $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -10133,98 +9630,100 @@ %} // float compare and set condition codes in EFLAGS by XMM regs -instruct cmpXD_cc(eFlagsRegU cr, regXD dst, regXD src, eAXRegI rax) %{ +instruct cmpXD_cc(eFlagsRegU cr, regXD src1, regXD src2) %{ predicate(UseSSE>=2); - match(Set cr (CmpD dst src)); - effect(KILL rax); - ins_cost(125); - format %{ "COMISD $dst,$src\n" - "\tJNP exit\n" - "\tMOV ah,1 // saw a NaN, set CF\n" - "\tSAHF\n" - "exit:\tNOP // avoid branch to branch" %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src), cmpF_P6_fixup); - ins_pipe( pipe_slow ); -%} - -instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{ + match(Set cr (CmpD src1 src2)); + ins_cost(145); + format %{ "UCOMISD $src1,$src2\n\t" + "JNP,s exit\n\t" + "PUSHF\t# saw NaN, set CF\n\t" + "AND [rsp], #0xffffff2b\n\t" + "POPF\n" + "exit:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp_fixup(_masm); + %} + ins_pipe( pipe_slow ); +%} + +instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD src1, regXD src2) %{ predicate(UseSSE>=2); - match(Set cr (CmpD dst src)); + match(Set cr (CmpD src1 src2)); ins_cost(100); - format %{ "COMISD $dst,$src" %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + format %{ "UCOMISD $src1,$src2" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + %} ins_pipe( pipe_slow ); %} // float compare and set condition codes in EFLAGS by XMM regs -instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ +instruct cmpXD_ccmem(eFlagsRegU cr, regXD src1, memory src2) %{ predicate(UseSSE>=2); - match(Set cr (CmpD dst (LoadD src))); - effect(KILL rax); + match(Set cr (CmpD src1 (LoadD src2))); ins_cost(145); - format %{ "COMISD $dst,$src\n" - "\tJNP exit\n" - "\tMOV ah,1 // saw a NaN, set CF\n" - "\tSAHF\n" - "exit:\tNOP // avoid branch to branch" %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src), cmpF_P6_fixup); - ins_pipe( pipe_slow ); -%} - -instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{ + format %{ "UCOMISD $src1,$src2\n\t" + "JNP,s exit\n\t" + "PUSHF\t# saw NaN, set CF\n\t" + "AND [rsp], #0xffffff2b\n\t" + "POPF\n" + "exit:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + emit_cmpfp_fixup(_masm); + %} + ins_pipe( pipe_slow ); +%} + +instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD src1, memory src2) %{ predicate(UseSSE>=2); - match(Set cr (CmpD dst (LoadD src))); + match(Set cr (CmpD src1 (LoadD src2))); ins_cost(100); - format %{ "COMISD $dst,$src" %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src)); + format %{ "UCOMISD $src1,$src2" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + %} ins_pipe( pipe_slow ); %} // Compare into -1,0,1 in XMM -instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ +instruct cmpXD_reg(xRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ predicate(UseSSE>=2); match(Set dst (CmpD3 src1 src2)); effect(KILL cr); ins_cost(255); - format %{ "XOR $dst,$dst\n" - "\tCOMISD $src1,$src2\n" - "\tJP,s nan\n" - "\tJEQ,s exit\n" - "\tJA,s inc\n" - "nan:\tDEC $dst\n" - "\tJMP,s exit\n" - "inc:\tINC $dst\n" - "exit:" - %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(Xor_Reg(dst), OpcP, OpcS, Opcode(tertiary), RegReg(src1, src2), - CmpX_Result(dst)); + format %{ "UCOMISD $src1, $src2\n\t" + "MOV $dst, #-1\n\t" + "JP,s done\n\t" + "JB,s done\n\t" + "SETNE $dst\n\t" + "MOVZB $dst, $dst\n" + "done:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe( pipe_slow ); %} // Compare into -1,0,1 in XMM and memory -instruct cmpXD_regmem(eRegI dst, regXD src1, memory mem, eFlagsReg cr) %{ +instruct cmpXD_regmem(xRegI dst, regXD src1, memory src2, eFlagsReg cr) %{ predicate(UseSSE>=2); - match(Set dst (CmpD3 src1 (LoadD mem))); + match(Set dst (CmpD3 src1 (LoadD src2))); effect(KILL cr); ins_cost(275); - format %{ "COMISD $src1,$mem\n" - "\tMOV $dst,0\t\t# do not blow flags\n" - "\tJP,s nan\n" - "\tJEQ,s exit\n" - "\tJA,s inc\n" - "nan:\tDEC $dst\n" - "\tJMP,s exit\n" - "inc:\tINC $dst\n" - "exit:" - %} - opcode(0x66, 0x0F, 0x2F); - ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(src1, mem), - LdImmI(dst,0x0), CmpX_Result(dst)); + format %{ "UCOMISD $src1, $src2\n\t" + "MOV $dst, #-1\n\t" + "JP,s done\n\t" + "JB,s done\n\t" + "SETNE $dst\n\t" + "MOVZB $dst, $dst\n" + "done:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe( pipe_slow ); %} @@ -10283,8 +9782,12 @@ instruct absXD_reg( regXD dst ) %{ predicate(UseSSE>=2); match(Set dst (AbsD dst)); + ins_cost(150); format %{ "ANDPD $dst,[0x7FFFFFFFFFFFFFFF]\t# ABS D by sign masking" %} - ins_encode( AbsXD_encoding(dst)); + ins_encode %{ + __ andpd($dst$$XMMRegister, + ExternalAddress((address)double_signmask_pool)); + %} ins_pipe( pipe_slow ); %} @@ -10301,10 +9804,11 @@ instruct negXD_reg( regXD dst ) %{ predicate(UseSSE>=2); match(Set dst (NegD dst)); + ins_cost(150); format %{ "XORPD $dst,[0x8000000000000000]\t# CHS D by sign flipping" %} ins_encode %{ - __ xorpd($dst$$XMMRegister, - ExternalAddress((address)double_signflip_pool)); + __ xorpd($dst$$XMMRegister, + ExternalAddress((address)double_signflip_pool)); %} ins_pipe( pipe_slow ); %} @@ -10414,7 +9918,9 @@ predicate(UseSSE>=2); match(Set dst (AddD dst src)); format %{ "ADDSD $dst,$src" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegReg(dst, src)); + ins_encode %{ + __ addsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -10432,7 +9938,9 @@ predicate(UseSSE>=2); match(Set dst (AddD dst (LoadD mem))); format %{ "ADDSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegMem(dst,mem)); + ins_encode %{ + __ addsd($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -10440,14 +9948,18 @@ instruct subXD_reg(regXD dst, regXD src) %{ predicate(UseSSE>=2); match(Set dst (SubD dst src)); + ins_cost(150); format %{ "SUBSD $dst,$src" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src)); + ins_encode %{ + __ subsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} instruct subXD_imm(regXD dst, immXD con) %{ predicate(UseSSE>=2); match(Set dst (SubD dst con)); + ins_cost(150); format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} ins_encode %{ __ subsd($dst$$XMMRegister, $constantaddress($con)); @@ -10458,8 +9970,11 @@ instruct subXD_mem(regXD dst, memory mem) %{ predicate(UseSSE>=2); match(Set dst (SubD dst (LoadD mem))); + ins_cost(150); format %{ "SUBSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem)); + ins_encode %{ + __ subsd($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -10468,7 +9983,9 @@ predicate(UseSSE>=2); match(Set dst (MulD dst src)); format %{ "MULSD $dst,$src" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegReg(dst, src)); + ins_encode %{ + __ mulsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -10486,7 +10003,9 @@ predicate(UseSSE>=2); match(Set dst (MulD dst (LoadD mem))); format %{ "MULSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem)); + ins_encode %{ + __ mulsd($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -10496,7 +10015,9 @@ match(Set dst (DivD dst src)); format %{ "DIVSD $dst,$src" %} opcode(0xF2, 0x0F, 0x5E); - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src)); + ins_encode %{ + __ divsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -10514,7 +10035,9 @@ predicate(UseSSE>=2); match(Set dst (DivD dst (LoadD mem))); format %{ "DIVSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem)); + ins_encode %{ + __ divsd($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11146,96 +10669,100 @@ %} // float compare and set condition codes in EFLAGS by XMM regs -instruct cmpX_cc(eFlagsRegU cr, regX dst, regX src, eAXRegI rax) %{ +instruct cmpX_cc(eFlagsRegU cr, regX src1, regX src2) %{ predicate(UseSSE>=1); - match(Set cr (CmpF dst src)); - effect(KILL rax); + match(Set cr (CmpF src1 src2)); ins_cost(145); - format %{ "COMISS $dst,$src\n" - "\tJNP exit\n" - "\tMOV ah,1 // saw a NaN, set CF\n" - "\tSAHF\n" - "exit:\tNOP // avoid branch to branch" %} - opcode(0x0F, 0x2F); - ins_encode(OpcP, OpcS, RegReg(dst, src), cmpF_P6_fixup); - ins_pipe( pipe_slow ); -%} - -instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{ + format %{ "UCOMISS $src1,$src2\n\t" + "JNP,s exit\n\t" + "PUSHF\t# saw NaN, set CF\n\t" + "AND [rsp], #0xffffff2b\n\t" + "POPF\n" + "exit:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp_fixup(_masm); + %} + ins_pipe( pipe_slow ); +%} + +instruct cmpX_ccCF(eFlagsRegUCF cr, regX src1, regX src2) %{ predicate(UseSSE>=1); - match(Set cr (CmpF dst src)); + match(Set cr (CmpF src1 src2)); ins_cost(100); - format %{ "COMISS $dst,$src" %} - opcode(0x0F, 0x2F); - ins_encode(OpcP, OpcS, RegReg(dst, src)); + format %{ "UCOMISS $src1,$src2" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + %} ins_pipe( pipe_slow ); %} // float compare and set condition codes in EFLAGS by XMM regs -instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ +instruct cmpX_ccmem(eFlagsRegU cr, regX src1, memory src2) %{ predicate(UseSSE>=1); - match(Set cr (CmpF dst (LoadF src))); - effect(KILL rax); + match(Set cr (CmpF src1 (LoadF src2))); ins_cost(165); - format %{ "COMISS $dst,$src\n" - "\tJNP exit\n" - "\tMOV ah,1 // saw a NaN, set CF\n" - "\tSAHF\n" - "exit:\tNOP // avoid branch to branch" %} - opcode(0x0F, 0x2F); - ins_encode(OpcP, OpcS, RegMem(dst, src), cmpF_P6_fixup); - ins_pipe( pipe_slow ); -%} - -instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{ + format %{ "UCOMISS $src1,$src2\n\t" + "JNP,s exit\n\t" + "PUSHF\t# saw NaN, set CF\n\t" + "AND [rsp], #0xffffff2b\n\t" + "POPF\n" + "exit:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + emit_cmpfp_fixup(_masm); + %} + ins_pipe( pipe_slow ); +%} + +instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX src1, memory src2) %{ predicate(UseSSE>=1); - match(Set cr (CmpF dst (LoadF src))); + match(Set cr (CmpF src1 (LoadF src2))); ins_cost(100); - format %{ "COMISS $dst,$src" %} - opcode(0x0F, 0x2F); - ins_encode(OpcP, OpcS, RegMem(dst, src)); + format %{ "UCOMISS $src1,$src2" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + %} ins_pipe( pipe_slow ); %} // Compare into -1,0,1 in XMM -instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ +instruct cmpX_reg(xRegI dst, regX src1, regX src2, eFlagsReg cr) %{ predicate(UseSSE>=1); match(Set dst (CmpF3 src1 src2)); effect(KILL cr); ins_cost(255); - format %{ "XOR $dst,$dst\n" - "\tCOMISS $src1,$src2\n" - "\tJP,s nan\n" - "\tJEQ,s exit\n" - "\tJA,s inc\n" - "nan:\tDEC $dst\n" - "\tJMP,s exit\n" - "inc:\tINC $dst\n" - "exit:" - %} - opcode(0x0F, 0x2F); - ins_encode(Xor_Reg(dst), OpcP, OpcS, RegReg(src1, src2), CmpX_Result(dst)); + format %{ "UCOMISS $src1, $src2\n\t" + "MOV $dst, #-1\n\t" + "JP,s done\n\t" + "JB,s done\n\t" + "SETNE $dst\n\t" + "MOVZB $dst, $dst\n" + "done:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe( pipe_slow ); %} // Compare into -1,0,1 in XMM and memory -instruct cmpX_regmem(eRegI dst, regX src1, memory mem, eFlagsReg cr) %{ +instruct cmpX_regmem(xRegI dst, regX src1, memory src2, eFlagsReg cr) %{ predicate(UseSSE>=1); - match(Set dst (CmpF3 src1 (LoadF mem))); + match(Set dst (CmpF3 src1 (LoadF src2))); effect(KILL cr); ins_cost(275); - format %{ "COMISS $src1,$mem\n" - "\tMOV $dst,0\t\t# do not blow flags\n" - "\tJP,s nan\n" - "\tJEQ,s exit\n" - "\tJA,s inc\n" - "nan:\tDEC $dst\n" - "\tJMP,s exit\n" - "inc:\tINC $dst\n" - "exit:" - %} - opcode(0x0F, 0x2F); - ins_encode(OpcP, OpcS, RegMem(src1, mem), LdImmI(dst,0x0), CmpX_Result(dst)); + format %{ "UCOMISS $src1, $src2\n\t" + "MOV $dst, #-1\n\t" + "JP,s done\n\t" + "JB,s done\n\t" + "SETNE $dst\n\t" + "MOVZB $dst, $dst\n" + "done:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe( pipe_slow ); %} @@ -11295,7 +10822,9 @@ predicate(UseSSE>=1); match(Set dst (AddF dst src)); format %{ "ADDSS $dst,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegReg(dst, src)); + ins_encode %{ + __ addss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11313,7 +10842,9 @@ predicate(UseSSE>=1); match(Set dst (AddF dst (LoadF mem))); format %{ "ADDSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegMem(dst, mem)); + ins_encode %{ + __ addss($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11321,14 +10852,18 @@ instruct subX_reg(regX dst, regX src) %{ predicate(UseSSE>=1); match(Set dst (SubF dst src)); + ins_cost(150); format %{ "SUBSS $dst,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src)); + ins_encode %{ + __ subss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} instruct subX_imm(regX dst, immXF con) %{ predicate(UseSSE>=1); match(Set dst (SubF dst con)); + ins_cost(150); format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} ins_encode %{ __ subss($dst$$XMMRegister, $constantaddress($con)); @@ -11339,8 +10874,11 @@ instruct subX_mem(regX dst, memory mem) %{ predicate(UseSSE>=1); match(Set dst (SubF dst (LoadF mem))); + ins_cost(150); format %{ "SUBSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem)); + ins_encode %{ + __ subss($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11349,7 +10887,9 @@ predicate(UseSSE>=1); match(Set dst (MulF dst src)); format %{ "MULSS $dst,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegReg(dst, src)); + ins_encode %{ + __ mulss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11367,7 +10907,9 @@ predicate(UseSSE>=1); match(Set dst (MulF dst (LoadF mem))); format %{ "MULSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem)); + ins_encode %{ + __ mulss($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11376,7 +10918,9 @@ predicate(UseSSE>=1); match(Set dst (DivF dst src)); format %{ "DIVSS $dst,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src)); + ins_encode %{ + __ divss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11394,7 +10938,9 @@ predicate(UseSSE>=1); match(Set dst (DivF dst (LoadF mem))); format %{ "DIVSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem)); + ins_encode %{ + __ divss($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11402,16 +10948,22 @@ instruct sqrtX_reg(regX dst, regX src) %{ predicate(UseSSE>=1); match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); + ins_cost(150); format %{ "SQRTSS $dst,$src" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x51), RegReg(dst, src)); + ins_encode %{ + __ sqrtss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} instruct sqrtX_mem(regX dst, memory mem) %{ predicate(UseSSE>=1); match(Set dst (ConvD2F (SqrtD (ConvF2D (LoadF mem))))); + ins_cost(150); format %{ "SQRTSS $dst,$mem" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x51), RegMem(dst, mem)); + ins_encode %{ + __ sqrtss($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11419,16 +10971,22 @@ instruct sqrtXD_reg(regXD dst, regXD src) %{ predicate(UseSSE>=2); match(Set dst (SqrtD src)); + ins_cost(150); format %{ "SQRTSD $dst,$src" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x51), RegReg(dst, src)); + ins_encode %{ + __ sqrtsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} instruct sqrtXD_mem(regXD dst, memory mem) %{ predicate(UseSSE>=2); match(Set dst (SqrtD (LoadD mem))); + ins_cost(150); format %{ "SQRTSD $dst,$mem" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x51), RegMem(dst, mem)); + ins_encode %{ + __ sqrtsd($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -11445,8 +11003,12 @@ instruct absX_reg(regX dst ) %{ predicate(UseSSE>=1); match(Set dst (AbsF dst)); + ins_cost(150); format %{ "ANDPS $dst,[0x7FFFFFFF]\t# ABS F by sign masking" %} - ins_encode( AbsXF_encoding(dst)); + ins_encode %{ + __ andps($dst$$XMMRegister, + ExternalAddress((address)float_signmask_pool)); + %} ins_pipe( pipe_slow ); %} @@ -11463,8 +11025,12 @@ instruct negX_reg( regX dst ) %{ predicate(UseSSE>=1); match(Set dst (NegF dst)); + ins_cost(150); format %{ "XORPS $dst,[0x80000000]\t# CHS F by sign flipping" %} - ins_encode( NegXF_encoding(dst)); + ins_encode %{ + __ xorps($dst$$XMMRegister, + ExternalAddress((address)float_signflip_pool)); + %} ins_pipe( pipe_slow ); %} @@ -11870,7 +11436,17 @@ "FST_S [ESP],$src\t# F-round\n\t" "MOVSS $dst,[ESP]\n\t" "ADD ESP,4" %} - ins_encode( D2X_encoding(dst, src) ); + ins_encode %{ + __ subptr(rsp, 4); + if ($src$$reg != FPR1L_enc) { + __ fld_s($src$$reg-1); + __ fstp_s(Address(rsp, 0)); + } else { + __ fst_s(Address(rsp, 0)); + } + __ movflt($dst$$XMMRegister, Address(rsp, 0)); + __ addptr(rsp, 4); + %} ins_pipe( pipe_slow ); %} @@ -11879,8 +11455,9 @@ predicate(UseSSE>=2); match(Set dst (ConvD2F src)); format %{ "CVTSD2SS $dst,$src\t# F-round" %} - opcode(0xF2, 0x0F, 0x5A); - ins_encode( OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_encode %{ + __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11910,7 +11487,13 @@ "FLD_S [ESP]\n\t" "ADD ESP,4\n\t" "FSTP $dst\t# D-round" %} - ins_encode( X2D_encoding(dst, src), Pop_Reg_D(dst)); + ins_encode %{ + __ subptr(rsp, 4); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ fld_s(Address(rsp, 0)); + __ addptr(rsp, 4); + __ fstp_d($dst$$reg); + %} ins_pipe( pipe_slow ); %} @@ -11918,8 +11501,9 @@ predicate(UseSSE>=2); match(Set dst (ConvF2D src)); format %{ "CVTSS2SD $dst,$src\t# D-round" %} - opcode(0xF3, 0x0F, 0x5A); - ins_encode( OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_encode %{ + __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11957,8 +11541,18 @@ "ADD ESP, 8\n\t" "CALL d2i_wrapper\n" "fast:" %} - opcode(0x1); // double-precision conversion - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x2C), FX2I_encoding(src,dst)); + ins_encode %{ + Label fast; + __ cvttsd2sil($dst$$Register, $src$$XMMRegister); + __ cmpl($dst$$Register, 0x80000000); + __ jccb(Assembler::notEqual, fast); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); + __ addptr(rsp, 8); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::d2i_wrapper()))); + __ bind(fast); + %} ins_pipe( pipe_slow ); %} @@ -12004,9 +11598,36 @@ "SUB ESP,8\n\t" "MOVSD [ESP],$src\n\t" "FLD_D [ESP]\n\t" + "ADD ESP,8\n\t" "CALL d2l_wrapper\n" "fast:" %} - ins_encode( XD2L_encoding(src) ); + ins_encode %{ + Label fast; + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_trunc())); + __ fistp_d(Address(rsp, 0)); + // Restore the rounding mode, mask the exception + if (Compile::current()->in_24_bit_fp_mode()) { + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); + } else { + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } + // Load the converted long, adjust CPU stack + __ pop(rax); + __ pop(rdx); + __ cmpl(rdx, 0x80000000); + __ jccb(Assembler::notEqual, fast); + __ testl(rax, rax); + __ jccb(Assembler::notEqual, fast); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); + __ addptr(rsp, 8); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::d2l_wrapper()))); + __ bind(fast); + %} ins_pipe( pipe_slow ); %} @@ -12050,8 +11671,18 @@ "ADD ESP, 4\n\t" "CALL d2i_wrapper\n" "fast:" %} - opcode(0x0); // single-precision conversion - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x2C), FX2I_encoding(src,dst)); + ins_encode %{ + Label fast; + __ cvttss2sil($dst$$Register, $src$$XMMRegister); + __ cmpl($dst$$Register, 0x80000000); + __ jccb(Assembler::notEqual, fast); + __ subptr(rsp, 4); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ fld_s(Address(rsp, 0)); + __ addptr(rsp, 4); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::d2i_wrapper()))); + __ bind(fast); + %} ins_pipe( pipe_slow ); %} @@ -12101,7 +11732,33 @@ "ADD ESP,4\n\t" "CALL d2l_wrapper\n" "fast:" %} - ins_encode( X2L_encoding(src) ); + ins_encode %{ + Label fast; + __ subptr(rsp, 8); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ fld_s(Address(rsp, 0)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_trunc())); + __ fistp_d(Address(rsp, 0)); + // Restore the rounding mode, mask the exception + if (Compile::current()->in_24_bit_fp_mode()) { + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); + } else { + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } + // Load the converted long, adjust CPU stack + __ pop(rax); + __ pop(rdx); + __ cmpl(rdx, 0x80000000); + __ jccb(Assembler::notEqual, fast); + __ testl(rax, rax); + __ jccb(Assembler::notEqual, fast); + __ subptr(rsp, 4); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ fld_s(Address(rsp, 0)); + __ addptr(rsp, 4); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::d2l_wrapper()))); + __ bind(fast); + %} ins_pipe( pipe_slow ); %} @@ -12119,8 +11776,9 @@ predicate( UseSSE>=2 && !UseXmmI2D ); match(Set dst (ConvI2D src)); format %{ "CVTSI2SD $dst,$src" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode( OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_encode %{ + __ cvtsi2sdl ($dst$$XMMRegister, $src$$Register); + %} ins_pipe( pipe_slow ); %} @@ -12128,8 +11786,9 @@ predicate( UseSSE>=2 ); match(Set dst (ConvI2D (LoadI mem))); format %{ "CVTSI2SD $dst,$mem" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode( OpcP, OpcS, Opcode(tertiary), RegMem(dst, mem)); + ins_encode %{ + __ cvtsi2sdl ($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -12225,9 +11884,9 @@ predicate( UseSSE==1 || UseSSE>=2 && !UseXmmI2F ); match(Set dst (ConvI2F src)); format %{ "CVTSI2SS $dst, $src" %} - - opcode(0xF3, 0x0F, 0x2A); /* F3 0F 2A /r */ - ins_encode( OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_encode %{ + __ cvtsi2ssl ($dst$$XMMRegister, $src$$Register); + %} ins_pipe( pipe_slow ); %} @@ -12351,8 +12010,9 @@ effect( DEF dst, USE src ); ins_cost(100); format %{ "MOV $dst,$src\t# MoveF2I_stack_reg" %} - opcode(0x8B); - ins_encode( OpcP, RegMem(dst,src)); + ins_encode %{ + __ movl($dst$$Register, Address(rsp, $src$$disp)); + %} ins_pipe( ialu_reg_mem ); %} @@ -12374,7 +12034,9 @@ ins_cost(95); format %{ "MOVSS $dst,$src\t# MoveF2I_reg_stack_sse" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x11), RegMem(src, dst)); + ins_encode %{ + __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -12384,7 +12046,9 @@ effect( DEF dst, USE src ); ins_cost(85); format %{ "MOVD $dst,$src\t# MoveF2I_reg_reg_sse" %} - ins_encode( MovX2I_reg(dst, src)); + ins_encode %{ + __ movdl($dst$$Register, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -12394,8 +12058,9 @@ ins_cost(100); format %{ "MOV $dst,$src\t# MoveI2F_reg_stack" %} - opcode(0x89); - ins_encode( OpcPRegSS( dst, src ) ); + ins_encode %{ + __ movl(Address(rsp, $dst$$disp), $src$$Register); + %} ins_pipe( ialu_mem_reg ); %} @@ -12421,7 +12086,9 @@ ins_cost(95); format %{ "MOVSS $dst,$src\t# MoveI2F_stack_reg_sse" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), RegMem(dst,src)); + ins_encode %{ + __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe( pipe_slow ); %} @@ -12432,7 +12099,9 @@ ins_cost(85); format %{ "MOVD $dst,$src\t# MoveI2F_reg_reg_sse" %} - ins_encode( MovI2X_reg(dst, src) ); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + %} ins_pipe( pipe_slow ); %} @@ -12464,9 +12133,10 @@ match(Set dst (MoveD2L src)); effect(DEF dst, USE src); ins_cost(95); - format %{ "MOVSD $dst,$src\t# MoveD2L_reg_stack_sse" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x11), RegMem(src,dst)); + ins_encode %{ + __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -12478,7 +12148,11 @@ format %{ "MOVD $dst.lo,$src\n\t" "PSHUFLW $tmp,$src,0x4E\n\t" "MOVD $dst.hi,$tmp\t# MoveD2L_reg_reg_sse" %} - ins_encode( MovXD2L_reg(dst, src, tmp) ); + ins_encode %{ + __ movdl($dst$$Register, $src$$XMMRegister); + __ pshuflw($tmp$$XMMRegister, $src$$XMMRegister, 0x4e); + __ movdl(HIGH_FROM_LOW($dst$$Register), $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -12517,7 +12191,9 @@ ins_cost(95); format %{ "MOVSD $dst,$src\t# MoveL2D_stack_reg_sse" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x10), RegMem(dst,src)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe( pipe_slow ); %} @@ -12528,7 +12204,9 @@ ins_cost(95); format %{ "MOVLPD $dst,$src\t# MoveL2D_stack_reg_sse" %} - ins_encode( Opcode(0x66), Opcode(0x0F), Opcode(0x12), RegMem(dst,src)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe( pipe_slow ); %} @@ -12540,7 +12218,11 @@ format %{ "MOVD $dst,$src.lo\n\t" "MOVD $tmp,$src.hi\n\t" "PUNPCKLDQ $dst,$tmp\t# MoveL2D_reg_reg_sse" %} - ins_encode( MovL2XD_reg(dst, src, tmp) ); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); + __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -12551,7 +12233,13 @@ format %{ "MOVDQA $dst,$src\n\t" "PUNPCKLBW $dst,$dst\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate8B" %} - ins_encode( pshufd_8x8(dst, src)); + ins_encode %{ + if ($dst$$reg != $src$$reg) { + __ movdqa($dst$$XMMRegister, $src$$XMMRegister); + } + __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( pipe_slow ); %} @@ -12562,7 +12250,11 @@ format %{ "MOVD $dst,$src\n\t" "PUNPCKLBW $dst,$dst\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate8B" %} - ins_encode( mov_i2x(dst, src), pshufd_8x8(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( pipe_slow ); %} @@ -12571,7 +12263,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate8B zero)); format %{ "PXOR $dst,$dst\t! replicate8B" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -12580,7 +12274,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate4S src)); format %{ "PSHUFLW $dst,$src,0x00\t! replicate4S" %} - ins_encode( pshufd_4x16(dst, src)); + ins_encode %{ + __ pshuflw($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12590,7 +12286,10 @@ match(Set dst (Replicate4S src)); format %{ "MOVD $dst,$src\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate4S" %} - ins_encode( mov_i2x(dst, src), pshufd_4x16(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12599,7 +12298,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate4S zero)); format %{ "PXOR $dst,$dst\t! replicate4S" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -12608,7 +12309,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate4C src)); format %{ "PSHUFLW $dst,$src,0x00\t! replicate4C" %} - ins_encode( pshufd_4x16(dst, src)); + ins_encode %{ + __ pshuflw($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12618,7 +12321,10 @@ match(Set dst (Replicate4C src)); format %{ "MOVD $dst,$src\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate4C" %} - ins_encode( mov_i2x(dst, src), pshufd_4x16(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12627,7 +12333,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate4C zero)); format %{ "PXOR $dst,$dst\t! replicate4C" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -12636,7 +12344,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate2I src)); format %{ "PSHUFD $dst,$src,0x00\t! replicate2I" %} - ins_encode( pshufd(dst, src, 0x00)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12646,7 +12356,10 @@ match(Set dst (Replicate2I src)); format %{ "MOVD $dst,$src\n\t" "PSHUFD $dst,$dst,0x00\t! replicate2I" %} - ins_encode( mov_i2x(dst, src), pshufd(dst, dst, 0x00)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -12655,7 +12368,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate2I zero)); format %{ "PXOR $dst,$dst\t! replicate2I" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -12664,7 +12379,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate2F src)); format %{ "PSHUFD $dst,$src,0xe0\t! replicate2F" %} - ins_encode( pshufd(dst, src, 0xe0)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0xe0); + %} ins_pipe( fpu_reg_reg ); %} @@ -12673,7 +12390,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate2F src)); format %{ "PSHUFD $dst,$src,0xe0\t! replicate2F" %} - ins_encode( pshufd(dst, src, 0xe0)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0xe0); + %} ins_pipe( fpu_reg_reg ); %} @@ -12682,7 +12401,9 @@ predicate(UseSSE>=2); match(Set dst (Replicate2F zero)); format %{ "PXOR $dst,$dst\t! replicate2F" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} diff -r d725f0affb1a -r 127b3692c168 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Tue Dec 13 17:10:52 2011 -0800 +++ b/src/cpu/x86/vm/x86_64.ad Wed Dec 14 14:54:38 2011 -0800 @@ -552,7 +552,7 @@ #define __ _masm. static int preserve_SP_size() { - return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) + return 3; // rex.w, op, rm(reg/reg) } // !!!!! Special hack to get all types of calls to specify the byte offset @@ -797,48 +797,35 @@ } } -void encode_copy(CodeBuffer &cbuf, int dstenc, int srcenc) -{ - if (dstenc != srcenc) { - if (dstenc < 8) { - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - emit_opcode(cbuf, Assembler::REX_R); - } else { - emit_opcode(cbuf, Assembler::REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } - - emit_opcode(cbuf, 0x8B); - emit_rm(cbuf, 0x3, dstenc, srcenc); - } -} - -void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) { - if( dst_encoding == src_encoding ) { - // reg-reg copy, use an empty encoding - } else { - MacroAssembler _masm(&cbuf); - - __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding)); - } -} - // This could be in MacroAssembler but it's fairly C2 specific void emit_cmpfp_fixup(MacroAssembler& _masm) { Label exit; __ jccb(Assembler::noParity, exit); __ pushf(); + // + // comiss/ucomiss instructions set ZF,PF,CF flags and + // zero OF,AF,SF for NaN values. + // Fixup flags by zeroing ZF,PF so that compare of NaN + // values returns 'less than' result (CF is set). + // Leave the rest of flags unchanged. + // + // 7 6 5 4 3 2 1 0 + // |S|Z|r|A|r|P|r|C| (r - reserved bit) + // 0 0 1 0 1 0 1 1 (0x2B) + // __ andq(Address(rsp, 0), 0xffffff2b); __ popf(); __ bind(exit); - __ nop(); // (target for branch to avoid branch to branch) +} + +void emit_cmpfp3(MacroAssembler& _masm, Register dst) { + Label done; + __ movl(dst, -1); + __ jcc(Assembler::parity, done); + __ jcc(Assembler::below, done); + __ setb(Assembler::notEqual, dst); + __ movzbl(dst, dst); + __ bind(done); } @@ -1274,16 +1261,8 @@ // 64-bit int offset = ra_->reg2offset(src_first); if (cbuf) { - emit_opcode(*cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - if (Matcher::_regEncode[dst_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12); - encode_RegMem(*cbuf, - Matcher::_regEncode[dst_first], - RSP_enc, 0x4, 0, offset, - false); + MacroAssembler _masm(cbuf); + __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset)); #ifndef PRODUCT } else if (!do_size) { st->print("%s %s, [rsp + #%d]\t# spill", @@ -1294,25 +1273,17 @@ } return ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + - ((Matcher::_regEncode[dst_first] < 8) - ? 5 - : 6); // REX + ((Matcher::_regEncode[dst_first] >= 8) + ? 6 + : (5 + ((UseAVX>0)?1:0))); // REX } else { // 32-bit assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); int offset = ra_->reg2offset(src_first); if (cbuf) { - emit_opcode(*cbuf, 0xF3); - if (Matcher::_regEncode[dst_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x10); - encode_RegMem(*cbuf, - Matcher::_regEncode[dst_first], - RSP_enc, 0x4, 0, offset, - false); + MacroAssembler _masm(cbuf); + __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset)); #ifndef PRODUCT } else if (!do_size) { st->print("movss %s, [rsp + #%d]\t# spill", @@ -1322,9 +1293,9 @@ } return ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + - ((Matcher::_regEncode[dst_first] < 8) - ? 5 - : 6); // REX + ((Matcher::_regEncode[dst_first] >= 8) + ? 6 + : (5 + ((UseAVX>0)?1:0))); // REX } } } else if (src_first_rc == rc_int) { @@ -1450,25 +1421,8 @@ (dst_first & 1) == 0 && dst_first + 1 == dst_second) { // 64-bit if (cbuf) { - emit_opcode(*cbuf, 0x66); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_W); - } else { - emit_opcode(*cbuf, Assembler::REX_WB); - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_WR); - } else { - emit_opcode(*cbuf, Assembler::REX_WRB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x6E); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[dst_first] & 7, - Matcher::_regEncode[src_first] & 7); + MacroAssembler _masm(cbuf); + __ movdq( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movdq %s, %s\t# spill", @@ -1482,23 +1436,8 @@ assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); if (cbuf) { - emit_opcode(*cbuf, 0x66); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_B); - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } else { - emit_opcode(*cbuf, Assembler::REX_RB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x6E); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[dst_first] & 7, - Matcher::_regEncode[src_first] & 7); + MacroAssembler _masm(cbuf); + __ movdl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movdl %s, %s\t# spill", @@ -1507,9 +1446,9 @@ #endif } return - (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8) - ? 4 - : 5; // REX + (Matcher::_regEncode[src_first] >= 8 || Matcher::_regEncode[dst_first] >= 8) + ? 5 + : (4 + ((UseAVX>0)?1:0)); // REX } } } else if (src_first_rc == rc_float) { @@ -1521,16 +1460,8 @@ // 64-bit int offset = ra_->reg2offset(dst_first); if (cbuf) { - emit_opcode(*cbuf, 0xF2); - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x11); - encode_RegMem(*cbuf, - Matcher::_regEncode[src_first], - RSP_enc, 0x4, 0, offset, - false); + MacroAssembler _masm(cbuf); + __ movdbl( Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movsd [rsp + #%d], %s\t# spill", @@ -1540,25 +1471,17 @@ } return ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + - ((Matcher::_regEncode[src_first] < 8) - ? 5 - : 6); // REX + ((Matcher::_regEncode[src_first] >= 8) + ? 6 + : (5 + ((UseAVX>0)?1:0))); // REX } else { // 32-bit assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); int offset = ra_->reg2offset(dst_first); if (cbuf) { - emit_opcode(*cbuf, 0xF3); - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x11); - encode_RegMem(*cbuf, - Matcher::_regEncode[src_first], - RSP_enc, 0x4, 0, offset, - false); + MacroAssembler _masm(cbuf); + __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movss [rsp + #%d], %s\t# spill", @@ -1568,9 +1491,9 @@ } return ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + - ((Matcher::_regEncode[src_first] < 8) - ? 5 - : 6); // REX + ((Matcher::_regEncode[src_first] >=8) + ? 6 + : (5 + ((UseAVX>0)?1:0))); // REX } } else if (dst_first_rc == rc_int) { // xmm -> gpr @@ -1578,25 +1501,8 @@ (dst_first & 1) == 0 && dst_first + 1 == dst_second) { // 64-bit if (cbuf) { - emit_opcode(*cbuf, 0x66); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_W); - } else { - emit_opcode(*cbuf, Assembler::REX_WR); // attention! - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_WB); // attention! - } else { - emit_opcode(*cbuf, Assembler::REX_WRB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x7E); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[src_first] & 7, - Matcher::_regEncode[dst_first] & 7); + MacroAssembler _masm(cbuf); + __ movdq( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movdq %s, %s\t# spill", @@ -1610,23 +1516,8 @@ assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); if (cbuf) { - emit_opcode(*cbuf, 0x66); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_R); // attention! - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_B); // attention! - } else { - emit_opcode(*cbuf, Assembler::REX_RB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, 0x7E); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[src_first] & 7, - Matcher::_regEncode[dst_first] & 7); + MacroAssembler _masm(cbuf); + __ movdl( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("movdl %s, %s\t# spill", @@ -1635,9 +1526,9 @@ #endif } return - (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8) - ? 4 - : 5; // REX + (Matcher::_regEncode[src_first] >= 8 || Matcher::_regEncode[dst_first] >= 8) + ? 5 + : (4 + ((UseAVX>0)?1:0)); // REX } } else if (dst_first_rc == rc_float) { // xmm -> xmm @@ -1645,23 +1536,8 @@ (dst_first & 1) == 0 && dst_first + 1 == dst_second) { // 64-bit if (cbuf) { - emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x66 : 0xF2); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_B); - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } else { - emit_opcode(*cbuf, Assembler::REX_RB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[dst_first] & 7, - Matcher::_regEncode[src_first] & 7); + MacroAssembler _masm(cbuf); + __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("%s %s, %s\t# spill", @@ -1671,32 +1547,16 @@ #endif } return - (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8) - ? 4 - : 5; // REX + (Matcher::_regEncode[src_first] >= 8 || Matcher::_regEncode[dst_first] >= 8) + ? 5 + : (4 + ((UseAVX>0)?1:0)); // REX } else { // 32-bit assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); if (cbuf) { - if (!UseXmmRegToRegMoveAll) - emit_opcode(*cbuf, 0xF3); - if (Matcher::_regEncode[dst_first] < 8) { - if (Matcher::_regEncode[src_first] >= 8) { - emit_opcode(*cbuf, Assembler::REX_B); - } - } else { - if (Matcher::_regEncode[src_first] < 8) { - emit_opcode(*cbuf, Assembler::REX_R); - } else { - emit_opcode(*cbuf, Assembler::REX_RB); - } - } - emit_opcode(*cbuf, 0x0F); - emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10); - emit_rm(*cbuf, 0x3, - Matcher::_regEncode[dst_first] & 7, - Matcher::_regEncode[src_first] & 7); + MacroAssembler _masm(cbuf); + __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first])); #ifndef PRODUCT } else if (!do_size) { st->print("%s %s, %s\t# spill", @@ -1705,10 +1565,10 @@ Matcher::regName[src_first]); #endif } - return - (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8) - ? (UseXmmRegToRegMoveAll ? 3 : 4) - : (UseXmmRegToRegMoveAll ? 4 : 5); // REX + return ((UseAVX>0) ? 5: + ((Matcher::_regEncode[src_first] >= 8 || Matcher::_regEncode[dst_first] >= 8) + ? (UseXmmRegToRegMoveAll ? 4 : 5) + : (UseXmmRegToRegMoveAll ? 3 : 4))); // REX } } } @@ -2205,47 +2065,6 @@ emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7); %} - enc_class cmpfp_fixup() %{ - MacroAssembler _masm(&cbuf); - emit_cmpfp_fixup(_masm); - %} - - enc_class cmpfp3(rRegI dst) - %{ - int dstenc = $dst$$reg; - - // movl $dst, -1 - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0xB8 | (dstenc & 7)); - emit_d32(cbuf, -1); - - // jp,s done - emit_opcode(cbuf, 0x7A); - emit_d8(cbuf, dstenc < 4 ? 0x08 : 0x0A); - - // jb,s done - emit_opcode(cbuf, 0x72); - emit_d8(cbuf, dstenc < 4 ? 0x06 : 0x08); - - // setne $dst - if (dstenc >= 4) { - emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_B); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x95); - emit_opcode(cbuf, 0xC0 | (dstenc & 7)); - - // movzbl $dst, $dst - if (dstenc >= 4) { - emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_RB); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0xB6); - emit_rm(cbuf, 0x3, dstenc & 7, dstenc & 7); - %} - enc_class cdql_enc(no_rax_rdx_RegI div) %{ // Full implementation of Java idiv and irem; checks for @@ -2472,55 +2291,6 @@ emit_cc(cbuf, $secondary, $cop$$cmpcode); %} - enc_class enc_cmovf_branch(cmpOp cop, regF dst, regF src) - %{ - // Invert sense of branch from sense of cmov - emit_cc(cbuf, 0x70, $cop$$cmpcode ^ 1); - emit_d8(cbuf, ($dst$$reg < 8 && $src$$reg < 8) - ? (UseXmmRegToRegMoveAll ? 3 : 4) - : (UseXmmRegToRegMoveAll ? 4 : 5) ); // REX - // UseXmmRegToRegMoveAll ? movaps(dst, src) : movss(dst, src) - if (!UseXmmRegToRegMoveAll) emit_opcode(cbuf, 0xF3); - if ($dst$$reg < 8) { - if ($src$$reg >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - } else { - if ($src$$reg < 8) { - emit_opcode(cbuf, Assembler::REX_R); - } else { - emit_opcode(cbuf, Assembler::REX_RB); - } - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10); - emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7); - %} - - enc_class enc_cmovd_branch(cmpOp cop, regD dst, regD src) - %{ - // Invert sense of branch from sense of cmov - emit_cc(cbuf, 0x70, $cop$$cmpcode ^ 1); - emit_d8(cbuf, $dst$$reg < 8 && $src$$reg < 8 ? 4 : 5); // REX - - // UseXmmRegToRegMoveAll ? movapd(dst, src) : movsd(dst, src) - emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x66 : 0xF2); - if ($dst$$reg < 8) { - if ($src$$reg >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - } else { - if ($src$$reg < 8) { - emit_opcode(cbuf, Assembler::REX_R); - } else { - emit_opcode(cbuf, Assembler::REX_RB); - } - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10); - emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7); - %} - enc_class enc_PartialSubtypeCheck() %{ Register Rrdi = as_Register(RDI_enc); // result register @@ -2751,68 +2521,6 @@ } %} - // Encode a reg-reg copy. If it is useless, then empty encoding. - enc_class enc_copy(rRegI dst, rRegI src) - %{ - encode_copy(cbuf, $dst$$reg, $src$$reg); - %} - - // Encode xmm reg-reg copy. If it is useless, then empty encoding. - enc_class enc_CopyXD( RegD dst, RegD src ) %{ - encode_CopyXD( cbuf, $dst$$reg, $src$$reg ); - %} - - enc_class enc_copy_always(rRegI dst, rRegI src) - %{ - int srcenc = $src$$reg; - int dstenc = $dst$$reg; - - if (dstenc < 8) { - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - emit_opcode(cbuf, Assembler::REX_R); - } else { - emit_opcode(cbuf, Assembler::REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } - - emit_opcode(cbuf, 0x8B); - emit_rm(cbuf, 0x3, dstenc, srcenc); - %} - - enc_class enc_copy_wide(rRegL dst, rRegL src) - %{ - int srcenc = $src$$reg; - int dstenc = $dst$$reg; - - if (dstenc != srcenc) { - if (dstenc < 8) { - if (srcenc < 8) { - emit_opcode(cbuf, Assembler::REX_W); - } else { - emit_opcode(cbuf, Assembler::REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - emit_opcode(cbuf, Assembler::REX_WR); - } else { - emit_opcode(cbuf, Assembler::REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } - emit_opcode(cbuf, 0x8B); - emit_rm(cbuf, 0x3, dstenc, srcenc); - } - %} - enc_class Con32(immI src) %{ // Output immediate @@ -3212,92 +2920,19 @@ %} enc_class Push_ResultXD(regD dst) %{ - int dstenc = $dst$$reg; - - store_to_stackslot( cbuf, 0xDD, 0x03, 0 ); //FSTP [RSP] - - // UseXmmLoadAndClearUpper ? movsd dst,[rsp] : movlpd dst,[rsp] - emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode (cbuf, 0x0F ); - emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12 ); - encode_RegMem(cbuf, dstenc, RSP_enc, 0x4, 0, 0, false); - - // add rsp,8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf,0x83); - emit_rm(cbuf,0x3, 0x0, RSP_enc); - emit_d8(cbuf,0x08); + MacroAssembler _masm(&cbuf); + __ fstp_d(Address(rsp, 0)); + __ movdbl($dst$$XMMRegister, Address(rsp, 0)); + __ addptr(rsp, 8); %} enc_class Push_SrcXD(regD src) %{ - int srcenc = $src$$reg; - - // subq rsp,#8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x83); - emit_rm(cbuf, 0x3, 0x5, RSP_enc); - emit_d8(cbuf, 0x8); - - // movsd [rsp],src - emit_opcode(cbuf, 0xF2); - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x11); - encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); - - // fldd [rsp] - emit_opcode(cbuf, 0x66); - emit_opcode(cbuf, 0xDD); - encode_RegMem(cbuf, 0x0, RSP_enc, 0x4, 0, 0, false); - %} - - - enc_class movq_ld(regD dst, memory mem) %{ MacroAssembler _masm(&cbuf); - __ movq($dst$$XMMRegister, $mem$$Address); - %} - - enc_class movq_st(memory mem, regD src) %{ - MacroAssembler _masm(&cbuf); - __ movq($mem$$Address, $src$$XMMRegister); - %} - - enc_class pshufd_8x8(regF dst, regF src) %{ - MacroAssembler _masm(&cbuf); - - encode_CopyXD(cbuf, $dst$$reg, $src$$reg); - __ punpcklbw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg)); - __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg), 0x00); - %} - - enc_class pshufd_4x16(regF dst, regF src) %{ - MacroAssembler _masm(&cbuf); - - __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), 0x00); - %} - - enc_class pshufd(regD dst, regD src, int mode) %{ - MacroAssembler _masm(&cbuf); - - __ pshufd(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), $mode); - %} - - enc_class pxor(regD dst, regD src) %{ - MacroAssembler _masm(&cbuf); - - __ pxor(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg)); - %} - - enc_class mov_i2x(regD dst, rRegI src) %{ - MacroAssembler _masm(&cbuf); - - __ movdl(as_XMMRegister($dst$$reg), as_Register($src$$reg)); - %} + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ fld_d(Address(rsp, 0)); + %} + // obj: object to lock // box: box address (header location) -- killed @@ -3534,303 +3169,6 @@ RELOC_DISP32); %} - enc_class absF_encoding(regF dst) - %{ - int dstenc = $dst$$reg; - address signmask_address = (address) StubRoutines::x86::float_sign_mask(); - - cbuf.set_insts_mark(); - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - dstenc -= 8; - } - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x54); - emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, signmask_address); - %} - - enc_class absD_encoding(regD dst) - %{ - int dstenc = $dst$$reg; - address signmask_address = (address) StubRoutines::x86::double_sign_mask(); - - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0x66); - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - dstenc -= 8; - } - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x54); - emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, signmask_address); - %} - - enc_class negF_encoding(regF dst) - %{ - int dstenc = $dst$$reg; - address signflip_address = (address) StubRoutines::x86::float_sign_flip(); - - cbuf.set_insts_mark(); - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - dstenc -= 8; - } - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x57); - emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, signflip_address); - %} - - enc_class negD_encoding(regD dst) - %{ - int dstenc = $dst$$reg; - address signflip_address = (address) StubRoutines::x86::double_sign_flip(); - - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0x66); - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - dstenc -= 8; - } - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x57); - emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, signflip_address); - %} - - enc_class f2i_fixup(rRegI dst, regF src) - %{ - int dstenc = $dst$$reg; - int srcenc = $src$$reg; - - // cmpl $dst, #0x80000000 - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x81); - emit_rm(cbuf, 0x3, 0x7, dstenc & 7); - emit_d32(cbuf, 0x80000000); - - // jne,s done - emit_opcode(cbuf, 0x75); - if (srcenc < 8 && dstenc < 8) { - emit_d8(cbuf, 0xF); - } else if (srcenc >= 8 && dstenc >= 8) { - emit_d8(cbuf, 0x11); - } else { - emit_d8(cbuf, 0x10); - } - - // subq rsp, #8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x83); - emit_rm(cbuf, 0x3, 0x5, RSP_enc); - emit_d8(cbuf, 8); - - // movss [rsp], $src - emit_opcode(cbuf, 0xF3); - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x11); - encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes - - // call f2i_fixup - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0xE8); - emit_d32_reloc(cbuf, - (int) - (StubRoutines::x86::f2i_fixup() - cbuf.insts_end() - 4), - runtime_call_Relocation::spec(), - RELOC_DISP32); - - // popq $dst - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x58 | (dstenc & 7)); - - // done: - %} - - enc_class f2l_fixup(rRegL dst, regF src) - %{ - int dstenc = $dst$$reg; - int srcenc = $src$$reg; - address const_address = (address) StubRoutines::x86::double_sign_flip(); - - // cmpq $dst, [0x8000000000000000] - cbuf.set_insts_mark(); - emit_opcode(cbuf, dstenc < 8 ? Assembler::REX_W : Assembler::REX_WR); - emit_opcode(cbuf, 0x39); - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_rm(cbuf, 0x0, dstenc & 7, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, const_address); - - - // jne,s done - emit_opcode(cbuf, 0x75); - if (srcenc < 8 && dstenc < 8) { - emit_d8(cbuf, 0xF); - } else if (srcenc >= 8 && dstenc >= 8) { - emit_d8(cbuf, 0x11); - } else { - emit_d8(cbuf, 0x10); - } - - // subq rsp, #8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x83); - emit_rm(cbuf, 0x3, 0x5, RSP_enc); - emit_d8(cbuf, 8); - - // movss [rsp], $src - emit_opcode(cbuf, 0xF3); - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x11); - encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes - - // call f2l_fixup - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0xE8); - emit_d32_reloc(cbuf, - (int) - (StubRoutines::x86::f2l_fixup() - cbuf.insts_end() - 4), - runtime_call_Relocation::spec(), - RELOC_DISP32); - - // popq $dst - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x58 | (dstenc & 7)); - - // done: - %} - - enc_class d2i_fixup(rRegI dst, regD src) - %{ - int dstenc = $dst$$reg; - int srcenc = $src$$reg; - - // cmpl $dst, #0x80000000 - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x81); - emit_rm(cbuf, 0x3, 0x7, dstenc & 7); - emit_d32(cbuf, 0x80000000); - - // jne,s done - emit_opcode(cbuf, 0x75); - if (srcenc < 8 && dstenc < 8) { - emit_d8(cbuf, 0xF); - } else if (srcenc >= 8 && dstenc >= 8) { - emit_d8(cbuf, 0x11); - } else { - emit_d8(cbuf, 0x10); - } - - // subq rsp, #8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x83); - emit_rm(cbuf, 0x3, 0x5, RSP_enc); - emit_d8(cbuf, 8); - - // movsd [rsp], $src - emit_opcode(cbuf, 0xF2); - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x11); - encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes - - // call d2i_fixup - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0xE8); - emit_d32_reloc(cbuf, - (int) - (StubRoutines::x86::d2i_fixup() - cbuf.insts_end() - 4), - runtime_call_Relocation::spec(), - RELOC_DISP32); - - // popq $dst - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x58 | (dstenc & 7)); - - // done: - %} - - enc_class d2l_fixup(rRegL dst, regD src) - %{ - int dstenc = $dst$$reg; - int srcenc = $src$$reg; - address const_address = (address) StubRoutines::x86::double_sign_flip(); - - // cmpq $dst, [0x8000000000000000] - cbuf.set_insts_mark(); - emit_opcode(cbuf, dstenc < 8 ? Assembler::REX_W : Assembler::REX_WR); - emit_opcode(cbuf, 0x39); - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_rm(cbuf, 0x0, dstenc & 7, 0x5); // 00 reg 101 - emit_d32_reloc(cbuf, const_address); - - - // jne,s done - emit_opcode(cbuf, 0x75); - if (srcenc < 8 && dstenc < 8) { - emit_d8(cbuf, 0xF); - } else if (srcenc >= 8 && dstenc >= 8) { - emit_d8(cbuf, 0x11); - } else { - emit_d8(cbuf, 0x10); - } - - // subq rsp, #8 - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x83); - emit_rm(cbuf, 0x3, 0x5, RSP_enc); - emit_d8(cbuf, 8); - - // movsd [rsp], $src - emit_opcode(cbuf, 0xF2); - if (srcenc >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x11); - encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes - - // call d2l_fixup - cbuf.set_insts_mark(); - emit_opcode(cbuf, 0xE8); - emit_d32_reloc(cbuf, - (int) - (StubRoutines::x86::d2l_fixup() - cbuf.insts_end() - 4), - runtime_call_Relocation::spec(), - RELOC_DISP32); - - // popq $dst - if (dstenc >= 8) { - emit_opcode(cbuf, Assembler::REX_B); - } - emit_opcode(cbuf, 0x58 | (dstenc & 7)); - - // done: - %} %} @@ -6156,8 +5494,9 @@ ins_cost(145); // XXX format %{ "movss $dst, $mem\t# float" %} - opcode(0xF3, 0x0F, 0x10); - ins_encode(OpcP, REX_reg_mem(dst, mem), OpcS, OpcT, reg_mem(dst, mem)); + ins_encode %{ + __ movflt($dst$$XMMRegister, $mem$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -6169,8 +5508,9 @@ ins_cost(145); // XXX format %{ "movlpd $dst, $mem\t# double" %} - opcode(0x66, 0x0F, 0x12); - ins_encode(OpcP, REX_reg_mem(dst, mem), OpcS, OpcT, reg_mem(dst, mem)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, $mem$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -6181,8 +5521,9 @@ ins_cost(145); // XXX format %{ "movsd $dst, $mem\t# double" %} - opcode(0xF2, 0x0F, 0x10); - ins_encode(OpcP, REX_reg_mem(dst, mem), OpcS, OpcT, reg_mem(dst, mem)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, $mem$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -6191,7 +5532,9 @@ match(Set dst (Load8B mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed8B" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6200,7 +5543,9 @@ match(Set dst (Load4S mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed4S" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6209,7 +5554,9 @@ match(Set dst (Load4C mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed4C" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6218,16 +5565,20 @@ match(Set dst (Load2I mem)); ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed2I" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} // Load Aligned Packed Single to XMM instruct loadA2F(regD dst, memory mem) %{ match(Set dst (Load2F mem)); - ins_cost(145); + ins_cost(125); format %{ "MOVQ $dst,$mem\t! packed2F" %} - ins_encode( movq_ld(dst, mem)); + ins_encode %{ + __ movq($dst$$XMMRegister, $mem$$Address); + %} ins_pipe( pipe_slow ); %} @@ -6540,8 +5891,9 @@ ins_cost(100); format %{ "xorps $dst, $dst\t# float 0.0" %} - opcode(0x0F, 0x57); - ins_encode(REX_reg_reg(dst, dst), OpcP, OpcS, reg_reg(dst, dst)); + ins_encode %{ + __ xorps($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -6562,8 +5914,9 @@ ins_cost(100); format %{ "xorpd $dst, $dst\t# double 0.0" %} - opcode(0x66, 0x0F, 0x57); - ins_encode(OpcP, REX_reg_reg(dst, dst), OpcS, OpcT, reg_reg(dst, dst)); + ins_encode %{ + __ xorpd ($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -6606,8 +5959,9 @@ ins_cost(125); format %{ "movss $dst, $src\t# float stk" %} - opcode(0xF3, 0x0F, 0x10); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe(pipe_slow); // XXX %} @@ -6972,7 +6326,9 @@ match(Set mem (Store8B mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed8B" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -6981,7 +6337,9 @@ match(Set mem (Store4C mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed4C" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -6990,7 +6348,9 @@ match(Set mem (Store2I mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed2I" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7024,7 +6384,9 @@ match(Set mem (Store2F mem src)); ins_cost(145); format %{ "MOVQ $mem,$src\t! packed2F" %} - ins_encode( movq_st(mem, src)); + ins_encode %{ + __ movq($mem$$Address, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -7035,8 +6397,9 @@ ins_cost(95); // XXX format %{ "movss $mem, $src\t# float" %} - opcode(0xF3, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, mem), OpcS, OpcT, reg_mem(src, mem)); + ins_encode %{ + __ movflt($mem$$Address, $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -7072,8 +6435,9 @@ ins_cost(95); // XXX format %{ "movsd $mem, $src\t# double" %} - opcode(0xF2, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, mem), OpcS, OpcT, reg_mem(src, mem)); + ins_encode %{ + __ movdbl($mem$$Address, $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -7142,8 +6506,9 @@ ins_cost(95); // XXX format %{ "movss $dst, $src\t# float stk" %} - opcode(0xF3, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, dst), OpcS, OpcT, reg_mem(src, dst)); + ins_encode %{ + __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -7153,8 +6518,9 @@ ins_cost(95); // XXX format %{ "movsd $dst, $src\t# double stk" %} - opcode(0xF2, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, dst), OpcS, OpcT, reg_mem(src, dst)); + ins_encode %{ + __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -7451,7 +6817,11 @@ match(Set dst (CastX2P src)); format %{ "movq $dst, $src\t# long->ptr" %} - ins_encode(enc_copy_wide(dst, src)); + ins_encode %{ + if ($dst$$reg != $src$$reg) { + __ movptr($dst$$Register, $src$$Register); + } + %} ins_pipe(ialu_reg_reg); // XXX %} @@ -7460,7 +6830,11 @@ match(Set dst (CastP2X src)); format %{ "movq $dst, $src\t# ptr -> long" %} - ins_encode(enc_copy_wide(dst, src)); + ins_encode %{ + if ($dst$$reg != $src$$reg) { + __ movptr($dst$$Register, $src$$Register); + } + %} ins_pipe(ialu_reg_reg); // XXX %} @@ -7813,7 +7187,13 @@ format %{ "jn$cop skip\t# signed cmove float\n\t" "movss $dst, $src\n" "skip:" %} - ins_encode(enc_cmovf_branch(cop, dst, src)); + ins_encode %{ + Label Lskip; + // Invert sense of branch from sense of CMOV + __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip); + __ movflt($dst$$XMMRegister, $src$$XMMRegister); + __ bind(Lskip); + %} ins_pipe(pipe_slow); %} @@ -7837,7 +7217,13 @@ format %{ "jn$cop skip\t# unsigned cmove float\n\t" "movss $dst, $src\n" "skip:" %} - ins_encode(enc_cmovf_branch(cop, dst, src)); + ins_encode %{ + Label Lskip; + // Invert sense of branch from sense of CMOV + __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip); + __ movflt($dst$$XMMRegister, $src$$XMMRegister); + __ bind(Lskip); + %} ins_pipe(pipe_slow); %} @@ -7857,7 +7243,13 @@ format %{ "jn$cop skip\t# signed cmove double\n\t" "movsd $dst, $src\n" "skip:" %} - ins_encode(enc_cmovd_branch(cop, dst, src)); + ins_encode %{ + Label Lskip; + // Invert sense of branch from sense of CMOV + __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip); + __ movdbl($dst$$XMMRegister, $src$$XMMRegister); + __ bind(Lskip); + %} ins_pipe(pipe_slow); %} @@ -7869,7 +7261,13 @@ format %{ "jn$cop skip\t# unsigned cmove double\n\t" "movsd $dst, $src\n" "skip:" %} - ins_encode(enc_cmovd_branch(cop, dst, src)); + ins_encode %{ + Label Lskip; + // Invert sense of branch from sense of CMOV + __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip); + __ movdbl($dst$$XMMRegister, $src$$XMMRegister); + __ bind(Lskip); + %} ins_pipe(pipe_slow); %} @@ -10191,17 +9589,18 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} - opcode(0x0F, 0x2E); - ins_encode(REX_reg_reg(src1, src2), OpcP, OpcS, reg_reg(src1, src2), - cmpfp_fixup); + "exit:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp_fixup(_masm); + %} ins_pipe(pipe_slow); %} instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{ match(Set cr (CmpF src1 src2)); - ins_cost(145); + ins_cost(100); format %{ "ucomiss $src1, $src2" %} ins_encode %{ __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); @@ -10219,10 +9618,11 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2), - cmpfp_fixup); + "exit:" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + emit_cmpfp_fixup(_masm); + %} ins_pipe(pipe_slow); %} @@ -10231,8 +9631,9 @@ ins_cost(100); format %{ "ucomiss $src1, $src2" %} - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2)); + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + %} ins_pipe(pipe_slow); %} @@ -10245,7 +9646,7 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} + "exit:" %} ins_encode %{ __ ucomiss($src$$XMMRegister, $constantaddress($con)); emit_cmpfp_fixup(_masm); @@ -10273,10 +9674,11 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_reg(src1, src2), OpcS, OpcT, reg_reg(src1, src2), - cmpfp_fixup); + "exit:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp_fixup(_masm); + %} ins_pipe(pipe_slow); %} @@ -10301,10 +9703,11 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2), - cmpfp_fixup); + "exit:" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + emit_cmpfp_fixup(_masm); + %} ins_pipe(pipe_slow); %} @@ -10313,8 +9716,9 @@ ins_cost(100); format %{ "ucomisd $src1, $src2" %} - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2)); + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + %} ins_pipe(pipe_slow); %} @@ -10327,7 +9731,7 @@ "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" - "exit: nop\t# avoid branch to branch" %} + "exit:" %} ins_encode %{ __ ucomisd($src$$XMMRegister, $constantaddress($con)); emit_cmpfp_fixup(_masm); @@ -10359,10 +9763,10 @@ "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x0F, 0x2E); - ins_encode(REX_reg_reg(src1, src2), OpcP, OpcS, reg_reg(src1, src2), - cmpfp3(dst)); + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe(pipe_slow); %} @@ -10380,10 +9784,10 @@ "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2), - cmpfp3(dst)); + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$Address); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe(pipe_slow); %} @@ -10401,15 +9805,8 @@ "movzbl $dst, $dst\n" "done:" %} ins_encode %{ - Label L_done; - Register Rdst = $dst$$Register; __ ucomiss($src$$XMMRegister, $constantaddress($con)); - __ movl(Rdst, -1); - __ jcc(Assembler::parity, L_done); - __ jcc(Assembler::below, L_done); - __ setb(Assembler::notEqual, Rdst); - __ movzbl(Rdst, Rdst); - __ bind(L_done); + emit_cmpfp3(_masm, $dst$$Register); %} ins_pipe(pipe_slow); %} @@ -10428,10 +9825,10 @@ "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_reg(src1, src2), OpcS, OpcT, reg_reg(src1, src2), - cmpfp3(dst)); + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe(pipe_slow); %} @@ -10449,10 +9846,10 @@ "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2), - cmpfp3(dst)); + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$Address); + emit_cmpfp3(_masm, $dst$$Register); + %} ins_pipe(pipe_slow); %} @@ -10470,15 +9867,8 @@ "movzbl $dst, $dst\n" "done:" %} ins_encode %{ - Register Rdst = $dst$$Register; - Label L_done; __ ucomisd($src$$XMMRegister, $constantaddress($con)); - __ movl(Rdst, -1); - __ jcc(Assembler::parity, L_done); - __ jcc(Assembler::below, L_done); - __ setb(Assembler::notEqual, Rdst); - __ movzbl(Rdst, Rdst); - __ bind(L_done); + emit_cmpfp3(_masm, $dst$$Register); %} ins_pipe(pipe_slow); %} @@ -10489,8 +9879,9 @@ format %{ "addss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ addss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10500,8 +9891,9 @@ format %{ "addss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ addss($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10521,8 +9913,9 @@ format %{ "addsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ addsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10532,8 +9925,9 @@ format %{ "addsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ addsd($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10553,8 +9947,9 @@ format %{ "subss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ subss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10564,8 +9959,9 @@ format %{ "subss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ subss($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10585,8 +9981,9 @@ format %{ "subsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ subsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10596,8 +9993,9 @@ format %{ "subsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ subsd($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10617,8 +10015,9 @@ format %{ "mulss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ mulss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10628,8 +10027,9 @@ format %{ "mulss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ mulss($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10649,8 +10049,9 @@ format %{ "mulsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ mulsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10660,8 +10061,9 @@ format %{ "mulsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ mulsd($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10681,8 +10083,9 @@ format %{ "divss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ divss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10692,8 +10095,9 @@ format %{ "divss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ divss($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10713,8 +10117,9 @@ format %{ "divsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ divsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10724,8 +10129,9 @@ format %{ "divsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ divsd($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10745,8 +10151,9 @@ format %{ "sqrtss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ sqrtss($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10756,8 +10163,9 @@ format %{ "sqrtss $dst, $src" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ sqrtss($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10777,8 +10185,9 @@ format %{ "sqrtsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ sqrtsd($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -10788,8 +10197,9 @@ format %{ "sqrtsd $dst, $src" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ sqrtsd($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); %} @@ -10806,38 +10216,50 @@ instruct absF_reg(regF dst) %{ match(Set dst (AbsF dst)); - + ins_cost(150); // XXX format %{ "andps $dst, [0x7fffffff]\t# abs float by sign masking" %} - ins_encode(absF_encoding(dst)); + ins_encode %{ + __ andps($dst$$XMMRegister, + ExternalAddress((address) StubRoutines::x86::float_sign_mask())); + %} ins_pipe(pipe_slow); %} instruct absD_reg(regD dst) %{ match(Set dst (AbsD dst)); - + ins_cost(150); // XXX format %{ "andpd $dst, [0x7fffffffffffffff]\t" "# abs double by sign masking" %} - ins_encode(absD_encoding(dst)); + ins_encode %{ + __ andpd($dst$$XMMRegister, + ExternalAddress((address) StubRoutines::x86::double_sign_mask())); + %} ins_pipe(pipe_slow); %} instruct negF_reg(regF dst) %{ match(Set dst (NegF dst)); - + ins_cost(150); // XXX format %{ "xorps $dst, [0x80000000]\t# neg float by sign flipping" %} - ins_encode(negF_encoding(dst)); + ins_encode %{ + __ xorps($dst$$XMMRegister, + ExternalAddress((address) StubRoutines::x86::float_sign_flip())); + %} ins_pipe(pipe_slow); %} instruct negD_reg(regD dst) %{ match(Set dst (NegD dst)); - + ins_cost(150); // XXX format %{ "xorpd $dst, [0x8000000000000000]\t" "# neg double by sign flipping" %} - ins_encode(negD_encoding(dst)); + ins_encode %{ + __ xorpd($dst$$XMMRegister, + ExternalAddress((address) StubRoutines::x86::double_sign_flip())); + %} ins_pipe(pipe_slow); %} @@ -10929,8 +10351,9 @@ match(Set dst (ConvF2D src)); format %{ "cvtss2sd $dst, $src" %} - opcode(0xF3, 0x0F, 0x5A); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -10939,8 +10362,9 @@ match(Set dst (ConvF2D (LoadF src))); format %{ "cvtss2sd $dst, $src" %} - opcode(0xF3, 0x0F, 0x5A); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtss2sd ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -10949,8 +10373,9 @@ match(Set dst (ConvD2F src)); format %{ "cvtsd2ss $dst, $src" %} - opcode(0xF2, 0x0F, 0x5A); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister); + %} ins_pipe(pipe_slow); // XXX %} @@ -10959,8 +10384,9 @@ match(Set dst (ConvD2F (LoadD src))); format %{ "cvtsd2ss $dst, $src" %} - opcode(0xF2, 0x0F, 0x5A); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtsd2ss ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -10978,9 +10404,17 @@ "call f2i_fixup\n\t" "popq $dst\n" "done: "%} - opcode(0xF3, 0x0F, 0x2C); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src), - f2i_fixup(dst, src)); + ins_encode %{ + Label done; + __ cvttss2sil($dst$$Register, $src$$XMMRegister); + __ cmpl($dst$$Register, 0x80000000); + __ jccb(Assembler::notEqual, done); + __ subptr(rsp, 8); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::f2i_fixup()))); + __ pop($dst$$Register); + __ bind(done); + %} ins_pipe(pipe_slow); %} @@ -10997,9 +10431,18 @@ "call f2l_fixup\n\t" "popq $dst\n" "done: "%} - opcode(0xF3, 0x0F, 0x2C); - ins_encode(OpcP, REX_reg_reg_wide(dst, src), OpcS, OpcT, reg_reg(dst, src), - f2l_fixup(dst, src)); + ins_encode %{ + Label done; + __ cvttss2siq($dst$$Register, $src$$XMMRegister); + __ cmp64($dst$$Register, + ExternalAddress((address) StubRoutines::x86::double_sign_flip())); + __ jccb(Assembler::notEqual, done); + __ subptr(rsp, 8); + __ movflt(Address(rsp, 0), $src$$XMMRegister); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::f2l_fixup()))); + __ pop($dst$$Register); + __ bind(done); + %} ins_pipe(pipe_slow); %} @@ -11016,9 +10459,17 @@ "call d2i_fixup\n\t" "popq $dst\n" "done: "%} - opcode(0xF2, 0x0F, 0x2C); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src), - d2i_fixup(dst, src)); + ins_encode %{ + Label done; + __ cvttsd2sil($dst$$Register, $src$$XMMRegister); + __ cmpl($dst$$Register, 0x80000000); + __ jccb(Assembler::notEqual, done); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::d2i_fixup()))); + __ pop($dst$$Register); + __ bind(done); + %} ins_pipe(pipe_slow); %} @@ -11035,9 +10486,18 @@ "call d2l_fixup\n\t" "popq $dst\n" "done: "%} - opcode(0xF2, 0x0F, 0x2C); - ins_encode(OpcP, REX_reg_reg_wide(dst, src), OpcS, OpcT, reg_reg(dst, src), - d2l_fixup(dst, src)); + ins_encode %{ + Label done; + __ cvttsd2siq($dst$$Register, $src$$XMMRegister); + __ cmp64($dst$$Register, + ExternalAddress((address) StubRoutines::x86::double_sign_flip())); + __ jccb(Assembler::notEqual, done); + __ subptr(rsp, 8); + __ movdbl(Address(rsp, 0), $src$$XMMRegister); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::d2l_fixup()))); + __ pop($dst$$Register); + __ bind(done); + %} ins_pipe(pipe_slow); %} @@ -11047,8 +10507,9 @@ match(Set dst (ConvI2F src)); format %{ "cvtsi2ssl $dst, $src\t# i2f" %} - opcode(0xF3, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtsi2ssl ($dst$$XMMRegister, $src$$Register); + %} ins_pipe(pipe_slow); // XXX %} @@ -11057,8 +10518,9 @@ match(Set dst (ConvI2F (LoadI src))); format %{ "cvtsi2ssl $dst, $src\t# i2f" %} - opcode(0xF3, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtsi2ssl ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -11068,8 +10530,9 @@ match(Set dst (ConvI2D src)); format %{ "cvtsi2sdl $dst, $src\t# i2d" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_reg(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtsi2sdl ($dst$$XMMRegister, $src$$Register); + %} ins_pipe(pipe_slow); // XXX %} @@ -11078,8 +10541,9 @@ match(Set dst (ConvI2D (LoadI src))); format %{ "cvtsi2sdl $dst, $src\t# i2d" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtsi2sdl ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -11116,8 +10580,9 @@ match(Set dst (ConvL2F src)); format %{ "cvtsi2ssq $dst, $src\t# l2f" %} - opcode(0xF3, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_reg_wide(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtsi2ssq ($dst$$XMMRegister, $src$$Register); + %} ins_pipe(pipe_slow); // XXX %} @@ -11126,8 +10591,9 @@ match(Set dst (ConvL2F (LoadL src))); format %{ "cvtsi2ssq $dst, $src\t# l2f" %} - opcode(0xF3, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_mem_wide(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtsi2ssq ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -11136,8 +10602,9 @@ match(Set dst (ConvL2D src)); format %{ "cvtsi2sdq $dst, $src\t# l2d" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_reg_wide(dst, src), OpcS, OpcT, reg_reg(dst, src)); + ins_encode %{ + __ cvtsi2sdq ($dst$$XMMRegister, $src$$Register); + %} ins_pipe(pipe_slow); // XXX %} @@ -11146,8 +10613,9 @@ match(Set dst (ConvL2D (LoadL src))); format %{ "cvtsi2sdq $dst, $src\t# l2d" %} - opcode(0xF2, 0x0F, 0x2A); - ins_encode(OpcP, REX_reg_mem_wide(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ cvtsi2sdq ($dst$$XMMRegister, $src$$Address); + %} ins_pipe(pipe_slow); // XXX %} @@ -11186,7 +10654,11 @@ match(Set dst (AndL (ConvI2L src) mask)); format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %} - ins_encode(enc_copy(dst, src)); + ins_encode %{ + if ($dst$$reg != $src$$reg) { + __ movl($dst$$Register, $src$$Register); + } + %} ins_pipe(ialu_reg_reg); %} @@ -11196,8 +10668,9 @@ match(Set dst (AndL (ConvI2L (LoadI src)) mask)); format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %} - opcode(0x8B); - ins_encode(REX_reg_mem(dst, src), OpcP, reg_mem(dst, src)); + ins_encode %{ + __ movl($dst$$Register, $src$$Address); + %} ins_pipe(ialu_reg_mem); %} @@ -11206,7 +10679,9 @@ match(Set dst (AndL src mask)); format %{ "movl $dst, $src\t# zero-extend long" %} - ins_encode(enc_copy_always(dst, src)); + ins_encode %{ + __ movl($dst$$Register, $src$$Register); + %} ins_pipe(ialu_reg_reg); %} @@ -11215,7 +10690,9 @@ match(Set dst (ConvL2I src)); format %{ "movl $dst, $src\t# l2i" %} - ins_encode(enc_copy_always(dst, src)); + ins_encode %{ + __ movl($dst$$Register, $src$$Register); + %} ins_pipe(ialu_reg_reg); %} @@ -11226,8 +10703,9 @@ ins_cost(125); format %{ "movl $dst, $src\t# MoveF2I_stack_reg" %} - opcode(0x8B); - ins_encode(REX_reg_mem(dst, src), OpcP, reg_mem(dst, src)); + ins_encode %{ + __ movl($dst$$Register, Address(rsp, $src$$disp)); + %} ins_pipe(ialu_reg_mem); %} @@ -11237,8 +10715,9 @@ ins_cost(125); format %{ "movss $dst, $src\t# MoveI2F_stack_reg" %} - opcode(0xF3, 0x0F, 0x10); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe(pipe_slow); %} @@ -11248,8 +10727,9 @@ ins_cost(125); format %{ "movq $dst, $src\t# MoveD2L_stack_reg" %} - opcode(0x8B); - ins_encode(REX_reg_mem_wide(dst, src), OpcP, reg_mem(dst, src)); + ins_encode %{ + __ movq($dst$$Register, Address(rsp, $src$$disp)); + %} ins_pipe(ialu_reg_mem); %} @@ -11260,8 +10740,9 @@ ins_cost(125); format %{ "movlpd $dst, $src\t# MoveL2D_stack_reg" %} - opcode(0x66, 0x0F, 0x12); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe(pipe_slow); %} @@ -11272,8 +10753,9 @@ ins_cost(125); format %{ "movsd $dst, $src\t# MoveL2D_stack_reg" %} - opcode(0xF2, 0x0F, 0x10); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); + ins_encode %{ + __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp)); + %} ins_pipe(pipe_slow); %} @@ -11284,8 +10766,9 @@ ins_cost(95); // XXX format %{ "movss $dst, $src\t# MoveF2I_reg_stack" %} - opcode(0xF3, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, dst), OpcS, OpcT, reg_mem(src, dst)); + ins_encode %{ + __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -11295,8 +10778,9 @@ ins_cost(100); format %{ "movl $dst, $src\t# MoveI2F_reg_stack" %} - opcode(0x89); - ins_encode(REX_reg_mem(src, dst), OpcP, reg_mem(src, dst)); + ins_encode %{ + __ movl(Address(rsp, $dst$$disp), $src$$Register); + %} ins_pipe( ialu_mem_reg ); %} @@ -11306,8 +10790,9 @@ ins_cost(95); // XXX format %{ "movsd $dst, $src\t# MoveL2D_reg_stack" %} - opcode(0xF2, 0x0F, 0x11); - ins_encode(OpcP, REX_reg_mem(src, dst), OpcS, OpcT, reg_mem(src, dst)); + ins_encode %{ + __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister); + %} ins_pipe(pipe_slow); %} @@ -11317,8 +10802,9 @@ ins_cost(100); format %{ "movq $dst, $src\t# MoveL2D_reg_stack" %} - opcode(0x89); - ins_encode(REX_reg_mem_wide(src, dst), OpcP, reg_mem(src, dst)); + ins_encode %{ + __ movq(Address(rsp, $dst$$disp), $src$$Register); + %} ins_pipe(ialu_mem_reg); %} @@ -11327,7 +10813,9 @@ effect(DEF dst, USE src); ins_cost(85); format %{ "movd $dst,$src\t# MoveF2I" %} - ins_encode %{ __ movdl($dst$$Register, $src$$XMMRegister); %} + ins_encode %{ + __ movdl($dst$$Register, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11336,7 +10824,9 @@ effect(DEF dst, USE src); ins_cost(85); format %{ "movd $dst,$src\t# MoveD2L" %} - ins_encode %{ __ movdq($dst$$Register, $src$$XMMRegister); %} + ins_encode %{ + __ movdq($dst$$Register, $src$$XMMRegister); + %} ins_pipe( pipe_slow ); %} @@ -11346,7 +10836,9 @@ effect(DEF dst, USE src); ins_cost(300); format %{ "movd $dst,$src\t# MoveI2F" %} - ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); %} + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + %} ins_pipe( pipe_slow ); %} @@ -11355,7 +10847,9 @@ effect(DEF dst, USE src); ins_cost(300); format %{ "movd $dst,$src\t# MoveL2D" %} - ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register); %} + ins_encode %{ + __ movdq($dst$$XMMRegister, $src$$Register); + %} ins_pipe( pipe_slow ); %} @@ -11365,7 +10859,13 @@ format %{ "MOVDQA $dst,$src\n\t" "PUNPCKLBW $dst,$dst\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate8B" %} - ins_encode( pshufd_8x8(dst, src)); + ins_encode %{ + if ($dst$$reg != $src$$reg) { + __ movdqa($dst$$XMMRegister, $src$$XMMRegister); + } + __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( pipe_slow ); %} @@ -11375,7 +10875,11 @@ format %{ "MOVD $dst,$src\n\t" "PUNPCKLBW $dst,$dst\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate8B" %} - ins_encode( mov_i2x(dst, src), pshufd_8x8(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( pipe_slow ); %} @@ -11383,7 +10887,9 @@ instruct Repl8B_immI0(regD dst, immI0 zero) %{ match(Set dst (Replicate8B zero)); format %{ "PXOR $dst,$dst\t! replicate8B" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -11391,7 +10897,9 @@ instruct Repl4S_reg(regD dst, regD src) %{ match(Set dst (Replicate4S src)); format %{ "PSHUFLW $dst,$src,0x00\t! replicate4S" %} - ins_encode( pshufd_4x16(dst, src)); + ins_encode %{ + __ pshuflw($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11400,7 +10908,10 @@ match(Set dst (Replicate4S src)); format %{ "MOVD $dst,$src\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate4S" %} - ins_encode( mov_i2x(dst, src), pshufd_4x16(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11408,7 +10919,9 @@ instruct Repl4S_immI0(regD dst, immI0 zero) %{ match(Set dst (Replicate4S zero)); format %{ "PXOR $dst,$dst\t! replicate4S" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -11416,7 +10929,9 @@ instruct Repl4C_reg(regD dst, regD src) %{ match(Set dst (Replicate4C src)); format %{ "PSHUFLW $dst,$src,0x00\t! replicate4C" %} - ins_encode( pshufd_4x16(dst, src)); + ins_encode %{ + __ pshuflw($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11425,7 +10940,10 @@ match(Set dst (Replicate4C src)); format %{ "MOVD $dst,$src\n\t" "PSHUFLW $dst,$dst,0x00\t! replicate4C" %} - ins_encode( mov_i2x(dst, src), pshufd_4x16(dst, dst)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11433,7 +10951,9 @@ instruct Repl4C_immI0(regD dst, immI0 zero) %{ match(Set dst (Replicate4C zero)); format %{ "PXOR $dst,$dst\t! replicate4C" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -11441,7 +10961,9 @@ instruct Repl2I_reg(regD dst, regD src) %{ match(Set dst (Replicate2I src)); format %{ "PSHUFD $dst,$src,0x00\t! replicate2I" %} - ins_encode( pshufd(dst, src, 0x00)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11450,7 +10972,10 @@ match(Set dst (Replicate2I src)); format %{ "MOVD $dst,$src\n\t" "PSHUFD $dst,$dst,0x00\t! replicate2I" %} - ins_encode( mov_i2x(dst, src), pshufd(dst, dst, 0x00)); + ins_encode %{ + __ movdl($dst$$XMMRegister, $src$$Register); + __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); + %} ins_pipe( fpu_reg_reg ); %} @@ -11458,7 +10983,9 @@ instruct Repl2I_immI0(regD dst, immI0 zero) %{ match(Set dst (Replicate2I zero)); format %{ "PXOR $dst,$dst\t! replicate2I" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} @@ -11466,7 +10993,9 @@ instruct Repl2F_reg(regD dst, regD src) %{ match(Set dst (Replicate2F src)); format %{ "PSHUFD $dst,$src,0xe0\t! replicate2F" %} - ins_encode( pshufd(dst, src, 0xe0)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0xe0); + %} ins_pipe( fpu_reg_reg ); %} @@ -11474,7 +11003,9 @@ instruct Repl2F_regF(regD dst, regF src) %{ match(Set dst (Replicate2F src)); format %{ "PSHUFD $dst,$src,0xe0\t! replicate2F" %} - ins_encode( pshufd(dst, src, 0xe0)); + ins_encode %{ + __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0xe0); + %} ins_pipe( fpu_reg_reg ); %} @@ -11482,7 +11013,9 @@ instruct Repl2F_immF0(regD dst, immF0 zero) %{ match(Set dst (Replicate2F zero)); format %{ "PXOR $dst,$dst\t! replicate2F" %} - ins_encode( pxor(dst, dst)); + ins_encode %{ + __ pxor($dst$$XMMRegister, $dst$$XMMRegister); + %} ins_pipe( fpu_reg_reg ); %} diff -r d725f0affb1a -r 127b3692c168 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Dec 13 17:10:52 2011 -0800 +++ b/src/share/vm/runtime/globals.hpp Wed Dec 14 14:54:38 2011 -0800 @@ -525,6 +525,9 @@ product(intx, UseSSE, 99, \ "Highest supported SSE instructions set on x86/x64") \ \ + product(intx, UseAVX, 99, \ + "Highest supported AVX instructions set on x86/x64") \ + \ product(intx, UseVIS, 99, \ "Highest supported VIS instructions set on Sparc") \ \