diff --git a/.github/actions/upload-bundles/action.yml b/.github/actions/upload-bundles/action.yml index 4e974ae58ba6b..30f4ac03c1e0c 100644 --- a/.github/actions/upload-bundles/action.yml +++ b/.github/actions/upload-bundles/action.yml @@ -32,6 +32,9 @@ inputs: debug-suffix: description: 'File name suffix denoting debug level, possibly empty' required: false + bundle-suffix: + description: 'Bundle name suffix, possibly empty' + required: false runs: using: composite @@ -75,7 +78,7 @@ runs: - name: 'Upload bundles artifact' uses: actions/upload-artifact@v4 with: - name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }} + name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.bundle-suffix }} path: bundles retention-days: 1 if: steps.bundles.outputs.bundles-found == 'true' diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index b1d4278f8b469..101668b2bd520 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -61,6 +61,9 @@ on: make-arguments: required: false type: string + bundle-suffix: + required: false + type: string jobs: build-linux: @@ -71,10 +74,6 @@ jobs: fail-fast: false matrix: debug-level: ${{ fromJSON(inputs.debug-levels) }} - include: - - debug-level: debug - flags: --with-debug-level=fastdebug - suffix: -debug steps: - name: 'Checkout the JDK source' @@ -118,7 +117,7 @@ jobs: run: > bash configure --with-conf-name=${{ inputs.platform }} - ${{ matrix.flags }} + ${{ matrix.debug-level == 'debug' && '--with-debug-level=fastdebug' || '' }} --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} --with-boot-jdk=${{ steps.bootjdk.outputs.path }} --with-jtreg=${{ steps.jtreg.outputs.path }} @@ -133,17 +132,14 @@ jobs: - name: 'Build' id: build uses: ./.github/actions/do-build - env: - # Only build static-libs-bundles for release builds. - # For debug builds, building static-libs often exceeds disk space. - STATIC_LIBS: ${{ matrix.debug-level == 'release' && 'static-libs-bundles' }} with: - make-target: '${{ inputs.make-target }} ${STATIC_LIBS} ${{ inputs.make-arguments }}' + make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} - debug-suffix: '${{ matrix.suffix }}' + debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} - debug-suffix: '${{ matrix.suffix }}' + debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" + bundle-suffix: ${{ inputs.bundle-suffix }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3ea07501477f8..8dce1d214dc1c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -225,6 +225,43 @@ jobs: make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.prepare.outputs.linux-x64-variants == 'true' + build-linux-x64-static: + name: linux-x64-static + needs: prepare + uses: ./.github/workflows/build-linux.yml + with: + platform: linux-x64 + make-target: 'static-jdk-image' + # There are issues with fastdebug static build in GHA due to space limit. + # Only do release build for now. + debug-levels: '[ "release" ]' + gcc-major-version: '10' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + # It currently doesn't produce any bundles, but probably will do in + # the future. + bundle-suffix: "-static" + if: needs.prepare.outputs.linux-x64 == 'true' + + build-linux-x64-static-libs: + name: linux-x64-static-libs + needs: prepare + uses: ./.github/workflows/build-linux.yml + with: + platform: linux-x64 + make-target: 'static-libs-bundles' + # Only build static-libs-bundles for release builds. + # For debug builds, building static-libs often exceeds disk space. + debug-levels: '[ "release" ]' + gcc-major-version: '10' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + # Upload static libs bundles separately to avoid interference with normal linux-x64 bundle. + # This bundle is not used by testing jobs, but downstreams use it to check that + # dependent projects, e.g. libgraal, builds fine. + bundle-suffix: "-static-libs" + if: needs.prepare.outputs.linux-x64-variants == 'true' + build-linux-cross-compile: name: linux-cross-compile needs: prepare diff --git a/.gitignore b/.gitignore index b57addfccc9ab..2d82e0d943c11 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ NashornProfile.txt /.cache /.gdbinit /.lldbinit +**/core.[0-9]* diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index 9f26fc6636205..7e7f4de362982 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -207,23 +207,38 @@
All source files must have a globally unique basename. The build system depends on this uniqueness.
Keep the include lines within a section alphabetically sorted by
+their lowercase value. If an include must be out of order for
+correctness, suffix with it a comment such as
+// do not reorder
. Source code processing tools can also
+use this hint.
Put conditional inclusions (#if ...
) at the end of
+the section of HotSpot include lines. This also applies to
+macro-expanded includes of platform dependent files.
Put system includes in a section after the HotSpot include lines +with a blank line separating the two sections.
Do not put non-trivial function implementations in .hpp files. If the implementation depends on other .hpp files, put it in a .cpp or a .inline.hpp file.
.inline.hpp files should only be included in .cpp or .inline.hpp files.
All .inline.hpp files should include their corresponding .hpp -file as the first include line. Declarations needed by other files -should be put in the .hpp file, and not in the .inline.hpp file. This -rule exists to resolve problems with circular dependencies between -.inline.hpp files.
Do not include a .hpp file if the corresponding .inline.hpp file +is included.
Use include guards for .hpp and .inline.hpp files. The name of +the defined guard should be derived from the full search path of the +file relative to the hotspot source directory. The guard should be all +upper case with all paths separators and periods replaced by +underscores.
Some build configurations use precompiled headers to speed up the build times. The precompiled headers are included in the precompiled.hpp file. Note that precompiled.hpp is just a build time optimization, so don't rely on it to resolve include problems.
Keep the include lines alphabetically sorted.
Put conditional inclusions (#if ...
) at the end of
-the include list.
_S [ESP+dst] - %} - - // Push FPU's double to a stack-slot, and pop FPU-stack - enc_class Pop_Mem_Reg_DPR( stackSlotD dst, regDPR src ) %{ - int pop = 0x02; - if ($src$$reg != FPR1L_enc) { - emit_opcode( masm, 0xD9 ); // FLD ST(i-1) - emit_d8( masm, 0xC0-1+$src$$reg ); - pop = 0x03; - } - store_to_stackslot( masm, 0xDD, pop, $dst$$disp ); // FST
_D [ESP+dst] - %} - - // Push FPU's double to a FPU-stack-slot, and pop FPU-stack - enc_class Pop_Reg_Reg_DPR( regDPR dst, regFPR src ) %{ - int pop = 0xD0 - 1; // -1 since we skip FLD - if ($src$$reg != FPR1L_enc) { - emit_opcode( masm, 0xD9 ); // FLD ST(src-1) - emit_d8( masm, 0xC0-1+$src$$reg ); - pop = 0xD8; - } - emit_opcode( masm, 0xDD ); - emit_d8( masm, pop+$dst$$reg ); // FST
ST(i)
- %}
-
-
- enc_class Push_Reg_Mod_DPR( regDPR dst, regDPR src) %{
- // load dst in FPR0
- emit_opcode( masm, 0xD9 );
- emit_d8( masm, 0xC0-1+$dst$$reg );
- if ($src$$reg != FPR1L_enc) {
- // fincstp
- emit_opcode (masm, 0xD9);
- emit_opcode (masm, 0xF7);
- // swap src with FPR1:
- // FXCH FPR1 with src
- emit_opcode(masm, 0xD9);
- emit_d8(masm, 0xC8-1+$src$$reg );
- // fdecstp
- emit_opcode (masm, 0xD9);
- emit_opcode (masm, 0xF6);
- }
- %}
-
- enc_class Push_ResultD(regD dst) %{
- __ fstp_d(Address(rsp, 0));
- __ movdbl($dst$$XMMRegister, Address(rsp, 0));
- __ addptr(rsp, 8);
- %}
-
- enc_class Push_ResultF(regF dst, immI d8) %{
- __ fstp_s(Address(rsp, 0));
- __ movflt($dst$$XMMRegister, Address(rsp, 0));
- __ addptr(rsp, $d8$$constant);
- %}
-
- enc_class Push_SrcD(regD src) %{
- __ subptr(rsp, 8);
- __ movdbl(Address(rsp, 0), $src$$XMMRegister);
- __ fld_d(Address(rsp, 0));
- %}
-
- enc_class push_stack_temp_qword() %{
- __ subptr(rsp, 8);
- %}
-
- enc_class pop_stack_temp_qword() %{
- __ addptr(rsp, 8);
- %}
-
- enc_class push_xmm_to_fpr1(regD src) %{
- __ movdbl(Address(rsp, 0), $src$$XMMRegister);
- __ fld_d(Address(rsp, 0));
- %}
-
- enc_class fnstsw_sahf_skip_parity() %{
- // fnstsw ax
- emit_opcode( masm, 0xDF );
- emit_opcode( masm, 0xE0 );
- // sahf
- emit_opcode( masm, 0x9E );
- // jnp ::skip
- emit_opcode( masm, 0x7B );
- emit_opcode( masm, 0x05 );
- %}
-
- enc_class fpu_flags() %{
- // fnstsw_ax
- emit_opcode( masm, 0xDF);
- emit_opcode( masm, 0xE0);
- // test ax,0x0400
- emit_opcode( masm, 0x66 ); // operand-size prefix for 16-bit immediate
- emit_opcode( masm, 0xA9 );
- emit_d16 ( masm, 0x0400 );
- // // // This sequence works, but stalls for 12-16 cycles on PPro
- // // test rax,0x0400
- // emit_opcode( masm, 0xA9 );
- // emit_d32 ( masm, 0x00000400 );
- //
- // jz exit (no unordered comparison)
- emit_opcode( masm, 0x74 );
- emit_d8 ( masm, 0x02 );
- // mov ah,1 - treat as LT case (set carry flag)
- emit_opcode( masm, 0xB4 );
- emit_d8 ( masm, 0x01 );
- // sahf
- emit_opcode( masm, 0x9E);
- %}
-
- enc_class cmpF_P6_fixup() %{
- // Fixup the integer flags in case comparison involved a NaN
- //
- // JNP exit (no unordered comparison, P-flag is set by NaN)
- emit_opcode( masm, 0x7B );
- emit_d8 ( masm, 0x03 );
- // MOV AH,1 - treat as LT case (set carry flag)
- emit_opcode( masm, 0xB4 );
- emit_d8 ( masm, 0x01 );
- // SAHF
- emit_opcode( masm, 0x9E);
- // NOP // target for branch to avoid branch to branch
- emit_opcode( masm, 0x90);
- %}
-
-// fnstsw_ax();
-// sahf();
-// movl(dst, nan_result);
-// jcc(Assembler::parity, exit);
-// movl(dst, less_result);
-// jcc(Assembler::below, exit);
-// movl(dst, equal_result);
-// jcc(Assembler::equal, exit);
-// movl(dst, greater_result);
-
-// less_result = 1;
-// greater_result = -1;
-// equal_result = 0;
-// nan_result = -1;
-
- enc_class CmpF_Result(rRegI dst) %{
- // fnstsw_ax();
- emit_opcode( masm, 0xDF);
- emit_opcode( masm, 0xE0);
- // sahf
- emit_opcode( masm, 0x9E);
- // movl(dst, nan_result);
- emit_opcode( masm, 0xB8 + $dst$$reg);
- emit_d32( masm, -1 );
- // jcc(Assembler::parity, exit);
- emit_opcode( masm, 0x7A );
- emit_d8 ( masm, 0x13 );
- // movl(dst, less_result);
- emit_opcode( masm, 0xB8 + $dst$$reg);
- emit_d32( masm, -1 );
- // jcc(Assembler::below, exit);
- emit_opcode( masm, 0x72 );
- emit_d8 ( masm, 0x0C );
- // movl(dst, equal_result);
- emit_opcode( masm, 0xB8 + $dst$$reg);
- emit_d32( masm, 0 );
- // jcc(Assembler::equal, exit);
- emit_opcode( masm, 0x74 );
- emit_d8 ( masm, 0x05 );
- // movl(dst, greater_result);
- emit_opcode( masm, 0xB8 + $dst$$reg);
- emit_d32( masm, 1 );
- %}
-
-
- // Compare the longs and set flags
- // BROKEN! Do Not use as-is
- enc_class cmpl_test( eRegL src1, eRegL src2 ) %{
- // CMP $src1.hi,$src2.hi
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, HIGH_FROM_LOW_ENC($src1$$reg), HIGH_FROM_LOW_ENC($src2$$reg) );
- // JNE,s done
- emit_opcode(masm,0x75);
- emit_d8(masm, 2 );
- // CMP $src1.lo,$src2.lo
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, $src1$$reg, $src2$$reg );
-// done:
- %}
-
- enc_class convert_int_long( regL dst, rRegI src ) %{
- // mov $dst.lo,$src
- int dst_encoding = $dst$$reg;
- int src_encoding = $src$$reg;
- encode_Copy( masm, dst_encoding , src_encoding );
- // mov $dst.hi,$src
- encode_Copy( masm, HIGH_FROM_LOW_ENC(dst_encoding), src_encoding );
- // sar $dst.hi,31
- emit_opcode( masm, 0xC1 );
- emit_rm(masm, 0x3, 7, HIGH_FROM_LOW_ENC(dst_encoding) );
- emit_d8(masm, 0x1F );
- %}
-
- enc_class convert_long_double( eRegL src ) %{
- // push $src.hi
- emit_opcode(masm, 0x50+HIGH_FROM_LOW_ENC($src$$reg));
- // push $src.lo
- emit_opcode(masm, 0x50+$src$$reg );
- // fild 64-bits at [SP]
- emit_opcode(masm,0xdf);
- emit_d8(masm, 0x6C);
- emit_d8(masm, 0x24);
- emit_d8(masm, 0x00);
- // pop stack
- emit_opcode(masm, 0x83); // add SP, #8
- emit_rm(masm, 0x3, 0x00, ESP_enc);
- emit_d8(masm, 0x8);
- %}
-
- enc_class multiply_con_and_shift_high( eDXRegI dst, nadxRegI src1, eADXRegL_low_only src2, immI_32_63 cnt, eFlagsReg cr ) %{
- // IMUL EDX:EAX,$src1
- emit_opcode( masm, 0xF7 );
- emit_rm( masm, 0x3, 0x5, $src1$$reg );
- // SAR EDX,$cnt-32
- int shift_count = ((int)$cnt$$constant) - 32;
- if (shift_count > 0) {
- emit_opcode(masm, 0xC1);
- emit_rm(masm, 0x3, 7, $dst$$reg );
- emit_d8(masm, shift_count);
- }
- %}
-
- // this version doesn't have add sp, 8
- enc_class convert_long_double2( eRegL src ) %{
- // push $src.hi
- emit_opcode(masm, 0x50+HIGH_FROM_LOW_ENC($src$$reg));
- // push $src.lo
- emit_opcode(masm, 0x50+$src$$reg );
- // fild 64-bits at [SP]
- emit_opcode(masm,0xdf);
- emit_d8(masm, 0x6C);
- emit_d8(masm, 0x24);
- emit_d8(masm, 0x00);
- %}
-
- enc_class long_int_multiply( eADXRegL dst, nadxRegI src) %{
- // Basic idea: long = (long)int * (long)int
- // IMUL EDX:EAX, src
- emit_opcode( masm, 0xF7 );
- emit_rm( masm, 0x3, 0x5, $src$$reg);
- %}
-
- enc_class long_uint_multiply( eADXRegL dst, nadxRegI src) %{
- // Basic Idea: long = (int & 0xffffffffL) * (int & 0xffffffffL)
- // MUL EDX:EAX, src
- emit_opcode( masm, 0xF7 );
- emit_rm( masm, 0x3, 0x4, $src$$reg);
- %}
-
- enc_class long_multiply( eADXRegL dst, eRegL src, rRegI tmp ) %{
- // Basic idea: lo(result) = lo(x_lo * y_lo)
- // hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi)
- // MOV $tmp,$src.lo
- encode_Copy( masm, $tmp$$reg, $src$$reg );
- // IMUL $tmp,EDX
- emit_opcode( masm, 0x0F );
- emit_opcode( masm, 0xAF );
- emit_rm( masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($dst$$reg) );
- // MOV EDX,$src.hi
- encode_Copy( masm, HIGH_FROM_LOW_ENC($dst$$reg), HIGH_FROM_LOW_ENC($src$$reg) );
- // IMUL EDX,EAX
- emit_opcode( masm, 0x0F );
- emit_opcode( masm, 0xAF );
- emit_rm( masm, 0x3, HIGH_FROM_LOW_ENC($dst$$reg), $dst$$reg );
- // ADD $tmp,EDX
- emit_opcode( masm, 0x03 );
- emit_rm( masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($dst$$reg) );
- // MUL EDX:EAX,$src.lo
- emit_opcode( masm, 0xF7 );
- emit_rm( masm, 0x3, 0x4, $src$$reg );
- // ADD EDX,ESI
- emit_opcode( masm, 0x03 );
- emit_rm( masm, 0x3, HIGH_FROM_LOW_ENC($dst$$reg), $tmp$$reg );
- %}
-
- enc_class long_multiply_con( eADXRegL dst, immL_127 src, rRegI tmp ) %{
- // Basic idea: lo(result) = lo(src * y_lo)
- // hi(result) = hi(src * y_lo) + lo(src * y_hi)
- // IMUL $tmp,EDX,$src
- emit_opcode( masm, 0x6B );
- emit_rm( masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($dst$$reg) );
- emit_d8( masm, (int)$src$$constant );
- // MOV EDX,$src
- emit_opcode(masm, 0xB8 + EDX_enc);
- emit_d32( masm, (int)$src$$constant );
- // MUL EDX:EAX,EDX
- emit_opcode( masm, 0xF7 );
- emit_rm( masm, 0x3, 0x4, EDX_enc );
- // ADD EDX,ESI
- emit_opcode( masm, 0x03 );
- emit_rm( masm, 0x3, EDX_enc, $tmp$$reg );
- %}
-
- enc_class long_div( eRegL src1, eRegL src2 ) %{
- // PUSH src1.hi
- emit_opcode(masm, HIGH_FROM_LOW_ENC(0x50+$src1$$reg) );
- // PUSH src1.lo
- emit_opcode(masm, 0x50+$src1$$reg );
- // PUSH src2.hi
- emit_opcode(masm, HIGH_FROM_LOW_ENC(0x50+$src2$$reg) );
- // PUSH src2.lo
- emit_opcode(masm, 0x50+$src2$$reg );
- // CALL directly to the runtime
- __ set_inst_mark();
- emit_opcode(masm,0xE8); // Call into runtime
- emit_d32_reloc(masm, (CAST_FROM_FN_PTR(address, SharedRuntime::ldiv) - __ pc()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 );
- __ clear_inst_mark();
- __ post_call_nop();
- // Restore stack
- emit_opcode(masm, 0x83); // add SP, #framesize
- emit_rm(masm, 0x3, 0x00, ESP_enc);
- emit_d8(masm, 4*4);
- %}
-
- enc_class long_mod( eRegL src1, eRegL src2 ) %{
- // PUSH src1.hi
- emit_opcode(masm, HIGH_FROM_LOW_ENC(0x50+$src1$$reg) );
- // PUSH src1.lo
- emit_opcode(masm, 0x50+$src1$$reg );
- // PUSH src2.hi
- emit_opcode(masm, HIGH_FROM_LOW_ENC(0x50+$src2$$reg) );
- // PUSH src2.lo
- emit_opcode(masm, 0x50+$src2$$reg );
- // CALL directly to the runtime
- __ set_inst_mark();
- emit_opcode(masm,0xE8); // Call into runtime
- emit_d32_reloc(masm, (CAST_FROM_FN_PTR(address, SharedRuntime::lrem ) - __ pc()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 );
- __ clear_inst_mark();
- __ post_call_nop();
- // Restore stack
- emit_opcode(masm, 0x83); // add SP, #framesize
- emit_rm(masm, 0x3, 0x00, ESP_enc);
- emit_d8(masm, 4*4);
- %}
-
- enc_class long_cmp_flags0( eRegL src, rRegI tmp ) %{
- // MOV $tmp,$src.lo
- emit_opcode(masm, 0x8B);
- emit_rm(masm, 0x3, $tmp$$reg, $src$$reg);
- // OR $tmp,$src.hi
- emit_opcode(masm, 0x0B);
- emit_rm(masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($src$$reg));
- %}
-
- enc_class long_cmp_flags1( eRegL src1, eRegL src2 ) %{
- // CMP $src1.lo,$src2.lo
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, $src1$$reg, $src2$$reg );
- // JNE,s skip
- emit_cc(masm, 0x70, 0x5);
- emit_d8(masm,2);
- // CMP $src1.hi,$src2.hi
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, HIGH_FROM_LOW_ENC($src1$$reg), HIGH_FROM_LOW_ENC($src2$$reg) );
- %}
-
- enc_class long_cmp_flags2( eRegL src1, eRegL src2, rRegI tmp ) %{
- // CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, $src1$$reg, $src2$$reg );
- // MOV $tmp,$src1.hi
- emit_opcode( masm, 0x8B );
- emit_rm(masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($src1$$reg) );
- // SBB $tmp,$src2.hi\t! Compute flags for long compare
- emit_opcode( masm, 0x1B );
- emit_rm(masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($src2$$reg) );
- %}
-
- enc_class long_cmp_flags3( eRegL src, rRegI tmp ) %{
- // XOR $tmp,$tmp
- emit_opcode(masm,0x33); // XOR
- emit_rm(masm,0x3, $tmp$$reg, $tmp$$reg);
- // CMP $tmp,$src.lo
- emit_opcode( masm, 0x3B );
- emit_rm(masm, 0x3, $tmp$$reg, $src$$reg );
- // SBB $tmp,$src.hi
- emit_opcode( masm, 0x1B );
- emit_rm(masm, 0x3, $tmp$$reg, HIGH_FROM_LOW_ENC($src$$reg) );
- %}
-
- // Sniff, sniff... smells like Gnu Superoptimizer
- enc_class neg_long( eRegL dst ) %{
- emit_opcode(masm,0xF7); // NEG hi
- emit_rm (masm,0x3, 0x3, HIGH_FROM_LOW_ENC($dst$$reg));
- emit_opcode(masm,0xF7); // NEG lo
- emit_rm (masm,0x3, 0x3, $dst$$reg );
- emit_opcode(masm,0x83); // SBB hi,0
- emit_rm (masm,0x3, 0x3, HIGH_FROM_LOW_ENC($dst$$reg));
- emit_d8 (masm,0 );
- %}
-
- enc_class enc_pop_rdx() %{
- emit_opcode(masm,0x5A);
- %}
-
- enc_class enc_rethrow() %{
- __ set_inst_mark();
- emit_opcode(masm, 0xE9); // jmp entry
- emit_d32_reloc(masm, (int)OptoRuntime::rethrow_stub() - ((int)__ pc())-4,
- runtime_call_Relocation::spec(), RELOC_IMM32 );
- __ clear_inst_mark();
- __ post_call_nop();
- %}
-
-
- // Convert a double to an int. Java semantics require we do complex
- // manglelations in the corner cases. So we set the rounding mode to
- // 'zero', store the darned double down as an int, and reset the
- // rounding mode to 'nearest'. The hardware throws an exception which
- // patches up the correct value directly to the stack.
- enc_class DPR2I_encoding( regDPR src ) %{
- // Flip to round-to-zero mode. We attempted to allow invalid-op
- // exceptions here, so that a NAN or other corner-case value will
- // thrown an exception (but normal values get converted at full speed).
- // However, I2C adapters and other float-stack manglers leave pending
- // invalid-op exceptions hanging. We would have to clear them before
- // enabling them and that is more expensive than just testing for the
- // invalid value Intel stores down in the corner cases.
- emit_opcode(masm,0xD9); // FLDCW trunc
- emit_opcode(masm,0x2D);
- emit_d32(masm,(int)StubRoutines::x86::addr_fpu_cntrl_wrd_trunc());
- // Allocate a word
- emit_opcode(masm,0x83); // SUB ESP,4
- emit_opcode(masm,0xEC);
- emit_d8(masm,0x04);
- // Encoding assumes a double has been pushed into FPR0.
- // Store down the double as an int, popping the FPU stack
- emit_opcode(masm,0xDB); // FISTP [ESP]
- emit_opcode(masm,0x1C);
- emit_d8(masm,0x24);
- // Restore the rounding mode; mask the exception
- emit_opcode(masm,0xD9); // FLDCW std/24-bit mode
- emit_opcode(masm,0x2D);
- emit_d32( masm, Compile::current()->in_24_bit_fp_mode()
- ? (int)StubRoutines::x86::addr_fpu_cntrl_wrd_24()
- : (int)StubRoutines::x86::addr_fpu_cntrl_wrd_std());
-
- // Load the converted int; adjust CPU stack
- emit_opcode(masm,0x58); // POP EAX
- emit_opcode(masm,0x3D); // CMP EAX,imm
- emit_d32 (masm,0x80000000); // 0x80000000
- emit_opcode(masm,0x75); // JNE around_slow_call
- emit_d8 (masm,0x07); // Size of slow_call
- // Push src onto stack slow-path
- emit_opcode(masm,0xD9 ); // FLD ST(i)
- emit_d8 (masm,0xC0-1+$src$$reg );
- // CALL directly to the runtime
- __ set_inst_mark();
- emit_opcode(masm,0xE8); // Call into runtime
- emit_d32_reloc(masm, (StubRoutines::x86::d2i_wrapper() - __ pc()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 );
- __ clear_inst_mark();
- __ post_call_nop();
- // Carry on here...
- %}
-
- enc_class DPR2L_encoding( regDPR src ) %{
- emit_opcode(masm,0xD9); // FLDCW trunc
- emit_opcode(masm,0x2D);
- emit_d32(masm,(int)StubRoutines::x86::addr_fpu_cntrl_wrd_trunc());
- // Allocate a word
- emit_opcode(masm,0x83); // SUB ESP,8
- emit_opcode(masm,0xEC);
- emit_d8(masm,0x08);
- // Encoding assumes a double has been pushed into FPR0.
- // Store down the double as a long, popping the FPU stack
- emit_opcode(masm,0xDF); // FISTP [ESP]
- emit_opcode(masm,0x3C);
- emit_d8(masm,0x24);
- // Restore the rounding mode; mask the exception
- emit_opcode(masm,0xD9); // FLDCW std/24-bit mode
- emit_opcode(masm,0x2D);
- emit_d32( masm, Compile::current()->in_24_bit_fp_mode()
- ? (int)StubRoutines::x86::addr_fpu_cntrl_wrd_24()
- : (int)StubRoutines::x86::addr_fpu_cntrl_wrd_std());
-
- // Load the converted int; adjust CPU stack
- emit_opcode(masm,0x58); // POP EAX
- emit_opcode(masm,0x5A); // POP EDX
- emit_opcode(masm,0x81); // CMP EDX,imm
- emit_d8 (masm,0xFA); // rdx
- emit_d32 (masm,0x80000000); // 0x80000000
- emit_opcode(masm,0x75); // JNE around_slow_call
- emit_d8 (masm,0x07+4); // Size of slow_call
- emit_opcode(masm,0x85); // TEST EAX,EAX
- emit_opcode(masm,0xC0); // 2/rax,/rax,
- emit_opcode(masm,0x75); // JNE around_slow_call
- emit_d8 (masm,0x07); // Size of slow_call
- // Push src onto stack slow-path
- emit_opcode(masm,0xD9 ); // FLD ST(i)
- emit_d8 (masm,0xC0-1+$src$$reg );
- // CALL directly to the runtime
- __ set_inst_mark();
- emit_opcode(masm,0xE8); // Call into runtime
- emit_d32_reloc(masm, (StubRoutines::x86::d2l_wrapper() - __ pc()) - 4, runtime_call_Relocation::spec(), RELOC_IMM32 );
- __ clear_inst_mark();
- __ post_call_nop();
- // Carry on here...
- %}
-
- enc_class FMul_ST_reg( eRegFPR src1 ) %{
- // Operand was loaded from memory into fp ST (stack top)
- // FMUL ST,$src /* D8 C8+i */
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xC8 + $src1$$reg);
- %}
-
- enc_class FAdd_ST_reg( eRegFPR src2 ) %{
- // FADDP ST,src2 /* D8 C0+i */
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xC0 + $src2$$reg);
- //could use FADDP src2,fpST /* DE C0+i */
- %}
-
- enc_class FAddP_reg_ST( eRegFPR src2 ) %{
- // FADDP src2,ST /* DE C0+i */
- emit_opcode(masm, 0xDE);
- emit_opcode(masm, 0xC0 + $src2$$reg);
- %}
-
- enc_class subFPR_divFPR_encode( eRegFPR src1, eRegFPR src2) %{
- // Operand has been loaded into fp ST (stack top)
- // FSUB ST,$src1
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xE0 + $src1$$reg);
-
- // FDIV
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xF0 + $src2$$reg);
- %}
-
- enc_class MulFAddF (eRegFPR src1, eRegFPR src2) %{
- // Operand was loaded from memory into fp ST (stack top)
- // FADD ST,$src /* D8 C0+i */
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xC0 + $src1$$reg);
-
- // FMUL ST,src2 /* D8 C*+i */
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xC8 + $src2$$reg);
- %}
-
-
- enc_class MulFAddFreverse (eRegFPR src1, eRegFPR src2) %{
- // Operand was loaded from memory into fp ST (stack top)
- // FADD ST,$src /* D8 C0+i */
- emit_opcode(masm, 0xD8);
- emit_opcode(masm, 0xC0 + $src1$$reg);
-
- // FMULP src2,ST /* DE C8+i */
- emit_opcode(masm, 0xDE);
- emit_opcode(masm, 0xC8 + $src2$$reg);
- %}
-
- // Atomically load the volatile long
- enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{
- emit_opcode(masm,0xDF);
- int rm_byte_opcode = 0x05;
- int base = $mem$$base;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int displace = $mem$$disp;
- relocInfo::relocType disp_reloc = $mem->disp_reloc(); // disp-as-oop when working with static globals
- encode_RegMem(masm, rm_byte_opcode, base, index, scale, displace, disp_reloc);
- store_to_stackslot( masm, 0x0DF, 0x07, $dst$$disp );
- %}
-
- // 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)
- // so the memory operand is used twice in the encoding.
- enc_class enc_storeL_volatile( memory mem, stackSlotL src ) %{
- store_to_stackslot( masm, 0x0DF, 0x05, $src$$disp );
- __ set_inst_mark(); // Mark start of FIST in case $mem has an oop
- emit_opcode(masm,0xDF);
- int rm_byte_opcode = 0x07;
- int base = $mem$$base;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int displace = $mem$$disp;
- relocInfo::relocType disp_reloc = $mem->disp_reloc(); // disp-as-oop when working with static globals
- encode_RegMem(masm, rm_byte_opcode, base, index, scale, displace, disp_reloc);
- __ clear_inst_mark();
- %}
-
-%}
-
-
-//----------FRAME--------------------------------------------------------------
-// Definition of frame structure and management information.
-//
-// S T A C K L A Y O U T Allocators stack-slot number
-// | (to get allocators register number
-// G Owned by | | v add OptoReg::stack0())
-// r CALLER | |
-// o | +--------+ pad to even-align allocators stack-slot
-// w V | pad0 | numbers; owned by CALLER
-// t -----------+--------+----> Matcher::_in_arg_limit, unaligned
-// h ^ | in | 5
-// | | args | 4 Holes in incoming args owned by SELF
-// | | | | 3
-// | | +--------+
-// V | | old out| Empty on Intel, window on Sparc
-// | old |preserve| Must be even aligned.
-// | SP-+--------+----> Matcher::_old_SP, even aligned
-// | | in | 3 area for Intel ret address
-// Owned by |preserve| Empty on Sparc.
-// SELF +--------+
-// | | pad2 | 2 pad to align old SP
-// | +--------+ 1
-// | | locks | 0
-// | +--------+----> OptoReg::stack0(), even aligned
-// | | pad1 | 11 pad to align new SP
-// | +--------+
-// | | | 10
-// | | spills | 9 spills
-// V | | 8 (pad0 slot for callee)
-// -----------+--------+----> Matcher::_out_arg_limit, unaligned
-// ^ | out | 7
-// | | args | 6 Holes in outgoing args owned by CALLEE
-// Owned by +--------+
-// CALLEE | new out| 6 Empty on Intel, window on Sparc
-// | new |preserve| Must be even-aligned.
-// | SP-+--------+----> Matcher::_new_SP, even aligned
-// | | |
-//
-// Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
-// known from SELF's arguments and the Java calling convention.
-// Region 6-7 is determined per call site.
-// Note 2: If the calling convention leaves holes in the incoming argument
-// area, those holes are owned by SELF. Holes in the outgoing area
-// are owned by the CALLEE. Holes should not be necessary in the
-// incoming area, as the Java calling convention is completely under
-// the control of the AD file. Doubles can be sorted and packed to
-// avoid holes. Holes in the outgoing arguments may be necessary for
-// varargs C calling conventions.
-// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
-// even aligned with pad0 as needed.
-// Region 6 is even aligned. Region 6-7 is NOT even aligned;
-// region 6-11 is even aligned; it may be padded out more so that
-// the region from SP to FP meets the minimum stack alignment.
-
-frame %{
- // These three registers define part of the calling convention
- // between compiled code and the interpreter.
- inline_cache_reg(EAX); // Inline Cache Register
-
- // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
- cisc_spilling_operand_name(indOffset32);
-
- // Number of stack slots consumed by locking an object
- sync_stack_slots(1);
-
- // Compiled code's Frame Pointer
- frame_pointer(ESP);
- // Interpreter stores its frame pointer in a register which is
- // stored to the stack by I2CAdaptors.
- // I2CAdaptors convert from interpreted java to compiled java.
- interpreter_frame_pointer(EBP);
-
- // Stack alignment requirement
- // Alignment size in bytes (128-bit -> 16 bytes)
- stack_alignment(StackAlignmentInBytes);
-
- // Number of outgoing stack slots killed above the out_preserve_stack_slots
- // for calls to C. Supports the var-args backing area for register parms.
- varargs_C_out_slots_killed(0);
-
- // The after-PROLOG location of the return address. Location of
- // return address specifies a type (REG or STACK) and a number
- // representing the register number (i.e. - use a register name) or
- // stack slot.
- // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
- // Otherwise, it is above the locks and verification slot and alignment word
- return_addr(STACK - 1 +
- align_up((Compile::current()->in_preserve_stack_slots() +
- Compile::current()->fixed_slots()),
- stack_alignment_in_slots()));
-
- // Location of C & interpreter return values
- c_return_value %{
- assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
- static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
- static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
-
- // in SSE2+ mode we want to keep the FPU stack clean so pretend
- // that C functions return float and double results in XMM0.
- if( ideal_reg == Op_RegD && UseSSE>=2 )
- return OptoRegPair(XMM0b_num,XMM0_num);
- if( ideal_reg == Op_RegF && UseSSE>=2 )
- return OptoRegPair(OptoReg::Bad,XMM0_num);
-
- return OptoRegPair(hi[ideal_reg],lo[ideal_reg]);
- %}
-
- // Location of return values
- return_value %{
- assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
- static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
- static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
- if( ideal_reg == Op_RegD && UseSSE>=2 )
- return OptoRegPair(XMM0b_num,XMM0_num);
- if( ideal_reg == Op_RegF && UseSSE>=1 )
- return OptoRegPair(OptoReg::Bad,XMM0_num);
- return OptoRegPair(hi[ideal_reg],lo[ideal_reg]);
- %}
-
-%}
-
-//----------ATTRIBUTES---------------------------------------------------------
-//----------Operand Attributes-------------------------------------------------
-op_attrib op_cost(0); // Required cost attribute
-
-//----------Instruction Attributes---------------------------------------------
-ins_attrib ins_cost(100); // Required cost attribute
-ins_attrib ins_size(8); // Required size attribute (in bits)
-ins_attrib ins_short_branch(0); // Required flag: is this instruction a
- // non-matching short branch variant of some
- // long branch?
-ins_attrib ins_alignment(1); // Required alignment attribute (must be a power of 2)
- // specifies the alignment that some part of the instruction (not
- // necessarily the start) requires. If > 1, a compute_padding()
- // function must be provided for the instruction
-
-//----------OPERANDS-----------------------------------------------------------
-// Operand definitions must precede instruction definitions for correct parsing
-// in the ADLC because operands constitute user defined types which are used in
-// instruction definitions.
-
-//----------Simple Operands----------------------------------------------------
-// Immediate Operands
-// Integer Immediate
-operand immI() %{
- match(ConI);
-
- op_cost(10);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for test vs zero
-operand immI_0() %{
- predicate(n->get_int() == 0);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for increment
-operand immI_1() %{
- predicate(n->get_int() == 1);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for decrement
-operand immI_M1() %{
- predicate(n->get_int() == -1);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Valid scale values for addressing modes
-operand immI2() %{
- predicate(0 <= n->get_int() && (n->get_int() <= 3));
- match(ConI);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI8() %{
- predicate((-128 <= n->get_int()) && (n->get_int() <= 127));
- match(ConI);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immU8() %{
- predicate((0 <= n->get_int()) && (n->get_int() <= 255));
- match(ConI);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI16() %{
- predicate((-32768 <= n->get_int()) && (n->get_int() <= 32767));
- match(ConI);
-
- op_cost(10);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Int Immediate non-negative
-operand immU31()
-%{
- predicate(n->get_int() >= 0);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for long shifts
-operand immI_32() %{
- predicate( n->get_int() == 32 );
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_1_31() %{
- predicate( n->get_int() >= 1 && n->get_int() <= 31 );
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_32_63() %{
- predicate( n->get_int() >= 32 && n->get_int() <= 63 );
- match(ConI);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_2() %{
- predicate( n->get_int() == 2 );
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_3() %{
- predicate( n->get_int() == 3 );
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_4()
-%{
- predicate(n->get_int() == 4);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_8()
-%{
- predicate(n->get_int() == 8);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Pointer Immediate
-operand immP() %{
- match(ConP);
-
- op_cost(10);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Null Pointer Immediate
-operand immP0() %{
- predicate( n->get_ptr() == 0 );
- match(ConP);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long Immediate
-operand immL() %{
- match(ConL);
-
- op_cost(20);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long Immediate zero
-operand immL0() %{
- predicate( n->get_long() == 0L );
- match(ConL);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long Immediate zero
-operand immL_M1() %{
- predicate( n->get_long() == -1L );
- match(ConL);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long immediate from 0 to 127.
-// Used for a shorter form of long mul by 10.
-operand immL_127() %{
- predicate((0 <= n->get_long()) && (n->get_long() <= 127));
- match(ConL);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long Immediate: low 32-bit mask
-operand immL_32bits() %{
- predicate(n->get_long() == 0xFFFFFFFFL);
- match(ConL);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Long Immediate: low 32-bit mask
-operand immL32() %{
- predicate(n->get_long() == (int)(n->get_long()));
- match(ConL);
- op_cost(20);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-//Double Immediate zero
-operand immDPR0() %{
- // Do additional (and counter-intuitive) test against NaN to work around VC++
- // bug that generates code such that NaNs compare equal to 0.0
- predicate( UseSSE<=1 && n->getd() == 0.0 && !g_isnan(n->getd()) );
- match(ConD);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Double Immediate one
-operand immDPR1() %{
- predicate( UseSSE<=1 && n->getd() == 1.0 );
- match(ConD);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Double Immediate
-operand immDPR() %{
- predicate(UseSSE<=1);
- match(ConD);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immD() %{
- predicate(UseSSE>=2);
- match(ConD);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Double Immediate zero
-operand immD0() %{
- // Do additional (and counter-intuitive) test against NaN to work around VC++
- // bug that generates code such that NaNs compare equal to 0.0 AND do not
- // compare equal to -0.0.
- predicate( UseSSE>=2 && jlong_cast(n->getd()) == 0 );
- match(ConD);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Float Immediate zero
-operand immFPR0() %{
- predicate(UseSSE == 0 && n->getf() == 0.0F);
- match(ConF);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Float Immediate one
-operand immFPR1() %{
- predicate(UseSSE == 0 && n->getf() == 1.0F);
- match(ConF);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Float Immediate
-operand immFPR() %{
- predicate( UseSSE == 0 );
- match(ConF);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Float Immediate
-operand immF() %{
- predicate(UseSSE >= 1);
- match(ConF);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Float Immediate zero. Zero and not -0.0
-operand immF0() %{
- predicate( UseSSE >= 1 && jint_cast(n->getf()) == 0 );
- match(ConF);
-
- op_cost(5);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Immediates for special shifts (sign extend)
-
-// Constants for increment
-operand immI_16() %{
- predicate( n->get_int() == 16 );
- match(ConI);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand immI_24() %{
- predicate( n->get_int() == 24 );
- match(ConI);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for byte-wide masking
-operand immI_255() %{
- predicate( n->get_int() == 255 );
- match(ConI);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Constant for short-wide masking
-operand immI_65535() %{
- predicate(n->get_int() == 65535);
- match(ConI);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-operand kReg()
-%{
- constraint(ALLOC_IN_RC(vectmask_reg));
- match(RegVectMask);
- format %{%}
- interface(REG_INTER);
-%}
-
-// Register Operands
-// Integer Register
-operand rRegI() %{
- constraint(ALLOC_IN_RC(int_reg));
- match(RegI);
- match(xRegI);
- match(eAXRegI);
- match(eBXRegI);
- match(eCXRegI);
- match(eDXRegI);
- match(eDIRegI);
- match(eSIRegI);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Subset of Integer Register
-operand xRegI(rRegI reg) %{
- constraint(ALLOC_IN_RC(int_x_reg));
- match(reg);
- match(eAXRegI);
- match(eBXRegI);
- match(eCXRegI);
- match(eDXRegI);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Special Registers
-operand eAXRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(eax_reg));
- match(reg);
- match(rRegI);
-
- format %{ "EAX" %}
- interface(REG_INTER);
-%}
-
-// Special Registers
-operand eBXRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(ebx_reg));
- match(reg);
- match(rRegI);
-
- format %{ "EBX" %}
- interface(REG_INTER);
-%}
-
-operand eCXRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(ecx_reg));
- match(reg);
- match(rRegI);
-
- format %{ "ECX" %}
- interface(REG_INTER);
-%}
-
-operand eDXRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(edx_reg));
- match(reg);
- match(rRegI);
-
- format %{ "EDX" %}
- interface(REG_INTER);
-%}
-
-operand eDIRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(edi_reg));
- match(reg);
- match(rRegI);
-
- format %{ "EDI" %}
- interface(REG_INTER);
-%}
-
-operand nadxRegI() %{
- constraint(ALLOC_IN_RC(nadx_reg));
- match(RegI);
- match(eBXRegI);
- match(eCXRegI);
- match(eSIRegI);
- match(eDIRegI);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand ncxRegI() %{
- constraint(ALLOC_IN_RC(ncx_reg));
- match(RegI);
- match(eAXRegI);
- match(eDXRegI);
- match(eSIRegI);
- match(eDIRegI);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// // This operand was used by cmpFastUnlock, but conflicted with 'object' reg
-// //
-operand eSIRegI(xRegI reg) %{
- constraint(ALLOC_IN_RC(esi_reg));
- match(reg);
- match(rRegI);
-
- format %{ "ESI" %}
- interface(REG_INTER);
-%}
-
-// Pointer Register
-operand anyRegP() %{
- constraint(ALLOC_IN_RC(any_reg));
- match(RegP);
- match(eAXRegP);
- match(eBXRegP);
- match(eCXRegP);
- match(eDIRegP);
- match(eRegP);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand eRegP() %{
- constraint(ALLOC_IN_RC(int_reg));
- match(RegP);
- match(eAXRegP);
- match(eBXRegP);
- match(eCXRegP);
- match(eDIRegP);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand rRegP() %{
- constraint(ALLOC_IN_RC(int_reg));
- match(RegP);
- match(eAXRegP);
- match(eBXRegP);
- match(eCXRegP);
- match(eDIRegP);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// On windows95, EBP is not safe to use for implicit null tests.
-operand eRegP_no_EBP() %{
- constraint(ALLOC_IN_RC(int_reg_no_ebp));
- match(RegP);
- match(eAXRegP);
- match(eBXRegP);
- match(eCXRegP);
- match(eDIRegP);
-
- op_cost(100);
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand pRegP() %{
- constraint(ALLOC_IN_RC(p_reg));
- match(RegP);
- match(eBXRegP);
- match(eDXRegP);
- match(eSIRegP);
- match(eDIRegP);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Special Registers
-// Return a pointer value
-operand eAXRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(eax_reg));
- match(reg);
- format %{ "EAX" %}
- interface(REG_INTER);
-%}
-
-// Used in AtomicAdd
-operand eBXRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(ebx_reg));
- match(reg);
- format %{ "EBX" %}
- interface(REG_INTER);
-%}
-
-// Tail-call (interprocedural jump) to interpreter
-operand eCXRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(ecx_reg));
- match(reg);
- format %{ "ECX" %}
- interface(REG_INTER);
-%}
-
-operand eDXRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(edx_reg));
- match(reg);
- format %{ "EDX" %}
- interface(REG_INTER);
-%}
-
-operand eSIRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(esi_reg));
- match(reg);
- format %{ "ESI" %}
- interface(REG_INTER);
-%}
-
-// Used in rep stosw
-operand eDIRegP(eRegP reg) %{
- constraint(ALLOC_IN_RC(edi_reg));
- match(reg);
- format %{ "EDI" %}
- interface(REG_INTER);
-%}
-
-operand eRegL() %{
- constraint(ALLOC_IN_RC(long_reg));
- match(RegL);
- match(eADXRegL);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand eADXRegL( eRegL reg ) %{
- constraint(ALLOC_IN_RC(eadx_reg));
- match(reg);
-
- format %{ "EDX:EAX" %}
- interface(REG_INTER);
-%}
-
-operand eBCXRegL( eRegL reg ) %{
- constraint(ALLOC_IN_RC(ebcx_reg));
- match(reg);
-
- format %{ "EBX:ECX" %}
- interface(REG_INTER);
-%}
-
-operand eBDPRegL( eRegL reg ) %{
- constraint(ALLOC_IN_RC(ebpd_reg));
- match(reg);
-
- format %{ "EBP:EDI" %}
- interface(REG_INTER);
-%}
-// Special case for integer high multiply
-operand eADXRegL_low_only() %{
- constraint(ALLOC_IN_RC(eadx_reg));
- match(RegL);
-
- format %{ "EAX" %}
- interface(REG_INTER);
-%}
-
-// Flags register, used as output of compare instructions
-operand rFlagsReg() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
-
- format %{ "EFLAGS" %}
- interface(REG_INTER);
-%}
-
-// Flags register, used as output of compare instructions
-operand eFlagsReg() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
-
- format %{ "EFLAGS" %}
- interface(REG_INTER);
-%}
-
-// Flags register, used as output of FLOATING POINT compare instructions
-operand eFlagsRegU() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
-
- format %{ "EFLAGS_U" %}
- interface(REG_INTER);
-%}
-
-operand eFlagsRegUCF() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- predicate(false);
-
- format %{ "EFLAGS_U_CF" %}
- interface(REG_INTER);
-%}
-
-// Condition Code Register used by long compare
-operand flagsReg_long_LTGE() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_LTGE" %}
- interface(REG_INTER);
-%}
-operand flagsReg_long_EQNE() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_EQNE" %}
- interface(REG_INTER);
-%}
-operand flagsReg_long_LEGT() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_LEGT" %}
- interface(REG_INTER);
-%}
-
-// Condition Code Register used by unsigned long compare
-operand flagsReg_ulong_LTGE() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_U_LTGE" %}
- interface(REG_INTER);
-%}
-operand flagsReg_ulong_EQNE() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_U_EQNE" %}
- interface(REG_INTER);
-%}
-operand flagsReg_ulong_LEGT() %{
- constraint(ALLOC_IN_RC(int_flags));
- match(RegFlags);
- format %{ "FLAGS_U_LEGT" %}
- interface(REG_INTER);
-%}
-
-// Float register operands
-operand regDPR() %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_dbl_reg));
- match(RegD);
- match(regDPR1);
- match(regDPR2);
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand regDPR1(regDPR reg) %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_dbl_reg0));
- match(reg);
- format %{ "FPR1" %}
- interface(REG_INTER);
-%}
-
-operand regDPR2(regDPR reg) %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_dbl_reg1));
- match(reg);
- format %{ "FPR2" %}
- interface(REG_INTER);
-%}
-
-operand regnotDPR1(regDPR reg) %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_dbl_notreg0));
- match(reg);
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Float register operands
-operand regFPR() %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_flt_reg));
- match(RegF);
- match(regFPR1);
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Float register operands
-operand regFPR1(regFPR reg) %{
- predicate( UseSSE < 2 );
- constraint(ALLOC_IN_RC(fp_flt_reg0));
- match(reg);
- format %{ "FPR1" %}
- interface(REG_INTER);
-%}
-
-// XMM Float register operands
-operand regF() %{
- predicate( UseSSE>=1 );
- constraint(ALLOC_IN_RC(float_reg_legacy));
- match(RegF);
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand legRegF() %{
- predicate( UseSSE>=1 );
- constraint(ALLOC_IN_RC(float_reg_legacy));
- match(RegF);
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Float register operands
-operand vlRegF() %{
- constraint(ALLOC_IN_RC(float_reg_vl));
- match(RegF);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-// XMM Double register operands
-operand regD() %{
- predicate( UseSSE>=2 );
- constraint(ALLOC_IN_RC(double_reg_legacy));
- match(RegD);
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Double register operands
-operand legRegD() %{
- predicate( UseSSE>=2 );
- constraint(ALLOC_IN_RC(double_reg_legacy));
- match(RegD);
- format %{ %}
- interface(REG_INTER);
-%}
-
-operand vlRegD() %{
- constraint(ALLOC_IN_RC(double_reg_vl));
- match(RegD);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
-//----------Memory Operands----------------------------------------------------
-// Direct Memory Operand
-operand direct(immP addr) %{
- match(addr);
-
- format %{ "[$addr]" %}
- interface(MEMORY_INTER) %{
- base(0xFFFFFFFF);
- index(0x4);
- scale(0x0);
- disp($addr);
- %}
-%}
-
-// Indirect Memory Operand
-operand indirect(eRegP reg) %{
- constraint(ALLOC_IN_RC(int_reg));
- match(reg);
-
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp(0x0);
- %}
-%}
-
-// Indirect Memory Plus Short Offset Operand
-operand indOffset8(eRegP reg, immI8 off) %{
- match(AddP reg off);
-
- format %{ "[$reg + $off]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp($off);
- %}
-%}
-
-// Indirect Memory Plus Long Offset Operand
-operand indOffset32(eRegP reg, immI off) %{
- match(AddP reg off);
-
- format %{ "[$reg + $off]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp($off);
- %}
-%}
-
-// Indirect Memory Plus Long Offset Operand
-operand indOffset32X(rRegI reg, immP off) %{
- match(AddP off reg);
-
- format %{ "[$reg + $off]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp($off);
- %}
-%}
-
-// Indirect Memory Plus Index Register Plus Offset Operand
-operand indIndexOffset(eRegP reg, rRegI ireg, immI off) %{
- match(AddP (AddP reg ireg) off);
-
- op_cost(10);
- format %{"[$reg + $off + $ireg]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index($ireg);
- scale(0x0);
- disp($off);
- %}
-%}
-
-// Indirect Memory Plus Index Register Plus Offset Operand
-operand indIndex(eRegP reg, rRegI ireg) %{
- match(AddP reg ireg);
-
- op_cost(10);
- format %{"[$reg + $ireg]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index($ireg);
- scale(0x0);
- disp(0x0);
- %}
-%}
-
-// // -------------------------------------------------------------------------
-// // 486 architecture doesn't support "scale * index + offset" with out a base
-// // -------------------------------------------------------------------------
-// // Scaled Memory Operands
-// // Indirect Memory Times Scale Plus Offset Operand
-// operand indScaleOffset(immP off, rRegI ireg, immI2 scale) %{
-// match(AddP off (LShiftI ireg scale));
-//
-// op_cost(10);
-// format %{"[$off + $ireg << $scale]" %}
-// interface(MEMORY_INTER) %{
-// base(0x4);
-// index($ireg);
-// scale($scale);
-// disp($off);
-// %}
-// %}
-
-// Indirect Memory Times Scale Plus Index Register
-operand indIndexScale(eRegP reg, rRegI ireg, immI2 scale) %{
- match(AddP reg (LShiftI ireg scale));
-
- op_cost(10);
- format %{"[$reg + $ireg << $scale]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index($ireg);
- scale($scale);
- disp(0x0);
- %}
-%}
-
-// Indirect Memory Times Scale Plus Index Register Plus Offset Operand
-operand indIndexScaleOffset(eRegP reg, immI off, rRegI ireg, immI2 scale) %{
- match(AddP (AddP reg (LShiftI ireg scale)) off);
-
- op_cost(10);
- format %{"[$reg + $off + $ireg << $scale]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index($ireg);
- scale($scale);
- disp($off);
- %}
-%}
-
-//----------Load Long Memory Operands------------------------------------------
-// The load-long idiom will use it's address expression again after loading
-// the first word of the long. If the load-long destination overlaps with
-// registers used in the addressing expression, the 2nd half will be loaded
-// from a clobbered address. Fix this by requiring that load-long use
-// address registers that do not overlap with the load-long target.
-
-// load-long support
-operand load_long_RegP() %{
- constraint(ALLOC_IN_RC(esi_reg));
- match(RegP);
- match(eSIRegP);
- op_cost(100);
- format %{ %}
- interface(REG_INTER);
-%}
-
-// Indirect Memory Operand Long
-operand load_long_indirect(load_long_RegP reg) %{
- constraint(ALLOC_IN_RC(esi_reg));
- match(reg);
-
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp(0x0);
- %}
-%}
-
-// Indirect Memory Plus Long Offset Operand
-operand load_long_indOffset32(load_long_RegP reg, immI off) %{
- match(AddP reg off);
-
- format %{ "[$reg + $off]" %}
- interface(MEMORY_INTER) %{
- base($reg);
- index(0x4);
- scale(0x0);
- disp($off);
- %}
-%}
-
-opclass load_long_memory(load_long_indirect, load_long_indOffset32);
-
-
-//----------Special Memory Operands--------------------------------------------
-// Stack Slot Operand - This operand is used for loading and storing temporary
-// values on the stack where a match requires a value to
-// flow through memory.
-operand stackSlotP(sRegP reg) %{
- constraint(ALLOC_IN_RC(stack_slots));
- // No match rule because this operand is only generated in matching
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base(0x4); // ESP
- index(0x4); // No Index
- scale(0x0); // No Scale
- disp($reg); // Stack Offset
- %}
-%}
-
-operand stackSlotI(sRegI reg) %{
- constraint(ALLOC_IN_RC(stack_slots));
- // No match rule because this operand is only generated in matching
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base(0x4); // ESP
- index(0x4); // No Index
- scale(0x0); // No Scale
- disp($reg); // Stack Offset
- %}
-%}
-
-operand stackSlotF(sRegF reg) %{
- constraint(ALLOC_IN_RC(stack_slots));
- // No match rule because this operand is only generated in matching
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base(0x4); // ESP
- index(0x4); // No Index
- scale(0x0); // No Scale
- disp($reg); // Stack Offset
- %}
-%}
-
-operand stackSlotD(sRegD reg) %{
- constraint(ALLOC_IN_RC(stack_slots));
- // No match rule because this operand is only generated in matching
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base(0x4); // ESP
- index(0x4); // No Index
- scale(0x0); // No Scale
- disp($reg); // Stack Offset
- %}
-%}
-
-operand stackSlotL(sRegL reg) %{
- constraint(ALLOC_IN_RC(stack_slots));
- // No match rule because this operand is only generated in matching
- format %{ "[$reg]" %}
- interface(MEMORY_INTER) %{
- base(0x4); // ESP
- index(0x4); // No Index
- scale(0x0); // No Scale
- disp($reg); // Stack Offset
- %}
-%}
-
-//----------Conditional Branch Operands----------------------------------------
-// Comparison Op - This is the operation of the comparison, and is limited to
-// the following set of codes:
-// L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
-//
-// Other attributes of the comparison, such as unsignedness, are specified
-// by the comparison instruction that sets a condition code flags register.
-// That result is represented by a flags operand whose subtype is appropriate
-// to the unsignedness (etc.) of the comparison.
-//
-// Later, the instruction which matches both the Comparison Op (a Bool) and
-// the flags (produced by the Cmp) specifies the coding of the comparison op
-// by matching a specific subtype of Bool operand below, such as cmpOpU.
-
-// Comparison Code
-operand cmpOp() %{
- match(Bool);
-
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0xC, "l");
- greater_equal(0xD, "ge");
- less_equal(0xE, "le");
- greater(0xF, "g");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-// Comparison Code, unsigned compare. Used by FP also, with
-// C2 (unordered) turned into GT or LT already. The other bits
-// C0 and C3 are turned into Carry & Zero flags.
-operand cmpOpU() %{
- match(Bool);
-
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0x2, "b");
- greater_equal(0x3, "nb");
- less_equal(0x6, "be");
- greater(0x7, "nbe");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-// Floating comparisons that don't require any fixup for the unordered case
-operand cmpOpUCF() %{
- match(Bool);
- predicate(n->as_Bool()->_test._test == BoolTest::lt ||
- n->as_Bool()->_test._test == BoolTest::ge ||
- n->as_Bool()->_test._test == BoolTest::le ||
- n->as_Bool()->_test._test == BoolTest::gt);
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0x2, "b");
- greater_equal(0x3, "nb");
- less_equal(0x6, "be");
- greater(0x7, "nbe");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-
-// Floating comparisons that can be fixed up with extra conditional jumps
-operand cmpOpUCF2() %{
- match(Bool);
- predicate(n->as_Bool()->_test._test == BoolTest::ne ||
- n->as_Bool()->_test._test == BoolTest::eq);
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0x2, "b");
- greater_equal(0x3, "nb");
- less_equal(0x6, "be");
- greater(0x7, "nbe");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-// Comparison Code for FP conditional move
-operand cmpOp_fcmov() %{
- match(Bool);
-
- predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
- n->as_Bool()->_test._test != BoolTest::no_overflow);
- format %{ "" %}
- interface(COND_INTER) %{
- equal (0x0C8);
- not_equal (0x1C8);
- less (0x0C0);
- greater_equal(0x1C0);
- less_equal (0x0D0);
- greater (0x1D0);
- overflow(0x0, "o"); // not really supported by the instruction
- no_overflow(0x1, "no"); // not really supported by the instruction
- %}
-%}
-
-// Comparison Code used in long compares
-operand cmpOp_commute() %{
- match(Bool);
-
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0xF, "g");
- greater_equal(0xE, "le");
- less_equal(0xD, "ge");
- greater(0xC, "l");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-// Comparison Code used in unsigned long compares
-operand cmpOpU_commute() %{
- match(Bool);
-
- format %{ "" %}
- interface(COND_INTER) %{
- equal(0x4, "e");
- not_equal(0x5, "ne");
- less(0x7, "nbe");
- greater_equal(0x6, "be");
- less_equal(0x3, "nb");
- greater(0x2, "b");
- overflow(0x0, "o");
- no_overflow(0x1, "no");
- %}
-%}
-
-//----------OPERAND CLASSES----------------------------------------------------
-// Operand Classes are groups of operands that are used as to simplify
-// instruction definitions by not requiring the AD writer to specify separate
-// instructions for every form of operand when the instruction accepts
-// multiple operand types with the same basic encoding and format. The classic
-// case of this is memory operands.
-
-opclass memory(direct, indirect, indOffset8, indOffset32, indOffset32X, indIndexOffset,
- indIndex, indIndexScale, indIndexScaleOffset);
-
-// Long memory operations are encoded in 2 instructions and a +4 offset.
-// This means some kind of offset is always required and you cannot use
-// an oop as the offset (done when working on static globals).
-opclass long_memory(direct, indirect, indOffset8, indOffset32, indIndexOffset,
- indIndex, indIndexScale, indIndexScaleOffset);
-
-
-//----------PIPELINE-----------------------------------------------------------
-// Rules which define the behavior of the target architectures pipeline.
-pipeline %{
-
-//----------ATTRIBUTES---------------------------------------------------------
-attributes %{
- variable_size_instructions; // Fixed size instructions
- max_instructions_per_bundle = 3; // Up to 3 instructions per bundle
- instruction_unit_size = 1; // An instruction is 1 bytes long
- instruction_fetch_unit_size = 16; // The processor fetches one line
- instruction_fetch_units = 1; // of 16 bytes
-
- // List of nop instructions
- nops( MachNop );
-%}
-
-//----------RESOURCES----------------------------------------------------------
-// Resources are the functional units available to the machine
-
-// Generic P2/P3 pipeline
-// 3 decoders, only D0 handles big operands; a "bundle" is the limit of
-// 3 instructions decoded per cycle.
-// 2 load/store ops per cycle, 1 branch, 1 FPU,
-// 2 ALU op, only ALU0 handles mul/div instructions.
-resources( D0, D1, D2, DECODE = D0 | D1 | D2,
- MS0, MS1, MEM = MS0 | MS1,
- BR, FPU,
- ALU0, ALU1, ALU = ALU0 | ALU1 );
-
-//----------PIPELINE DESCRIPTION-----------------------------------------------
-// Pipeline Description specifies the stages in the machine's pipeline
-
-// Generic P2/P3 pipeline
-pipe_desc(S0, S1, S2, S3, S4, S5);
-
-//----------PIPELINE CLASSES---------------------------------------------------
-// Pipeline Classes describe the stages in which input and output are
-// referenced by the hardware pipeline.
-
-// Naming convention: ialu or fpu
-// Then: _reg
-// Then: _reg if there is a 2nd register
-// Then: _long if it's a pair of instructions implementing a long
-// Then: _fat if it requires the big decoder
-// Or: _mem if it requires the big decoder and a memory unit.
-
-// Integer ALU reg operation
-pipe_class ialu_reg(rRegI dst) %{
- single_instruction;
- dst : S4(write);
- dst : S3(read);
- DECODE : S0; // any decoder
- ALU : S3; // any alu
-%}
-
-// Long ALU reg operation
-pipe_class ialu_reg_long(eRegL dst) %{
- instruction_count(2);
- dst : S4(write);
- dst : S3(read);
- DECODE : S0(2); // any 2 decoders
- ALU : S3(2); // both alus
-%}
-
-// Integer ALU reg operation using big decoder
-pipe_class ialu_reg_fat(rRegI dst) %{
- single_instruction;
- dst : S4(write);
- dst : S3(read);
- D0 : S0; // big decoder only
- ALU : S3; // any alu
-%}
-
-// Long ALU reg operation using big decoder
-pipe_class ialu_reg_long_fat(eRegL dst) %{
- instruction_count(2);
- dst : S4(write);
- dst : S3(read);
- D0 : S0(2); // big decoder only; twice
- ALU : S3(2); // any 2 alus
-%}
-
-// Integer ALU reg-reg operation
-pipe_class ialu_reg_reg(rRegI dst, rRegI src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- DECODE : S0; // any decoder
- ALU : S3; // any alu
-%}
-
-// Long ALU reg-reg operation
-pipe_class ialu_reg_reg_long(eRegL dst, eRegL src) %{
- instruction_count(2);
- dst : S4(write);
- src : S3(read);
- DECODE : S0(2); // any 2 decoders
- ALU : S3(2); // both alus
-%}
-
-// Integer ALU reg-reg operation
-pipe_class ialu_reg_reg_fat(rRegI dst, memory src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- D0 : S0; // big decoder only
- ALU : S3; // any alu
-%}
-
-// Long ALU reg-reg operation
-pipe_class ialu_reg_reg_long_fat(eRegL dst, eRegL src) %{
- instruction_count(2);
- dst : S4(write);
- src : S3(read);
- D0 : S0(2); // big decoder only; twice
- ALU : S3(2); // both alus
-%}
-
-// Integer ALU reg-mem operation
-pipe_class ialu_reg_mem(rRegI dst, memory mem) %{
- single_instruction;
- dst : S5(write);
- mem : S3(read);
- D0 : S0; // big decoder only
- ALU : S4; // any alu
- MEM : S3; // any mem
-%}
-
-// Long ALU reg-mem operation
-pipe_class ialu_reg_long_mem(eRegL dst, load_long_memory mem) %{
- instruction_count(2);
- dst : S5(write);
- mem : S3(read);
- D0 : S0(2); // big decoder only; twice
- ALU : S4(2); // any 2 alus
- MEM : S3(2); // both mems
-%}
-
-// Integer mem operation (prefetch)
-pipe_class ialu_mem(memory mem)
-%{
- single_instruction;
- mem : S3(read);
- D0 : S0; // big decoder only
- MEM : S3; // any mem
-%}
-
-// Integer Store to Memory
-pipe_class ialu_mem_reg(memory mem, rRegI src) %{
- single_instruction;
- mem : S3(read);
- src : S5(read);
- D0 : S0; // big decoder only
- ALU : S4; // any alu
- MEM : S3;
-%}
-
-// Long Store to Memory
-pipe_class ialu_mem_long_reg(memory mem, eRegL src) %{
- instruction_count(2);
- mem : S3(read);
- src : S5(read);
- D0 : S0(2); // big decoder only; twice
- ALU : S4(2); // any 2 alus
- MEM : S3(2); // Both mems
-%}
-
-// Integer Store to Memory
-pipe_class ialu_mem_imm(memory mem) %{
- single_instruction;
- mem : S3(read);
- D0 : S0; // big decoder only
- ALU : S4; // any alu
- MEM : S3;
-%}
-
-// Integer ALU0 reg-reg operation
-pipe_class ialu_reg_reg_alu0(rRegI dst, rRegI src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- D0 : S0; // Big decoder only
- ALU0 : S3; // only alu0
-%}
-
-// Integer ALU0 reg-mem operation
-pipe_class ialu_reg_mem_alu0(rRegI dst, memory mem) %{
- single_instruction;
- dst : S5(write);
- mem : S3(read);
- D0 : S0; // big decoder only
- ALU0 : S4; // ALU0 only
- MEM : S3; // any mem
-%}
-
-// Integer ALU reg-reg operation
-pipe_class ialu_cr_reg_reg(eFlagsReg cr, rRegI src1, rRegI src2) %{
- single_instruction;
- cr : S4(write);
- src1 : S3(read);
- src2 : S3(read);
- DECODE : S0; // any decoder
- ALU : S3; // any alu
-%}
-
-// Integer ALU reg-imm operation
-pipe_class ialu_cr_reg_imm(eFlagsReg cr, rRegI src1) %{
- single_instruction;
- cr : S4(write);
- src1 : S3(read);
- DECODE : S0; // any decoder
- ALU : S3; // any alu
-%}
-
-// Integer ALU reg-mem operation
-pipe_class ialu_cr_reg_mem(eFlagsReg cr, rRegI src1, memory src2) %{
- single_instruction;
- cr : S4(write);
- src1 : S3(read);
- src2 : S3(read);
- D0 : S0; // big decoder only
- ALU : S4; // any alu
- MEM : S3;
-%}
-
-// Conditional move reg-reg
-pipe_class pipe_cmplt( rRegI p, rRegI q, rRegI y ) %{
- instruction_count(4);
- y : S4(read);
- q : S3(read);
- p : S3(read);
- DECODE : S0(4); // any decoder
-%}
-
-// Conditional move reg-reg
-pipe_class pipe_cmov_reg( rRegI dst, rRegI src, eFlagsReg cr ) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- cr : S3(read);
- DECODE : S0; // any decoder
-%}
-
-// Conditional move reg-mem
-pipe_class pipe_cmov_mem( eFlagsReg cr, rRegI dst, memory src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- cr : S3(read);
- DECODE : S0; // any decoder
- MEM : S3;
-%}
-
-// Conditional move reg-reg long
-pipe_class pipe_cmov_reg_long( eFlagsReg cr, eRegL dst, eRegL src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- cr : S3(read);
- DECODE : S0(2); // any 2 decoders
-%}
-
-// Conditional move double reg-reg
-pipe_class pipe_cmovDPR_reg( eFlagsReg cr, regDPR1 dst, regDPR src) %{
- single_instruction;
- dst : S4(write);
- src : S3(read);
- cr : S3(read);
- DECODE : S0; // any decoder
-%}
-
-// Float reg-reg operation
-pipe_class fpu_reg(regDPR dst) %{
- instruction_count(2);
- dst : S3(read);
- DECODE : S0(2); // any 2 decoders
- FPU : S3;
-%}
-
-// Float reg-reg operation
-pipe_class fpu_reg_reg(regDPR dst, regDPR src) %{
- instruction_count(2);
- dst : S4(write);
- src : S3(read);
- DECODE : S0(2); // any 2 decoders
- FPU : S3;
-%}
-
-// Float reg-reg operation
-pipe_class fpu_reg_reg_reg(regDPR dst, regDPR src1, regDPR src2) %{
- instruction_count(3);
- dst : S4(write);
- src1 : S3(read);
- src2 : S3(read);
- DECODE : S0(3); // any 3 decoders
- FPU : S3(2);
-%}
-
-// Float reg-reg operation
-pipe_class fpu_reg_reg_reg_reg(regDPR dst, regDPR src1, regDPR src2, regDPR src3) %{
- instruction_count(4);
- dst : S4(write);
- src1 : S3(read);
- src2 : S3(read);
- src3 : S3(read);
- DECODE : S0(4); // any 3 decoders
- FPU : S3(2);
-%}
-
-// Float reg-reg operation
-pipe_class fpu_reg_mem_reg_reg(regDPR dst, memory src1, regDPR src2, regDPR src3) %{
- instruction_count(4);
- dst : S4(write);
- src1 : S3(read);
- src2 : S3(read);
- src3 : S3(read);
- DECODE : S1(3); // any 3 decoders
- D0 : S0; // Big decoder only
- FPU : S3(2);
- MEM : S3;
-%}
-
-// Float reg-mem operation
-pipe_class fpu_reg_mem(regDPR dst, memory mem) %{
- instruction_count(2);
- dst : S5(write);
- mem : S3(read);
- D0 : S0; // big decoder only
- DECODE : S1; // any decoder for FPU POP
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-// Float reg-mem operation
-pipe_class fpu_reg_reg_mem(regDPR dst, regDPR src1, memory mem) %{
- instruction_count(3);
- dst : S5(write);
- src1 : S3(read);
- mem : S3(read);
- D0 : S0; // big decoder only
- DECODE : S1(2); // any decoder for FPU POP
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-// Float mem-reg operation
-pipe_class fpu_mem_reg(memory mem, regDPR src) %{
- instruction_count(2);
- src : S5(read);
- mem : S3(read);
- DECODE : S0; // any decoder for FPU PUSH
- D0 : S1; // big decoder only
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-pipe_class fpu_mem_reg_reg(memory mem, regDPR src1, regDPR src2) %{
- instruction_count(3);
- src1 : S3(read);
- src2 : S3(read);
- mem : S3(read);
- DECODE : S0(2); // any decoder for FPU PUSH
- D0 : S1; // big decoder only
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-pipe_class fpu_mem_reg_mem(memory mem, regDPR src1, memory src2) %{
- instruction_count(3);
- src1 : S3(read);
- src2 : S3(read);
- mem : S4(read);
- DECODE : S0; // any decoder for FPU PUSH
- D0 : S0(2); // big decoder only
- FPU : S4;
- MEM : S3(2); // any mem
-%}
-
-pipe_class fpu_mem_mem(memory dst, memory src1) %{
- instruction_count(2);
- src1 : S3(read);
- dst : S4(read);
- D0 : S0(2); // big decoder only
- MEM : S3(2); // any mem
-%}
-
-pipe_class fpu_mem_mem_mem(memory dst, memory src1, memory src2) %{
- instruction_count(3);
- src1 : S3(read);
- src2 : S3(read);
- dst : S4(read);
- D0 : S0(3); // big decoder only
- FPU : S4;
- MEM : S3(3); // any mem
-%}
-
-pipe_class fpu_mem_reg_con(memory mem, regDPR src1) %{
- instruction_count(3);
- src1 : S4(read);
- mem : S4(read);
- DECODE : S0; // any decoder for FPU PUSH
- D0 : S0(2); // big decoder only
- FPU : S4;
- MEM : S3(2); // any mem
-%}
-
-// Float load constant
-pipe_class fpu_reg_con(regDPR dst) %{
- instruction_count(2);
- dst : S5(write);
- D0 : S0; // big decoder only for the load
- DECODE : S1; // any decoder for FPU POP
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-// Float load constant
-pipe_class fpu_reg_reg_con(regDPR dst, regDPR src) %{
- instruction_count(3);
- dst : S5(write);
- src : S3(read);
- D0 : S0; // big decoder only for the load
- DECODE : S1(2); // any decoder for FPU POP
- FPU : S4;
- MEM : S3; // any mem
-%}
-
-// UnConditional branch
-pipe_class pipe_jmp( label labl ) %{
- single_instruction;
- BR : S3;
-%}
-
-// Conditional branch
-pipe_class pipe_jcc( cmpOp cmp, eFlagsReg cr, label labl ) %{
- single_instruction;
- cr : S1(read);
- BR : S3;
-%}
-
-// Allocation idiom
-pipe_class pipe_cmpxchg( eRegP dst, eRegP heap_ptr ) %{
- instruction_count(1); force_serialization;
- fixed_latency(6);
- heap_ptr : S3(read);
- DECODE : S0(3);
- D0 : S2;
- MEM : S3;
- ALU : S3(2);
- dst : S5(write);
- BR : S5;
-%}
-
-// Generic big/slow expanded idiom
-pipe_class pipe_slow( ) %{
- instruction_count(10); multiple_bundles; force_serialization;
- fixed_latency(100);
- D0 : S0(2);
- MEM : S3(2);
-%}
-
-// The real do-nothing guy
-pipe_class empty( ) %{
- instruction_count(0);
-%}
-
-// Define the class for the Nop node
-define %{
- MachNop = empty;
-%}
-
-%}
-
-//----------INSTRUCTIONS-------------------------------------------------------
-//
-// match -- States which machine-independent subtree may be replaced
-// by this instruction.
-// ins_cost -- The estimated cost of this instruction is used by instruction
-// selection to identify a minimum cost tree of machine
-// instructions that matches a tree of machine-independent
-// instructions.
-// format -- A string providing the disassembly for this instruction.
-// The value of an instruction's operand may be inserted
-// by referring to it with a '$' prefix.
-// opcode -- Three instruction opcodes may be provided. These are referred
-// to within an encode class as $primary, $secondary, and $tertiary
-// respectively. The primary opcode is commonly used to
-// indicate the type of machine instruction, while secondary
-// and tertiary are often used for prefix options or addressing
-// modes.
-// ins_encode -- A list of encode classes with parameters. The encode class
-// name must have been defined in an 'enc_class' specification
-// in the encode section of the architecture description.
-
-// Dummy reg-to-reg vector moves. Removed during post-selection cleanup.
-// Load Float
-instruct MoveF2LEG(legRegF dst, regF src) %{
- match(Set dst src);
- format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Float
-instruct MoveLEG2F(regF dst, legRegF src) %{
- match(Set dst src);
- format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Float
-instruct MoveF2VL(vlRegF dst, regF src) %{
- match(Set dst src);
- format %{ "movss $dst,$src\t! load float (4 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Float
-instruct MoveVL2F(regF dst, vlRegF src) %{
- match(Set dst src);
- format %{ "movss $dst,$src\t! load float (4 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-
-
-// Load Double
-instruct MoveD2LEG(legRegD dst, regD src) %{
- match(Set dst src);
- format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Double
-instruct MoveLEG2D(regD dst, legRegD src) %{
- match(Set dst src);
- format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Double
-instruct MoveD2VL(vlRegD dst, regD src) %{
- match(Set dst src);
- format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-// Load Double
-instruct MoveVL2D(regD dst, vlRegD src) %{
- match(Set dst src);
- format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
- ins_encode %{
- ShouldNotReachHere();
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-//----------BSWAP-Instruction--------------------------------------------------
-instruct bytes_reverse_int(rRegI dst) %{
- match(Set dst (ReverseBytesI dst));
-
- format %{ "BSWAP $dst" %}
- opcode(0x0F, 0xC8);
- ins_encode( OpcP, OpcSReg(dst) );
- ins_pipe( ialu_reg );
-%}
-
-instruct bytes_reverse_long(eRegL dst) %{
- match(Set dst (ReverseBytesL dst));
-
- format %{ "BSWAP $dst.lo\n\t"
- "BSWAP $dst.hi\n\t"
- "XCHG $dst.lo $dst.hi" %}
-
- ins_cost(125);
- ins_encode( bswap_long_bytes(dst) );
- ins_pipe( ialu_reg_reg);
-%}
-
-instruct bytes_reverse_unsigned_short(rRegI dst, eFlagsReg cr) %{
- match(Set dst (ReverseBytesUS dst));
- effect(KILL cr);
-
- format %{ "BSWAP $dst\n\t"
- "SHR $dst,16\n\t" %}
- ins_encode %{
- __ bswapl($dst$$Register);
- __ shrl($dst$$Register, 16);
- %}
- ins_pipe( ialu_reg );
-%}
-
-instruct bytes_reverse_short(rRegI dst, eFlagsReg cr) %{
- match(Set dst (ReverseBytesS dst));
- effect(KILL cr);
-
- format %{ "BSWAP $dst\n\t"
- "SAR $dst,16\n\t" %}
- ins_encode %{
- __ bswapl($dst$$Register);
- __ sarl($dst$$Register, 16);
- %}
- ins_pipe( ialu_reg );
-%}
-
-
-//---------- Zeros Count Instructions ------------------------------------------
-
-instruct countLeadingZerosI(rRegI dst, rRegI src, eFlagsReg cr) %{
- predicate(UseCountLeadingZerosInstruction);
- match(Set dst (CountLeadingZerosI src));
- effect(KILL cr);
-
- format %{ "LZCNT $dst, $src\t# count leading zeros (int)" %}
- ins_encode %{
- __ lzcntl($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countLeadingZerosI_bsr(rRegI dst, rRegI src, eFlagsReg cr) %{
- predicate(!UseCountLeadingZerosInstruction);
- match(Set dst (CountLeadingZerosI src));
- effect(KILL cr);
-
- format %{ "BSR $dst, $src\t# count leading zeros (int)\n\t"
- "JNZ skip\n\t"
- "MOV $dst, -1\n"
- "skip:\n\t"
- "NEG $dst\n\t"
- "ADD $dst, 31" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- Label skip;
- __ bsrl(Rdst, Rsrc);
- __ jccb(Assembler::notZero, skip);
- __ movl(Rdst, -1);
- __ bind(skip);
- __ negl(Rdst);
- __ addl(Rdst, BitsPerInt - 1);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countLeadingZerosL(rRegI dst, eRegL src, eFlagsReg cr) %{
- predicate(UseCountLeadingZerosInstruction);
- match(Set dst (CountLeadingZerosL src));
- effect(TEMP dst, KILL cr);
-
- format %{ "LZCNT $dst, $src.hi\t# count leading zeros (long)\n\t"
- "JNC done\n\t"
- "LZCNT $dst, $src.lo\n\t"
- "ADD $dst, 32\n"
- "done:" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- Label done;
- __ lzcntl(Rdst, HIGH_FROM_LOW(Rsrc));
- __ jccb(Assembler::carryClear, done);
- __ lzcntl(Rdst, Rsrc);
- __ addl(Rdst, BitsPerInt);
- __ bind(done);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countLeadingZerosL_bsr(rRegI dst, eRegL src, eFlagsReg cr) %{
- predicate(!UseCountLeadingZerosInstruction);
- match(Set dst (CountLeadingZerosL src));
- effect(TEMP dst, KILL cr);
-
- format %{ "BSR $dst, $src.hi\t# count leading zeros (long)\n\t"
- "JZ msw_is_zero\n\t"
- "ADD $dst, 32\n\t"
- "JMP not_zero\n"
- "msw_is_zero:\n\t"
- "BSR $dst, $src.lo\n\t"
- "JNZ not_zero\n\t"
- "MOV $dst, -1\n"
- "not_zero:\n\t"
- "NEG $dst\n\t"
- "ADD $dst, 63\n" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- Label msw_is_zero;
- Label not_zero;
- __ bsrl(Rdst, HIGH_FROM_LOW(Rsrc));
- __ jccb(Assembler::zero, msw_is_zero);
- __ addl(Rdst, BitsPerInt);
- __ jmpb(not_zero);
- __ bind(msw_is_zero);
- __ bsrl(Rdst, Rsrc);
- __ jccb(Assembler::notZero, not_zero);
- __ movl(Rdst, -1);
- __ bind(not_zero);
- __ negl(Rdst);
- __ addl(Rdst, BitsPerLong - 1);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countTrailingZerosI(rRegI dst, rRegI src, eFlagsReg cr) %{
- predicate(UseCountTrailingZerosInstruction);
- match(Set dst (CountTrailingZerosI src));
- effect(KILL cr);
-
- format %{ "TZCNT $dst, $src\t# count trailing zeros (int)" %}
- ins_encode %{
- __ tzcntl($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countTrailingZerosI_bsf(rRegI dst, rRegI src, eFlagsReg cr) %{
- predicate(!UseCountTrailingZerosInstruction);
- match(Set dst (CountTrailingZerosI src));
- effect(KILL cr);
-
- format %{ "BSF $dst, $src\t# count trailing zeros (int)\n\t"
- "JNZ done\n\t"
- "MOV $dst, 32\n"
- "done:" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Label done;
- __ bsfl(Rdst, $src$$Register);
- __ jccb(Assembler::notZero, done);
- __ movl(Rdst, BitsPerInt);
- __ bind(done);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countTrailingZerosL(rRegI dst, eRegL src, eFlagsReg cr) %{
- predicate(UseCountTrailingZerosInstruction);
- match(Set dst (CountTrailingZerosL src));
- effect(TEMP dst, KILL cr);
-
- format %{ "TZCNT $dst, $src.lo\t# count trailing zeros (long) \n\t"
- "JNC done\n\t"
- "TZCNT $dst, $src.hi\n\t"
- "ADD $dst, 32\n"
- "done:" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- Label done;
- __ tzcntl(Rdst, Rsrc);
- __ jccb(Assembler::carryClear, done);
- __ tzcntl(Rdst, HIGH_FROM_LOW(Rsrc));
- __ addl(Rdst, BitsPerInt);
- __ bind(done);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct countTrailingZerosL_bsf(rRegI dst, eRegL src, eFlagsReg cr) %{
- predicate(!UseCountTrailingZerosInstruction);
- match(Set dst (CountTrailingZerosL src));
- effect(TEMP dst, KILL cr);
-
- format %{ "BSF $dst, $src.lo\t# count trailing zeros (long)\n\t"
- "JNZ done\n\t"
- "BSF $dst, $src.hi\n\t"
- "JNZ msw_not_zero\n\t"
- "MOV $dst, 32\n"
- "msw_not_zero:\n\t"
- "ADD $dst, 32\n"
- "done:" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- Label msw_not_zero;
- Label done;
- __ bsfl(Rdst, Rsrc);
- __ jccb(Assembler::notZero, done);
- __ bsfl(Rdst, HIGH_FROM_LOW(Rsrc));
- __ jccb(Assembler::notZero, msw_not_zero);
- __ movl(Rdst, BitsPerInt);
- __ bind(msw_not_zero);
- __ addl(Rdst, BitsPerInt);
- __ bind(done);
- %}
- ins_pipe(ialu_reg);
-%}
-
-
-//---------- Population Count Instructions -------------------------------------
-
-instruct popCountI(rRegI dst, rRegI src, eFlagsReg cr) %{
- predicate(UsePopCountInstruction);
- match(Set dst (PopCountI src));
- effect(KILL cr);
-
- format %{ "POPCNT $dst, $src" %}
- ins_encode %{
- __ popcntl($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct popCountI_mem(rRegI dst, memory mem, eFlagsReg cr) %{
- predicate(UsePopCountInstruction);
- match(Set dst (PopCountI (LoadI mem)));
- effect(KILL cr);
-
- format %{ "POPCNT $dst, $mem" %}
- ins_encode %{
- __ popcntl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg);
-%}
-
-// Note: Long.bitCount(long) returns an int.
-instruct popCountL(rRegI dst, eRegL src, rRegI tmp, eFlagsReg cr) %{
- predicate(UsePopCountInstruction);
- match(Set dst (PopCountL src));
- effect(KILL cr, TEMP tmp, TEMP dst);
-
- format %{ "POPCNT $dst, $src.lo\n\t"
- "POPCNT $tmp, $src.hi\n\t"
- "ADD $dst, $tmp" %}
- ins_encode %{
- __ popcntl($dst$$Register, $src$$Register);
- __ popcntl($tmp$$Register, HIGH_FROM_LOW($src$$Register));
- __ addl($dst$$Register, $tmp$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-// Note: Long.bitCount(long) returns an int.
-instruct popCountL_mem(rRegI dst, memory mem, rRegI tmp, eFlagsReg cr) %{
- predicate(UsePopCountInstruction);
- match(Set dst (PopCountL (LoadL mem)));
- effect(KILL cr, TEMP tmp, TEMP dst);
-
- format %{ "POPCNT $dst, $mem\n\t"
- "POPCNT $tmp, $mem+4\n\t"
- "ADD $dst, $tmp" %}
- ins_encode %{
- //__ popcntl($dst$$Register, $mem$$Address$$first);
- //__ popcntl($tmp$$Register, $mem$$Address$$second);
- __ popcntl($dst$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none));
- __ popcntl($tmp$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none));
- __ addl($dst$$Register, $tmp$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-
-//----------Load/Store/Move Instructions---------------------------------------
-//----------Load Instructions--------------------------------------------------
-// Load Byte (8bit signed)
-instruct loadB(xRegI dst, memory mem) %{
- match(Set dst (LoadB mem));
-
- ins_cost(125);
- format %{ "MOVSX8 $dst,$mem\t# byte" %}
-
- ins_encode %{
- __ movsbl($dst$$Register, $mem$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Byte (8bit signed) into Long Register
-instruct loadB2L(eRegL dst, memory mem, eFlagsReg cr) %{
- match(Set dst (ConvI2L (LoadB mem)));
- effect(KILL cr);
-
- ins_cost(375);
- format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t"
- "MOV $dst.hi,$dst.lo\n\t"
- "SAR $dst.hi,7" %}
-
- ins_encode %{
- __ movsbl($dst$$Register, $mem$$Address);
- __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
- __ sarl(HIGH_FROM_LOW($dst$$Register), 7); // 24+1 MSB are already signed extended.
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Byte (8bit UNsigned)
-instruct loadUB(xRegI dst, memory mem) %{
- match(Set dst (LoadUB mem));
-
- ins_cost(125);
- format %{ "MOVZX8 $dst,$mem\t# ubyte -> int" %}
-
- ins_encode %{
- __ movzbl($dst$$Register, $mem$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Byte (8 bit UNsigned) into Long Register
-instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{
- match(Set dst (ConvI2L (LoadUB mem)));
- effect(KILL cr);
-
- ins_cost(250);
- format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
-
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzbl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register
-instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
- effect(KILL cr);
-
- format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t"
- "XOR $dst.hi,$dst.hi\n\t"
- "AND $dst.lo,right_n_bits($mask, 8)" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzbl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- __ andl(Rdst, $mask$$constant & right_n_bits(8));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Short (16bit signed)
-instruct loadS(rRegI dst, memory mem) %{
- match(Set dst (LoadS mem));
-
- ins_cost(125);
- format %{ "MOVSX $dst,$mem\t# short" %}
-
- ins_encode %{
- __ movswl($dst$$Register, $mem$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Short (16 bit signed) to Byte (8 bit signed)
-instruct loadS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
- match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
-
- ins_cost(125);
- format %{ "MOVSX $dst, $mem\t# short -> byte" %}
- ins_encode %{
- __ movsbl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Short (16bit signed) into Long Register
-instruct loadS2L(eRegL dst, memory mem, eFlagsReg cr) %{
- match(Set dst (ConvI2L (LoadS mem)));
- effect(KILL cr);
-
- ins_cost(375);
- format %{ "MOVSX $dst.lo,$mem\t# short -> long\n\t"
- "MOV $dst.hi,$dst.lo\n\t"
- "SAR $dst.hi,15" %}
-
- ins_encode %{
- __ movswl($dst$$Register, $mem$$Address);
- __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
- __ sarl(HIGH_FROM_LOW($dst$$Register), 15); // 16+1 MSB are already signed extended.
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Short/Char (16bit unsigned)
-instruct loadUS(rRegI dst, memory mem) %{
- match(Set dst (LoadUS mem));
-
- ins_cost(125);
- format %{ "MOVZX $dst,$mem\t# ushort/char -> int" %}
-
- ins_encode %{
- __ movzwl($dst$$Register, $mem$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
-instruct loadUS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
- match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
-
- ins_cost(125);
- format %{ "MOVSX $dst, $mem\t# ushort -> byte" %}
- ins_encode %{
- __ movsbl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
-instruct loadUS2L(eRegL dst, memory mem, eFlagsReg cr) %{
- match(Set dst (ConvI2L (LoadUS mem)));
- effect(KILL cr);
-
- ins_cost(250);
- format %{ "MOVZX $dst.lo,$mem\t# ushort/char -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
-
- ins_encode %{
- __ movzwl($dst$$Register, $mem$$Address);
- __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register
-instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
- effect(KILL cr);
-
- format %{ "MOVZX8 $dst.lo,$mem\t# ushort/char & 0xFF -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzbl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register
-instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
- effect(KILL cr);
-
- format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t"
- "XOR $dst.hi,$dst.hi\n\t"
- "AND $dst.lo,right_n_bits($mask, 16)" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzwl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- __ andl(Rdst, $mask$$constant & right_n_bits(16));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer
-instruct loadI(rRegI dst, memory mem) %{
- match(Set dst (LoadI mem));
-
- ins_cost(125);
- format %{ "MOV $dst,$mem\t# int" %}
-
- ins_encode %{
- __ movl($dst$$Register, $mem$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer (32 bit signed) to Byte (8 bit signed)
-instruct loadI2B(rRegI dst, memory mem, immI_24 twentyfour) %{
- match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
-
- ins_cost(125);
- format %{ "MOVSX $dst, $mem\t# int -> byte" %}
- ins_encode %{
- __ movsbl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned)
-instruct loadI2UB(rRegI dst, memory mem, immI_255 mask) %{
- match(Set dst (AndI (LoadI mem) mask));
-
- ins_cost(125);
- format %{ "MOVZX $dst, $mem\t# int -> ubyte" %}
- ins_encode %{
- __ movzbl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer (32 bit signed) to Short (16 bit signed)
-instruct loadI2S(rRegI dst, memory mem, immI_16 sixteen) %{
- match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
-
- ins_cost(125);
- format %{ "MOVSX $dst, $mem\t# int -> short" %}
- ins_encode %{
- __ movswl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned)
-instruct loadI2US(rRegI dst, memory mem, immI_65535 mask) %{
- match(Set dst (AndI (LoadI mem) mask));
-
- ins_cost(125);
- format %{ "MOVZX $dst, $mem\t# int -> ushort/char" %}
- ins_encode %{
- __ movzwl($dst$$Register, $mem$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer into Long Register
-instruct loadI2L(eRegL dst, memory mem, eFlagsReg cr) %{
- match(Set dst (ConvI2L (LoadI mem)));
- effect(KILL cr);
-
- ins_cost(375);
- format %{ "MOV $dst.lo,$mem\t# int -> long\n\t"
- "MOV $dst.hi,$dst.lo\n\t"
- "SAR $dst.hi,31" %}
-
- ins_encode %{
- __ movl($dst$$Register, $mem$$Address);
- __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
- __ sarl(HIGH_FROM_LOW($dst$$Register), 31);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer with mask 0xFF into Long Register
-instruct loadI2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
- effect(KILL cr);
-
- format %{ "MOVZX8 $dst.lo,$mem\t# int & 0xFF -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzbl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer with mask 0xFFFF into Long Register
-instruct loadI2L_immI_65535(eRegL dst, memory mem, immI_65535 mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
- effect(KILL cr);
-
- format %{ "MOVZX $dst.lo,$mem\t# int & 0xFFFF -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movzwl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Integer with 31-bit mask into Long Register
-instruct loadI2L_immU31(eRegL dst, memory mem, immU31 mask, eFlagsReg cr) %{
- match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
- effect(KILL cr);
-
- format %{ "MOV $dst.lo,$mem\t# int & 31-bit mask -> long\n\t"
- "XOR $dst.hi,$dst.hi\n\t"
- "AND $dst.lo,$mask" %}
- ins_encode %{
- Register Rdst = $dst$$Register;
- __ movl(Rdst, $mem$$Address);
- __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- __ andl(Rdst, $mask$$constant);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Unsigned Integer into Long Register
-instruct loadUI2L(eRegL dst, memory mem, immL_32bits mask, eFlagsReg cr) %{
- match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
- effect(KILL cr);
-
- ins_cost(250);
- format %{ "MOV $dst.lo,$mem\t# uint -> long\n\t"
- "XOR $dst.hi,$dst.hi" %}
-
- ins_encode %{
- __ movl($dst$$Register, $mem$$Address);
- __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Load Long. Cannot clobber address while loading, so restrict address
-// register to ESI
-instruct loadL(eRegL dst, load_long_memory mem) %{
- predicate(!((LoadLNode*)n)->require_atomic_access());
- match(Set dst (LoadL mem));
-
- ins_cost(250);
- format %{ "MOV $dst.lo,$mem\t# long\n\t"
- "MOV $dst.hi,$mem+4" %}
-
- ins_encode %{
- Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
- Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
- __ movl($dst$$Register, Amemlo);
- __ movl(HIGH_FROM_LOW($dst$$Register), Amemhi);
- %}
-
- ins_pipe(ialu_reg_long_mem);
-%}
-
-// Volatile Load Long. Must be atomic, so do 64-bit FILD
-// then store it down to the stack and reload on the int
-// side.
-instruct loadL_volatile(stackSlotL dst, memory mem) %{
- predicate(UseSSE<=1 && ((LoadLNode*)n)->require_atomic_access());
- match(Set dst (LoadL mem));
-
- ins_cost(200);
- format %{ "FILD $mem\t# Atomic volatile long load\n\t"
- "FISTp $dst" %}
- ins_encode(enc_loadL_volatile(mem,dst));
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct loadLX_volatile(stackSlotL dst, memory mem, regD tmp) %{
- predicate(UseSSE>=2 && ((LoadLNode*)n)->require_atomic_access());
- match(Set dst (LoadL mem));
- effect(TEMP tmp);
- ins_cost(180);
- format %{ "MOVSD $tmp,$mem\t# Atomic volatile long load\n\t"
- "MOVSD $dst,$tmp" %}
- ins_encode %{
- __ movdbl($tmp$$XMMRegister, $mem$$Address);
- __ movdbl(Address(rsp, $dst$$disp), $tmp$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct loadLX_reg_volatile(eRegL dst, memory mem, regD tmp) %{
- predicate(UseSSE>=2 && ((LoadLNode*)n)->require_atomic_access());
- match(Set dst (LoadL mem));
- effect(TEMP tmp);
- ins_cost(160);
- format %{ "MOVSD $tmp,$mem\t# Atomic volatile long load\n\t"
- "MOVD $dst.lo,$tmp\n\t"
- "PSRLQ $tmp,32\n\t"
- "MOVD $dst.hi,$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 );
-%}
-
-// Load Range
-instruct loadRange(rRegI dst, memory mem) %{
- match(Set dst (LoadRange mem));
-
- ins_cost(125);
- format %{ "MOV $dst,$mem" %}
- opcode(0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_mem );
-%}
-
-
-// Load Pointer
-instruct loadP(eRegP dst, memory mem) %{
- match(Set dst (LoadP mem));
-
- ins_cost(125);
- format %{ "MOV $dst,$mem" %}
- opcode(0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_mem );
-%}
-
-// Load Klass Pointer
-instruct loadKlass(eRegP dst, memory mem) %{
- match(Set dst (LoadKlass mem));
-
- ins_cost(125);
- format %{ "MOV $dst,$mem" %}
- opcode(0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_mem );
-%}
-
-// Load Double
-instruct loadDPR(regDPR dst, memory mem) %{
- predicate(UseSSE<=1);
- match(Set dst (LoadD mem));
-
- ins_cost(150);
- format %{ "FLD_D ST,$mem\n\t"
- "FSTP $dst" %}
- opcode(0xDD); /* DD /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem),
- Pop_Reg_DPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// Load Double to XMM
-instruct loadD(regD dst, memory mem) %{
- predicate(UseSSE>=2 && UseXmmLoadAndClearUpper);
- match(Set dst (LoadD mem));
- ins_cost(145);
- format %{ "MOVSD $dst,$mem" %}
- ins_encode %{
- __ movdbl ($dst$$XMMRegister, $mem$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct loadD_partial(regD dst, memory mem) %{
- predicate(UseSSE>=2 && !UseXmmLoadAndClearUpper);
- match(Set dst (LoadD mem));
- ins_cost(145);
- format %{ "MOVLPD $dst,$mem" %}
- ins_encode %{
- __ movdbl ($dst$$XMMRegister, $mem$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Load to XMM register (single-precision floating point)
-// MOVSS instruction
-instruct loadF(regF dst, memory mem) %{
- predicate(UseSSE>=1);
- match(Set dst (LoadF mem));
- ins_cost(145);
- format %{ "MOVSS $dst,$mem" %}
- ins_encode %{
- __ movflt ($dst$$XMMRegister, $mem$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Load Float
-instruct loadFPR(regFPR dst, memory mem) %{
- predicate(UseSSE==0);
- match(Set dst (LoadF mem));
-
- ins_cost(150);
- format %{ "FLD_S ST,$mem\n\t"
- "FSTP $dst" %}
- opcode(0xD9); /* D9 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// Load Effective Address
-instruct leaP8(eRegP dst, indOffset8 mem) %{
- match(Set dst mem);
-
- ins_cost(110);
- format %{ "LEA $dst,$mem" %}
- opcode(0x8D);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_reg_fat );
-%}
-
-instruct leaP32(eRegP dst, indOffset32 mem) %{
- match(Set dst mem);
-
- ins_cost(110);
- format %{ "LEA $dst,$mem" %}
- opcode(0x8D);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_reg_fat );
-%}
-
-instruct leaPIdxOff(eRegP dst, indIndexOffset mem) %{
- match(Set dst mem);
-
- ins_cost(110);
- format %{ "LEA $dst,$mem" %}
- opcode(0x8D);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_reg_fat );
-%}
-
-instruct leaPIdxScale(eRegP dst, indIndexScale mem) %{
- match(Set dst mem);
-
- ins_cost(110);
- format %{ "LEA $dst,$mem" %}
- opcode(0x8D);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_reg_fat );
-%}
-
-instruct leaPIdxScaleOff(eRegP dst, indIndexScaleOffset mem) %{
- match(Set dst mem);
-
- ins_cost(110);
- format %{ "LEA $dst,$mem" %}
- opcode(0x8D);
- ins_encode( SetInstMark, OpcP, RegMem(dst,mem), ClearInstMark);
- ins_pipe( ialu_reg_reg_fat );
-%}
-
-// Load Constant
-instruct loadConI(rRegI dst, immI src) %{
- match(Set dst src);
-
- format %{ "MOV $dst,$src" %}
- ins_encode( SetInstMark, LdImmI(dst, src), ClearInstMark );
- ins_pipe( ialu_reg_fat );
-%}
-
-// Load Constant zero
-instruct loadConI0(rRegI dst, immI_0 src, eFlagsReg cr) %{
- match(Set dst src);
- effect(KILL cr);
-
- ins_cost(50);
- format %{ "XOR $dst,$dst" %}
- opcode(0x33); /* + rd */
- ins_encode( OpcP, RegReg( dst, dst ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct loadConP(eRegP dst, immP src) %{
- match(Set dst src);
-
- format %{ "MOV $dst,$src" %}
- opcode(0xB8); /* + rd */
- ins_encode( SetInstMark, LdImmP(dst, src), ClearInstMark );
- ins_pipe( ialu_reg_fat );
-%}
-
-instruct loadConL(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst src);
- effect(KILL cr);
- ins_cost(200);
- format %{ "MOV $dst.lo,$src.lo\n\t"
- "MOV $dst.hi,$src.hi" %}
- opcode(0xB8);
- ins_encode( LdImmL_Lo(dst, src), LdImmL_Hi(dst, src) );
- ins_pipe( ialu_reg_long_fat );
-%}
-
-instruct loadConL0(eRegL dst, immL0 src, eFlagsReg cr) %{
- match(Set dst src);
- effect(KILL cr);
- ins_cost(150);
- format %{ "XOR $dst.lo,$dst.lo\n\t"
- "XOR $dst.hi,$dst.hi" %}
- opcode(0x33,0x33);
- ins_encode( RegReg_Lo(dst,dst), RegReg_Hi(dst, dst) );
- ins_pipe( ialu_reg_long );
-%}
-
-// The instruction usage is guarded by predicate in operand immFPR().
-instruct loadConFPR(regFPR dst, immFPR con) %{
- match(Set dst con);
- ins_cost(125);
- format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld_s($constantaddress($con));
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immFPR0().
-instruct loadConFPR0(regFPR dst, immFPR0 con) %{
- match(Set dst con);
- ins_cost(125);
- format %{ "FLDZ ST\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fldz();
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immFPR1().
-instruct loadConFPR1(regFPR dst, immFPR1 con) %{
- match(Set dst con);
- ins_cost(125);
- format %{ "FLD1 ST\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld1();
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immF().
-instruct loadConF(regF dst, immF con) %{
- match(Set dst con);
- ins_cost(125);
- format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
- ins_encode %{
- __ movflt($dst$$XMMRegister, $constantaddress($con));
- %}
- ins_pipe(pipe_slow);
-%}
-
-// The instruction usage is guarded by predicate in operand immF0().
-instruct loadConF0(regF dst, immF0 src) %{
- match(Set dst src);
- ins_cost(100);
- format %{ "XORPS $dst,$dst\t# float 0.0" %}
- ins_encode %{
- __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe(pipe_slow);
-%}
-
-// The instruction usage is guarded by predicate in operand immDPR().
-instruct loadConDPR(regDPR dst, immDPR con) %{
- match(Set dst con);
- ins_cost(125);
-
- format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld_d($constantaddress($con));
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immDPR0().
-instruct loadConDPR0(regDPR dst, immDPR0 con) %{
- match(Set dst con);
- ins_cost(125);
-
- format %{ "FLDZ ST\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fldz();
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immDPR1().
-instruct loadConDPR1(regDPR dst, immDPR1 con) %{
- match(Set dst con);
- ins_cost(125);
-
- format %{ "FLD1 ST\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld1();
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_con);
-%}
-
-// The instruction usage is guarded by predicate in operand immD().
-instruct loadConD(regD dst, immD con) %{
- match(Set dst con);
- ins_cost(125);
- format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
- ins_encode %{
- __ movdbl($dst$$XMMRegister, $constantaddress($con));
- %}
- ins_pipe(pipe_slow);
-%}
-
-// The instruction usage is guarded by predicate in operand immD0().
-instruct loadConD0(regD dst, immD0 src) %{
- match(Set dst src);
- ins_cost(100);
- format %{ "XORPD $dst,$dst\t# double 0.0" %}
- ins_encode %{
- __ xorpd ($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Load Stack Slot
-instruct loadSSI(rRegI dst, stackSlotI src) %{
- match(Set dst src);
- ins_cost(125);
-
- format %{ "MOV $dst,$src" %}
- opcode(0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,src), ClearInstMark);
- ins_pipe( ialu_reg_mem );
-%}
-
-instruct loadSSL(eRegL dst, stackSlotL src) %{
- match(Set dst src);
-
- ins_cost(200);
- format %{ "MOV $dst,$src.lo\n\t"
- "MOV $dst+4,$src.hi" %}
- opcode(0x8B, 0x8B);
- ins_encode( SetInstMark, OpcP, RegMem( dst, src ), OpcS, RegMem_Hi( dst, src ), ClearInstMark );
- ins_pipe( ialu_mem_long_reg );
-%}
-
-// Load Stack Slot
-instruct loadSSP(eRegP dst, stackSlotP src) %{
- match(Set dst src);
- ins_cost(125);
-
- format %{ "MOV $dst,$src" %}
- opcode(0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,src), ClearInstMark);
- ins_pipe( ialu_reg_mem );
-%}
-
-// Load Stack Slot
-instruct loadSSF(regFPR dst, stackSlotF src) %{
- match(Set dst src);
- ins_cost(125);
-
- format %{ "FLD_S $src\n\t"
- "FSTP $dst" %}
- opcode(0xD9); /* D9 /0, FLD m32real */
- ins_encode( SetInstMark, OpcP, RMopc_Mem_no_oop(0x00,src),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// Load Stack Slot
-instruct loadSSD(regDPR dst, stackSlotD src) %{
- match(Set dst src);
- ins_cost(125);
-
- format %{ "FLD_D $src\n\t"
- "FSTP $dst" %}
- opcode(0xDD); /* DD /0, FLD m64real */
- ins_encode( SetInstMark, OpcP, RMopc_Mem_no_oop(0x00,src),
- Pop_Reg_DPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// Prefetch instructions for allocation.
-// Must be safe to execute with invalid address (cannot fault).
-
-instruct prefetchAlloc0( memory mem ) %{
- predicate(UseSSE==0 && AllocatePrefetchInstr!=3);
- match(PrefetchAllocation mem);
- ins_cost(0);
- size(0);
- format %{ "Prefetch allocation (non-SSE is empty encoding)" %}
- ins_encode();
- ins_pipe(empty);
-%}
-
-instruct prefetchAlloc( memory mem ) %{
- predicate(AllocatePrefetchInstr==3);
- match( PrefetchAllocation mem );
- ins_cost(100);
-
- format %{ "PREFETCHW $mem\t! Prefetch allocation into L1 cache and mark modified" %}
- ins_encode %{
- __ prefetchw($mem$$Address);
- %}
- ins_pipe(ialu_mem);
-%}
-
-instruct prefetchAllocNTA( memory mem ) %{
- predicate(UseSSE>=1 && AllocatePrefetchInstr==0);
- match(PrefetchAllocation mem);
- ins_cost(100);
-
- format %{ "PREFETCHNTA $mem\t! Prefetch allocation into non-temporal cache for write" %}
- ins_encode %{
- __ prefetchnta($mem$$Address);
- %}
- ins_pipe(ialu_mem);
-%}
-
-instruct prefetchAllocT0( memory mem ) %{
- predicate(UseSSE>=1 && AllocatePrefetchInstr==1);
- match(PrefetchAllocation mem);
- ins_cost(100);
-
- format %{ "PREFETCHT0 $mem\t! Prefetch allocation into L1 and L2 caches for write" %}
- ins_encode %{
- __ prefetcht0($mem$$Address);
- %}
- ins_pipe(ialu_mem);
-%}
-
-instruct prefetchAllocT2( memory mem ) %{
- predicate(UseSSE>=1 && AllocatePrefetchInstr==2);
- match(PrefetchAllocation mem);
- ins_cost(100);
-
- format %{ "PREFETCHT2 $mem\t! Prefetch allocation into L2 cache for write" %}
- ins_encode %{
- __ prefetcht2($mem$$Address);
- %}
- ins_pipe(ialu_mem);
-%}
-
-//----------Store Instructions-------------------------------------------------
-
-// Store Byte
-instruct storeB(memory mem, xRegI src) %{
- match(Set mem (StoreB mem src));
-
- ins_cost(125);
- format %{ "MOV8 $mem,$src" %}
- opcode(0x88);
- ins_encode( SetInstMark, OpcP, RegMem( src, mem ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Char/Short
-instruct storeC(memory mem, rRegI src) %{
- match(Set mem (StoreC mem src));
-
- ins_cost(125);
- format %{ "MOV16 $mem,$src" %}
- opcode(0x89, 0x66);
- ins_encode( SetInstMark, OpcS, OpcP, RegMem( src, mem ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Integer
-instruct storeI(memory mem, rRegI src) %{
- match(Set mem (StoreI mem src));
-
- ins_cost(125);
- format %{ "MOV $mem,$src" %}
- opcode(0x89);
- ins_encode( SetInstMark, OpcP, RegMem( src, mem ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Long
-instruct storeL(long_memory mem, eRegL src) %{
- predicate(!((StoreLNode*)n)->require_atomic_access());
- match(Set mem (StoreL mem src));
-
- ins_cost(200);
- format %{ "MOV $mem,$src.lo\n\t"
- "MOV $mem+4,$src.hi" %}
- opcode(0x89, 0x89);
- ins_encode( SetInstMark, OpcP, RegMem( src, mem ), OpcS, RegMem_Hi( src, mem ), ClearInstMark );
- ins_pipe( ialu_mem_long_reg );
-%}
-
-// Store Long to Integer
-instruct storeL2I(memory mem, eRegL src) %{
- match(Set mem (StoreI mem (ConvL2I src)));
-
- format %{ "MOV $mem,$src.lo\t# long -> int" %}
- ins_encode %{
- __ movl($mem$$Address, $src$$Register);
- %}
- ins_pipe(ialu_mem_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)
-// so the memory operand is used twice in the encoding.
-instruct storeL_volatile(memory mem, stackSlotL src, eFlagsReg cr ) %{
- predicate(UseSSE<=1 && ((StoreLNode*)n)->require_atomic_access());
- match(Set mem (StoreL mem src));
- effect( KILL cr );
- ins_cost(400);
- format %{ "CMP $mem,EAX\t# Probe address for implicit null check\n\t"
- "FILD $src\n\t"
- "FISTp $mem\t # 64-bit atomic volatile long store" %}
- opcode(0x3B);
- ins_encode( SetInstMark, OpcP, RegMem( EAX, mem ), enc_storeL_volatile(mem,src), ClearInstMark);
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct storeLX_volatile(memory mem, stackSlotL src, regD tmp, eFlagsReg cr) %{
- predicate(UseSSE>=2 && ((StoreLNode*)n)->require_atomic_access());
- match(Set mem (StoreL mem src));
- effect( TEMP tmp, KILL cr );
- ins_cost(380);
- 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" %}
- ins_encode %{
- __ cmpl(rax, $mem$$Address);
- __ movdbl($tmp$$XMMRegister, Address(rsp, $src$$disp));
- __ movdbl($mem$$Address, $tmp$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct storeLX_reg_volatile(memory mem, eRegL src, regD tmp2, regD tmp, eFlagsReg cr) %{
- predicate(UseSSE>=2 && ((StoreLNode*)n)->require_atomic_access());
- match(Set mem (StoreL mem src));
- effect( TEMP tmp2 , TEMP tmp, KILL cr );
- ins_cost(360);
- format %{ "CMP $mem,EAX\t# Probe address for implicit null check\n\t"
- "MOVD $tmp,$src.lo\n\t"
- "MOVD $tmp2,$src.hi\n\t"
- "PUNPCKLDQ $tmp,$tmp2\n\t"
- "MOVSD $mem,$tmp\t # 64-bit atomic volatile long store" %}
- 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 );
-%}
-
-// Store Pointer; for storing unknown oops and raw pointers
-instruct storeP(memory mem, anyRegP src) %{
- match(Set mem (StoreP mem src));
-
- ins_cost(125);
- format %{ "MOV $mem,$src" %}
- opcode(0x89);
- ins_encode( SetInstMark, OpcP, RegMem( src, mem ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Integer Immediate
-instruct storeImmI(memory mem, immI src) %{
- match(Set mem (StoreI mem src));
-
- ins_cost(150);
- format %{ "MOV $mem,$src" %}
- opcode(0xC7); /* C7 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem), Con32(src), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store Short/Char Immediate
-instruct storeImmI16(memory mem, immI16 src) %{
- predicate(UseStoreImmI16);
- match(Set mem (StoreC mem src));
-
- ins_cost(150);
- format %{ "MOV16 $mem,$src" %}
- opcode(0xC7); /* C7 /0 Same as 32 store immediate with prefix */
- ins_encode( SetInstMark, SizePrefix, OpcP, RMopc_Mem(0x00,mem), Con16(src), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store Pointer Immediate; null pointers or constant oops that do not
-// need card-mark barriers.
-instruct storeImmP(memory mem, immP src) %{
- match(Set mem (StoreP mem src));
-
- ins_cost(150);
- format %{ "MOV $mem,$src" %}
- opcode(0xC7); /* C7 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem), Con32( src ), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store Byte Immediate
-instruct storeImmB(memory mem, immI8 src) %{
- match(Set mem (StoreB mem src));
-
- ins_cost(150);
- format %{ "MOV8 $mem,$src" %}
- opcode(0xC6); /* C6 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem), Con8or32(src), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store Double
-instruct storeDPR( memory mem, regDPR1 src) %{
- predicate(UseSSE<=1);
- match(Set mem (StoreD mem src));
-
- ins_cost(100);
- format %{ "FST_D $mem,$src" %}
- opcode(0xDD); /* DD /2 */
- ins_encode( enc_FPR_store(mem,src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Store double does rounding on x86
-instruct storeDPR_rounded( memory mem, regDPR1 src) %{
- predicate(UseSSE<=1);
- match(Set mem (StoreD mem (RoundDouble src)));
-
- ins_cost(100);
- format %{ "FST_D $mem,$src\t# round" %}
- opcode(0xDD); /* DD /2 */
- ins_encode( enc_FPR_store(mem,src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Store XMM register to memory (double-precision floating points)
-// MOVSD instruction
-instruct storeD(memory mem, regD src) %{
- predicate(UseSSE>=2);
- match(Set mem (StoreD mem src));
- ins_cost(95);
- format %{ "MOVSD $mem,$src" %}
- ins_encode %{
- __ movdbl($mem$$Address, $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Store XMM register to memory (single-precision floating point)
-// MOVSS instruction
-instruct storeF(memory mem, regF src) %{
- predicate(UseSSE>=1);
- match(Set mem (StoreF mem src));
- ins_cost(95);
- format %{ "MOVSS $mem,$src" %}
- ins_encode %{
- __ movflt($mem$$Address, $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-
-// Store Float
-instruct storeFPR( memory mem, regFPR1 src) %{
- predicate(UseSSE==0);
- match(Set mem (StoreF mem src));
-
- ins_cost(100);
- format %{ "FST_S $mem,$src" %}
- opcode(0xD9); /* D9 /2 */
- ins_encode( enc_FPR_store(mem,src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Store Float does rounding on x86
-instruct storeFPR_rounded( memory mem, regFPR1 src) %{
- predicate(UseSSE==0);
- match(Set mem (StoreF mem (RoundFloat src)));
-
- ins_cost(100);
- format %{ "FST_S $mem,$src\t# round" %}
- opcode(0xD9); /* D9 /2 */
- ins_encode( enc_FPR_store(mem,src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Store Float does rounding on x86
-instruct storeFPR_Drounded( memory mem, regDPR1 src) %{
- predicate(UseSSE<=1);
- match(Set mem (StoreF mem (ConvD2F src)));
-
- ins_cost(100);
- format %{ "FST_S $mem,$src\t# D-round" %}
- opcode(0xD9); /* D9 /2 */
- ins_encode( enc_FPR_store(mem,src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Store immediate Float value (it is faster than store from FPU register)
-// The instruction usage is guarded by predicate in operand immFPR().
-instruct storeFPR_imm( memory mem, immFPR src) %{
- match(Set mem (StoreF mem src));
-
- ins_cost(50);
- format %{ "MOV $mem,$src\t# store float" %}
- opcode(0xC7); /* C7 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem), Con32FPR_as_bits(src), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store immediate Float value (it is faster than store from XMM register)
-// The instruction usage is guarded by predicate in operand immF().
-instruct storeF_imm( memory mem, immF src) %{
- match(Set mem (StoreF mem src));
-
- ins_cost(50);
- format %{ "MOV $mem,$src\t# store float" %}
- opcode(0xC7); /* C7 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem), Con32F_as_bits(src), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-// Store Integer to stack slot
-instruct storeSSI(stackSlotI dst, rRegI src) %{
- match(Set dst src);
-
- ins_cost(100);
- format %{ "MOV $dst,$src" %}
- opcode(0x89);
- ins_encode( OpcPRegSS( dst, src ) );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Integer to stack slot
-instruct storeSSP(stackSlotP dst, eRegP src) %{
- match(Set dst src);
-
- ins_cost(100);
- format %{ "MOV $dst,$src" %}
- opcode(0x89);
- ins_encode( OpcPRegSS( dst, src ) );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Store Long to stack slot
-instruct storeSSL(stackSlotL dst, eRegL src) %{
- match(Set dst src);
-
- ins_cost(200);
- format %{ "MOV $dst,$src.lo\n\t"
- "MOV $dst+4,$src.hi" %}
- opcode(0x89, 0x89);
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), OpcS, RegMem_Hi( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_long_reg );
-%}
-
-//----------MemBar Instructions-----------------------------------------------
-// Memory barrier flavors
-
-instruct membar_acquire() %{
- match(MemBarAcquire);
- match(LoadFence);
- ins_cost(400);
-
- size(0);
- format %{ "MEMBAR-acquire ! (empty encoding)" %}
- ins_encode();
- ins_pipe(empty);
-%}
-
-instruct membar_acquire_lock() %{
- match(MemBarAcquireLock);
- ins_cost(0);
-
- size(0);
- format %{ "MEMBAR-acquire (prior CMPXCHG in FastLock so empty encoding)" %}
- ins_encode( );
- ins_pipe(empty);
-%}
-
-instruct membar_release() %{
- match(MemBarRelease);
- match(StoreFence);
- ins_cost(400);
-
- size(0);
- format %{ "MEMBAR-release ! (empty encoding)" %}
- ins_encode( );
- ins_pipe(empty);
-%}
-
-instruct membar_release_lock() %{
- match(MemBarReleaseLock);
- ins_cost(0);
-
- size(0);
- format %{ "MEMBAR-release (a FastUnlock follows so empty encoding)" %}
- ins_encode( );
- ins_pipe(empty);
-%}
-
-instruct membar_volatile(eFlagsReg cr) %{
- match(MemBarVolatile);
- effect(KILL cr);
- ins_cost(400);
-
- format %{
- $$template
- $$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile"
- %}
- ins_encode %{
- __ membar(Assembler::StoreLoad);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct unnecessary_membar_volatile() %{
- match(MemBarVolatile);
- predicate(Matcher::post_store_load_barrier(n));
- ins_cost(0);
-
- size(0);
- format %{ "MEMBAR-volatile (unnecessary so empty encoding)" %}
- ins_encode( );
- ins_pipe(empty);
-%}
-
-instruct membar_storestore() %{
- match(MemBarStoreStore);
- match(StoreStoreFence);
- ins_cost(0);
-
- size(0);
- format %{ "MEMBAR-storestore (empty encoding)" %}
- ins_encode( );
- ins_pipe(empty);
-%}
-
-//----------Move Instructions--------------------------------------------------
-instruct castX2P(eAXRegP dst, eAXRegI src) %{
- match(Set dst (CastX2P src));
- format %{ "# X2P $dst, $src" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe(empty);
-%}
-
-instruct castP2X(rRegI dst, eRegP src ) %{
- match(Set dst (CastP2X src));
- ins_cost(50);
- format %{ "MOV $dst, $src\t# CastP2X" %}
- ins_encode( enc_Copy( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-//----------Conditional Move---------------------------------------------------
-// Conditional move
-instruct jmovI_reg(cmpOp cop, eFlagsReg cr, rRegI dst, rRegI src) %{
- predicate(!VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "J$cop,us skip\t# signed cmove\n\t"
- "MOV $dst,$src\n"
- "skip:" %}
- ins_encode %{
- Label Lskip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
- __ movl($dst$$Register, $src$$Register);
- __ bind(Lskip);
- %}
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct jmovI_regU(cmpOpU cop, eFlagsRegU cr, rRegI dst, rRegI src) %{
- predicate(!VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "J$cop,us skip\t# unsigned cmove\n\t"
- "MOV $dst,$src\n"
- "skip:" %}
- ins_encode %{
- Label Lskip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
- __ movl($dst$$Register, $src$$Register);
- __ bind(Lskip);
- %}
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovI_reg(rRegI dst, rRegI src, eFlagsReg cr, cmpOp cop ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, rRegI dst, rRegI src ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, rRegI dst, rRegI src ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovI_regU(cop, cr, dst, src);
- %}
-%}
-
-// Conditional move
-instruct cmovI_mem(cmpOp cop, eFlagsReg cr, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
- ins_cost(250);
- format %{ "CMOV$cop $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cop), RegMem( dst, src ), ClearInstMark );
- ins_pipe( pipe_cmov_mem );
-%}
-
-// Conditional move
-instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
- ins_cost(250);
- format %{ "CMOV$cop $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cop), RegMem( dst, src ), ClearInstMark );
- ins_pipe( pipe_cmov_mem );
-%}
-
-instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
- ins_cost(250);
- expand %{
- cmovI_memU(cop, cr, dst, src);
- %}
-%}
-
-// Conditional move
-instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst,$src\t# ptr" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-// Conditional move (non-P6 version)
-// Note: a CMoveP is generated for stubs and native wrappers
-// regardless of whether we are on a P6, so we
-// emulate a cmov here
-instruct cmovP_reg_nonP6(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
- match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
- ins_cost(300);
- format %{ "Jn$cop skip\n\t"
- "MOV $dst,$src\t# pointer\n"
- "skip:" %}
- opcode(0x8b);
- ins_encode( enc_cmov_branch(cop, 0x2), OpcP, RegReg(dst, src));
- ins_pipe( pipe_cmov_reg );
-%}
-
-// Conditional move
-instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst,$src\t# ptr" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovP_regU(cop, cr, dst, src);
- %}
-%}
-
-// DISABLED: Requires the ADLC to emit a bottom_type call that
-// correctly meets the two pointer arguments; one is an incoming
-// register but the other is a memory operand. ALSO appears to
-// be buggy with implicit null checks.
-//
-//// Conditional move
-//instruct cmovP_mem(cmpOp cop, eFlagsReg cr, eRegP dst, memory src) %{
-// predicate(VM_Version::supports_cmov() );
-// match(Set dst (CMoveP (Binary cop cr) (Binary dst (LoadP src))));
-// ins_cost(250);
-// format %{ "CMOV$cop $dst,$src\t# ptr" %}
-// opcode(0x0F,0x40);
-// ins_encode( enc_cmov(cop), RegMem( dst, src ) );
-// ins_pipe( pipe_cmov_mem );
-//%}
-//
-//// Conditional move
-//instruct cmovP_memU(cmpOpU cop, eFlagsRegU cr, eRegP dst, memory src) %{
-// predicate(VM_Version::supports_cmov() );
-// match(Set dst (CMoveP (Binary cop cr) (Binary dst (LoadP src))));
-// ins_cost(250);
-// format %{ "CMOV$cop $dst,$src\t# ptr" %}
-// opcode(0x0F,0x40);
-// ins_encode( enc_cmov(cop), RegMem( dst, src ) );
-// ins_pipe( pipe_cmov_mem );
-//%}
-
-// Conditional move
-instruct fcmovDPR_regU(cmpOp_fcmov cop, eFlagsRegU cr, regDPR1 dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "FCMOV$cop $dst,$src\t# double" %}
- opcode(0xDA);
- ins_encode( enc_cmov_dpr(cop,src) );
- ins_pipe( pipe_cmovDPR_reg );
-%}
-
-// Conditional move
-instruct fcmovFPR_regU(cmpOp_fcmov cop, eFlagsRegU cr, regFPR1 dst, regFPR src) %{
- predicate(UseSSE==0);
- match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "FCMOV$cop $dst,$src\t# float" %}
- opcode(0xDA);
- ins_encode( enc_cmov_dpr(cop,src) );
- ins_pipe( pipe_cmovDPR_reg );
-%}
-
-// Float CMOV on Intel doesn't handle *signed* compares, only unsigned.
-instruct fcmovDPR_regS(cmpOp cop, eFlagsReg cr, regDPR dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOV $dst,$src\t# double\n"
- "skip:" %}
- opcode (0xdd, 0x3); /* DD D8+i or DD /3 */
- ins_encode( enc_cmov_branch( cop, 0x4 ), Push_Reg_DPR(src), OpcP, RegOpc(dst) );
- ins_pipe( pipe_cmovDPR_reg );
-%}
-
-// Float CMOV on Intel doesn't handle *signed* compares, only unsigned.
-instruct fcmovFPR_regS(cmpOp cop, eFlagsReg cr, regFPR dst, regFPR src) %{
- predicate(UseSSE==0);
- match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOV $dst,$src\t# float\n"
- "skip:" %}
- opcode (0xdd, 0x3); /* DD D8+i or DD /3 */
- ins_encode( enc_cmov_branch( cop, 0x4 ), Push_Reg_FPR(src), OpcP, RegOpc(dst) );
- ins_pipe( pipe_cmovDPR_reg );
-%}
-
-// No CMOVE with SSE/SSE2
-instruct fcmovF_regS(cmpOp cop, eFlagsReg cr, regF dst, regF src) %{
- predicate (UseSSE>=1);
- match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOVSS $dst,$src\t# float\n"
- "skip:" %}
- ins_encode %{
- Label skip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), skip);
- __ movflt($dst$$XMMRegister, $src$$XMMRegister);
- __ bind(skip);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// No CMOVE with SSE/SSE2
-instruct fcmovD_regS(cmpOp cop, eFlagsReg cr, regD dst, regD src) %{
- predicate (UseSSE>=2);
- match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOVSD $dst,$src\t# float\n"
- "skip:" %}
- ins_encode %{
- Label skip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), skip);
- __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
- __ bind(skip);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// unsigned version
-instruct fcmovF_regU(cmpOpU cop, eFlagsRegU cr, regF dst, regF src) %{
- predicate (UseSSE>=1);
- match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOVSS $dst,$src\t# float\n"
- "skip:" %}
- ins_encode %{
- Label skip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), skip);
- __ movflt($dst$$XMMRegister, $src$$XMMRegister);
- __ bind(skip);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct fcmovF_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regF dst, regF src) %{
- predicate (UseSSE>=1);
- match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovF_regU(cop, cr, dst, src);
- %}
-%}
-
-// unsigned version
-instruct fcmovD_regU(cmpOpU cop, eFlagsRegU cr, regD dst, regD src) %{
- predicate (UseSSE>=2);
- match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "Jn$cop skip\n\t"
- "MOVSD $dst,$src\t# float\n"
- "skip:" %}
- ins_encode %{
- Label skip;
- // Invert sense of branch from sense of CMOV
- __ jccb((Assembler::Condition)($cop$$cmpcode^1), skip);
- __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
- __ bind(skip);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct fcmovD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regD dst, regD src) %{
- predicate (UseSSE>=2);
- match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovD_regU(cop, cr, dst, src);
- %}
-%}
-
-instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst.lo,$src.lo\n\t"
- "CMOV$cop $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg_Lo2( dst, src ), enc_cmov(cop), RegReg_Hi2( dst, src ) );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovL_regU(cmpOpU cop, eFlagsRegU cr, eRegL dst, eRegL src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cop $dst.lo,$src.lo\n\t"
- "CMOV$cop $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cop), RegReg_Lo2( dst, src ), enc_cmov(cop), RegReg_Hi2( dst, src ) );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{
- predicate(VM_Version::supports_cmov() );
- match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovL_regU(cop, cr, dst, src);
- %}
-%}
-
-//----------Arithmetic Instructions--------------------------------------------
-//----------Addition Instructions----------------------------------------------
-
-// Integer Addition Instructions
-instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (AddI dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "ADD $dst,$src" %}
- opcode(0x03);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct addI_eReg_imm(rRegI dst, immI src, eFlagsReg cr) %{
- match(Set dst (AddI dst src));
- effect(KILL cr);
-
- format %{ "ADD $dst,$src" %}
- opcode(0x81, 0x00); /* /0 id */
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct incI_eReg(rRegI dst, immI_1 src, eFlagsReg cr) %{
- predicate(UseIncDec);
- match(Set dst (AddI dst src));
- effect(KILL cr);
-
- size(1);
- format %{ "INC $dst" %}
- opcode(0x40); /* */
- ins_encode( Opc_plus( primary, dst ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct leaI_eReg_immI(rRegI dst, rRegI src0, immI src1) %{
- match(Set dst (AddI src0 src1));
- ins_cost(110);
-
- format %{ "LEA $dst,[$src0 + $src1]" %}
- opcode(0x8D); /* 0x8D /r */
- ins_encode( SetInstMark, OpcP, RegLea( dst, src0, src1 ), ClearInstMark );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct leaP_eReg_immI(eRegP dst, eRegP src0, immI src1) %{
- match(Set dst (AddP src0 src1));
- ins_cost(110);
-
- format %{ "LEA $dst,[$src0 + $src1]\t# ptr" %}
- opcode(0x8D); /* 0x8D /r */
- ins_encode( SetInstMark, OpcP, RegLea( dst, src0, src1 ), ClearInstMark );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct decI_eReg(rRegI dst, immI_M1 src, eFlagsReg cr) %{
- predicate(UseIncDec);
- match(Set dst (AddI dst src));
- effect(KILL cr);
-
- size(1);
- format %{ "DEC $dst" %}
- opcode(0x48); /* */
- ins_encode( Opc_plus( primary, dst ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct addP_eReg(eRegP dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (AddP dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "ADD $dst,$src" %}
- opcode(0x03);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct addP_eReg_imm(eRegP dst, immI src, eFlagsReg cr) %{
- match(Set dst (AddP dst src));
- effect(KILL cr);
-
- format %{ "ADD $dst,$src" %}
- opcode(0x81,0x00); /* Opcode 81 /0 id */
- // ins_encode( RegImm( dst, src) );
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct addI_eReg_mem(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (AddI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "ADD $dst,$src" %}
- opcode(0x03);
- ins_encode( SetInstMark, OpcP, RegMem( dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem );
-%}
-
-instruct addI_mem_eReg(memory dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AddI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "ADD $dst,$src" %}
- opcode(0x01); /* Opcode 01 /r */
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Add Memory with Immediate
-instruct addI_mem_imm(memory dst, immI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AddI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "ADD $dst,$src" %}
- opcode(0x81); /* Opcode 81 /0 id */
- ins_encode( SetInstMark, OpcSE( src ), RMopc_Mem(0x00,dst), Con8or32(src), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-instruct incI_mem(memory dst, immI_1 src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AddI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "INC $dst" %}
- opcode(0xFF); /* Opcode FF /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,dst), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-instruct decI_mem(memory dst, immI_M1 src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AddI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "DEC $dst" %}
- opcode(0xFF); /* Opcode FF /1 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x01,dst), ClearInstMark);
- ins_pipe( ialu_mem_imm );
-%}
-
-
-instruct checkCastPP( eRegP dst ) %{
- match(Set dst (CheckCastPP dst));
-
- size(0);
- format %{ "#checkcastPP of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_pipe( empty );
-%}
-
-instruct castPP( eRegP dst ) %{
- match(Set dst (CastPP dst));
- format %{ "#castPP of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_pipe( empty );
-%}
-
-instruct castII( rRegI dst ) %{
- match(Set dst (CastII dst));
- format %{ "#castII of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-instruct castLL( eRegL dst ) %{
- match(Set dst (CastLL dst));
- format %{ "#castLL of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-instruct castFF( regF dst ) %{
- predicate(UseSSE >= 1);
- match(Set dst (CastFF dst));
- format %{ "#castFF of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-instruct castDD( regD dst ) %{
- predicate(UseSSE >= 2);
- match(Set dst (CastDD dst));
- format %{ "#castDD of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-instruct castFF_PR( regFPR dst ) %{
- predicate(UseSSE < 1);
- match(Set dst (CastFF dst));
- format %{ "#castFF of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-instruct castDD_PR( regDPR dst ) %{
- predicate(UseSSE < 2);
- match(Set dst (CastDD dst));
- format %{ "#castDD of $dst" %}
- ins_encode( /*empty encoding*/ );
- ins_cost(0);
- ins_pipe( empty );
-%}
-
-// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
-
-instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
- match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
- match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
- format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
- "MOV $res,0\n\t"
- "JNE,s fail\n\t"
- "MOV $res,1\n"
- "fail:" %}
- ins_encode( enc_cmpxchg8(mem_ptr),
- enc_flags_ne_to_boolean(res) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
- match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
- match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
- format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
- "MOV $res,0\n\t"
- "JNE,s fail\n\t"
- "MOV $res,1\n"
- "fail:" %}
- ins_encode( enc_cmpxchg(mem_ptr), enc_flags_ne_to_boolean(res) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndSwapB( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr ) %{
- match(Set res (CompareAndSwapB mem_ptr (Binary oldval newval)));
- match(Set res (WeakCompareAndSwapB mem_ptr (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
- format %{ "CMPXCHGB [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
- "MOV $res,0\n\t"
- "JNE,s fail\n\t"
- "MOV $res,1\n"
- "fail:" %}
- ins_encode( enc_cmpxchgb(mem_ptr),
- enc_flags_ne_to_boolean(res) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndSwapS( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr ) %{
- match(Set res (CompareAndSwapS mem_ptr (Binary oldval newval)));
- match(Set res (WeakCompareAndSwapS mem_ptr (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
- format %{ "CMPXCHGW [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
- "MOV $res,0\n\t"
- "JNE,s fail\n\t"
- "MOV $res,1\n"
- "fail:" %}
- ins_encode( enc_cmpxchgw(mem_ptr),
- enc_flags_ne_to_boolean(res) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
- match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
- match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
- format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
- "MOV $res,0\n\t"
- "JNE,s fail\n\t"
- "MOV $res,1\n"
- "fail:" %}
- ins_encode( enc_cmpxchg(mem_ptr), enc_flags_ne_to_boolean(res) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndExchangeL( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
- match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
- effect(KILL cr);
- format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
- ins_encode( enc_cmpxchg8(mem_ptr) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndExchangeP( pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
- match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
- effect(KILL cr);
- format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
- ins_encode( enc_cmpxchg(mem_ptr) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndExchangeB( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
- match(Set oldval (CompareAndExchangeB mem_ptr (Binary oldval newval)));
- effect(KILL cr);
- format %{ "CMPXCHGB [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
- ins_encode( enc_cmpxchgb(mem_ptr) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndExchangeS( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
- match(Set oldval (CompareAndExchangeS mem_ptr (Binary oldval newval)));
- effect(KILL cr);
- format %{ "CMPXCHGW [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
- ins_encode( enc_cmpxchgw(mem_ptr) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct compareAndExchangeI( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
- match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
- effect(KILL cr);
- format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
- ins_encode( enc_cmpxchg(mem_ptr) );
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xaddB_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
- predicate(n->as_LoadStore()->result_not_used());
- match(Set dummy (GetAndAddB mem add));
- effect(KILL cr);
- format %{ "ADDB [$mem],$add" %}
- ins_encode %{
- __ lock();
- __ addb($mem$$Address, $add$$constant);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-// Important to match to xRegI: only 8-bit regs.
-instruct xaddB( memory mem, xRegI newval, eFlagsReg cr) %{
- match(Set newval (GetAndAddB mem newval));
- effect(KILL cr);
- format %{ "XADDB [$mem],$newval" %}
- ins_encode %{
- __ lock();
- __ xaddb($mem$$Address, $newval$$Register);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xaddS_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
- predicate(n->as_LoadStore()->result_not_used());
- match(Set dummy (GetAndAddS mem add));
- effect(KILL cr);
- format %{ "ADDS [$mem],$add" %}
- ins_encode %{
- __ lock();
- __ addw($mem$$Address, $add$$constant);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xaddS( memory mem, rRegI newval, eFlagsReg cr) %{
- match(Set newval (GetAndAddS mem newval));
- effect(KILL cr);
- format %{ "XADDS [$mem],$newval" %}
- ins_encode %{
- __ lock();
- __ xaddw($mem$$Address, $newval$$Register);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
- predicate(n->as_LoadStore()->result_not_used());
- match(Set dummy (GetAndAddI mem add));
- effect(KILL cr);
- format %{ "ADDL [$mem],$add" %}
- ins_encode %{
- __ lock();
- __ addl($mem$$Address, $add$$constant);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xaddI( memory mem, rRegI newval, eFlagsReg cr) %{
- match(Set newval (GetAndAddI mem newval));
- effect(KILL cr);
- format %{ "XADDL [$mem],$newval" %}
- ins_encode %{
- __ lock();
- __ xaddl($mem$$Address, $newval$$Register);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-// Important to match to xRegI: only 8-bit regs.
-instruct xchgB( memory mem, xRegI newval) %{
- match(Set newval (GetAndSetB mem newval));
- format %{ "XCHGB $newval,[$mem]" %}
- ins_encode %{
- __ xchgb($newval$$Register, $mem$$Address);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xchgS( memory mem, rRegI newval) %{
- match(Set newval (GetAndSetS mem newval));
- format %{ "XCHGW $newval,[$mem]" %}
- ins_encode %{
- __ xchgw($newval$$Register, $mem$$Address);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xchgI( memory mem, rRegI newval) %{
- match(Set newval (GetAndSetI mem newval));
- format %{ "XCHGL $newval,[$mem]" %}
- ins_encode %{
- __ xchgl($newval$$Register, $mem$$Address);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-instruct xchgP( memory mem, pRegP newval) %{
- match(Set newval (GetAndSetP mem newval));
- format %{ "XCHGL $newval,[$mem]" %}
- ins_encode %{
- __ xchgl($newval$$Register, $mem$$Address);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
-
-//----------Subtraction Instructions-------------------------------------------
-
-// Integer Subtraction Instructions
-instruct subI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (SubI dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "SUB $dst,$src" %}
- opcode(0x2B);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct subI_eReg_imm(rRegI dst, immI src, eFlagsReg cr) %{
- match(Set dst (SubI dst src));
- effect(KILL cr);
-
- format %{ "SUB $dst,$src" %}
- opcode(0x81,0x05); /* Opcode 81 /5 */
- // ins_encode( RegImm( dst, src) );
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct subI_eReg_mem(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (SubI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "SUB $dst,$src" %}
- opcode(0x2B);
- ins_encode( SetInstMark, OpcP, RegMem( dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem );
-%}
-
-instruct subI_mem_eReg(memory dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (SubI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "SUB $dst,$src" %}
- opcode(0x29); /* Opcode 29 /r */
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Subtract from a pointer
-instruct subP_eReg(eRegP dst, rRegI src, immI_0 zero, eFlagsReg cr) %{
- match(Set dst (AddP dst (SubI zero src)));
- effect(KILL cr);
-
- size(2);
- format %{ "SUB $dst,$src" %}
- opcode(0x2B);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct negI_eReg(rRegI dst, immI_0 zero, eFlagsReg cr) %{
- match(Set dst (SubI zero dst));
- effect(KILL cr);
-
- size(2);
- format %{ "NEG $dst" %}
- opcode(0xF7,0x03); // Opcode F7 /3
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg );
-%}
-
-//----------Multiplication/Division Instructions-------------------------------
-// Integer Multiplication Instructions
-// Multiply Register
-instruct mulI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (MulI dst src));
- effect(KILL cr);
-
- size(3);
- ins_cost(300);
- format %{ "IMUL $dst,$src" %}
- opcode(0xAF, 0x0F);
- ins_encode( OpcS, OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-// Multiply 32-bit Immediate
-instruct mulI_eReg_imm(rRegI dst, rRegI src, immI imm, eFlagsReg cr) %{
- match(Set dst (MulI src imm));
- effect(KILL cr);
-
- ins_cost(300);
- format %{ "IMUL $dst,$src,$imm" %}
- opcode(0x69); /* 69 /r id */
- ins_encode( OpcSE(imm), RegReg( dst, src ), Con8or32( imm ) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-instruct loadConL_low_only(eADXRegL_low_only dst, immL32 src, eFlagsReg cr) %{
- match(Set dst src);
- effect(KILL cr);
-
- // Note that this is artificially increased to make it more expensive than loadConL
- ins_cost(250);
- format %{ "MOV EAX,$src\t// low word only" %}
- opcode(0xB8);
- ins_encode( LdImmL_Lo(dst, src) );
- ins_pipe( ialu_reg_fat );
-%}
-
-// Multiply by 32-bit Immediate, taking the shifted high order results
-// (special case for shift by 32)
-instruct mulI_imm_high(eDXRegI dst, nadxRegI src1, eADXRegL_low_only src2, immI_32 cnt, eFlagsReg cr) %{
- match(Set dst (ConvL2I (RShiftL (MulL (ConvI2L src1) src2) cnt)));
- predicate( _kids[0]->_kids[0]->_kids[1]->_leaf->Opcode() == Op_ConL &&
- _kids[0]->_kids[0]->_kids[1]->_leaf->as_Type()->type()->is_long()->get_con() >= min_jint &&
- _kids[0]->_kids[0]->_kids[1]->_leaf->as_Type()->type()->is_long()->get_con() <= max_jint );
- effect(USE src1, KILL cr);
-
- // Note that this is adjusted by 150 to compensate for the overcosting of loadConL_low_only
- ins_cost(0*100 + 1*400 - 150);
- format %{ "IMUL EDX:EAX,$src1" %}
- ins_encode( multiply_con_and_shift_high( dst, src1, src2, cnt, cr ) );
- ins_pipe( pipe_slow );
-%}
-
-// Multiply by 32-bit Immediate, taking the shifted high order results
-instruct mulI_imm_RShift_high(eDXRegI dst, nadxRegI src1, eADXRegL_low_only src2, immI_32_63 cnt, eFlagsReg cr) %{
- match(Set dst (ConvL2I (RShiftL (MulL (ConvI2L src1) src2) cnt)));
- predicate( _kids[0]->_kids[0]->_kids[1]->_leaf->Opcode() == Op_ConL &&
- _kids[0]->_kids[0]->_kids[1]->_leaf->as_Type()->type()->is_long()->get_con() >= min_jint &&
- _kids[0]->_kids[0]->_kids[1]->_leaf->as_Type()->type()->is_long()->get_con() <= max_jint );
- effect(USE src1, KILL cr);
-
- // Note that this is adjusted by 150 to compensate for the overcosting of loadConL_low_only
- ins_cost(1*100 + 1*400 - 150);
- format %{ "IMUL EDX:EAX,$src1\n\t"
- "SAR EDX,$cnt-32" %}
- ins_encode( multiply_con_and_shift_high( dst, src1, src2, cnt, cr ) );
- ins_pipe( pipe_slow );
-%}
-
-// Multiply Memory 32-bit Immediate
-instruct mulI_mem_imm(rRegI dst, memory src, immI imm, eFlagsReg cr) %{
- match(Set dst (MulI (LoadI src) imm));
- effect(KILL cr);
-
- ins_cost(300);
- format %{ "IMUL $dst,$src,$imm" %}
- opcode(0x69); /* 69 /r id */
- ins_encode( SetInstMark, OpcSE(imm), RegMem( dst, src ), Con8or32( imm ), ClearInstMark );
- ins_pipe( ialu_reg_mem_alu0 );
-%}
-
-// Multiply Memory
-instruct mulI(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (MulI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(350);
- format %{ "IMUL $dst,$src" %}
- opcode(0xAF, 0x0F);
- ins_encode( SetInstMark, OpcS, OpcP, RegMem( dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem_alu0 );
-%}
-
-instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, eFlagsReg cr)
-%{
- match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3)));
- effect(KILL cr, KILL src2);
-
- expand %{ mulI_eReg(dst, src1, cr);
- mulI_eReg(src2, src3, cr);
- addI_eReg(dst, src2, cr); %}
-%}
-
-// Multiply Register Int to Long
-instruct mulI2L(eADXRegL dst, eAXRegI src, nadxRegI src1, eFlagsReg flags) %{
- // Basic Idea: long = (long)int * (long)int
- match(Set dst (MulL (ConvI2L src) (ConvI2L src1)));
- effect(DEF dst, USE src, USE src1, KILL flags);
-
- ins_cost(300);
- format %{ "IMUL $dst,$src1" %}
-
- ins_encode( long_int_multiply( dst, src1 ) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-instruct mulIS_eReg(eADXRegL dst, immL_32bits mask, eFlagsReg flags, eAXRegI src, nadxRegI src1) %{
- // Basic Idea: long = (int & 0xffffffffL) * (int & 0xffffffffL)
- match(Set dst (MulL (AndL (ConvI2L src) mask) (AndL (ConvI2L src1) mask)));
- effect(KILL flags);
-
- ins_cost(300);
- format %{ "MUL $dst,$src1" %}
-
- ins_encode( long_uint_multiply(dst, src1) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-// Multiply Register Long
-instruct mulL_eReg(eADXRegL dst, eRegL src, rRegI tmp, eFlagsReg cr) %{
- match(Set dst (MulL dst src));
- effect(KILL cr, TEMP tmp);
- ins_cost(4*100+3*400);
-// Basic idea: lo(result) = lo(x_lo * y_lo)
-// hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi)
- format %{ "MOV $tmp,$src.lo\n\t"
- "IMUL $tmp,EDX\n\t"
- "MOV EDX,$src.hi\n\t"
- "IMUL EDX,EAX\n\t"
- "ADD $tmp,EDX\n\t"
- "MUL EDX:EAX,$src.lo\n\t"
- "ADD EDX,$tmp" %}
- ins_encode( long_multiply( dst, src, tmp ) );
- ins_pipe( pipe_slow );
-%}
-
-// Multiply Register Long where the left operand's high 32 bits are zero
-instruct mulL_eReg_lhi0(eADXRegL dst, eRegL src, rRegI tmp, eFlagsReg cr) %{
- predicate(is_operand_hi32_zero(n->in(1)));
- match(Set dst (MulL dst src));
- effect(KILL cr, TEMP tmp);
- ins_cost(2*100+2*400);
-// Basic idea: lo(result) = lo(x_lo * y_lo)
-// hi(result) = hi(x_lo * y_lo) + lo(x_lo * y_hi) where lo(x_hi * y_lo) = 0 because x_hi = 0
- format %{ "MOV $tmp,$src.hi\n\t"
- "IMUL $tmp,EAX\n\t"
- "MUL EDX:EAX,$src.lo\n\t"
- "ADD EDX,$tmp" %}
- ins_encode %{
- __ movl($tmp$$Register, HIGH_FROM_LOW($src$$Register));
- __ imull($tmp$$Register, rax);
- __ mull($src$$Register);
- __ addl(rdx, $tmp$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Multiply Register Long where the right operand's high 32 bits are zero
-instruct mulL_eReg_rhi0(eADXRegL dst, eRegL src, rRegI tmp, eFlagsReg cr) %{
- predicate(is_operand_hi32_zero(n->in(2)));
- match(Set dst (MulL dst src));
- effect(KILL cr, TEMP tmp);
- ins_cost(2*100+2*400);
-// Basic idea: lo(result) = lo(x_lo * y_lo)
-// hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) where lo(x_lo * y_hi) = 0 because y_hi = 0
- format %{ "MOV $tmp,$src.lo\n\t"
- "IMUL $tmp,EDX\n\t"
- "MUL EDX:EAX,$src.lo\n\t"
- "ADD EDX,$tmp" %}
- ins_encode %{
- __ movl($tmp$$Register, $src$$Register);
- __ imull($tmp$$Register, rdx);
- __ mull($src$$Register);
- __ addl(rdx, $tmp$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Multiply Register Long where the left and the right operands' high 32 bits are zero
-instruct mulL_eReg_hi0(eADXRegL dst, eRegL src, eFlagsReg cr) %{
- predicate(is_operand_hi32_zero(n->in(1)) && is_operand_hi32_zero(n->in(2)));
- match(Set dst (MulL dst src));
- effect(KILL cr);
- ins_cost(1*400);
-// Basic idea: lo(result) = lo(x_lo * y_lo)
-// hi(result) = hi(x_lo * y_lo) where lo(x_hi * y_lo) = 0 and lo(x_lo * y_hi) = 0 because x_hi = 0 and y_hi = 0
- format %{ "MUL EDX:EAX,$src.lo\n\t" %}
- ins_encode %{
- __ mull($src$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Multiply Register Long by small constant
-instruct mulL_eReg_con(eADXRegL dst, immL_127 src, rRegI tmp, eFlagsReg cr) %{
- match(Set dst (MulL dst src));
- effect(KILL cr, TEMP tmp);
- ins_cost(2*100+2*400);
- size(12);
-// Basic idea: lo(result) = lo(src * EAX)
-// hi(result) = hi(src * EAX) + lo(src * EDX)
- format %{ "IMUL $tmp,EDX,$src\n\t"
- "MOV EDX,$src\n\t"
- "MUL EDX\t# EDX*EAX -> EDX:EAX\n\t"
- "ADD EDX,$tmp" %}
- ins_encode( long_multiply_con( dst, src, tmp ) );
- ins_pipe( pipe_slow );
-%}
-
-// Integer DIV with Register
-instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
- match(Set rax (DivI rax div));
- effect(KILL rdx, KILL cr);
- size(26);
- ins_cost(30*100+10*100);
- format %{ "CMP EAX,0x80000000\n\t"
- "JNE,s normal\n\t"
- "XOR EDX,EDX\n\t"
- "CMP ECX,-1\n\t"
- "JE,s done\n"
- "normal: CDQ\n\t"
- "IDIV $div\n\t"
- "done:" %}
- opcode(0xF7, 0x7); /* Opcode F7 /7 */
- ins_encode( cdq_enc, OpcP, RegOpc(div) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-// Divide Register Long
-instruct divL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{
- match(Set dst (DivL src1 src2));
- effect(CALL);
- ins_cost(10000);
- format %{ "PUSH $src1.hi\n\t"
- "PUSH $src1.lo\n\t"
- "PUSH $src2.hi\n\t"
- "PUSH $src2.lo\n\t"
- "CALL SharedRuntime::ldiv\n\t"
- "ADD ESP,16" %}
- ins_encode( long_div(src1,src2) );
- ins_pipe( pipe_slow );
-%}
-
-// Integer DIVMOD with Register, both quotient and mod results
-instruct divModI_eReg_divmod(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
- match(DivModI rax div);
- effect(KILL cr);
- size(26);
- ins_cost(30*100+10*100);
- format %{ "CMP EAX,0x80000000\n\t"
- "JNE,s normal\n\t"
- "XOR EDX,EDX\n\t"
- "CMP ECX,-1\n\t"
- "JE,s done\n"
- "normal: CDQ\n\t"
- "IDIV $div\n\t"
- "done:" %}
- opcode(0xF7, 0x7); /* Opcode F7 /7 */
- ins_encode( cdq_enc, OpcP, RegOpc(div) );
- ins_pipe( pipe_slow );
-%}
-
-// Integer MOD with Register
-instruct modI_eReg(eDXRegI rdx, eAXRegI rax, eCXRegI div, eFlagsReg cr) %{
- match(Set rdx (ModI rax div));
- effect(KILL rax, KILL cr);
-
- size(26);
- ins_cost(300);
- format %{ "CDQ\n\t"
- "IDIV $div" %}
- opcode(0xF7, 0x7); /* Opcode F7 /7 */
- ins_encode( cdq_enc, OpcP, RegOpc(div) );
- ins_pipe( ialu_reg_reg_alu0 );
-%}
-
-// Remainder Register Long
-instruct modL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{
- match(Set dst (ModL src1 src2));
- effect(CALL);
- ins_cost(10000);
- format %{ "PUSH $src1.hi\n\t"
- "PUSH $src1.lo\n\t"
- "PUSH $src2.hi\n\t"
- "PUSH $src2.lo\n\t"
- "CALL SharedRuntime::lrem\n\t"
- "ADD ESP,16" %}
- ins_encode( long_mod(src1,src2) );
- ins_pipe( pipe_slow );
-%}
-
-// Divide Register Long (no special case since divisor != -1)
-instruct divL_eReg_imm32( eADXRegL dst, immL32 imm, rRegI tmp, rRegI tmp2, eFlagsReg cr ) %{
- match(Set dst (DivL dst imm));
- effect( TEMP tmp, TEMP tmp2, KILL cr );
- ins_cost(1000);
- format %{ "MOV $tmp,abs($imm) # ldiv EDX:EAX,$imm\n\t"
- "XOR $tmp2,$tmp2\n\t"
- "CMP $tmp,EDX\n\t"
- "JA,s fast\n\t"
- "MOV $tmp2,EAX\n\t"
- "MOV EAX,EDX\n\t"
- "MOV EDX,0\n\t"
- "JLE,s pos\n\t"
- "LNEG EAX : $tmp2\n\t"
- "DIV $tmp # unsigned division\n\t"
- "XCHG EAX,$tmp2\n\t"
- "DIV $tmp\n\t"
- "LNEG $tmp2 : EAX\n\t"
- "JMP,s done\n"
- "pos:\n\t"
- "DIV $tmp\n\t"
- "XCHG EAX,$tmp2\n"
- "fast:\n\t"
- "DIV $tmp\n"
- "done:\n\t"
- "MOV EDX,$tmp2\n\t"
- "NEG EDX:EAX # if $imm < 0" %}
- ins_encode %{
- int con = (int)$imm$$constant;
- assert(con != 0 && con != -1 && con != min_jint, "wrong divisor");
- int pcon = (con > 0) ? con : -con;
- Label Lfast, Lpos, Ldone;
-
- __ movl($tmp$$Register, pcon);
- __ xorl($tmp2$$Register,$tmp2$$Register);
- __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register));
- __ jccb(Assembler::above, Lfast); // result fits into 32 bit
-
- __ movl($tmp2$$Register, $dst$$Register); // save
- __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
- __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags
- __ jccb(Assembler::lessEqual, Lpos); // result is positive
-
- // Negative dividend.
- // convert value to positive to use unsigned division
- __ lneg($dst$$Register, $tmp2$$Register);
- __ divl($tmp$$Register);
- __ xchgl($dst$$Register, $tmp2$$Register);
- __ divl($tmp$$Register);
- // revert result back to negative
- __ lneg($tmp2$$Register, $dst$$Register);
- __ jmpb(Ldone);
-
- __ bind(Lpos);
- __ divl($tmp$$Register); // Use unsigned division
- __ xchgl($dst$$Register, $tmp2$$Register);
- // Fallthrow for final divide, tmp2 has 32 bit hi result
-
- __ bind(Lfast);
- // fast path: src is positive
- __ divl($tmp$$Register); // Use unsigned division
-
- __ bind(Ldone);
- __ movl(HIGH_FROM_LOW($dst$$Register),$tmp2$$Register);
- if (con < 0) {
- __ lneg(HIGH_FROM_LOW($dst$$Register), $dst$$Register);
- }
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Remainder Register Long (remainder fit into 32 bits)
-instruct modL_eReg_imm32( eADXRegL dst, immL32 imm, rRegI tmp, rRegI tmp2, eFlagsReg cr ) %{
- match(Set dst (ModL dst imm));
- effect( TEMP tmp, TEMP tmp2, KILL cr );
- ins_cost(1000);
- format %{ "MOV $tmp,abs($imm) # lrem EDX:EAX,$imm\n\t"
- "CMP $tmp,EDX\n\t"
- "JA,s fast\n\t"
- "MOV $tmp2,EAX\n\t"
- "MOV EAX,EDX\n\t"
- "MOV EDX,0\n\t"
- "JLE,s pos\n\t"
- "LNEG EAX : $tmp2\n\t"
- "DIV $tmp # unsigned division\n\t"
- "MOV EAX,$tmp2\n\t"
- "DIV $tmp\n\t"
- "NEG EDX\n\t"
- "JMP,s done\n"
- "pos:\n\t"
- "DIV $tmp\n\t"
- "MOV EAX,$tmp2\n"
- "fast:\n\t"
- "DIV $tmp\n"
- "done:\n\t"
- "MOV EAX,EDX\n\t"
- "SAR EDX,31\n\t" %}
- ins_encode %{
- int con = (int)$imm$$constant;
- assert(con != 0 && con != -1 && con != min_jint, "wrong divisor");
- int pcon = (con > 0) ? con : -con;
- Label Lfast, Lpos, Ldone;
-
- __ movl($tmp$$Register, pcon);
- __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register));
- __ jccb(Assembler::above, Lfast); // src is positive and result fits into 32 bit
-
- __ movl($tmp2$$Register, $dst$$Register); // save
- __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
- __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags
- __ jccb(Assembler::lessEqual, Lpos); // result is positive
-
- // Negative dividend.
- // convert value to positive to use unsigned division
- __ lneg($dst$$Register, $tmp2$$Register);
- __ divl($tmp$$Register);
- __ movl($dst$$Register, $tmp2$$Register);
- __ divl($tmp$$Register);
- // revert remainder back to negative
- __ negl(HIGH_FROM_LOW($dst$$Register));
- __ jmpb(Ldone);
-
- __ bind(Lpos);
- __ divl($tmp$$Register);
- __ movl($dst$$Register, $tmp2$$Register);
-
- __ bind(Lfast);
- // fast path: src is positive
- __ divl($tmp$$Register);
-
- __ bind(Ldone);
- __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
- __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // result sign
-
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Integer Shift Instructions
-// Shift Left by one
-instruct shlI_eReg_1(rRegI dst, immI_1 shift, eFlagsReg cr) %{
- match(Set dst (LShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SHL $dst,$shift" %}
- opcode(0xD1, 0x4); /* D1 /4 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg );
-%}
-
-// Shift Left by 8-bit immediate
-instruct salI_eReg_imm(rRegI dst, immI8 shift, eFlagsReg cr) %{
- match(Set dst (LShiftI dst shift));
- effect(KILL cr);
-
- size(3);
- format %{ "SHL $dst,$shift" %}
- opcode(0xC1, 0x4); /* C1 /4 ib */
- ins_encode( RegOpcImm( dst, shift) );
- ins_pipe( ialu_reg );
-%}
-
-// Shift Left by variable
-instruct salI_eReg_CL(rRegI dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (LShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SHL $dst,$shift" %}
- opcode(0xD3, 0x4); /* D3 /4 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg_reg );
-%}
-
-// Arithmetic shift right by one
-instruct sarI_eReg_1(rRegI dst, immI_1 shift, eFlagsReg cr) %{
- match(Set dst (RShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SAR $dst,$shift" %}
- opcode(0xD1, 0x7); /* D1 /7 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg );
-%}
-
-// Arithmetic shift right by one
-instruct sarI_mem_1(memory dst, immI_1 shift, eFlagsReg cr) %{
- match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
- effect(KILL cr);
- format %{ "SAR $dst,$shift" %}
- opcode(0xD1, 0x7); /* D1 /7 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(secondary,dst), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-// Arithmetic Shift Right by 8-bit immediate
-instruct sarI_eReg_imm(rRegI dst, immI8 shift, eFlagsReg cr) %{
- match(Set dst (RShiftI dst shift));
- effect(KILL cr);
-
- size(3);
- format %{ "SAR $dst,$shift" %}
- opcode(0xC1, 0x7); /* C1 /7 ib */
- ins_encode( RegOpcImm( dst, shift ) );
- ins_pipe( ialu_mem_imm );
-%}
-
-// Arithmetic Shift Right by 8-bit immediate
-instruct sarI_mem_imm(memory dst, immI8 shift, eFlagsReg cr) %{
- match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
- effect(KILL cr);
-
- format %{ "SAR $dst,$shift" %}
- opcode(0xC1, 0x7); /* C1 /7 ib */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(secondary, dst ), Con8or32(shift), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-// Arithmetic Shift Right by variable
-instruct sarI_eReg_CL(rRegI dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (RShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SAR $dst,$shift" %}
- opcode(0xD3, 0x7); /* D3 /7 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg_reg );
-%}
-
-// Logical shift right by one
-instruct shrI_eReg_1(rRegI dst, immI_1 shift, eFlagsReg cr) %{
- match(Set dst (URShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SHR $dst,$shift" %}
- opcode(0xD1, 0x5); /* D1 /5 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg );
-%}
-
-// Logical Shift Right by 8-bit immediate
-instruct shrI_eReg_imm(rRegI dst, immI8 shift, eFlagsReg cr) %{
- match(Set dst (URShiftI dst shift));
- effect(KILL cr);
-
- size(3);
- format %{ "SHR $dst,$shift" %}
- opcode(0xC1, 0x5); /* C1 /5 ib */
- ins_encode( RegOpcImm( dst, shift) );
- ins_pipe( ialu_reg );
-%}
-
-
-// Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
-// This idiom is used by the compiler for the i2b bytecode.
-instruct i2b(rRegI dst, xRegI src, immI_24 twentyfour) %{
- match(Set dst (RShiftI (LShiftI src twentyfour) twentyfour));
-
- size(3);
- format %{ "MOVSX $dst,$src :8" %}
- ins_encode %{
- __ movsbl($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-// Logical Shift Right by 16, followed by Arithmetic Shift Left by 16.
-// This idiom is used by the compiler the i2s bytecode.
-instruct i2s(rRegI dst, xRegI src, immI_16 sixteen) %{
- match(Set dst (RShiftI (LShiftI src sixteen) sixteen));
-
- size(3);
- format %{ "MOVSX $dst,$src :16" %}
- ins_encode %{
- __ movswl($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-
-// Logical Shift Right by variable
-instruct shrI_eReg_CL(rRegI dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (URShiftI dst shift));
- effect(KILL cr);
-
- size(2);
- format %{ "SHR $dst,$shift" %}
- opcode(0xD3, 0x5); /* D3 /5 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg_reg );
-%}
-
-
-//----------Logical Instructions-----------------------------------------------
-//----------Integer Logical Instructions---------------------------------------
-// And Instructions
-// And Register with Register
-instruct andI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (AndI dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "AND $dst,$src" %}
- opcode(0x23);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-// And Register with Immediate
-instruct andI_eReg_imm(rRegI dst, immI src, eFlagsReg cr) %{
- match(Set dst (AndI dst src));
- effect(KILL cr);
-
- format %{ "AND $dst,$src" %}
- opcode(0x81,0x04); /* Opcode 81 /4 */
- // ins_encode( RegImm( dst, src) );
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-// And Register with Memory
-instruct andI_eReg_mem(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (AndI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "AND $dst,$src" %}
- opcode(0x23);
- ins_encode( SetInstMark, OpcP, RegMem( dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem );
-%}
-
-// And Memory with Register
-instruct andI_mem_eReg(memory dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AndI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "AND $dst,$src" %}
- opcode(0x21); /* Opcode 21 /r */
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// And Memory with Immediate
-instruct andI_mem_imm(memory dst, immI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (AndI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "AND $dst,$src" %}
- opcode(0x81, 0x4); /* Opcode 81 /4 id */
- // ins_encode( MemImm( dst, src) );
- ins_encode( SetInstMark, OpcSE( src ), RMopc_Mem(secondary, dst ), Con8or32(src), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-// BMI1 instructions
-instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, eFlagsReg cr) %{
- match(Set dst (AndI (XorI src1 minus_1) src2));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- format %{ "ANDNL $dst, $src1, $src2" %}
-
- ins_encode %{
- __ andnl($dst$$Register, $src1$$Register, $src2$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, eFlagsReg cr) %{
- match(Set dst (AndI (XorI src1 minus_1) (LoadI src2) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "ANDNL $dst, $src1, $src2" %}
-
- ins_encode %{
- __ andnl($dst$$Register, $src1$$Register, $src2$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, eFlagsReg cr) %{
- match(Set dst (AndI (SubI imm_zero src) src));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- format %{ "BLSIL $dst, $src" %}
-
- ins_encode %{
- __ blsil($dst$$Register, $src$$Register);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, eFlagsReg cr) %{
- match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "BLSIL $dst, $src" %}
-
- ins_encode %{
- __ blsil($dst$$Register, $src$$Address);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (XorI (AddI src minus_1) src));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- format %{ "BLSMSKL $dst, $src" %}
-
- ins_encode %{
- __ blsmskl($dst$$Register, $src$$Register);
- %}
-
- ins_pipe(ialu_reg);
-%}
-
-instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "BLSMSKL $dst, $src" %}
-
- ins_encode %{
- __ blsmskl($dst$$Register, $src$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (AndI (AddI src minus_1) src) );
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- format %{ "BLSRL $dst, $src" %}
-
- ins_encode %{
- __ blsrl($dst$$Register, $src$$Register);
- %}
-
- ins_pipe(ialu_reg);
-%}
-
-instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "BLSRL $dst, $src" %}
-
- ins_encode %{
- __ blsrl($dst$$Register, $src$$Address);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Or Instructions
-// Or Register with Register
-instruct orI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (OrI dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "OR $dst,$src" %}
- opcode(0x0B);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct orI_eReg_castP2X(rRegI dst, eRegP src, eFlagsReg cr) %{
- match(Set dst (OrI dst (CastP2X src)));
- effect(KILL cr);
-
- size(2);
- format %{ "OR $dst,$src" %}
- opcode(0x0B);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-
-// Or Register with Immediate
-instruct orI_eReg_imm(rRegI dst, immI src, eFlagsReg cr) %{
- match(Set dst (OrI dst src));
- effect(KILL cr);
-
- format %{ "OR $dst,$src" %}
- opcode(0x81,0x01); /* Opcode 81 /1 id */
- // ins_encode( RegImm( dst, src) );
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-// Or Register with Memory
-instruct orI_eReg_mem(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (OrI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "OR $dst,$src" %}
- opcode(0x0B);
- ins_encode( SetInstMark, OpcP, RegMem( dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem );
-%}
-
-// Or Memory with Register
-instruct orI_mem_eReg(memory dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (OrI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "OR $dst,$src" %}
- opcode(0x09); /* Opcode 09 /r */
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Or Memory with Immediate
-instruct orI_mem_imm(memory dst, immI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (OrI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "OR $dst,$src" %}
- opcode(0x81,0x1); /* Opcode 81 /1 id */
- // ins_encode( MemImm( dst, src) );
- ins_encode( SetInstMark, OpcSE( src ), RMopc_Mem(secondary, dst ), Con8or32(src), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-// ROL/ROR
-// ROL expand
-instruct rolI_eReg_imm1(rRegI dst, immI_1 shift, eFlagsReg cr) %{
- effect(USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROL $dst, $shift" %}
- opcode(0xD1, 0x0); /* Opcode D1 /0 */
- ins_encode( OpcP, RegOpc( dst ));
- ins_pipe( ialu_reg );
-%}
-
-instruct rolI_eReg_imm8(rRegI dst, immI8 shift, eFlagsReg cr) %{
- effect(USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROL $dst, $shift" %}
- opcode(0xC1, 0x0); /*Opcode /C1 /0 */
- ins_encode( RegOpcImm(dst, shift) );
- ins_pipe(ialu_reg);
-%}
-
-instruct rolI_eReg_CL(ncxRegI dst, eCXRegI shift, eFlagsReg cr) %{
- effect(USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROL $dst, $shift" %}
- opcode(0xD3, 0x0); /* Opcode D3 /0 */
- ins_encode(OpcP, RegOpc(dst));
- ins_pipe( ialu_reg_reg );
-%}
-// end of ROL expand
-
-// ROL 32bit by one once
-instruct rolI_eReg_i1(rRegI dst, immI_1 lshift, immI_M1 rshift, eFlagsReg cr) %{
- match(Set dst ( OrI (LShiftI dst lshift) (URShiftI dst rshift)));
-
- expand %{
- rolI_eReg_imm1(dst, lshift, cr);
- %}
-%}
-
-// ROL 32bit var by imm8 once
-instruct rolI_eReg_i8(rRegI dst, immI8 lshift, immI8 rshift, eFlagsReg cr) %{
- predicate( 0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f));
- match(Set dst ( OrI (LShiftI dst lshift) (URShiftI dst rshift)));
-
- expand %{
- rolI_eReg_imm8(dst, lshift, cr);
- %}
-%}
-
-// ROL 32bit var by var once
-instruct rolI_eReg_Var_C0(ncxRegI dst, eCXRegI shift, immI_0 zero, eFlagsReg cr) %{
- match(Set dst ( OrI (LShiftI dst shift) (URShiftI dst (SubI zero shift))));
-
- expand %{
- rolI_eReg_CL(dst, shift, cr);
- %}
-%}
-
-// ROL 32bit var by var once
-instruct rolI_eReg_Var_C32(ncxRegI dst, eCXRegI shift, immI_32 c32, eFlagsReg cr) %{
- match(Set dst ( OrI (LShiftI dst shift) (URShiftI dst (SubI c32 shift))));
-
- expand %{
- rolI_eReg_CL(dst, shift, cr);
- %}
-%}
-
-// ROR expand
-instruct rorI_eReg_imm1(rRegI dst, immI_1 shift, eFlagsReg cr) %{
- effect(USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROR $dst, $shift" %}
- opcode(0xD1,0x1); /* Opcode D1 /1 */
- ins_encode( OpcP, RegOpc( dst ) );
- ins_pipe( ialu_reg );
-%}
-
-instruct rorI_eReg_imm8(rRegI dst, immI8 shift, eFlagsReg cr) %{
- effect (USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROR $dst, $shift" %}
- opcode(0xC1, 0x1); /* Opcode /C1 /1 ib */
- ins_encode( RegOpcImm(dst, shift) );
- ins_pipe( ialu_reg );
-%}
-
-instruct rorI_eReg_CL(ncxRegI dst, eCXRegI shift, eFlagsReg cr)%{
- effect(USE_DEF dst, USE shift, KILL cr);
-
- format %{ "ROR $dst, $shift" %}
- opcode(0xD3, 0x1); /* Opcode D3 /1 */
- ins_encode(OpcP, RegOpc(dst));
- ins_pipe( ialu_reg_reg );
-%}
-// end of ROR expand
-
-// ROR right once
-instruct rorI_eReg_i1(rRegI dst, immI_1 rshift, immI_M1 lshift, eFlagsReg cr) %{
- match(Set dst ( OrI (URShiftI dst rshift) (LShiftI dst lshift)));
-
- expand %{
- rorI_eReg_imm1(dst, rshift, cr);
- %}
-%}
-
-// ROR 32bit by immI8 once
-instruct rorI_eReg_i8(rRegI dst, immI8 rshift, immI8 lshift, eFlagsReg cr) %{
- predicate( 0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f));
- match(Set dst ( OrI (URShiftI dst rshift) (LShiftI dst lshift)));
-
- expand %{
- rorI_eReg_imm8(dst, rshift, cr);
- %}
-%}
-
-// ROR 32bit var by var once
-instruct rorI_eReg_Var_C0(ncxRegI dst, eCXRegI shift, immI_0 zero, eFlagsReg cr) %{
- match(Set dst ( OrI (URShiftI dst shift) (LShiftI dst (SubI zero shift))));
-
- expand %{
- rorI_eReg_CL(dst, shift, cr);
- %}
-%}
-
-// ROR 32bit var by var once
-instruct rorI_eReg_Var_C32(ncxRegI dst, eCXRegI shift, immI_32 c32, eFlagsReg cr) %{
- match(Set dst ( OrI (URShiftI dst shift) (LShiftI dst (SubI c32 shift))));
-
- expand %{
- rorI_eReg_CL(dst, shift, cr);
- %}
-%}
-
-// Xor Instructions
-// Xor Register with Register
-instruct xorI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (XorI dst src));
- effect(KILL cr);
-
- size(2);
- format %{ "XOR $dst,$src" %}
- opcode(0x33);
- ins_encode( OpcP, RegReg( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-// Xor Register with Immediate -1
-instruct xorI_eReg_im1(rRegI dst, immI_M1 imm) %{
- match(Set dst (XorI dst imm));
-
- size(2);
- format %{ "NOT $dst" %}
- ins_encode %{
- __ notl($dst$$Register);
- %}
- ins_pipe( ialu_reg );
-%}
-
-// Xor Register with Immediate
-instruct xorI_eReg_imm(rRegI dst, immI src, eFlagsReg cr) %{
- match(Set dst (XorI dst src));
- effect(KILL cr);
-
- format %{ "XOR $dst,$src" %}
- opcode(0x81,0x06); /* Opcode 81 /6 id */
- // ins_encode( RegImm( dst, src) );
- ins_encode( OpcSErm( dst, src ), Con8or32( src ) );
- ins_pipe( ialu_reg );
-%}
-
-// Xor Register with Memory
-instruct xorI_eReg_mem(rRegI dst, memory src, eFlagsReg cr) %{
- match(Set dst (XorI dst (LoadI src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "XOR $dst,$src" %}
- opcode(0x33);
- ins_encode( SetInstMark, OpcP, RegMem(dst, src), ClearInstMark );
- ins_pipe( ialu_reg_mem );
-%}
-
-// Xor Memory with Register
-instruct xorI_mem_eReg(memory dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (XorI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(150);
- format %{ "XOR $dst,$src" %}
- opcode(0x31); /* Opcode 31 /r */
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_reg );
-%}
-
-// Xor Memory with Immediate
-instruct xorI_mem_imm(memory dst, immI src, eFlagsReg cr) %{
- match(Set dst (StoreI dst (XorI (LoadI dst) src)));
- effect(KILL cr);
-
- ins_cost(125);
- format %{ "XOR $dst,$src" %}
- opcode(0x81,0x6); /* Opcode 81 /6 id */
- ins_encode( SetInstMark, OpcSE( src ), RMopc_Mem(secondary, dst ), Con8or32(src), ClearInstMark );
- ins_pipe( ialu_mem_imm );
-%}
-
-//----------Convert Int to Boolean---------------------------------------------
-
-instruct movI_nocopy(rRegI dst, rRegI src) %{
- effect( DEF dst, USE src );
- format %{ "MOV $dst,$src" %}
- ins_encode( enc_Copy( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct ci2b( rRegI dst, rRegI src, eFlagsReg cr ) %{
- effect( USE_DEF dst, USE src, KILL cr );
-
- size(4);
- format %{ "NEG $dst\n\t"
- "ADC $dst,$src" %}
- ins_encode( neg_reg(dst),
- OpcRegReg(0x13,dst,src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-instruct convI2B( rRegI dst, rRegI src, eFlagsReg cr ) %{
- match(Set dst (Conv2B src));
-
- expand %{
- movI_nocopy(dst,src);
- ci2b(dst,src,cr);
- %}
-%}
-
-instruct movP_nocopy(rRegI dst, eRegP src) %{
- effect( DEF dst, USE src );
- format %{ "MOV $dst,$src" %}
- ins_encode( enc_Copy( dst, src) );
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct cp2b( rRegI dst, eRegP src, eFlagsReg cr ) %{
- effect( USE_DEF dst, USE src, KILL cr );
- format %{ "NEG $dst\n\t"
- "ADC $dst,$src" %}
- ins_encode( neg_reg(dst),
- OpcRegReg(0x13,dst,src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-instruct convP2B( rRegI dst, eRegP src, eFlagsReg cr ) %{
- match(Set dst (Conv2B src));
-
- expand %{
- movP_nocopy(dst,src);
- cp2b(dst,src,cr);
- %}
-%}
-
-instruct cmpLTMask(eCXRegI dst, ncxRegI p, ncxRegI q, eFlagsReg cr) %{
- match(Set dst (CmpLTMask p q));
- effect(KILL cr);
- ins_cost(400);
-
- // SETlt can only use low byte of EAX,EBX, ECX, or EDX as destination
- format %{ "XOR $dst,$dst\n\t"
- "CMP $p,$q\n\t"
- "SETlt $dst\n\t"
- "NEG $dst" %}
- ins_encode %{
- Register Rp = $p$$Register;
- Register Rq = $q$$Register;
- Register Rd = $dst$$Register;
- Label done;
- __ xorl(Rd, Rd);
- __ cmpl(Rp, Rq);
- __ setb(Assembler::less, Rd);
- __ negl(Rd);
- %}
-
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpLTMask0(rRegI dst, immI_0 zero, eFlagsReg cr) %{
- match(Set dst (CmpLTMask dst zero));
- effect(DEF dst, KILL cr);
- ins_cost(100);
-
- format %{ "SAR $dst,31\t# cmpLTMask0" %}
- ins_encode %{
- __ sarl($dst$$Register, 31);
- %}
- ins_pipe(ialu_reg);
-%}
-
-/* better to save a register than avoid a branch */
-instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, eFlagsReg cr) %{
- match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
- effect(KILL cr);
- ins_cost(400);
- format %{ "SUB $p,$q\t# cadd_cmpLTMask\n\t"
- "JGE done\n\t"
- "ADD $p,$y\n"
- "done: " %}
- ins_encode %{
- Register Rp = $p$$Register;
- Register Rq = $q$$Register;
- Register Ry = $y$$Register;
- Label done;
- __ subl(Rp, Rq);
- __ jccb(Assembler::greaterEqual, done);
- __ addl(Rp, Ry);
- __ bind(done);
- %}
-
- ins_pipe(pipe_cmplt);
-%}
-
-/* better to save a register than avoid a branch */
-instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, eFlagsReg cr) %{
- match(Set y (AndI (CmpLTMask p q) y));
- effect(KILL cr);
-
- ins_cost(300);
-
- format %{ "CMPL $p, $q\t# and_cmpLTMask\n\t"
- "JLT done\n\t"
- "XORL $y, $y\n"
- "done: " %}
- ins_encode %{
- Register Rp = $p$$Register;
- Register Rq = $q$$Register;
- Register Ry = $y$$Register;
- Label done;
- __ cmpl(Rp, Rq);
- __ jccb(Assembler::less, done);
- __ xorl(Ry, Ry);
- __ bind(done);
- %}
-
- ins_pipe(pipe_cmplt);
-%}
-
-/* If I enable this, I encourage spilling in the inner loop of compress.
-instruct cadd_cmpLTMask_mem(ncxRegI p, ncxRegI q, memory y, eCXRegI tmp, eFlagsReg cr) %{
- match(Set p (AddI (AndI (CmpLTMask p q) (LoadI y)) (SubI p q)));
-*/
-//----------Overflow Math Instructions-----------------------------------------
-
-instruct overflowAddI_eReg(eFlagsReg cr, eAXRegI op1, rRegI op2)
-%{
- match(Set cr (OverflowAddI op1 op2));
- effect(DEF cr, USE_KILL op1, USE op2);
-
- format %{ "ADD $op1, $op2\t# overflow check int" %}
-
- ins_encode %{
- __ addl($op1$$Register, $op2$$Register);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-instruct overflowAddI_rReg_imm(eFlagsReg cr, eAXRegI op1, immI op2)
-%{
- match(Set cr (OverflowAddI op1 op2));
- effect(DEF cr, USE_KILL op1, USE op2);
-
- format %{ "ADD $op1, $op2\t# overflow check int" %}
-
- ins_encode %{
- __ addl($op1$$Register, $op2$$constant);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-instruct overflowSubI_rReg(eFlagsReg cr, rRegI op1, rRegI op2)
-%{
- match(Set cr (OverflowSubI op1 op2));
-
- format %{ "CMP $op1, $op2\t# overflow check int" %}
- ins_encode %{
- __ cmpl($op1$$Register, $op2$$Register);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-instruct overflowSubI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2)
-%{
- match(Set cr (OverflowSubI op1 op2));
-
- format %{ "CMP $op1, $op2\t# overflow check int" %}
- ins_encode %{
- __ cmpl($op1$$Register, $op2$$constant);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-instruct overflowNegI_rReg(eFlagsReg cr, immI_0 zero, eAXRegI op2)
-%{
- match(Set cr (OverflowSubI zero op2));
- effect(DEF cr, USE_KILL op2);
-
- format %{ "NEG $op2\t# overflow check int" %}
- ins_encode %{
- __ negl($op2$$Register);
- %}
- ins_pipe(ialu_reg_reg);
-%}
-
-instruct overflowMulI_rReg(eFlagsReg cr, eAXRegI op1, rRegI op2)
-%{
- match(Set cr (OverflowMulI op1 op2));
- effect(DEF cr, USE_KILL op1, USE op2);
-
- format %{ "IMUL $op1, $op2\t# overflow check int" %}
- ins_encode %{
- __ imull($op1$$Register, $op2$$Register);
- %}
- ins_pipe(ialu_reg_reg_alu0);
-%}
-
-instruct overflowMulI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2, rRegI tmp)
-%{
- match(Set cr (OverflowMulI op1 op2));
- effect(DEF cr, TEMP tmp, USE op1, USE op2);
-
- format %{ "IMUL $tmp, $op1, $op2\t# overflow check int" %}
- ins_encode %{
- __ imull($tmp$$Register, $op1$$Register, $op2$$constant);
- %}
- ins_pipe(ialu_reg_reg_alu0);
-%}
-
-// Integer Absolute Instructions
-instruct absI_rReg(rRegI dst, rRegI src, rRegI tmp, eFlagsReg cr)
-%{
- match(Set dst (AbsI src));
- effect(TEMP dst, TEMP tmp, KILL cr);
- format %{ "movl $tmp, $src\n\t"
- "sarl $tmp, 31\n\t"
- "movl $dst, $src\n\t"
- "xorl $dst, $tmp\n\t"
- "subl $dst, $tmp\n"
- %}
- ins_encode %{
- __ movl($tmp$$Register, $src$$Register);
- __ sarl($tmp$$Register, 31);
- __ movl($dst$$Register, $src$$Register);
- __ xorl($dst$$Register, $tmp$$Register);
- __ subl($dst$$Register, $tmp$$Register);
- %}
-
- ins_pipe(ialu_reg_reg);
-%}
-
-//----------Long Instructions------------------------------------------------
-// Add Long Register with Register
-instruct addL_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (AddL dst src));
- effect(KILL cr);
- ins_cost(200);
- format %{ "ADD $dst.lo,$src.lo\n\t"
- "ADC $dst.hi,$src.hi" %}
- opcode(0x03, 0x13);
- ins_encode( RegReg_Lo(dst, src), RegReg_Hi(dst,src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Add Long Register with Immediate
-instruct addL_eReg_imm(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst (AddL dst src));
- effect(KILL cr);
- format %{ "ADD $dst.lo,$src.lo\n\t"
- "ADC $dst.hi,$src.hi" %}
- opcode(0x81,0x00,0x02); /* Opcode 81 /0, 81 /2 */
- ins_encode( Long_OpcSErm_Lo( dst, src ), Long_OpcSErm_Hi( dst, src ) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Add Long Register with Memory
-instruct addL_eReg_mem(eRegL dst, load_long_memory mem, eFlagsReg cr) %{
- match(Set dst (AddL dst (LoadL mem)));
- effect(KILL cr);
- ins_cost(125);
- format %{ "ADD $dst.lo,$mem\n\t"
- "ADC $dst.hi,$mem+4" %}
- opcode(0x03, 0x13);
- ins_encode( SetInstMark, OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem), ClearInstMark );
- ins_pipe( ialu_reg_long_mem );
-%}
-
-// Subtract Long Register with Register.
-instruct subL_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (SubL dst src));
- effect(KILL cr);
- ins_cost(200);
- format %{ "SUB $dst.lo,$src.lo\n\t"
- "SBB $dst.hi,$src.hi" %}
- opcode(0x2B, 0x1B);
- ins_encode( RegReg_Lo(dst, src), RegReg_Hi(dst,src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Subtract Long Register with Immediate
-instruct subL_eReg_imm(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst (SubL dst src));
- effect(KILL cr);
- format %{ "SUB $dst.lo,$src.lo\n\t"
- "SBB $dst.hi,$src.hi" %}
- opcode(0x81,0x05,0x03); /* Opcode 81 /5, 81 /3 */
- ins_encode( Long_OpcSErm_Lo( dst, src ), Long_OpcSErm_Hi( dst, src ) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Subtract Long Register with Memory
-instruct subL_eReg_mem(eRegL dst, load_long_memory mem, eFlagsReg cr) %{
- match(Set dst (SubL dst (LoadL mem)));
- effect(KILL cr);
- ins_cost(125);
- format %{ "SUB $dst.lo,$mem\n\t"
- "SBB $dst.hi,$mem+4" %}
- opcode(0x2B, 0x1B);
- ins_encode( SetInstMark, OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem), ClearInstMark );
- ins_pipe( ialu_reg_long_mem );
-%}
-
-instruct negL_eReg(eRegL dst, immL0 zero, eFlagsReg cr) %{
- match(Set dst (SubL zero dst));
- effect(KILL cr);
- ins_cost(300);
- format %{ "NEG $dst.hi\n\tNEG $dst.lo\n\tSBB $dst.hi,0" %}
- ins_encode( neg_long(dst) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// And Long Register with Register
-instruct andL_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (AndL dst src));
- effect(KILL cr);
- format %{ "AND $dst.lo,$src.lo\n\t"
- "AND $dst.hi,$src.hi" %}
- opcode(0x23,0x23);
- ins_encode( RegReg_Lo( dst, src), RegReg_Hi( dst, src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// And Long Register with Immediate
-instruct andL_eReg_imm(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst (AndL dst src));
- effect(KILL cr);
- format %{ "AND $dst.lo,$src.lo\n\t"
- "AND $dst.hi,$src.hi" %}
- opcode(0x81,0x04,0x04); /* Opcode 81 /4, 81 /4 */
- ins_encode( Long_OpcSErm_Lo( dst, src ), Long_OpcSErm_Hi( dst, src ) );
- ins_pipe( ialu_reg_long );
-%}
-
-// And Long Register with Memory
-instruct andL_eReg_mem(eRegL dst, load_long_memory mem, eFlagsReg cr) %{
- match(Set dst (AndL dst (LoadL mem)));
- effect(KILL cr);
- ins_cost(125);
- format %{ "AND $dst.lo,$mem\n\t"
- "AND $dst.hi,$mem+4" %}
- opcode(0x23, 0x23);
- ins_encode( SetInstMark, OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem), ClearInstMark );
- ins_pipe( ialu_reg_long_mem );
-%}
-
-// BMI1 instructions
-instruct andnL_eReg_eReg_eReg(eRegL dst, eRegL src1, eRegL src2, immL_M1 minus_1, eFlagsReg cr) %{
- match(Set dst (AndL (XorL src1 minus_1) src2));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- format %{ "ANDNL $dst.lo, $src1.lo, $src2.lo\n\t"
- "ANDNL $dst.hi, $src1.hi, $src2.hi"
- %}
-
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc1 = $src1$$Register;
- Register Rsrc2 = $src2$$Register;
- __ andnl(Rdst, Rsrc1, Rsrc2);
- __ andnl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc1), HIGH_FROM_LOW(Rsrc2));
- %}
- ins_pipe(ialu_reg_reg_long);
-%}
-
-instruct andnL_eReg_eReg_mem(eRegL dst, eRegL src1, memory src2, immL_M1 minus_1, eFlagsReg cr) %{
- match(Set dst (AndL (XorL src1 minus_1) (LoadL src2) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- ins_cost(125);
- format %{ "ANDNL $dst.lo, $src1.lo, $src2\n\t"
- "ANDNL $dst.hi, $src1.hi, $src2+4"
- %}
-
- ins_encode %{
- Register Rdst = $dst$$Register;
- Register Rsrc1 = $src1$$Register;
- Address src2_hi = Address::make_raw($src2$$base, $src2$$index, $src2$$scale, $src2$$disp + 4, relocInfo::none);
-
- __ andnl(Rdst, Rsrc1, $src2$$Address);
- __ andnl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc1), src2_hi);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsiL_eReg_eReg(eRegL dst, eRegL src, immL0 imm_zero, eFlagsReg cr) %{
- match(Set dst (AndL (SubL imm_zero src) src));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- format %{ "MOVL $dst.hi, 0\n\t"
- "BLSIL $dst.lo, $src.lo\n\t"
- "JNZ done\n\t"
- "BLSIL $dst.hi, $src.hi\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- __ movl(HIGH_FROM_LOW(Rdst), 0);
- __ blsil(Rdst, Rsrc);
- __ jccb(Assembler::notZero, done);
- __ blsil(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc));
- __ bind(done);
- %}
- ins_pipe(ialu_reg);
-%}
-
-instruct blsiL_eReg_mem(eRegL dst, memory src, immL0 imm_zero, eFlagsReg cr) %{
- match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- ins_cost(125);
- format %{ "MOVL $dst.hi, 0\n\t"
- "BLSIL $dst.lo, $src\n\t"
- "JNZ done\n\t"
- "BLSIL $dst.hi, $src+4\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none);
-
- __ movl(HIGH_FROM_LOW(Rdst), 0);
- __ blsil(Rdst, $src$$Address);
- __ jccb(Assembler::notZero, done);
- __ blsil(HIGH_FROM_LOW(Rdst), src_hi);
- __ bind(done);
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsmskL_eReg_eReg(eRegL dst, eRegL src, immL_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (XorL (AddL src minus_1) src));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- format %{ "MOVL $dst.hi, 0\n\t"
- "BLSMSKL $dst.lo, $src.lo\n\t"
- "JNC done\n\t"
- "BLSMSKL $dst.hi, $src.hi\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- __ movl(HIGH_FROM_LOW(Rdst), 0);
- __ blsmskl(Rdst, Rsrc);
- __ jccb(Assembler::carryClear, done);
- __ blsmskl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc));
- __ bind(done);
- %}
-
- ins_pipe(ialu_reg);
-%}
-
-instruct blsmskL_eReg_mem(eRegL dst, memory src, immL_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- ins_cost(125);
- format %{ "MOVL $dst.hi, 0\n\t"
- "BLSMSKL $dst.lo, $src\n\t"
- "JNC done\n\t"
- "BLSMSKL $dst.hi, $src+4\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none);
-
- __ movl(HIGH_FROM_LOW(Rdst), 0);
- __ blsmskl(Rdst, $src$$Address);
- __ jccb(Assembler::carryClear, done);
- __ blsmskl(HIGH_FROM_LOW(Rdst), src_hi);
- __ bind(done);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct blsrL_eReg_eReg(eRegL dst, eRegL src, immL_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (AndL (AddL src minus_1) src) );
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- format %{ "MOVL $dst.hi, $src.hi\n\t"
- "BLSRL $dst.lo, $src.lo\n\t"
- "JNC done\n\t"
- "BLSRL $dst.hi, $src.hi\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Register Rsrc = $src$$Register;
- __ movl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc));
- __ blsrl(Rdst, Rsrc);
- __ jccb(Assembler::carryClear, done);
- __ blsrl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc));
- __ bind(done);
- %}
-
- ins_pipe(ialu_reg);
-%}
-
-instruct blsrL_eReg_mem(eRegL dst, memory src, immL_M1 minus_1, eFlagsReg cr)
-%{
- match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src) ));
- predicate(UseBMI1Instructions);
- effect(KILL cr, TEMP dst);
-
- ins_cost(125);
- format %{ "MOVL $dst.hi, $src+4\n\t"
- "BLSRL $dst.lo, $src\n\t"
- "JNC done\n\t"
- "BLSRL $dst.hi, $src+4\n"
- "done:"
- %}
-
- ins_encode %{
- Label done;
- Register Rdst = $dst$$Register;
- Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none);
- __ movl(HIGH_FROM_LOW(Rdst), src_hi);
- __ blsrl(Rdst, $src$$Address);
- __ jccb(Assembler::carryClear, done);
- __ blsrl(HIGH_FROM_LOW(Rdst), src_hi);
- __ bind(done);
- %}
-
- ins_pipe(ialu_reg_mem);
-%}
-
-// Or Long Register with Register
-instruct orl_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (OrL dst src));
- effect(KILL cr);
- format %{ "OR $dst.lo,$src.lo\n\t"
- "OR $dst.hi,$src.hi" %}
- opcode(0x0B,0x0B);
- ins_encode( RegReg_Lo( dst, src), RegReg_Hi( dst, src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Or Long Register with Immediate
-instruct orl_eReg_imm(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst (OrL dst src));
- effect(KILL cr);
- format %{ "OR $dst.lo,$src.lo\n\t"
- "OR $dst.hi,$src.hi" %}
- opcode(0x81,0x01,0x01); /* Opcode 81 /1, 81 /1 */
- ins_encode( Long_OpcSErm_Lo( dst, src ), Long_OpcSErm_Hi( dst, src ) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Or Long Register with Memory
-instruct orl_eReg_mem(eRegL dst, load_long_memory mem, eFlagsReg cr) %{
- match(Set dst (OrL dst (LoadL mem)));
- effect(KILL cr);
- ins_cost(125);
- format %{ "OR $dst.lo,$mem\n\t"
- "OR $dst.hi,$mem+4" %}
- opcode(0x0B,0x0B);
- ins_encode( SetInstMark, OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem), ClearInstMark );
- ins_pipe( ialu_reg_long_mem );
-%}
-
-// Xor Long Register with Register
-instruct xorl_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (XorL dst src));
- effect(KILL cr);
- format %{ "XOR $dst.lo,$src.lo\n\t"
- "XOR $dst.hi,$src.hi" %}
- opcode(0x33,0x33);
- ins_encode( RegReg_Lo( dst, src), RegReg_Hi( dst, src) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Xor Long Register with Immediate -1
-instruct xorl_eReg_im1(eRegL dst, immL_M1 imm) %{
- match(Set dst (XorL dst imm));
- format %{ "NOT $dst.lo\n\t"
- "NOT $dst.hi" %}
- ins_encode %{
- __ notl($dst$$Register);
- __ notl(HIGH_FROM_LOW($dst$$Register));
- %}
- ins_pipe( ialu_reg_long );
-%}
-
-// Xor Long Register with Immediate
-instruct xorl_eReg_imm(eRegL dst, immL src, eFlagsReg cr) %{
- match(Set dst (XorL dst src));
- effect(KILL cr);
- format %{ "XOR $dst.lo,$src.lo\n\t"
- "XOR $dst.hi,$src.hi" %}
- opcode(0x81,0x06,0x06); /* Opcode 81 /6, 81 /6 */
- ins_encode( Long_OpcSErm_Lo( dst, src ), Long_OpcSErm_Hi( dst, src ) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Xor Long Register with Memory
-instruct xorl_eReg_mem(eRegL dst, load_long_memory mem, eFlagsReg cr) %{
- match(Set dst (XorL dst (LoadL mem)));
- effect(KILL cr);
- ins_cost(125);
- format %{ "XOR $dst.lo,$mem\n\t"
- "XOR $dst.hi,$mem+4" %}
- opcode(0x33,0x33);
- ins_encode( SetInstMark, OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem), ClearInstMark );
- ins_pipe( ialu_reg_long_mem );
-%}
-
-// Shift Left Long by 1
-instruct shlL_eReg_1(eRegL dst, immI_1 cnt, eFlagsReg cr) %{
- predicate(UseNewLongLShift);
- match(Set dst (LShiftL dst cnt));
- effect(KILL cr);
- ins_cost(100);
- format %{ "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi" %}
- ins_encode %{
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- %}
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Left Long by 2
-instruct shlL_eReg_2(eRegL dst, immI_2 cnt, eFlagsReg cr) %{
- predicate(UseNewLongLShift);
- match(Set dst (LShiftL dst cnt));
- effect(KILL cr);
- ins_cost(100);
- format %{ "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi\n\t"
- "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi" %}
- ins_encode %{
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- %}
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Left Long by 3
-instruct shlL_eReg_3(eRegL dst, immI_3 cnt, eFlagsReg cr) %{
- predicate(UseNewLongLShift);
- match(Set dst (LShiftL dst cnt));
- effect(KILL cr);
- ins_cost(100);
- format %{ "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi\n\t"
- "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi\n\t"
- "ADD $dst.lo,$dst.lo\n\t"
- "ADC $dst.hi,$dst.hi" %}
- ins_encode %{
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- __ addl($dst$$Register,$dst$$Register);
- __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
- %}
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Left Long by 1-31
-instruct shlL_eReg_1_31(eRegL dst, immI_1_31 cnt, eFlagsReg cr) %{
- match(Set dst (LShiftL dst cnt));
- effect(KILL cr);
- ins_cost(200);
- format %{ "SHLD $dst.hi,$dst.lo,$cnt\n\t"
- "SHL $dst.lo,$cnt" %}
- opcode(0xC1, 0x4, 0xA4); /* 0F/A4, then C1 /4 ib */
- ins_encode( move_long_small_shift(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Left Long by 32-63
-instruct shlL_eReg_32_63(eRegL dst, immI_32_63 cnt, eFlagsReg cr) %{
- match(Set dst (LShiftL dst cnt));
- effect(KILL cr);
- ins_cost(300);
- format %{ "MOV $dst.hi,$dst.lo\n"
- "\tSHL $dst.hi,$cnt-32\n"
- "\tXOR $dst.lo,$dst.lo" %}
- opcode(0xC1, 0x4); /* C1 /4 ib */
- ins_encode( move_long_big_shift_clr(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Left Long by variable
-instruct salL_eReg_CL(eRegL dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (LShiftL dst shift));
- effect(KILL cr);
- ins_cost(500+200);
- size(17);
- format %{ "TEST $shift,32\n\t"
- "JEQ,s small\n\t"
- "MOV $dst.hi,$dst.lo\n\t"
- "XOR $dst.lo,$dst.lo\n"
- "small:\tSHLD $dst.hi,$dst.lo,$shift\n\t"
- "SHL $dst.lo,$shift" %}
- ins_encode( shift_left_long( dst, shift ) );
- ins_pipe( pipe_slow );
-%}
-
-// Shift Right Long by 1-31
-instruct shrL_eReg_1_31(eRegL dst, immI_1_31 cnt, eFlagsReg cr) %{
- match(Set dst (URShiftL dst cnt));
- effect(KILL cr);
- ins_cost(200);
- format %{ "SHRD $dst.lo,$dst.hi,$cnt\n\t"
- "SHR $dst.hi,$cnt" %}
- opcode(0xC1, 0x5, 0xAC); /* 0F/AC, then C1 /5 ib */
- ins_encode( move_long_small_shift(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Right Long by 32-63
-instruct shrL_eReg_32_63(eRegL dst, immI_32_63 cnt, eFlagsReg cr) %{
- match(Set dst (URShiftL dst cnt));
- effect(KILL cr);
- ins_cost(300);
- format %{ "MOV $dst.lo,$dst.hi\n"
- "\tSHR $dst.lo,$cnt-32\n"
- "\tXOR $dst.hi,$dst.hi" %}
- opcode(0xC1, 0x5); /* C1 /5 ib */
- ins_encode( move_long_big_shift_clr(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Right Long by variable
-instruct shrL_eReg_CL(eRegL dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (URShiftL dst shift));
- effect(KILL cr);
- ins_cost(600);
- size(17);
- format %{ "TEST $shift,32\n\t"
- "JEQ,s small\n\t"
- "MOV $dst.lo,$dst.hi\n\t"
- "XOR $dst.hi,$dst.hi\n"
- "small:\tSHRD $dst.lo,$dst.hi,$shift\n\t"
- "SHR $dst.hi,$shift" %}
- ins_encode( shift_right_long( dst, shift ) );
- ins_pipe( pipe_slow );
-%}
-
-// Shift Right Long by 1-31
-instruct sarL_eReg_1_31(eRegL dst, immI_1_31 cnt, eFlagsReg cr) %{
- match(Set dst (RShiftL dst cnt));
- effect(KILL cr);
- ins_cost(200);
- format %{ "SHRD $dst.lo,$dst.hi,$cnt\n\t"
- "SAR $dst.hi,$cnt" %}
- opcode(0xC1, 0x7, 0xAC); /* 0F/AC, then C1 /7 ib */
- ins_encode( move_long_small_shift(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Right Long by 32-63
-instruct sarL_eReg_32_63( eRegL dst, immI_32_63 cnt, eFlagsReg cr) %{
- match(Set dst (RShiftL dst cnt));
- effect(KILL cr);
- ins_cost(300);
- format %{ "MOV $dst.lo,$dst.hi\n"
- "\tSAR $dst.lo,$cnt-32\n"
- "\tSAR $dst.hi,31" %}
- opcode(0xC1, 0x7); /* C1 /7 ib */
- ins_encode( move_long_big_shift_sign(dst,cnt) );
- ins_pipe( ialu_reg_long );
-%}
-
-// Shift Right arithmetic Long by variable
-instruct sarL_eReg_CL(eRegL dst, eCXRegI shift, eFlagsReg cr) %{
- match(Set dst (RShiftL dst shift));
- effect(KILL cr);
- ins_cost(600);
- size(18);
- format %{ "TEST $shift,32\n\t"
- "JEQ,s small\n\t"
- "MOV $dst.lo,$dst.hi\n\t"
- "SAR $dst.hi,31\n"
- "small:\tSHRD $dst.lo,$dst.hi,$shift\n\t"
- "SAR $dst.hi,$shift" %}
- ins_encode( shift_right_arith_long( dst, shift ) );
- ins_pipe( pipe_slow );
-%}
-
-
-//----------Double Instructions------------------------------------------------
-// Double Math
-
-// Compare & branch
-
-// P6 version of float compare, sets condition codes in EFLAGS
-instruct cmpDPR_cc_P6(eFlagsRegU cr, regDPR src1, regDPR src2, eAXRegI rax) %{
- predicate(VM_Version::supports_cmov() && UseSSE <=1);
- match(Set cr (CmpD src1 src2));
- effect(KILL rax);
- ins_cost(150);
- format %{ "FLD $src1\n\t"
- "FUCOMIP ST,$src2 // P6 instruction\n\t"
- "JNP exit\n\t"
- "MOV ah,1 // saw a NaN, set CF\n\t"
- "SAHF\n"
- "exit:\tNOP // avoid branch to branch" %}
- opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- cmpF_P6_fixup );
- ins_pipe( pipe_slow );
-%}
-
-instruct cmpDPR_cc_P6CF(eFlagsRegUCF cr, regDPR src1, regDPR src2) %{
- predicate(VM_Version::supports_cmov() && UseSSE <=1);
- match(Set cr (CmpD src1 src2));
- ins_cost(150);
- format %{ "FLD $src1\n\t"
- "FUCOMIP ST,$src2 // P6 instruction" %}
- opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2));
- ins_pipe( pipe_slow );
-%}
-
-// Compare & branch
-instruct cmpDPR_cc(eFlagsRegU cr, regDPR src1, regDPR src2, eAXRegI rax) %{
- predicate(UseSSE<=1);
- match(Set cr (CmpD src1 src2));
- effect(KILL rax);
- ins_cost(200);
- format %{ "FLD $src1\n\t"
- "FCOMp $src2\n\t"
- "FNSTSW AX\n\t"
- "TEST AX,0x400\n\t"
- "JZ,s flags\n\t"
- "MOV AH,1\t# unordered treat as LT\n"
- "flags:\tSAHF" %}
- opcode(0xD8, 0x3); /* D8 D8+i or D8 /3 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- fpu_flags);
- ins_pipe( pipe_slow );
-%}
-
-// Compare vs zero into -1,0,1
-instruct cmpDPR_0(rRegI dst, regDPR src1, immDPR0 zero, eAXRegI rax, eFlagsReg cr) %{
- predicate(UseSSE<=1);
- match(Set dst (CmpD3 src1 zero));
- effect(KILL cr, KILL rax);
- ins_cost(280);
- format %{ "FTSTD $dst,$src1" %}
- opcode(0xE4, 0xD9);
- ins_encode( Push_Reg_DPR(src1),
- OpcS, OpcP, PopFPU,
- CmpF_Result(dst));
- ins_pipe( pipe_slow );
-%}
-
-// Compare into -1,0,1
-instruct cmpDPR_reg(rRegI dst, regDPR src1, regDPR src2, eAXRegI rax, eFlagsReg cr) %{
- predicate(UseSSE<=1);
- match(Set dst (CmpD3 src1 src2));
- effect(KILL cr, KILL rax);
- ins_cost(300);
- format %{ "FCMPD $dst,$src1,$src2" %}
- opcode(0xD8, 0x3); /* D8 D8+i or D8 /3 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- CmpF_Result(dst));
- ins_pipe( pipe_slow );
-%}
-
-// float compare and set condition codes in EFLAGS by XMM regs
-instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2) %{
- predicate(UseSSE>=2);
- 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 cmpD_ccCF(eFlagsRegUCF cr, regD src1, regD src2) %{
- predicate(UseSSE>=2);
- match(Set cr (CmpD src1 src2));
- ins_cost(100);
- 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 cmpD_ccmem(eFlagsRegU cr, regD src1, memory src2) %{
- predicate(UseSSE>=2);
- match(Set cr (CmpD src1 (LoadD 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$$Address);
- emit_cmpfp_fixup(masm);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct cmpD_ccmemCF(eFlagsRegUCF cr, regD src1, memory src2) %{
- predicate(UseSSE>=2);
- match(Set cr (CmpD src1 (LoadD src2)));
- ins_cost(100);
- format %{ "UCOMISD $src1,$src2" %}
- ins_encode %{
- __ ucomisd($src1$$XMMRegister, $src2$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Compare into -1,0,1 in XMM
-instruct cmpD_reg(xRegI dst, regD src1, regD src2, eFlagsReg cr) %{
- predicate(UseSSE>=2);
- match(Set dst (CmpD3 src1 src2));
- effect(KILL cr);
- ins_cost(255);
- 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 cmpD_regmem(xRegI dst, regD src1, memory src2, eFlagsReg cr) %{
- predicate(UseSSE>=2);
- match(Set dst (CmpD3 src1 (LoadD src2)));
- effect(KILL cr);
- ins_cost(275);
- 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 );
-%}
-
-
-instruct subDPR_reg(regDPR dst, regDPR src) %{
- predicate (UseSSE <=1);
- match(Set dst (SubD dst src));
-
- format %{ "FLD $src\n\t"
- "DSUBp $dst,ST" %}
- opcode(0xDE, 0x5); /* DE E8+i or DE /5 */
- ins_cost(150);
- ins_encode( Push_Reg_DPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct subDPR_reg_round(stackSlotD dst, regDPR src1, regDPR src2) %{
- predicate (UseSSE <=1);
- match(Set dst (RoundDouble (SubD src1 src2)));
- ins_cost(250);
-
- format %{ "FLD $src2\n\t"
- "DSUB ST,$src1\n\t"
- "FSTP_D $dst\t# D-round" %}
- opcode(0xD8, 0x5);
- ins_encode( Push_Reg_DPR(src2),
- OpcP, RegOpc(src1), Pop_Mem_DPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-
-
-instruct subDPR_reg_mem(regDPR dst, memory src) %{
- predicate (UseSSE <=1);
- match(Set dst (SubD dst (LoadD src)));
- ins_cost(150);
-
- format %{ "FLD $src\n\t"
- "DSUBp $dst,ST" %}
- opcode(0xDE, 0x5, 0xDD); /* DE C0+i */ /* LoadD DD /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src),
- OpcP, RegOpc(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct absDPR_reg(regDPR1 dst, regDPR1 src) %{
- predicate (UseSSE<=1);
- match(Set dst (AbsD src));
- ins_cost(100);
- format %{ "FABS" %}
- opcode(0xE1, 0xD9);
- ins_encode( OpcS, OpcP );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct negDPR_reg(regDPR1 dst, regDPR1 src) %{
- predicate(UseSSE<=1);
- match(Set dst (NegD src));
- ins_cost(100);
- format %{ "FCHS" %}
- opcode(0xE0, 0xD9);
- ins_encode( OpcS, OpcP );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct addDPR_reg(regDPR dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (AddD dst src));
- format %{ "FLD $src\n\t"
- "DADD $dst,ST" %}
- size(4);
- ins_cost(150);
- opcode(0xDE, 0x0); /* DE C0+i or DE /0*/
- ins_encode( Push_Reg_DPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-
-instruct addDPR_reg_round(stackSlotD dst, regDPR src1, regDPR src2) %{
- predicate(UseSSE<=1);
- match(Set dst (RoundDouble (AddD src1 src2)));
- ins_cost(250);
-
- format %{ "FLD $src2\n\t"
- "DADD ST,$src1\n\t"
- "FSTP_D $dst\t# D-round" %}
- opcode(0xD8, 0x0); /* D8 C0+i or D8 /0*/
- ins_encode( Push_Reg_DPR(src2),
- OpcP, RegOpc(src1), Pop_Mem_DPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-
-
-instruct addDPR_reg_mem(regDPR dst, memory src) %{
- predicate(UseSSE<=1);
- match(Set dst (AddD dst (LoadD src)));
- ins_cost(150);
-
- format %{ "FLD $src\n\t"
- "DADDp $dst,ST" %}
- opcode(0xDE, 0x0, 0xDD); /* DE C0+i */ /* LoadD DD /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src),
- OpcP, RegOpc(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// add-to-memory
-instruct addDPR_mem_reg(memory dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (StoreD dst (RoundDouble (AddD (LoadD dst) src))));
- ins_cost(150);
-
- format %{ "FLD_D $dst\n\t"
- "DADD ST,$src\n\t"
- "FST_D $dst" %}
- opcode(0xDD, 0x0);
- ins_encode( SetInstMark, Opcode(0xDD), RMopc_Mem(0x00,dst),
- Opcode(0xD8), RegOpc(src), ClearInstMark,
- SetInstMark,
- Opcode(0xDD), RMopc_Mem(0x03,dst),
- ClearInstMark);
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct addDPR_reg_imm1(regDPR dst, immDPR1 con) %{
- predicate(UseSSE<=1);
- match(Set dst (AddD dst con));
- ins_cost(125);
- format %{ "FLD1\n\t"
- "DADDp $dst,ST" %}
- ins_encode %{
- __ fld1();
- __ faddp($dst$$reg);
- %}
- ins_pipe(fpu_reg);
-%}
-
-instruct addDPR_reg_imm(regDPR dst, immDPR con) %{
- predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (AddD dst con));
- ins_cost(200);
- format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
- "DADDp $dst,ST" %}
- ins_encode %{
- __ fld_d($constantaddress($con));
- __ faddp($dst$$reg);
- %}
- ins_pipe(fpu_reg_mem);
-%}
-
-instruct addDPR_reg_imm_round(stackSlotD dst, regDPR src, immDPR con) %{
- predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (RoundDouble (AddD src con)));
- ins_cost(200);
- format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
- "DADD ST,$src\n\t"
- "FSTP_D $dst\t# D-round" %}
- ins_encode %{
- __ fld_d($constantaddress($con));
- __ fadd($src$$reg);
- __ fstp_d(Address(rsp, $dst$$disp));
- %}
- ins_pipe(fpu_mem_reg_con);
-%}
-
-instruct mulDPR_reg(regDPR dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (MulD dst src));
- format %{ "FLD $src\n\t"
- "DMULp $dst,ST" %}
- opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
- ins_cost(150);
- ins_encode( Push_Reg_DPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-// Strict FP instruction biases argument before multiply then
-// biases result to avoid double rounding of subnormals.
-//
-// scale arg1 by multiplying arg1 by 2^(-15360)
-// load arg2
-// multiply scaled arg1 by arg2
-// rescale product by 2^(15360)
-//
-instruct strictfp_mulDPR_reg(regDPR1 dst, regnotDPR1 src) %{
- predicate( UseSSE<=1 && Compile::current()->has_method() );
- match(Set dst (MulD dst src));
- ins_cost(1); // Select this instruction for all FP double multiplies
-
- format %{ "FLD StubRoutines::x86::_fpu_subnormal_bias1\n\t"
- "DMULp $dst,ST\n\t"
- "FLD $src\n\t"
- "DMULp $dst,ST\n\t"
- "FLD StubRoutines::x86::_fpu_subnormal_bias2\n\t"
- "DMULp $dst,ST\n\t" %}
- opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
- ins_encode( strictfp_bias1(dst),
- Push_Reg_DPR(src),
- OpcP, RegOpc(dst),
- strictfp_bias2(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct mulDPR_reg_imm(regDPR dst, immDPR con) %{
- predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (MulD dst con));
- ins_cost(200);
- format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
- "DMULp $dst,ST" %}
- ins_encode %{
- __ fld_d($constantaddress($con));
- __ fmulp($dst$$reg);
- %}
- ins_pipe(fpu_reg_mem);
-%}
-
-
-instruct mulDPR_reg_mem(regDPR dst, memory src) %{
- predicate( UseSSE<=1 );
- match(Set dst (MulD dst (LoadD src)));
- ins_cost(200);
- format %{ "FLD_D $src\n\t"
- "DMULp $dst,ST" %}
- opcode(0xDE, 0x1, 0xDD); /* DE C8+i or DE /1*/ /* LoadD DD /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src),
- OpcP, RegOpc(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-//
-// Cisc-alternate to reg-reg multiply
-instruct mulDPR_reg_mem_cisc(regDPR dst, regDPR src, memory mem) %{
- predicate( UseSSE<=1 );
- match(Set dst (MulD src (LoadD mem)));
- ins_cost(250);
- format %{ "FLD_D $mem\n\t"
- "DMUL ST,$src\n\t"
- "FSTP_D $dst" %}
- opcode(0xD8, 0x1, 0xD9); /* D8 C8+i */ /* LoadD D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,mem),
- OpcReg_FPR(src),
- Pop_Reg_DPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_reg_mem );
-%}
-
-
-// MACRO3 -- addDPR a mulDPR
-// This instruction is a '2-address' instruction in that the result goes
-// back to src2. This eliminates a move from the macro; possibly the
-// register allocator will have to add it back (and maybe not).
-instruct addDPR_mulDPR_reg(regDPR src2, regDPR src1, regDPR src0) %{
- predicate( UseSSE<=1 );
- match(Set src2 (AddD (MulD src0 src1) src2));
- format %{ "FLD $src0\t# ===MACRO3d===\n\t"
- "DMUL ST,$src1\n\t"
- "DADDp $src2,ST" %}
- ins_cost(250);
- opcode(0xDD); /* LoadD DD /0 */
- ins_encode( Push_Reg_FPR(src0),
- FMul_ST_reg(src1),
- FAddP_reg_ST(src2) );
- ins_pipe( fpu_reg_reg_reg );
-%}
-
-
-// MACRO3 -- subDPR a mulDPR
-instruct subDPR_mulDPR_reg(regDPR src2, regDPR src1, regDPR src0) %{
- predicate( UseSSE<=1 );
- match(Set src2 (SubD (MulD src0 src1) src2));
- format %{ "FLD $src0\t# ===MACRO3d===\n\t"
- "DMUL ST,$src1\n\t"
- "DSUBRp $src2,ST" %}
- ins_cost(250);
- ins_encode( Push_Reg_FPR(src0),
- FMul_ST_reg(src1),
- Opcode(0xDE), Opc_plus(0xE0,src2));
- ins_pipe( fpu_reg_reg_reg );
-%}
-
-
-instruct divDPR_reg(regDPR dst, regDPR src) %{
- predicate( UseSSE<=1 );
- match(Set dst (DivD dst src));
-
- format %{ "FLD $src\n\t"
- "FDIVp $dst,ST" %}
- opcode(0xDE, 0x7); /* DE F8+i or DE /7*/
- ins_cost(150);
- ins_encode( Push_Reg_DPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-// Strict FP instruction biases argument before division then
-// biases result, to avoid double rounding of subnormals.
-//
-// scale dividend by multiplying dividend by 2^(-15360)
-// load divisor
-// divide scaled dividend by divisor
-// rescale quotient by 2^(15360)
-//
-instruct strictfp_divDPR_reg(regDPR1 dst, regnotDPR1 src) %{
- predicate (UseSSE<=1);
- match(Set dst (DivD dst src));
- predicate( UseSSE<=1 && Compile::current()->has_method() );
- ins_cost(01);
-
- format %{ "FLD StubRoutines::x86::_fpu_subnormal_bias1\n\t"
- "DMULp $dst,ST\n\t"
- "FLD $src\n\t"
- "FDIVp $dst,ST\n\t"
- "FLD StubRoutines::x86::_fpu_subnormal_bias2\n\t"
- "DMULp $dst,ST\n\t" %}
- opcode(0xDE, 0x7); /* DE F8+i or DE /7*/
- ins_encode( strictfp_bias1(dst),
- Push_Reg_DPR(src),
- OpcP, RegOpc(dst),
- strictfp_bias2(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct atanDPR_reg(regDPR dst, regDPR src) %{
- predicate (UseSSE<=1);
- match(Set dst(AtanD dst src));
- format %{ "DATA $dst,$src" %}
- opcode(0xD9, 0xF3);
- ins_encode( Push_Reg_DPR(src),
- OpcP, OpcS, RegOpc(dst) );
- ins_pipe( pipe_slow );
-%}
-
-instruct atanD_reg(regD dst, regD src, eFlagsReg cr) %{
- predicate (UseSSE>=2);
- match(Set dst(AtanD dst src));
- effect(KILL cr); // Push_{Src|Result}D() uses "{SUB|ADD} ESP,8"
- format %{ "DATA $dst,$src" %}
- opcode(0xD9, 0xF3);
- ins_encode( Push_SrcD(src),
- OpcP, OpcS, Push_ResultD(dst) );
- ins_pipe( pipe_slow );
-%}
-
-instruct sqrtDPR_reg(regDPR dst, regDPR src) %{
- predicate (UseSSE<=1);
- match(Set dst (SqrtD src));
- format %{ "DSQRT $dst,$src" %}
- opcode(0xFA, 0xD9);
- ins_encode( Push_Reg_DPR(src),
- OpcS, OpcP, Pop_Reg_DPR(dst) );
- ins_pipe( pipe_slow );
-%}
-
-//-------------Float Instructions-------------------------------
-// Float Math
-
-// Code for float compare:
-// fcompp();
-// fwait(); fnstsw_ax();
-// sahf();
-// movl(dst, unordered_result);
-// jcc(Assembler::parity, exit);
-// movl(dst, less_result);
-// jcc(Assembler::below, exit);
-// movl(dst, equal_result);
-// jcc(Assembler::equal, exit);
-// movl(dst, greater_result);
-// exit:
-
-// P6 version of float compare, sets condition codes in EFLAGS
-instruct cmpFPR_cc_P6(eFlagsRegU cr, regFPR src1, regFPR src2, eAXRegI rax) %{
- predicate(VM_Version::supports_cmov() && UseSSE == 0);
- match(Set cr (CmpF src1 src2));
- effect(KILL rax);
- ins_cost(150);
- format %{ "FLD $src1\n\t"
- "FUCOMIP ST,$src2 // P6 instruction\n\t"
- "JNP exit\n\t"
- "MOV ah,1 // saw a NaN, set CF (treat as LT)\n\t"
- "SAHF\n"
- "exit:\tNOP // avoid branch to branch" %}
- opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- cmpF_P6_fixup );
- ins_pipe( pipe_slow );
-%}
-
-instruct cmpFPR_cc_P6CF(eFlagsRegUCF cr, regFPR src1, regFPR src2) %{
- predicate(VM_Version::supports_cmov() && UseSSE == 0);
- match(Set cr (CmpF src1 src2));
- ins_cost(100);
- format %{ "FLD $src1\n\t"
- "FUCOMIP ST,$src2 // P6 instruction" %}
- opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2));
- ins_pipe( pipe_slow );
-%}
-
-
-// Compare & branch
-instruct cmpFPR_cc(eFlagsRegU cr, regFPR src1, regFPR src2, eAXRegI rax) %{
- predicate(UseSSE == 0);
- match(Set cr (CmpF src1 src2));
- effect(KILL rax);
- ins_cost(200);
- format %{ "FLD $src1\n\t"
- "FCOMp $src2\n\t"
- "FNSTSW AX\n\t"
- "TEST AX,0x400\n\t"
- "JZ,s flags\n\t"
- "MOV AH,1\t# unordered treat as LT\n"
- "flags:\tSAHF" %}
- opcode(0xD8, 0x3); /* D8 D8+i or D8 /3 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- fpu_flags);
- ins_pipe( pipe_slow );
-%}
-
-// Compare vs zero into -1,0,1
-instruct cmpFPR_0(rRegI dst, regFPR src1, immFPR0 zero, eAXRegI rax, eFlagsReg cr) %{
- predicate(UseSSE == 0);
- match(Set dst (CmpF3 src1 zero));
- effect(KILL cr, KILL rax);
- ins_cost(280);
- format %{ "FTSTF $dst,$src1" %}
- opcode(0xE4, 0xD9);
- ins_encode( Push_Reg_DPR(src1),
- OpcS, OpcP, PopFPU,
- CmpF_Result(dst));
- ins_pipe( pipe_slow );
-%}
-
-// Compare into -1,0,1
-instruct cmpFPR_reg(rRegI dst, regFPR src1, regFPR src2, eAXRegI rax, eFlagsReg cr) %{
- predicate(UseSSE == 0);
- match(Set dst (CmpF3 src1 src2));
- effect(KILL cr, KILL rax);
- ins_cost(300);
- format %{ "FCMPF $dst,$src1,$src2" %}
- opcode(0xD8, 0x3); /* D8 D8+i or D8 /3 */
- ins_encode( Push_Reg_DPR(src1),
- OpcP, RegOpc(src2),
- CmpF_Result(dst));
- ins_pipe( pipe_slow );
-%}
-
-// float compare and set condition codes in EFLAGS by XMM regs
-instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2) %{
- predicate(UseSSE>=1);
- match(Set cr (CmpF src1 src2));
- ins_cost(145);
- 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 cmpF_ccCF(eFlagsRegUCF cr, regF src1, regF src2) %{
- predicate(UseSSE>=1);
- match(Set cr (CmpF src1 src2));
- ins_cost(100);
- 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 cmpF_ccmem(eFlagsRegU cr, regF src1, memory src2) %{
- predicate(UseSSE>=1);
- match(Set cr (CmpF src1 (LoadF src2)));
- ins_cost(165);
- 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 cmpF_ccmemCF(eFlagsRegUCF cr, regF src1, memory src2) %{
- predicate(UseSSE>=1);
- match(Set cr (CmpF src1 (LoadF src2)));
- ins_cost(100);
- format %{ "UCOMISS $src1,$src2" %}
- ins_encode %{
- __ ucomiss($src1$$XMMRegister, $src2$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Compare into -1,0,1 in XMM
-instruct cmpF_reg(xRegI dst, regF src1, regF src2, eFlagsReg cr) %{
- predicate(UseSSE>=1);
- match(Set dst (CmpF3 src1 src2));
- effect(KILL cr);
- ins_cost(255);
- 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 cmpF_regmem(xRegI dst, regF src1, memory src2, eFlagsReg cr) %{
- predicate(UseSSE>=1);
- match(Set dst (CmpF3 src1 (LoadF src2)));
- effect(KILL cr);
- ins_cost(275);
- 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 );
-%}
-
-// Spill to obtain 24-bit precision
-instruct subFPR24_reg(stackSlotF dst, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (SubF src1 src2));
-
- format %{ "FSUB $dst,$src1 - $src2" %}
- opcode(0xD8, 0x4); /* D8 E0+i or D8 /4 mod==0x3 ;; result in TOS */
- ins_encode( Push_Reg_FPR(src1),
- OpcReg_FPR(src2),
- Pop_Mem_FPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-//
-// This instruction does not round to 24-bits
-instruct subFPR_reg(regFPR dst, regFPR src) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (SubF dst src));
-
- format %{ "FSUB $dst,$src" %}
- opcode(0xDE, 0x5); /* DE E8+i or DE /5 */
- ins_encode( Push_Reg_FPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-// Spill to obtain 24-bit precision
-instruct addFPR24_reg(stackSlotF dst, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
-
- format %{ "FADD $dst,$src1,$src2" %}
- opcode(0xD8, 0x0); /* D8 C0+i */
- ins_encode( Push_Reg_FPR(src2),
- OpcReg_FPR(src1),
- Pop_Mem_FPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-//
-// This instruction does not round to 24-bits
-instruct addFPR_reg(regFPR dst, regFPR src) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF dst src));
-
- format %{ "FLD $src\n\t"
- "FADDp $dst,ST" %}
- opcode(0xDE, 0x0); /* DE C0+i or DE /0*/
- ins_encode( Push_Reg_FPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct absFPR_reg(regFPR1 dst, regFPR1 src) %{
- predicate(UseSSE==0);
- match(Set dst (AbsF src));
- ins_cost(100);
- format %{ "FABS" %}
- opcode(0xE1, 0xD9);
- ins_encode( OpcS, OpcP );
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct negFPR_reg(regFPR1 dst, regFPR1 src) %{
- predicate(UseSSE==0);
- match(Set dst (NegF src));
- ins_cost(100);
- format %{ "FCHS" %}
- opcode(0xE0, 0xD9);
- ins_encode( OpcS, OpcP );
- ins_pipe( fpu_reg_reg );
-%}
-
-// Cisc-alternate to addFPR_reg
-// Spill to obtain 24-bit precision
-instruct addFPR24_reg_mem(stackSlotF dst, regFPR src1, memory src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 (LoadF src2)));
-
- format %{ "FLD $src2\n\t"
- "FADD ST,$src1\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x0, 0xD9); /* D8 C0+i */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcReg_FPR(src1),
- Pop_Mem_FPR(dst), ClearInstMark );
- ins_pipe( fpu_mem_reg_mem );
-%}
-//
-// Cisc-alternate to addFPR_reg
-// This instruction does not round to 24-bits
-instruct addFPR_reg_mem(regFPR dst, memory src) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF dst (LoadF src)));
-
- format %{ "FADD $dst,$src" %}
- opcode(0xDE, 0x0, 0xD9); /* DE C0+i or DE /0*/ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src),
- OpcP, RegOpc(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-// // Following two instructions for _222_mpegaudio
-// Spill to obtain 24-bit precision
-instruct addFPR24_mem_reg(stackSlotF dst, regFPR src2, memory src1 ) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
-
- format %{ "FADD $dst,$src1,$src2" %}
- opcode(0xD8, 0x0, 0xD9); /* D8 C0+i */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src1),
- OpcReg_FPR(src2),
- Pop_Mem_FPR(dst), ClearInstMark );
- ins_pipe( fpu_mem_reg_mem );
-%}
-
-// Cisc-spill variant
-// Spill to obtain 24-bit precision
-instruct addFPR24_mem_cisc(stackSlotF dst, memory src1, memory src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 (LoadF src2)));
-
- format %{ "FADD $dst,$src1,$src2 cisc" %}
- opcode(0xD8, 0x0, 0xD9); /* D8 C0+i */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcP, RMopc_Mem(secondary,src1),
- Pop_Mem_FPR(dst),
- ClearInstMark);
- ins_pipe( fpu_mem_mem_mem );
-%}
-
-// Spill to obtain 24-bit precision
-instruct addFPR24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
-
- format %{ "FADD $dst,$src1,$src2" %}
- opcode(0xD8, 0x0, 0xD9); /* D8 /0 */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcP, RMopc_Mem(secondary,src1),
- Pop_Mem_FPR(dst),
- ClearInstMark);
- ins_pipe( fpu_mem_mem_mem );
-%}
-
-
-// Spill to obtain 24-bit precision
-instruct addFPR24_reg_imm(stackSlotF dst, regFPR src, immFPR con) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src con));
- format %{ "FLD $src\n\t"
- "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
- "FSTP_S $dst" %}
- ins_encode %{
- __ fld_s($src$$reg - 1); // FLD ST(i-1)
- __ fadd_s($constantaddress($con));
- __ fstp_s(Address(rsp, $dst$$disp));
- %}
- ins_pipe(fpu_mem_reg_con);
-%}
-//
-// This instruction does not round to 24-bits
-instruct addFPR_reg_imm(regFPR dst, regFPR src, immFPR con) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src con));
- format %{ "FLD $src\n\t"
- "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld_s($src$$reg - 1); // FLD ST(i-1)
- __ fadd_s($constantaddress($con));
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_reg_con);
-%}
-
-// Spill to obtain 24-bit precision
-instruct mulFPR24_reg(stackSlotF dst, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
-
- format %{ "FLD $src1\n\t"
- "FMUL $src2\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x1); /* D8 C8+i or D8 /1 ;; result in TOS */
- ins_encode( Push_Reg_FPR(src1),
- OpcReg_FPR(src2),
- Pop_Mem_FPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-//
-// This instruction does not round to 24-bits
-instruct mulFPR_reg(regFPR dst, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
-
- format %{ "FLD $src1\n\t"
- "FMUL $src2\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x1); /* D8 C8+i */
- ins_encode( Push_Reg_FPR(src2),
- OpcReg_FPR(src1),
- Pop_Reg_FPR(dst) );
- ins_pipe( fpu_reg_reg_reg );
-%}
-
-
-// Spill to obtain 24-bit precision
-// Cisc-alternate to reg-reg multiply
-instruct mulFPR24_reg_mem(stackSlotF dst, regFPR src1, memory src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 (LoadF src2)));
-
- format %{ "FLD_S $src2\n\t"
- "FMUL $src1\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x1, 0xD9); /* D8 C8+i or DE /1*/ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcReg_FPR(src1),
- Pop_Mem_FPR(dst), ClearInstMark );
- ins_pipe( fpu_mem_reg_mem );
-%}
-//
-// This instruction does not round to 24-bits
-// Cisc-alternate to reg-reg multiply
-instruct mulFPR_reg_mem(regFPR dst, regFPR src1, memory src2) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 (LoadF src2)));
-
- format %{ "FMUL $dst,$src1,$src2" %}
- opcode(0xD8, 0x1, 0xD9); /* D8 C8+i */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcReg_FPR(src1),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_reg_mem );
-%}
-
-// Spill to obtain 24-bit precision
-instruct mulFPR24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
-
- format %{ "FMUL $dst,$src1,$src2" %}
- opcode(0xD8, 0x1, 0xD9); /* D8 /1 */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,src2),
- OpcP, RMopc_Mem(secondary,src1),
- Pop_Mem_FPR(dst),
- ClearInstMark );
- ins_pipe( fpu_mem_mem_mem );
-%}
-
-// Spill to obtain 24-bit precision
-instruct mulFPR24_reg_imm(stackSlotF dst, regFPR src, immFPR con) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src con));
-
- format %{ "FLD $src\n\t"
- "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
- "FSTP_S $dst" %}
- ins_encode %{
- __ fld_s($src$$reg - 1); // FLD ST(i-1)
- __ fmul_s($constantaddress($con));
- __ fstp_s(Address(rsp, $dst$$disp));
- %}
- ins_pipe(fpu_mem_reg_con);
-%}
-//
-// This instruction does not round to 24-bits
-instruct mulFPR_reg_imm(regFPR dst, regFPR src, immFPR con) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src con));
-
- format %{ "FLD $src\n\t"
- "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
- "FSTP $dst" %}
- ins_encode %{
- __ fld_s($src$$reg - 1); // FLD ST(i-1)
- __ fmul_s($constantaddress($con));
- __ fstp_d($dst$$reg);
- %}
- ins_pipe(fpu_reg_reg_con);
-%}
-
-
-//
-// MACRO1 -- subsume unshared load into mulFPR
-// This instruction does not round to 24-bits
-instruct mulFPR_reg_load1(regFPR dst, regFPR src, memory mem1 ) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF (LoadF mem1) src));
-
- format %{ "FLD $mem1 ===MACRO1===\n\t"
- "FMUL ST,$src\n\t"
- "FSTP $dst" %}
- opcode(0xD8, 0x1, 0xD9); /* D8 C8+i or D8 /1 */ /* LoadF D9 /0 */
- ins_encode( SetInstMark, Opcode(tertiary), RMopc_Mem(0x00,mem1),
- OpcReg_FPR(src),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_reg_mem );
-%}
-//
-// MACRO2 -- addFPR a mulFPR which subsumed an unshared load
-// This instruction does not round to 24-bits
-instruct addFPR_mulFPR_reg_load1(regFPR dst, memory mem1, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF (MulF (LoadF mem1) src1) src2));
- ins_cost(95);
-
- format %{ "FLD $mem1 ===MACRO2===\n\t"
- "FMUL ST,$src1 subsume mulFPR left load\n\t"
- "FADD ST,$src2\n\t"
- "FSTP $dst" %}
- opcode(0xD9); /* LoadF D9 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem1),
- FMul_ST_reg(src1),
- FAdd_ST_reg(src2),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem_reg_reg );
-%}
-
-// MACRO3 -- addFPR a mulFPR
-// This instruction does not round to 24-bits. It is a '2-address'
-// instruction in that the result goes back to src2. This eliminates
-// a move from the macro; possibly the register allocator will have
-// to add it back (and maybe not).
-instruct addFPR_mulFPR_reg(regFPR src2, regFPR src1, regFPR src0) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set src2 (AddF (MulF src0 src1) src2));
-
- format %{ "FLD $src0 ===MACRO3===\n\t"
- "FMUL ST,$src1\n\t"
- "FADDP $src2,ST" %}
- opcode(0xD9); /* LoadF D9 /0 */
- ins_encode( Push_Reg_FPR(src0),
- FMul_ST_reg(src1),
- FAddP_reg_ST(src2) );
- ins_pipe( fpu_reg_reg_reg );
-%}
-
-// MACRO4 -- divFPR subFPR
-// This instruction does not round to 24-bits
-instruct subFPR_divFPR_reg(regFPR dst, regFPR src1, regFPR src2, regFPR src3) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (DivF (SubF src2 src1) src3));
-
- format %{ "FLD $src2 ===MACRO4===\n\t"
- "FSUB ST,$src1\n\t"
- "FDIV ST,$src3\n\t"
- "FSTP $dst" %}
- opcode(0xDE, 0x7); /* DE F8+i or DE /7*/
- ins_encode( Push_Reg_FPR(src2),
- subFPR_divFPR_encode(src1,src3),
- Pop_Reg_FPR(dst) );
- ins_pipe( fpu_reg_reg_reg_reg );
-%}
-
-// Spill to obtain 24-bit precision
-instruct divFPR24_reg(stackSlotF dst, regFPR src1, regFPR src2) %{
- predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (DivF src1 src2));
-
- format %{ "FDIV $dst,$src1,$src2" %}
- opcode(0xD8, 0x6); /* D8 F0+i or DE /6*/
- ins_encode( Push_Reg_FPR(src1),
- OpcReg_FPR(src2),
- Pop_Mem_FPR(dst) );
- ins_pipe( fpu_mem_reg_reg );
-%}
-//
-// This instruction does not round to 24-bits
-instruct divFPR_reg(regFPR dst, regFPR src) %{
- predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (DivF dst src));
-
- format %{ "FDIV $dst,$src" %}
- opcode(0xDE, 0x7); /* DE F8+i or DE /7*/
- ins_encode( Push_Reg_FPR(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_reg );
-%}
-
-
-//----------Arithmetic Conversion Instructions---------------------------------
-// The conversions operations are all Alpha sorted. Please keep it that way!
-
-instruct roundFloat_mem_reg(stackSlotF dst, regFPR src) %{
- predicate(UseSSE==0);
- match(Set dst (RoundFloat src));
- ins_cost(125);
- format %{ "FST_S $dst,$src\t# F-round" %}
- ins_encode( Pop_Mem_Reg_FPR(dst, src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-instruct roundDouble_mem_reg(stackSlotD dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (RoundDouble src));
- ins_cost(125);
- format %{ "FST_D $dst,$src\t# D-round" %}
- ins_encode( Pop_Mem_Reg_DPR(dst, src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-// Force rounding to 24-bit precision and 6-bit exponent
-instruct convDPR2FPR_reg(stackSlotF dst, regDPR src) %{
- predicate(UseSSE==0);
- match(Set dst (ConvD2F src));
- format %{ "FST_S $dst,$src\t# F-round" %}
- expand %{
- roundFloat_mem_reg(dst,src);
- %}
-%}
-
-// Force rounding to 24-bit precision and 6-bit exponent
-instruct convDPR2F_reg(regF dst, regDPR src, eFlagsReg cr) %{
- predicate(UseSSE==1);
- match(Set dst (ConvD2F src));
- effect( KILL cr );
- format %{ "SUB ESP,4\n\t"
- "FST_S [ESP],$src\t# F-round\n\t"
- "MOVSS $dst,[ESP]\n\t"
- "ADD ESP,4" %}
- 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 );
-%}
-
-// Force rounding double precision to single precision
-instruct convD2F_reg(regF dst, regD src) %{
- predicate(UseSSE>=2);
- match(Set dst (ConvD2F src));
- format %{ "CVTSD2SS $dst,$src\t# F-round" %}
- ins_encode %{
- __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convFPR2DPR_reg_reg(regDPR dst, regFPR src) %{
- predicate(UseSSE==0);
- match(Set dst (ConvF2D src));
- format %{ "FST_S $dst,$src\t# D-round" %}
- ins_encode( Pop_Reg_Reg_DPR(dst, src));
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct convFPR2D_reg(stackSlotD dst, regFPR src) %{
- predicate(UseSSE==1);
- match(Set dst (ConvF2D src));
- format %{ "FST_D $dst,$src\t# D-round" %}
- expand %{
- roundDouble_mem_reg(dst,src);
- %}
-%}
-
-instruct convF2DPR_reg(regDPR dst, regF src, eFlagsReg cr) %{
- predicate(UseSSE==1);
- match(Set dst (ConvF2D src));
- effect( KILL cr );
- format %{ "SUB ESP,4\n\t"
- "MOVSS [ESP] $src\n\t"
- "FLD_S [ESP]\n\t"
- "ADD ESP,4\n\t"
- "FSTP $dst\t# D-round" %}
- 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 );
-%}
-
-instruct convF2D_reg(regD dst, regF src) %{
- predicate(UseSSE>=2);
- match(Set dst (ConvF2D src));
- format %{ "CVTSS2SD $dst,$src\t# D-round" %}
- ins_encode %{
- __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Convert a double to an int. If the double is a NAN, stuff a zero in instead.
-instruct convDPR2I_reg_reg( eAXRegI dst, eDXRegI tmp, regDPR src, eFlagsReg cr ) %{
- predicate(UseSSE<=1);
- match(Set dst (ConvD2I src));
- effect( KILL tmp, KILL cr );
- format %{ "FLD $src\t# Convert double to int \n\t"
- "FLDCW trunc mode\n\t"
- "SUB ESP,4\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "CMP EAX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "FLD_D $src\n\t"
- "CALL d2i_wrapper\n"
- "fast:" %}
- ins_encode( Push_Reg_DPR(src), DPR2I_encoding(src) );
- ins_pipe( pipe_slow );
-%}
-
-// Convert a double to an int. If the double is a NAN, stuff a zero in instead.
-instruct convD2I_reg_reg( eAXRegI dst, eDXRegI tmp, regD src, eFlagsReg cr ) %{
- predicate(UseSSE>=2);
- match(Set dst (ConvD2I src));
- effect( KILL tmp, KILL cr );
- format %{ "CVTTSD2SI $dst, $src\n\t"
- "CMP $dst,0x80000000\n\t"
- "JNE,s fast\n\t"
- "SUB ESP, 8\n\t"
- "MOVSD [ESP], $src\n\t"
- "FLD_D [ESP]\n\t"
- "ADD ESP, 8\n\t"
- "CALL d2i_wrapper\n"
- "fast:" %}
- 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::x86::d2i_wrapper())));
- __ post_call_nop();
- __ bind(fast);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convDPR2L_reg_reg( eADXRegL dst, regDPR src, eFlagsReg cr ) %{
- predicate(UseSSE<=1);
- match(Set dst (ConvD2L src));
- effect( KILL cr );
- format %{ "FLD $src\t# Convert double to long\n\t"
- "FLDCW trunc mode\n\t"
- "SUB ESP,8\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "POP EDX\n\t"
- "CMP EDX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "TEST EAX,EAX\n\t"
- "JNE,s fast\n\t"
- "FLD $src\n\t"
- "CALL d2l_wrapper\n"
- "fast:" %}
- ins_encode( Push_Reg_DPR(src), DPR2L_encoding(src) );
- ins_pipe( pipe_slow );
-%}
-
-// XMM lacks a float/double->long conversion, so use the old FPU stack.
-instruct convD2L_reg_reg( eADXRegL dst, regD src, eFlagsReg cr ) %{
- predicate (UseSSE>=2);
- match(Set dst (ConvD2L src));
- effect( KILL cr );
- format %{ "SUB ESP,8\t# Convert double to long\n\t"
- "MOVSD [ESP],$src\n\t"
- "FLD_D [ESP]\n\t"
- "FLDCW trunc mode\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "POP EDX\n\t"
- "CMP EDX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "TEST EAX,EAX\n\t"
- "JNE,s fast\n\t"
- "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 %{
- Label fast;
- __ subptr(rsp, 8);
- __ movdbl(Address(rsp, 0), $src$$XMMRegister);
- __ fld_d(Address(rsp, 0));
- __ fldcw(ExternalAddress(StubRoutines::x86::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::x86::addr_fpu_cntrl_wrd_24()));
- } else {
- __ fldcw(ExternalAddress(StubRoutines::x86::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::x86::d2l_wrapper())));
- __ post_call_nop();
- __ bind(fast);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Convert a double to an int. Java semantics require we do complex
-// manglations in the corner cases. So we set the rounding mode to
-// 'zero', store the darned double down as an int, and reset the
-// rounding mode to 'nearest'. The hardware stores a flag value down
-// if we would overflow or converted a NAN; we check for this and
-// and go the slow path if needed.
-instruct convFPR2I_reg_reg(eAXRegI dst, eDXRegI tmp, regFPR src, eFlagsReg cr ) %{
- predicate(UseSSE==0);
- match(Set dst (ConvF2I src));
- effect( KILL tmp, KILL cr );
- format %{ "FLD $src\t# Convert float to int \n\t"
- "FLDCW trunc mode\n\t"
- "SUB ESP,4\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "CMP EAX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "FLD $src\n\t"
- "CALL d2i_wrapper\n"
- "fast:" %}
- // DPR2I_encoding works for FPR2I
- ins_encode( Push_Reg_FPR(src), DPR2I_encoding(src) );
- ins_pipe( pipe_slow );
-%}
-
-// Convert a float in xmm to an int reg.
-instruct convF2I_reg(eAXRegI dst, eDXRegI tmp, regF src, eFlagsReg cr ) %{
- predicate(UseSSE>=1);
- match(Set dst (ConvF2I src));
- effect( KILL tmp, KILL cr );
- format %{ "CVTTSS2SI $dst, $src\n\t"
- "CMP $dst,0x80000000\n\t"
- "JNE,s fast\n\t"
- "SUB ESP, 4\n\t"
- "MOVSS [ESP], $src\n\t"
- "FLD [ESP]\n\t"
- "ADD ESP, 4\n\t"
- "CALL d2i_wrapper\n"
- "fast:" %}
- 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::x86::d2i_wrapper())));
- __ post_call_nop();
- __ bind(fast);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convFPR2L_reg_reg( eADXRegL dst, regFPR src, eFlagsReg cr ) %{
- predicate(UseSSE==0);
- match(Set dst (ConvF2L src));
- effect( KILL cr );
- format %{ "FLD $src\t# Convert float to long\n\t"
- "FLDCW trunc mode\n\t"
- "SUB ESP,8\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "POP EDX\n\t"
- "CMP EDX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "TEST EAX,EAX\n\t"
- "JNE,s fast\n\t"
- "FLD $src\n\t"
- "CALL d2l_wrapper\n"
- "fast:" %}
- // DPR2L_encoding works for FPR2L
- ins_encode( Push_Reg_FPR(src), DPR2L_encoding(src) );
- ins_pipe( pipe_slow );
-%}
-
-// XMM lacks a float/double->long conversion, so use the old FPU stack.
-instruct convF2L_reg_reg( eADXRegL dst, regF src, eFlagsReg cr ) %{
- predicate (UseSSE>=1);
- match(Set dst (ConvF2L src));
- effect( KILL cr );
- format %{ "SUB ESP,8\t# Convert float to long\n\t"
- "MOVSS [ESP],$src\n\t"
- "FLD_S [ESP]\n\t"
- "FLDCW trunc mode\n\t"
- "FISTp [ESP + #0]\n\t"
- "FLDCW std/24-bit mode\n\t"
- "POP EAX\n\t"
- "POP EDX\n\t"
- "CMP EDX,0x80000000\n\t"
- "JNE,s fast\n\t"
- "TEST EAX,EAX\n\t"
- "JNE,s fast\n\t"
- "SUB ESP,4\t# Convert float to long\n\t"
- "MOVSS [ESP],$src\n\t"
- "FLD_S [ESP]\n\t"
- "ADD ESP,4\n\t"
- "CALL d2l_wrapper\n"
- "fast:" %}
- ins_encode %{
- Label fast;
- __ subptr(rsp, 8);
- __ movflt(Address(rsp, 0), $src$$XMMRegister);
- __ fld_s(Address(rsp, 0));
- __ fldcw(ExternalAddress(StubRoutines::x86::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::x86::addr_fpu_cntrl_wrd_24()));
- } else {
- __ fldcw(ExternalAddress(StubRoutines::x86::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::x86::d2l_wrapper())));
- __ post_call_nop();
- __ bind(fast);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convI2DPR_reg(regDPR dst, stackSlotI src) %{
- predicate( UseSSE<=1 );
- match(Set dst (ConvI2D src));
- format %{ "FILD $src\n\t"
- "FSTP $dst" %}
- opcode(0xDB, 0x0); /* DB /0 */
- ins_encode(Push_Mem_I(src), Pop_Reg_DPR(dst));
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct convI2D_reg(regD dst, rRegI src) %{
- predicate( UseSSE>=2 && !UseXmmI2D );
- match(Set dst (ConvI2D src));
- format %{ "CVTSI2SD $dst,$src" %}
- ins_encode %{
- __ cvtsi2sdl ($dst$$XMMRegister, $src$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convI2D_mem(regD dst, memory mem) %{
- predicate( UseSSE>=2 );
- match(Set dst (ConvI2D (LoadI mem)));
- format %{ "CVTSI2SD $dst,$mem" %}
- ins_encode %{
- __ cvtsi2sdl ($dst$$XMMRegister, $mem$$Address);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct convXI2D_reg(regD dst, rRegI src)
-%{
- predicate( UseSSE>=2 && UseXmmI2D );
- match(Set dst (ConvI2D src));
-
- format %{ "MOVD $dst,$src\n\t"
- "CVTDQ2PD $dst,$dst\t# i2d" %}
- ins_encode %{
- __ movdl($dst$$XMMRegister, $src$$Register);
- __ cvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe(pipe_slow); // XXX
-%}
-
-instruct convI2DPR_mem(regDPR dst, memory mem) %{
- predicate( UseSSE<=1 && !Compile::current()->select_24_bit_instr());
- match(Set dst (ConvI2D (LoadI mem)));
- format %{ "FILD $mem\n\t"
- "FSTP $dst" %}
- opcode(0xDB); /* DB /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem),
- Pop_Reg_DPR(dst), ClearInstMark);
- ins_pipe( fpu_reg_mem );
-%}
-
-// Convert a byte to a float; no rounding step needed.
-instruct conv24I2FPR_reg(regFPR dst, stackSlotI src) %{
- predicate( UseSSE==0 && n->in(1)->Opcode() == Op_AndI && n->in(1)->in(2)->is_Con() && n->in(1)->in(2)->get_int() == 255 );
- match(Set dst (ConvI2F src));
- format %{ "FILD $src\n\t"
- "FSTP $dst" %}
-
- opcode(0xDB, 0x0); /* DB /0 */
- ins_encode(Push_Mem_I(src), Pop_Reg_FPR(dst));
- ins_pipe( fpu_reg_mem );
-%}
-
-// In 24-bit mode, force exponent rounding by storing back out
-instruct convI2FPR_SSF(stackSlotF dst, stackSlotI src) %{
- predicate( UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (ConvI2F src));
- ins_cost(200);
- format %{ "FILD $src\n\t"
- "FSTP_S $dst" %}
- opcode(0xDB, 0x0); /* DB /0 */
- ins_encode( Push_Mem_I(src),
- Pop_Mem_FPR(dst));
- ins_pipe( fpu_mem_mem );
-%}
-
-// In 24-bit mode, force exponent rounding by storing back out
-instruct convI2FPR_SSF_mem(stackSlotF dst, memory mem) %{
- predicate( UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (ConvI2F (LoadI mem)));
- ins_cost(200);
- format %{ "FILD $mem\n\t"
- "FSTP_S $dst" %}
- opcode(0xDB); /* DB /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem),
- Pop_Mem_FPR(dst), ClearInstMark);
- ins_pipe( fpu_mem_mem );
-%}
-
-// This instruction does not round to 24-bits
-instruct convI2FPR_reg(regFPR dst, stackSlotI src) %{
- predicate( UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (ConvI2F src));
- format %{ "FILD $src\n\t"
- "FSTP $dst" %}
- opcode(0xDB, 0x0); /* DB /0 */
- ins_encode( Push_Mem_I(src),
- Pop_Reg_FPR(dst));
- ins_pipe( fpu_reg_mem );
-%}
-
-// This instruction does not round to 24-bits
-instruct convI2FPR_mem(regFPR dst, memory mem) %{
- predicate( UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (ConvI2F (LoadI mem)));
- format %{ "FILD $mem\n\t"
- "FSTP $dst" %}
- opcode(0xDB); /* DB /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,mem),
- Pop_Reg_FPR(dst), ClearInstMark);
- ins_pipe( fpu_reg_mem );
-%}
-
-// Convert an int to a float in xmm; no rounding step needed.
-instruct convI2F_reg(regF dst, rRegI src) %{
- predicate( UseSSE==1 || ( UseSSE>=2 && !UseXmmI2F ));
- match(Set dst (ConvI2F src));
- format %{ "CVTSI2SS $dst, $src" %}
- ins_encode %{
- __ cvtsi2ssl ($dst$$XMMRegister, $src$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
- instruct convXI2F_reg(regF dst, rRegI src)
-%{
- predicate( UseSSE>=2 && UseXmmI2F );
- match(Set dst (ConvI2F src));
-
- format %{ "MOVD $dst,$src\n\t"
- "CVTDQ2PS $dst,$dst\t# i2f" %}
- ins_encode %{
- __ movdl($dst$$XMMRegister, $src$$Register);
- __ cvtdq2ps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe(pipe_slow); // XXX
-%}
-
-instruct convI2L_reg( eRegL dst, rRegI src, eFlagsReg cr) %{
- match(Set dst (ConvI2L src));
- effect(KILL cr);
- ins_cost(375);
- format %{ "MOV $dst.lo,$src\n\t"
- "MOV $dst.hi,$src\n\t"
- "SAR $dst.hi,31" %}
- ins_encode(convert_int_long(dst,src));
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Zero-extend convert int to long
-instruct convI2L_reg_zex(eRegL dst, rRegI src, immL_32bits mask, eFlagsReg flags ) %{
- match(Set dst (AndL (ConvI2L src) mask) );
- effect( KILL flags );
- ins_cost(250);
- format %{ "MOV $dst.lo,$src\n\t"
- "XOR $dst.hi,$dst.hi" %}
- opcode(0x33); // XOR
- ins_encode(enc_Copy(dst,src), OpcP, RegReg_Hi2(dst,dst) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Zero-extend long
-instruct zerox_long(eRegL dst, eRegL src, immL_32bits mask, eFlagsReg flags ) %{
- match(Set dst (AndL src mask) );
- effect( KILL flags );
- ins_cost(250);
- format %{ "MOV $dst.lo,$src.lo\n\t"
- "XOR $dst.hi,$dst.hi\n\t" %}
- opcode(0x33); // XOR
- ins_encode(enc_Copy(dst,src), OpcP, RegReg_Hi2(dst,dst) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-instruct convL2DPR_reg( stackSlotD dst, eRegL src, eFlagsReg cr) %{
- predicate (UseSSE<=1);
- match(Set dst (ConvL2D src));
- effect( KILL cr );
- format %{ "PUSH $src.hi\t# Convert long to double\n\t"
- "PUSH $src.lo\n\t"
- "FILD ST,[ESP + #0]\n\t"
- "ADD ESP,8\n\t"
- "FSTP_D $dst\t# D-round" %}
- opcode(0xDF, 0x5); /* DF /5 */
- ins_encode(convert_long_double(src), Pop_Mem_DPR(dst));
- ins_pipe( pipe_slow );
-%}
-
-instruct convL2D_reg( regD dst, eRegL src, eFlagsReg cr) %{
- predicate (UseSSE>=2);
- match(Set dst (ConvL2D src));
- effect( KILL cr );
- format %{ "PUSH $src.hi\t# Convert long to double\n\t"
- "PUSH $src.lo\n\t"
- "FILD_D [ESP]\n\t"
- "FSTP_D [ESP]\n\t"
- "MOVSD $dst,[ESP]\n\t"
- "ADD ESP,8" %}
- opcode(0xDF, 0x5); /* DF /5 */
- ins_encode(convert_long_double2(src), Push_ResultD(dst));
- ins_pipe( pipe_slow );
-%}
-
-instruct convL2F_reg( regF dst, eRegL src, eFlagsReg cr) %{
- predicate (UseSSE>=1);
- match(Set dst (ConvL2F src));
- effect( KILL cr );
- format %{ "PUSH $src.hi\t# Convert long to single float\n\t"
- "PUSH $src.lo\n\t"
- "FILD_D [ESP]\n\t"
- "FSTP_S [ESP]\n\t"
- "MOVSS $dst,[ESP]\n\t"
- "ADD ESP,8" %}
- opcode(0xDF, 0x5); /* DF /5 */
- ins_encode(convert_long_double2(src), Push_ResultF(dst,0x8));
- ins_pipe( pipe_slow );
-%}
-
-instruct convL2FPR_reg( stackSlotF dst, eRegL src, eFlagsReg cr) %{
- match(Set dst (ConvL2F src));
- effect( KILL cr );
- format %{ "PUSH $src.hi\t# Convert long to single float\n\t"
- "PUSH $src.lo\n\t"
- "FILD ST,[ESP + #0]\n\t"
- "ADD ESP,8\n\t"
- "FSTP_S $dst\t# F-round" %}
- opcode(0xDF, 0x5); /* DF /5 */
- ins_encode(convert_long_double(src), Pop_Mem_FPR(dst));
- ins_pipe( pipe_slow );
-%}
-
-instruct convL2I_reg( rRegI dst, eRegL src ) %{
- match(Set dst (ConvL2I src));
- effect( DEF dst, USE src );
- format %{ "MOV $dst,$src.lo" %}
- ins_encode(enc_CopyL_Lo(dst,src));
- ins_pipe( ialu_reg_reg );
-%}
-
-instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
- match(Set dst (MoveF2I src));
- effect( DEF dst, USE src );
- ins_cost(100);
- format %{ "MOV $dst,$src\t# MoveF2I_stack_reg" %}
- ins_encode %{
- __ movl($dst$$Register, Address(rsp, $src$$disp));
- %}
- ins_pipe( ialu_reg_mem );
-%}
-
-instruct MoveFPR2I_reg_stack(stackSlotI dst, regFPR src) %{
- predicate(UseSSE==0);
- match(Set dst (MoveF2I src));
- effect( DEF dst, USE src );
-
- ins_cost(125);
- format %{ "FST_S $dst,$src\t# MoveF2I_reg_stack" %}
- ins_encode( Pop_Mem_Reg_FPR(dst, src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-instruct MoveF2I_reg_stack_sse(stackSlotI dst, regF src) %{
- predicate(UseSSE>=1);
- match(Set dst (MoveF2I src));
- effect( DEF dst, USE src );
-
- ins_cost(95);
- format %{ "MOVSS $dst,$src\t# MoveF2I_reg_stack_sse" %}
- ins_encode %{
- __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveF2I_reg_reg_sse(rRegI dst, regF src) %{
- predicate(UseSSE>=2);
- match(Set dst (MoveF2I src));
- effect( DEF dst, USE src );
- ins_cost(85);
- format %{ "MOVD $dst,$src\t# MoveF2I_reg_reg_sse" %}
- ins_encode %{
- __ movdl($dst$$Register, $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveI2F_reg_stack(stackSlotF dst, rRegI src) %{
- match(Set dst (MoveI2F src));
- effect( DEF dst, USE src );
-
- ins_cost(100);
- format %{ "MOV $dst,$src\t# MoveI2F_reg_stack" %}
- ins_encode %{
- __ movl(Address(rsp, $dst$$disp), $src$$Register);
- %}
- ins_pipe( ialu_mem_reg );
-%}
-
-
-instruct MoveI2FPR_stack_reg(regFPR dst, stackSlotI src) %{
- predicate(UseSSE==0);
- match(Set dst (MoveI2F src));
- effect(DEF dst, USE src);
-
- ins_cost(125);
- format %{ "FLD_S $src\n\t"
- "FSTP $dst\t# MoveI2F_stack_reg" %}
- opcode(0xD9); /* D9 /0, FLD m32real */
- ins_encode( SetInstMark, OpcP, RMopc_Mem_no_oop(0x00,src),
- Pop_Reg_FPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-instruct MoveI2F_stack_reg_sse(regF dst, stackSlotI src) %{
- predicate(UseSSE>=1);
- match(Set dst (MoveI2F src));
- effect( DEF dst, USE src );
-
- ins_cost(95);
- format %{ "MOVSS $dst,$src\t# MoveI2F_stack_reg_sse" %}
- ins_encode %{
- __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp));
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveI2F_reg_reg_sse(regF dst, rRegI src) %{
- predicate(UseSSE>=2);
- match(Set dst (MoveI2F src));
- effect( DEF dst, USE src );
-
- ins_cost(85);
- format %{ "MOVD $dst,$src\t# MoveI2F_reg_reg_sse" %}
- ins_encode %{
- __ movdl($dst$$XMMRegister, $src$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveD2L_stack_reg(eRegL dst, stackSlotD src) %{
- match(Set dst (MoveD2L src));
- effect(DEF dst, USE src);
-
- ins_cost(250);
- format %{ "MOV $dst.lo,$src\n\t"
- "MOV $dst.hi,$src+4\t# MoveD2L_stack_reg" %}
- opcode(0x8B, 0x8B);
- ins_encode( SetInstMark, OpcP, RegMem(dst,src), OpcS, RegMem_Hi(dst,src), ClearInstMark);
- ins_pipe( ialu_mem_long_reg );
-%}
-
-instruct MoveDPR2L_reg_stack(stackSlotL dst, regDPR src) %{
- predicate(UseSSE<=1);
- match(Set dst (MoveD2L src));
- effect(DEF dst, USE src);
-
- ins_cost(125);
- format %{ "FST_D $dst,$src\t# MoveD2L_reg_stack" %}
- ins_encode( Pop_Mem_Reg_DPR(dst, src) );
- ins_pipe( fpu_mem_reg );
-%}
-
-instruct MoveD2L_reg_stack_sse(stackSlotL dst, regD src) %{
- predicate(UseSSE>=2);
- match(Set dst (MoveD2L src));
- effect(DEF dst, USE src);
- ins_cost(95);
- format %{ "MOVSD $dst,$src\t# MoveD2L_reg_stack_sse" %}
- ins_encode %{
- __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveD2L_reg_reg_sse(eRegL dst, regD src, regD tmp) %{
- predicate(UseSSE>=2);
- match(Set dst (MoveD2L src));
- effect(DEF dst, USE src, TEMP tmp);
- ins_cost(85);
- format %{ "MOVD $dst.lo,$src\n\t"
- "PSHUFLW $tmp,$src,0x4E\n\t"
- "MOVD $dst.hi,$tmp\t# MoveD2L_reg_reg_sse" %}
- 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 );
-%}
-
-instruct MoveL2D_reg_stack(stackSlotD dst, eRegL src) %{
- match(Set dst (MoveL2D src));
- effect(DEF dst, USE src);
-
- ins_cost(200);
- format %{ "MOV $dst,$src.lo\n\t"
- "MOV $dst+4,$src.hi\t# MoveL2D_reg_stack" %}
- opcode(0x89, 0x89);
- ins_encode( SetInstMark, OpcP, RegMem( src, dst ), OpcS, RegMem_Hi( src, dst ), ClearInstMark );
- ins_pipe( ialu_mem_long_reg );
-%}
-
-
-instruct MoveL2DPR_stack_reg(regDPR dst, stackSlotL src) %{
- predicate(UseSSE<=1);
- match(Set dst (MoveL2D src));
- effect(DEF dst, USE src);
- ins_cost(125);
-
- format %{ "FLD_D $src\n\t"
- "FSTP $dst\t# MoveL2D_stack_reg" %}
- opcode(0xDD); /* DD /0, FLD m64real */
- ins_encode( SetInstMark, OpcP, RMopc_Mem_no_oop(0x00,src),
- Pop_Reg_DPR(dst), ClearInstMark );
- ins_pipe( fpu_reg_mem );
-%}
-
-
-instruct MoveL2D_stack_reg_sse(regD dst, stackSlotL src) %{
- predicate(UseSSE>=2 && UseXmmLoadAndClearUpper);
- match(Set dst (MoveL2D src));
- effect(DEF dst, USE src);
-
- ins_cost(95);
- format %{ "MOVSD $dst,$src\t# MoveL2D_stack_reg_sse" %}
- ins_encode %{
- __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveL2D_stack_reg_sse_partial(regD dst, stackSlotL src) %{
- predicate(UseSSE>=2 && !UseXmmLoadAndClearUpper);
- match(Set dst (MoveL2D src));
- effect(DEF dst, USE src);
-
- ins_cost(95);
- format %{ "MOVLPD $dst,$src\t# MoveL2D_stack_reg_sse" %}
- ins_encode %{
- __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct MoveL2D_reg_reg_sse(regD dst, eRegL src, regD tmp) %{
- predicate(UseSSE>=2);
- match(Set dst (MoveL2D src));
- effect(TEMP dst, USE src, TEMP tmp);
- ins_cost(85);
- format %{ "MOVD $dst,$src.lo\n\t"
- "MOVD $tmp,$src.hi\n\t"
- "PUNPCKLDQ $dst,$tmp\t# MoveL2D_reg_reg_sse" %}
- ins_encode %{
- __ movdl($dst$$XMMRegister, $src$$Register);
- __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register));
- __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-//----------------------------- CompressBits/ExpandBits ------------------------
-
-instruct compressBitsL_reg(eADXRegL dst, eBCXRegL src, eBDPRegL mask, eSIRegI rtmp, regF xtmp, eFlagsReg cr) %{
- predicate(n->bottom_type()->isa_long());
- match(Set dst (CompressBits src mask));
- effect(TEMP rtmp, TEMP xtmp, KILL cr);
- format %{ "compress_bits $dst, $src, $mask\t! using $rtmp and $xtmp as TEMP" %}
- ins_encode %{
- Label exit, partail_result;
- // Parallely extract both upper and lower 32 bits of source into destination register pair.
- // Merge the results of upper and lower destination registers such that upper destination
- // results are contiguously laid out after the lower destination result.
- __ pextl($dst$$Register, $src$$Register, $mask$$Register);
- __ pextl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($src$$Register), HIGH_FROM_LOW($mask$$Register));
- __ popcntl($rtmp$$Register, $mask$$Register);
- // Skip merging if bit count of lower mask register is equal to 32 (register size).
- __ cmpl($rtmp$$Register, 32);
- __ jccb(Assembler::equal, exit);
- // Due to constraint on number of GPRs on 32 bit target, using XMM register as potential spill slot.
- __ movdl($xtmp$$XMMRegister, $rtmp$$Register);
- // Shift left the contents of upper destination register by true bit count of lower mask register
- // and merge with lower destination register.
- __ shlxl($rtmp$$Register, HIGH_FROM_LOW($dst$$Register), $rtmp$$Register);
- __ orl($dst$$Register, $rtmp$$Register);
- __ movdl($rtmp$$Register, $xtmp$$XMMRegister);
- // Zero out upper destination register if true bit count of lower 32 bit mask is zero
- // since contents of upper destination have already been copied to lower destination
- // register.
- __ cmpl($rtmp$$Register, 0);
- __ jccb(Assembler::greater, partail_result);
- __ movl(HIGH_FROM_LOW($dst$$Register), 0);
- __ jmp(exit);
- __ bind(partail_result);
- // Perform right shift over upper destination register to move out bits already copied
- // to lower destination register.
- __ subl($rtmp$$Register, 32);
- __ negl($rtmp$$Register);
- __ shrxl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register), $rtmp$$Register);
- __ bind(exit);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct expandBitsL_reg(eADXRegL dst, eBCXRegL src, eBDPRegL mask, eSIRegI rtmp, regF xtmp, eFlagsReg cr) %{
- predicate(n->bottom_type()->isa_long());
- match(Set dst (ExpandBits src mask));
- effect(TEMP rtmp, TEMP xtmp, KILL cr);
- format %{ "expand_bits $dst, $src, $mask\t! using $rtmp and $xtmp as TEMP" %}
- ins_encode %{
- // Extraction operation sequentially reads the bits from source register starting from LSB
- // and lays them out into destination register at bit locations corresponding to true bits
- // in mask register. Thus number of source bits read are equal to combined true bit count
- // of mask register pair.
- Label exit, mask_clipping;
- __ pdepl($dst$$Register, $src$$Register, $mask$$Register);
- __ pdepl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($src$$Register), HIGH_FROM_LOW($mask$$Register));
- __ popcntl($rtmp$$Register, $mask$$Register);
- // If true bit count of lower mask register is 32 then none of bit of lower source register
- // will feed to upper destination register.
- __ cmpl($rtmp$$Register, 32);
- __ jccb(Assembler::equal, exit);
- // Due to constraint on number of GPRs on 32 bit target, using XMM register as potential spill slot.
- __ movdl($xtmp$$XMMRegister, $rtmp$$Register);
- // Shift right the contents of lower source register to remove already consumed bits.
- __ shrxl($rtmp$$Register, $src$$Register, $rtmp$$Register);
- // Extract the bits from lower source register starting from LSB under the influence
- // of upper mask register.
- __ pdepl(HIGH_FROM_LOW($dst$$Register), $rtmp$$Register, HIGH_FROM_LOW($mask$$Register));
- __ movdl($rtmp$$Register, $xtmp$$XMMRegister);
- __ subl($rtmp$$Register, 32);
- __ negl($rtmp$$Register);
- __ movdl($xtmp$$XMMRegister, $mask$$Register);
- __ movl($mask$$Register, HIGH_FROM_LOW($mask$$Register));
- // Clear the set bits in upper mask register which have been used to extract the contents
- // from lower source register.
- __ bind(mask_clipping);
- __ blsrl($mask$$Register, $mask$$Register);
- __ decrementl($rtmp$$Register, 1);
- __ jccb(Assembler::greater, mask_clipping);
- // Starting from LSB extract the bits from upper source register under the influence of
- // remaining set bits in upper mask register.
- __ pdepl($rtmp$$Register, HIGH_FROM_LOW($src$$Register), $mask$$Register);
- // Merge the partial results extracted from lower and upper source register bits.
- __ orl(HIGH_FROM_LOW($dst$$Register), $rtmp$$Register);
- __ movdl($mask$$Register, $xtmp$$XMMRegister);
- __ bind(exit);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// =======================================================================
-// Fast clearing of an array
-// Small non-constant length ClearArray for non-AVX512 targets.
-instruct rep_stos(eCXRegI cnt, eDIRegP base, regD tmp, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate(!((ClearArrayNode*)n)->is_large() && (UseAVX <= 2));
- match(Set dummy (ClearArray cnt base));
- effect(USE_KILL cnt, USE_KILL base, TEMP tmp, KILL zero, KILL cr);
-
- format %{ $$template
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"CMP InitArrayShortSize,rcx\n\t"
- $$emit$$"JG LARGE\n\t"
- $$emit$$"SHL ECX, 1\n\t"
- $$emit$$"DEC ECX\n\t"
- $$emit$$"JS DONE\t# Zero length\n\t"
- $$emit$$"MOV EAX,(EDI,ECX,4)\t# LOOP\n\t"
- $$emit$$"DEC ECX\n\t"
- $$emit$$"JGE LOOP\n\t"
- $$emit$$"JMP DONE\n\t"
- $$emit$$"# LARGE:\n\t"
- if (UseFastStosb) {
- $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
- $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
- } else if (UseXMMForObjInit) {
- $$emit$$"MOV RDI,RAX\n\t"
- $$emit$$"VPXOR YMM0,YMM0,YMM0\n\t"
- $$emit$$"JMPQ L_zero_64_bytes\n\t"
- $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"VMOVDQU YMM0,0x20(RAX)\n\t"
- $$emit$$"ADD 0x40,RAX\n\t"
- $$emit$$"# L_zero_64_bytes:\n\t"
- $$emit$$"SUB 0x8,RCX\n\t"
- $$emit$$"JGE L_loop\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JL L_tail\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"ADD 0x20,RAX\n\t"
- $$emit$$"SUB 0x4,RCX\n\t"
- $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JLE L_end\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
- $$emit$$"VMOVQ XMM0,(RAX)\n\t"
- $$emit$$"ADD 0x8,RAX\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"JGE L_sloop\n\t"
- $$emit$$"# L_end:\n\t"
- } else {
- $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
- $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
- }
- $$emit$$"# DONE"
- %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
- $tmp$$XMMRegister, false, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Small non-constant length ClearArray for AVX512 targets.
-instruct rep_stos_evex(eCXRegI cnt, eDIRegP base, legRegD tmp, kReg ktmp, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate(!((ClearArrayNode*)n)->is_large() && (UseAVX > 2));
- match(Set dummy (ClearArray cnt base));
- ins_cost(125);
- effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, KILL zero, KILL cr);
-
- format %{ $$template
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"CMP InitArrayShortSize,rcx\n\t"
- $$emit$$"JG LARGE\n\t"
- $$emit$$"SHL ECX, 1\n\t"
- $$emit$$"DEC ECX\n\t"
- $$emit$$"JS DONE\t# Zero length\n\t"
- $$emit$$"MOV EAX,(EDI,ECX,4)\t# LOOP\n\t"
- $$emit$$"DEC ECX\n\t"
- $$emit$$"JGE LOOP\n\t"
- $$emit$$"JMP DONE\n\t"
- $$emit$$"# LARGE:\n\t"
- if (UseFastStosb) {
- $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
- $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
- } else if (UseXMMForObjInit) {
- $$emit$$"MOV RDI,RAX\n\t"
- $$emit$$"VPXOR YMM0,YMM0,YMM0\n\t"
- $$emit$$"JMPQ L_zero_64_bytes\n\t"
- $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"VMOVDQU YMM0,0x20(RAX)\n\t"
- $$emit$$"ADD 0x40,RAX\n\t"
- $$emit$$"# L_zero_64_bytes:\n\t"
- $$emit$$"SUB 0x8,RCX\n\t"
- $$emit$$"JGE L_loop\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JL L_tail\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"ADD 0x20,RAX\n\t"
- $$emit$$"SUB 0x4,RCX\n\t"
- $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JLE L_end\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
- $$emit$$"VMOVQ XMM0,(RAX)\n\t"
- $$emit$$"ADD 0x8,RAX\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"JGE L_sloop\n\t"
- $$emit$$"# L_end:\n\t"
- } else {
- $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
- $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
- }
- $$emit$$"# DONE"
- %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
- $tmp$$XMMRegister, false, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Large non-constant length ClearArray for non-AVX512 targets.
-instruct rep_stos_large(eCXRegI cnt, eDIRegP base, regD tmp, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate((UseAVX <= 2) && ((ClearArrayNode*)n)->is_large());
- match(Set dummy (ClearArray cnt base));
- effect(USE_KILL cnt, USE_KILL base, TEMP tmp, KILL zero, KILL cr);
- format %{ $$template
- if (UseFastStosb) {
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
- $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
- } else if (UseXMMForObjInit) {
- $$emit$$"MOV RDI,RAX\t# ClearArray:\n\t"
- $$emit$$"VPXOR YMM0,YMM0,YMM0\n\t"
- $$emit$$"JMPQ L_zero_64_bytes\n\t"
- $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"VMOVDQU YMM0,0x20(RAX)\n\t"
- $$emit$$"ADD 0x40,RAX\n\t"
- $$emit$$"# L_zero_64_bytes:\n\t"
- $$emit$$"SUB 0x8,RCX\n\t"
- $$emit$$"JGE L_loop\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JL L_tail\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"ADD 0x20,RAX\n\t"
- $$emit$$"SUB 0x4,RCX\n\t"
- $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JLE L_end\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
- $$emit$$"VMOVQ XMM0,(RAX)\n\t"
- $$emit$$"ADD 0x8,RAX\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"JGE L_sloop\n\t"
- $$emit$$"# L_end:\n\t"
- } else {
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
- $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
- }
- $$emit$$"# DONE"
- %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
- $tmp$$XMMRegister, true, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Large non-constant length ClearArray for AVX512 targets.
-instruct rep_stos_large_evex(eCXRegI cnt, eDIRegP base, legRegD tmp, kReg ktmp, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate((UseAVX > 2) && ((ClearArrayNode*)n)->is_large());
- match(Set dummy (ClearArray cnt base));
- effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, KILL zero, KILL cr);
- format %{ $$template
- if (UseFastStosb) {
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
- $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
- } else if (UseXMMForObjInit) {
- $$emit$$"MOV RDI,RAX\t# ClearArray:\n\t"
- $$emit$$"VPXOR YMM0,YMM0,YMM0\n\t"
- $$emit$$"JMPQ L_zero_64_bytes\n\t"
- $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"VMOVDQU YMM0,0x20(RAX)\n\t"
- $$emit$$"ADD 0x40,RAX\n\t"
- $$emit$$"# L_zero_64_bytes:\n\t"
- $$emit$$"SUB 0x8,RCX\n\t"
- $$emit$$"JGE L_loop\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JL L_tail\n\t"
- $$emit$$"VMOVDQU YMM0,(RAX)\n\t"
- $$emit$$"ADD 0x20,RAX\n\t"
- $$emit$$"SUB 0x4,RCX\n\t"
- $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
- $$emit$$"ADD 0x4,RCX\n\t"
- $$emit$$"JLE L_end\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
- $$emit$$"VMOVQ XMM0,(RAX)\n\t"
- $$emit$$"ADD 0x8,RAX\n\t"
- $$emit$$"DEC RCX\n\t"
- $$emit$$"JGE L_sloop\n\t"
- $$emit$$"# L_end:\n\t"
- } else {
- $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
- $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
- $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
- }
- $$emit$$"# DONE"
- %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
- $tmp$$XMMRegister, true, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// Small constant length ClearArray for AVX512 targets.
-instruct rep_stos_im(immI cnt, kReg ktmp, eRegP base, regD tmp, rRegI zero, Universe dummy, eFlagsReg cr)
-%{
- predicate(!((ClearArrayNode*)n)->is_large() && (MaxVectorSize >= 32) && VM_Version::supports_avx512vl());
- match(Set dummy (ClearArray cnt base));
- ins_cost(100);
- effect(TEMP tmp, TEMP zero, TEMP ktmp, KILL cr);
- format %{ "clear_mem_imm $base , $cnt \n\t" %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$constant, $zero$$Register, $tmp$$XMMRegister, $ktmp$$KRegister);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct string_compareL(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::LL, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareL_evex(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, kReg ktmp, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::LL, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::UU, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareU_evex(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, kReg ktmp, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::UU, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareLU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::LU, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareLU_evex(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
- eAXRegI result, regD tmp1, kReg ktmp, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::LU, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareUL(eSIRegP str1, eDXRegI cnt1, eDIRegP str2, eCXRegI cnt2,
- eAXRegI result, regD tmp1, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str2$$Register, $str1$$Register,
- $cnt2$$Register, $cnt1$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::UL, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compareUL_evex(eSIRegP str1, eDXRegI cnt1, eDIRegP str2, eCXRegI cnt2,
- eAXRegI result, regD tmp1, kReg ktmp, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
- match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
-
- format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
- ins_encode %{
- __ string_compare($str2$$Register, $str1$$Register,
- $cnt2$$Register, $cnt1$$Register, $result$$Register,
- $tmp1$$XMMRegister, StrIntrinsicNode::UL, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// fast string equals
-instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
- regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw());
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
-
- format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
- ins_encode %{
- __ arrays_equals(false, $str1$$Register, $str2$$Register,
- $cnt$$Register, $result$$Register, $tmp3$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
- %}
-
- ins_pipe( pipe_slow );
-%}
-
-instruct string_equals_evex(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
- regD tmp1, regD tmp2, kReg ktmp, eBXRegI tmp3, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw());
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
-
- format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
- ins_encode %{
- __ arrays_equals(false, $str1$$Register, $str2$$Register,
- $cnt$$Register, $result$$Register, $tmp3$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
- %}
-
- ins_pipe( pipe_slow );
-%}
-
-
-// fast search of substring with known size.
-instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
- eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
- ins_encode %{
- int icnt2 = (int)$int_cnt2$$constant;
- if (icnt2 >= 16) {
- // IndexOf for constant substrings with size >= 16 elements
- // which don't need to be loaded through stack.
- __ string_indexofC8($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
- } else {
- // Small strings are loaded through stack if they cross page boundary.
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
- }
- %}
- ins_pipe( pipe_slow );
-%}
-
-// fast search of substring with known size.
-instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
- eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
- ins_encode %{
- int icnt2 = (int)$int_cnt2$$constant;
- if (icnt2 >= 8) {
- // IndexOf for constant substrings with size >= 8 elements
- // which don't need to be loaded through stack.
- __ string_indexofC8($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
- } else {
- // Small strings are loaded through stack if they cross page boundary.
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
- }
- %}
- ins_pipe( pipe_slow );
-%}
-
-// fast search of substring with known size.
-instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
- eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
- ins_encode %{
- int icnt2 = (int)$int_cnt2$$constant;
- if (icnt2 >= 8) {
- // IndexOf for constant substrings with size >= 8 elements
- // which don't need to be loaded through stack.
- __ string_indexofC8($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
- } else {
- // Small strings are loaded through stack if they cross page boundary.
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- icnt2, $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
- }
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
- eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
- ins_encode %{
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- (-1), $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
- eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
- ins_encode %{
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- (-1), $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
- eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
-
- format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
- ins_encode %{
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- (-1), $result$$Register,
- $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_indexof_char(eDIRegP str1, eDXRegI cnt1, eAXRegI ch,
- eBXRegI result, regD vec1, regD vec2, regD vec3, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U));
- match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
- effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
- format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
- ins_encode %{
- __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
- $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct stringL_indexof_char(eDIRegP str1, eDXRegI cnt1, eAXRegI ch,
- eBXRegI result, regD vec1, regD vec2, regD vec3, eCXRegI tmp, eFlagsReg cr) %{
- predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L));
- match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
- effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
- format %{ "StringLatin1 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
- ins_encode %{
- __ stringL_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
- $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-
-// fast array equals
-instruct array_equalsB(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
- regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
-%{
- predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
- match(Set result (AryEq ary1 ary2));
- effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
- //ins_cost(300);
-
- format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
- ins_encode %{
- __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
- $tmp3$$Register, $result$$Register, $tmp4$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct array_equalsB_evex(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
- regD tmp1, regD tmp2, kReg ktmp, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
-%{
- predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
- match(Set result (AryEq ary1 ary2));
- effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
- //ins_cost(300);
-
- format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
- ins_encode %{
- __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
- $tmp3$$Register, $result$$Register, $tmp4$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct array_equalsC(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
- regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
-%{
- predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (AryEq ary1 ary2));
- effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
- //ins_cost(300);
-
- format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
- ins_encode %{
- __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
- $tmp3$$Register, $result$$Register, $tmp4$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct array_equalsC_evex(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
- regD tmp1, regD tmp2, kReg ktmp, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
-%{
- predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (AryEq ary1 ary2));
- effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
- //ins_cost(300);
-
- format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
- ins_encode %{
- __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
- $tmp3$$Register, $result$$Register, $tmp4$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct count_positives(eSIRegP ary1, eCXRegI len, eAXRegI result,
- regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr)
-%{
- predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
- match(Set result (CountPositives ary1 len));
- effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
-
- format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
- ins_encode %{
- __ count_positives($ary1$$Register, $len$$Register,
- $result$$Register, $tmp3$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct count_positives_evex(eSIRegP ary1, eCXRegI len, eAXRegI result,
- regD tmp1, regD tmp2, kReg ktmp1, kReg ktmp2, eBXRegI tmp3, eFlagsReg cr)
-%{
- predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
- match(Set result (CountPositives ary1 len));
- effect(TEMP tmp1, TEMP tmp2, TEMP ktmp1, TEMP ktmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
-
- format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
- ins_encode %{
- __ count_positives($ary1$$Register, $len$$Register,
- $result$$Register, $tmp3$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-
-// fast char[] to byte[] compression
-instruct string_compress(eSIRegP src, eDIRegP dst, eDXRegI len, regD tmp1, regD tmp2,
- regD tmp3, regD tmp4, eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
- match(Set result (StrCompressedCopy src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
-
- format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
- ins_encode %{
- __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
- $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
- knoreg, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_compress_evex(eSIRegP src, eDIRegP dst, eDXRegI len, regD tmp1, regD tmp2,
- regD tmp3, regD tmp4, kReg ktmp1, kReg ktmp2, eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
- match(Set result (StrCompressedCopy src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ktmp1, TEMP ktmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
-
- format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
- ins_encode %{
- __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
- $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
- $ktmp1$$KRegister, $ktmp2$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// fast byte[] to char[] inflation
-instruct string_inflate(Universe dummy, eSIRegP src, eDIRegP dst, eDXRegI len,
- regD tmp1, eCXRegI tmp2, eFlagsReg cr) %{
- predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
- match(Set dummy (StrInflatedCopy src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
-
- format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
- ins_encode %{
- __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$Register, knoreg);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct string_inflate_evex(Universe dummy, eSIRegP src, eDIRegP dst, eDXRegI len,
- regD tmp1, kReg ktmp, eCXRegI tmp2, eFlagsReg cr) %{
- predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
- match(Set dummy (StrInflatedCopy src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
-
- format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
- ins_encode %{
- __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$Register, $ktmp$$KRegister);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// encode char[] to byte[] in ISO_8859_1
-instruct encode_iso_array(eSIRegP src, eDIRegP dst, eDXRegI len,
- regD tmp1, regD tmp2, regD tmp3, regD tmp4,
- eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
- predicate(!((EncodeISOArrayNode*)n)->is_ascii());
- match(Set result (EncodeISOArray src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
-
- format %{ "Encode iso array $src,$dst,$len -> $result // KILL ECX, EDX, $tmp1, $tmp2, $tmp3, $tmp4, ESI, EDI " %}
- ins_encode %{
- __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
- $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, false);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// encode char[] to byte[] in ASCII
-instruct encode_ascii_array(eSIRegP src, eDIRegP dst, eDXRegI len,
- regD tmp1, regD tmp2, regD tmp3, regD tmp4,
- eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
- predicate(((EncodeISOArrayNode*)n)->is_ascii());
- match(Set result (EncodeISOArray src (Binary dst len)));
- effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
-
- format %{ "Encode ascii array $src,$dst,$len -> $result // KILL ECX, EDX, $tmp1, $tmp2, $tmp3, $tmp4, ESI, EDI " %}
- ins_encode %{
- __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
- $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
- $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, true);
- %}
- ins_pipe( pipe_slow );
-%}
-
-//----------Control Flow Instructions------------------------------------------
-// Signed compare Instructions
-instruct compI_eReg(eFlagsReg cr, rRegI op1, rRegI op2) %{
- match(Set cr (CmpI op1 op2));
- effect( DEF cr, USE op1, USE op2 );
- format %{ "CMP $op1,$op2" %}
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( OpcP, RegReg( op1, op2) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-instruct compI_eReg_imm(eFlagsReg cr, rRegI op1, immI op2) %{
- match(Set cr (CmpI op1 op2));
- effect( DEF cr, USE op1 );
- format %{ "CMP $op1,$op2" %}
- opcode(0x81,0x07); /* Opcode 81 /7 */
- // ins_encode( RegImm( op1, op2) ); /* Was CmpImm */
- ins_encode( OpcSErm( op1, op2 ), Con8or32( op2 ) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// Cisc-spilled version of cmpI_eReg
-instruct compI_eReg_mem(eFlagsReg cr, rRegI op1, memory op2) %{
- match(Set cr (CmpI op1 (LoadI op2)));
-
- format %{ "CMP $op1,$op2" %}
- ins_cost(500);
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( SetInstMark, OpcP, RegMem( op1, op2), ClearInstMark );
- ins_pipe( ialu_cr_reg_mem );
-%}
-
-instruct testI_reg( eFlagsReg cr, rRegI src, immI_0 zero ) %{
- match(Set cr (CmpI src zero));
- effect( DEF cr, USE src );
-
- format %{ "TEST $src,$src" %}
- opcode(0x85);
- ins_encode( OpcP, RegReg( src, src ) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-instruct testI_reg_imm( eFlagsReg cr, rRegI src, immI con, immI_0 zero ) %{
- match(Set cr (CmpI (AndI src con) zero));
-
- format %{ "TEST $src,$con" %}
- opcode(0xF7,0x00);
- ins_encode( OpcP, RegOpc(src), Con32(con) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-instruct testI_reg_mem( eFlagsReg cr, rRegI src, memory mem, immI_0 zero ) %{
- match(Set cr (CmpI (AndI src mem) zero));
-
- format %{ "TEST $src,$mem" %}
- opcode(0x85);
- ins_encode( SetInstMark, OpcP, RegMem( src, mem ), ClearInstMark );
- ins_pipe( ialu_cr_reg_mem );
-%}
-
-// Unsigned compare Instructions; really, same as signed except they
-// produce an eFlagsRegU instead of eFlagsReg.
-instruct compU_eReg(eFlagsRegU cr, rRegI op1, rRegI op2) %{
- match(Set cr (CmpU op1 op2));
-
- format %{ "CMPu $op1,$op2" %}
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( OpcP, RegReg( op1, op2) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-instruct compU_eReg_imm(eFlagsRegU cr, rRegI op1, immI op2) %{
- match(Set cr (CmpU op1 op2));
-
- format %{ "CMPu $op1,$op2" %}
- opcode(0x81,0x07); /* Opcode 81 /7 */
- ins_encode( OpcSErm( op1, op2 ), Con8or32( op2 ) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// // Cisc-spilled version of cmpU_eReg
-instruct compU_eReg_mem(eFlagsRegU cr, rRegI op1, memory op2) %{
- match(Set cr (CmpU op1 (LoadI op2)));
-
- format %{ "CMPu $op1,$op2" %}
- ins_cost(500);
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( SetInstMark, OpcP, RegMem( op1, op2), ClearInstMark );
- ins_pipe( ialu_cr_reg_mem );
-%}
-
-// // Cisc-spilled version of cmpU_eReg
-//instruct compU_mem_eReg(eFlagsRegU cr, memory op1, rRegI op2) %{
-// match(Set cr (CmpU (LoadI op1) op2));
-//
-// format %{ "CMPu $op1,$op2" %}
-// ins_cost(500);
-// opcode(0x39); /* Opcode 39 /r */
-// ins_encode( OpcP, RegMem( op1, op2) );
-//%}
-
-instruct testU_reg( eFlagsRegU cr, rRegI src, immI_0 zero ) %{
- match(Set cr (CmpU src zero));
-
- format %{ "TESTu $src,$src" %}
- opcode(0x85);
- ins_encode( OpcP, RegReg( src, src ) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// Unsigned pointer compare Instructions
-instruct compP_eReg(eFlagsRegU cr, eRegP op1, eRegP op2) %{
- match(Set cr (CmpP op1 op2));
-
- format %{ "CMPu $op1,$op2" %}
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( OpcP, RegReg( op1, op2) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-instruct compP_eReg_imm(eFlagsRegU cr, eRegP op1, immP op2) %{
- match(Set cr (CmpP op1 op2));
-
- format %{ "CMPu $op1,$op2" %}
- opcode(0x81,0x07); /* Opcode 81 /7 */
- ins_encode( SetInstMark, OpcSErm( op1, op2 ), Con8or32( op2 ), ClearInstMark );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// // Cisc-spilled version of cmpP_eReg
-instruct compP_eReg_mem(eFlagsRegU cr, eRegP op1, memory op2) %{
- match(Set cr (CmpP op1 (LoadP op2)));
-
- format %{ "CMPu $op1,$op2" %}
- ins_cost(500);
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( SetInstMark, OpcP, RegMem( op1, op2), ClearInstMark );
- ins_pipe( ialu_cr_reg_mem );
-%}
-
-// // Cisc-spilled version of cmpP_eReg
-//instruct compP_mem_eReg(eFlagsRegU cr, memory op1, eRegP op2) %{
-// match(Set cr (CmpP (LoadP op1) op2));
-//
-// format %{ "CMPu $op1,$op2" %}
-// ins_cost(500);
-// opcode(0x39); /* Opcode 39 /r */
-// ins_encode( OpcP, RegMem( op1, op2) );
-//%}
-
-// Compare raw pointer (used in out-of-heap check).
-// Only works because non-oop pointers must be raw pointers
-// and raw pointers have no anti-dependencies.
-instruct compP_mem_eReg( eFlagsRegU cr, eRegP op1, memory op2 ) %{
- predicate( n->in(2)->in(2)->bottom_type()->reloc() == relocInfo::none );
- match(Set cr (CmpP op1 (LoadP op2)));
-
- format %{ "CMPu $op1,$op2" %}
- opcode(0x3B); /* Opcode 3B /r */
- ins_encode( SetInstMark, OpcP, RegMem( op1, op2), ClearInstMark );
- ins_pipe( ialu_cr_reg_mem );
-%}
-
-//
-// This will generate a signed flags result. This should be ok
-// since any compare to a zero should be eq/neq.
-instruct testP_reg( eFlagsReg cr, eRegP src, immP0 zero ) %{
- match(Set cr (CmpP src zero));
-
- format %{ "TEST $src,$src" %}
- opcode(0x85);
- ins_encode( OpcP, RegReg( src, src ) );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// Cisc-spilled version of testP_reg
-// This will generate a signed flags result. This should be ok
-// since any compare to a zero should be eq/neq.
-instruct testP_Reg_mem( eFlagsReg cr, memory op, immI_0 zero ) %{
- match(Set cr (CmpP (LoadP op) zero));
-
- format %{ "TEST $op,0xFFFFFFFF" %}
- ins_cost(500);
- opcode(0xF7); /* Opcode F7 /0 */
- ins_encode( SetInstMark, OpcP, RMopc_Mem(0x00,op), Con_d32(0xFFFFFFFF), ClearInstMark );
- ins_pipe( ialu_cr_reg_imm );
-%}
-
-// Yanked all unsigned pointer compare operations.
-// Pointer compares are done with CmpP which is already unsigned.
-
-//----------Max and Min--------------------------------------------------------
-// Min Instructions
-////
-// *** Min and Max using the conditional move are slower than the
-// *** branch version on a Pentium III.
-// // Conditional move for min
-//instruct cmovI_reg_lt( rRegI op2, rRegI op1, eFlagsReg cr ) %{
-// effect( USE_DEF op2, USE op1, USE cr );
-// format %{ "CMOVlt $op2,$op1\t! min" %}
-// opcode(0x4C,0x0F);
-// ins_encode( OpcS, OpcP, RegReg( op2, op1 ) );
-// ins_pipe( pipe_cmov_reg );
-//%}
-//
-//// Min Register with Register (P6 version)
-//instruct minI_eReg_p6( rRegI op1, rRegI op2 ) %{
-// predicate(VM_Version::supports_cmov() );
-// match(Set op2 (MinI op1 op2));
-// ins_cost(200);
-// expand %{
-// eFlagsReg cr;
-// compI_eReg(cr,op1,op2);
-// cmovI_reg_lt(op2,op1,cr);
-// %}
-//%}
-
-// Min Register with Register (generic version)
-instruct minI_eReg(rRegI dst, rRegI src, eFlagsReg flags) %{
- match(Set dst (MinI dst src));
- effect(KILL flags);
- ins_cost(300);
-
- format %{ "MIN $dst,$src" %}
- opcode(0xCC);
- ins_encode( min_enc(dst,src) );
- ins_pipe( pipe_slow );
-%}
-
-// Max Register with Register
-// *** Min and Max using the conditional move are slower than the
-// *** branch version on a Pentium III.
-// // Conditional move for max
-//instruct cmovI_reg_gt( rRegI op2, rRegI op1, eFlagsReg cr ) %{
-// effect( USE_DEF op2, USE op1, USE cr );
-// format %{ "CMOVgt $op2,$op1\t! max" %}
-// opcode(0x4F,0x0F);
-// ins_encode( OpcS, OpcP, RegReg( op2, op1 ) );
-// ins_pipe( pipe_cmov_reg );
-//%}
-//
-// // Max Register with Register (P6 version)
-//instruct maxI_eReg_p6( rRegI op1, rRegI op2 ) %{
-// predicate(VM_Version::supports_cmov() );
-// match(Set op2 (MaxI op1 op2));
-// ins_cost(200);
-// expand %{
-// eFlagsReg cr;
-// compI_eReg(cr,op1,op2);
-// cmovI_reg_gt(op2,op1,cr);
-// %}
-//%}
-
-// Max Register with Register (generic version)
-instruct maxI_eReg(rRegI dst, rRegI src, eFlagsReg flags) %{
- match(Set dst (MaxI dst src));
- effect(KILL flags);
- ins_cost(300);
-
- format %{ "MAX $dst,$src" %}
- opcode(0xCC);
- ins_encode( max_enc(dst,src) );
- ins_pipe( pipe_slow );
-%}
-
-// ============================================================================
-// Counted Loop limit node which represents exact final iterator value.
-// Note: the resulting value should fit into integer range since
-// counted loops have limit check on overflow.
-instruct loopLimit_eReg(eAXRegI limit, nadxRegI init, immI stride, eDXRegI limit_hi, nadxRegI tmp, eFlagsReg flags) %{
- match(Set limit (LoopLimit (Binary init limit) stride));
- effect(TEMP limit_hi, TEMP tmp, KILL flags);
- ins_cost(300);
-
- format %{ "loopLimit $init,$limit,$stride # $limit = $init + $stride *( $limit - $init + $stride -1)/ $stride, kills $limit_hi" %}
- ins_encode %{
- int strd = (int)$stride$$constant;
- assert(strd != 1 && strd != -1, "sanity");
- int m1 = (strd > 0) ? 1 : -1;
- // Convert limit to long (EAX:EDX)
- __ cdql();
- // Convert init to long (init:tmp)
- __ movl($tmp$$Register, $init$$Register);
- __ sarl($tmp$$Register, 31);
- // $limit - $init
- __ subl($limit$$Register, $init$$Register);
- __ sbbl($limit_hi$$Register, $tmp$$Register);
- // + ($stride - 1)
- if (strd > 0) {
- __ addl($limit$$Register, (strd - 1));
- __ adcl($limit_hi$$Register, 0);
- __ movl($tmp$$Register, strd);
- } else {
- __ addl($limit$$Register, (strd + 1));
- __ adcl($limit_hi$$Register, -1);
- __ lneg($limit_hi$$Register, $limit$$Register);
- __ movl($tmp$$Register, -strd);
- }
- // signed division: (EAX:EDX) / pos_stride
- __ idivl($tmp$$Register);
- if (strd < 0) {
- // restore sign
- __ negl($tmp$$Register);
- }
- // (EAX) * stride
- __ mull($tmp$$Register);
- // + init (ignore upper bits)
- __ addl($limit$$Register, $init$$Register);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// ============================================================================
-// Branch Instructions
-// Jump Table
-instruct jumpXtnd(rRegI switch_val) %{
- match(Jump switch_val);
- ins_cost(350);
- format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %}
- ins_encode %{
- // Jump to Address(table_base + switch_reg)
- Address index(noreg, $switch_val$$Register, Address::times_1);
- __ jump(ArrayAddress($constantaddress, index), noreg);
- %}
- ins_pipe(pipe_jmp);
-%}
-
-// Jump Direct - Label defines a relative address from JMP+1
-instruct jmpDir(label labl) %{
- match(Goto);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "JMP $labl" %}
- size(5);
- ins_encode %{
- Label* L = $labl$$label;
- __ jmp(*L, false); // Always long jump
- %}
- ins_pipe( pipe_jmp );
-%}
-
-// Jump Direct Conditional - Label defines a relative address from Jcc+1
-instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{
- match(If cop cr);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop $labl" %}
- size(6);
- ins_encode %{
- Label* L = $labl$$label;
- __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
- %}
- ins_pipe( pipe_jcc );
-%}
-
-// Jump Direct Conditional - Label defines a relative address from Jcc+1
-instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{
- match(CountedLoopEnd cop cr);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop $labl\t# Loop end" %}
- size(6);
- ins_encode %{
- Label* L = $labl$$label;
- __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
- %}
- ins_pipe( pipe_jcc );
-%}
-
-// Jump Direct Conditional - using unsigned comparison
-instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop,u $labl" %}
- size(6);
- ins_encode %{
- Label* L = $labl$$label;
- __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
- %}
- ins_pipe(pipe_jcc);
-%}
-
-instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(200);
- format %{ "J$cop,u $labl" %}
- size(6);
- ins_encode %{
- Label* L = $labl$$label;
- __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
- %}
- ins_pipe(pipe_jcc);
-%}
-
-instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(200);
- format %{ $$template
- if ($cop$$cmpcode == Assembler::notEqual) {
- $$emit$$"JP,u $labl\n\t"
- $$emit$$"J$cop,u $labl"
- } else {
- $$emit$$"JP,u done\n\t"
- $$emit$$"J$cop,u $labl\n\t"
- $$emit$$"done:"
- }
- %}
- ins_encode %{
- Label* l = $labl$$label;
- if ($cop$$cmpcode == Assembler::notEqual) {
- __ jcc(Assembler::parity, *l, false);
- __ jcc(Assembler::notEqual, *l, false);
- } else if ($cop$$cmpcode == Assembler::equal) {
- Label done;
- __ jccb(Assembler::parity, done);
- __ jcc(Assembler::equal, *l, false);
- __ bind(done);
- } else {
- ShouldNotReachHere();
- }
- %}
- ins_pipe(pipe_jcc);
-%}
-
-// ============================================================================
-// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass
-// array for an instance of the superklass. Set a hidden internal cache on a
-// hit (cache is checked with exposed code in gen_subtype_check()). Return
-// NZ for a miss or zero for a hit. The encoding ALSO sets flags.
-instruct partialSubtypeCheck( eDIRegP result, eSIRegP sub, eAXRegP super, eCXRegI rcx, eFlagsReg cr ) %{
- match(Set result (PartialSubtypeCheck sub super));
- effect( KILL rcx, KILL cr );
-
- ins_cost(1100); // slightly larger than the next version
- format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t"
- "MOV ECX,[EDI+ArrayKlass::length]\t# length to scan\n\t"
- "ADD EDI,ArrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t"
- "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t"
- "JNE,s miss\t\t# Missed: EDI not-zero\n\t"
- "MOV [$sub+Klass::secondary_super_cache],$super\t# Hit: update cache\n\t"
- "XOR $result,$result\t\t Hit: EDI zero\n\t"
- "miss:\t" %}
-
- opcode(0x1); // Force a XOR of EDI
- ins_encode( enc_PartialSubtypeCheck() );
- ins_pipe( pipe_slow );
-%}
-
-instruct partialSubtypeCheck_vs_Zero( eFlagsReg cr, eSIRegP sub, eAXRegP super, eCXRegI rcx, eDIRegP result, immP0 zero ) %{
- match(Set cr (CmpP (PartialSubtypeCheck sub super) zero));
- effect( KILL rcx, KILL result );
-
- ins_cost(1000);
- format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t"
- "MOV ECX,[EDI+ArrayKlass::length]\t# length to scan\n\t"
- "ADD EDI,ArrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t"
- "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t"
- "JNE,s miss\t\t# Missed: flags NZ\n\t"
- "MOV [$sub+Klass::secondary_super_cache],$super\t# Hit: update cache, flags Z\n\t"
- "miss:\t" %}
-
- opcode(0x0); // No need to XOR EDI
- ins_encode( enc_PartialSubtypeCheck() );
- ins_pipe( pipe_slow );
-%}
-
-// ============================================================================
-// Branch Instructions -- short offset versions
-//
-// These instructions are used to replace jumps of a long offset (the default
-// match) with jumps of a shorter offset. These instructions are all tagged
-// with the ins_short_branch attribute, which causes the ADLC to suppress the
-// match rules in general matching. Instead, the ADLC generates a conversion
-// method in the MachNode which can be used to do in-place replacement of the
-// long variant with the shorter variant. The compiler will determine if a
-// branch can be taken by the is_short_branch_offset() predicate in the machine
-// specific code section of the file.
-
-// Jump Direct - Label defines a relative address from JMP+1
-instruct jmpDir_short(label labl) %{
- match(Goto);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "JMP,s $labl" %}
- size(2);
- ins_encode %{
- Label* L = $labl$$label;
- __ jmpb(*L);
- %}
- ins_pipe( pipe_jmp );
- ins_short_branch(1);
-%}
-
-// Jump Direct Conditional - Label defines a relative address from Jcc+1
-instruct jmpCon_short(cmpOp cop, eFlagsReg cr, label labl) %{
- match(If cop cr);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop,s $labl" %}
- size(2);
- ins_encode %{
- Label* L = $labl$$label;
- __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
- %}
- ins_pipe( pipe_jcc );
- ins_short_branch(1);
-%}
-
-// Jump Direct Conditional - Label defines a relative address from Jcc+1
-instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{
- match(CountedLoopEnd cop cr);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop,s $labl\t# Loop end" %}
- size(2);
- ins_encode %{
- Label* L = $labl$$label;
- __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
- %}
- ins_pipe( pipe_jcc );
- ins_short_branch(1);
-%}
-
-// Jump Direct Conditional - using unsigned comparison
-instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop,us $labl" %}
- size(2);
- ins_encode %{
- Label* L = $labl$$label;
- __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
- %}
- ins_pipe( pipe_jcc );
- ins_short_branch(1);
-%}
-
-instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(300);
- format %{ "J$cop,us $labl" %}
- size(2);
- ins_encode %{
- Label* L = $labl$$label;
- __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
- %}
- ins_pipe( pipe_jcc );
- ins_short_branch(1);
-%}
-
-instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
- match(If cop cmp);
- effect(USE labl);
-
- ins_cost(300);
- format %{ $$template
- if ($cop$$cmpcode == Assembler::notEqual) {
- $$emit$$"JP,u,s $labl\n\t"
- $$emit$$"J$cop,u,s $labl"
- } else {
- $$emit$$"JP,u,s done\n\t"
- $$emit$$"J$cop,u,s $labl\n\t"
- $$emit$$"done:"
- }
- %}
- size(4);
- ins_encode %{
- Label* l = $labl$$label;
- if ($cop$$cmpcode == Assembler::notEqual) {
- __ jccb(Assembler::parity, *l);
- __ jccb(Assembler::notEqual, *l);
- } else if ($cop$$cmpcode == Assembler::equal) {
- Label done;
- __ jccb(Assembler::parity, done);
- __ jccb(Assembler::equal, *l);
- __ bind(done);
- } else {
- ShouldNotReachHere();
- }
- %}
- ins_pipe(pipe_jcc);
- ins_short_branch(1);
-%}
-
-// ============================================================================
-// Long Compare
-//
-// Currently we hold longs in 2 registers. Comparing such values efficiently
-// is tricky. The flavor of compare used depends on whether we are testing
-// for LT, LE, or EQ. For a simple LT test we can check just the sign bit.
-// The GE test is the negated LT test. The LE test can be had by commuting
-// the operands (yielding a GE test) and then negating; negate again for the
-// GT test. The EQ test is done by ORcc'ing the high and low halves, and the
-// NE test is negated from that.
-
-// Due to a shortcoming in the ADLC, it mixes up expressions like:
-// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the
-// difference between 'Y' and '0L'. The tree-matches for the CmpI sections
-// are collapsed internally in the ADLC's dfa-gen code. The match for
-// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
-// foo match ends up with the wrong leaf. One fix is to not match both
-// reg-reg and reg-zero forms of long-compare. This is unfortunate because
-// both forms beat the trinary form of long-compare and both are very useful
-// on Intel which has so few registers.
-
-// Manifest a CmpL result in an integer register. Very painful.
-// This is the test to avoid.
-instruct cmpL3_reg_reg(eSIRegI dst, eRegL src1, eRegL src2, eFlagsReg flags ) %{
- match(Set dst (CmpL3 src1 src2));
- effect( KILL flags );
- ins_cost(1000);
- format %{ "XOR $dst,$dst\n\t"
- "CMP $src1.hi,$src2.hi\n\t"
- "JLT,s m_one\n\t"
- "JGT,s p_one\n\t"
- "CMP $src1.lo,$src2.lo\n\t"
- "JB,s m_one\n\t"
- "JEQ,s done\n"
- "p_one:\tINC $dst\n\t"
- "JMP,s done\n"
- "m_one:\tDEC $dst\n"
- "done:" %}
- ins_encode %{
- Label p_one, m_one, done;
- __ xorptr($dst$$Register, $dst$$Register);
- __ cmpl(HIGH_FROM_LOW($src1$$Register), HIGH_FROM_LOW($src2$$Register));
- __ jccb(Assembler::less, m_one);
- __ jccb(Assembler::greater, p_one);
- __ cmpl($src1$$Register, $src2$$Register);
- __ jccb(Assembler::below, m_one);
- __ jccb(Assembler::equal, done);
- __ bind(p_one);
- __ incrementl($dst$$Register);
- __ jmpb(done);
- __ bind(m_one);
- __ decrementl($dst$$Register);
- __ bind(done);
- %}
- ins_pipe( pipe_slow );
-%}
-
-//======
-// Manifest a CmpL result in the normal flags. Only good for LT or GE
-// compares. Can be used for LE or GT compares by reversing arguments.
-// NOT GOOD FOR EQ/NE tests.
-instruct cmpL_zero_flags_LTGE( flagsReg_long_LTGE flags, eRegL src, immL0 zero ) %{
- match( Set flags (CmpL src zero ));
- ins_cost(100);
- format %{ "TEST $src.hi,$src.hi" %}
- opcode(0x85);
- ins_encode( OpcP, RegReg_Hi2( src, src ) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-// Manifest a CmpL result in the normal flags. Only good for LT or GE
-// compares. Can be used for LE or GT compares by reversing arguments.
-// NOT GOOD FOR EQ/NE tests.
-instruct cmpL_reg_flags_LTGE( flagsReg_long_LTGE flags, eRegL src1, eRegL src2, rRegI tmp ) %{
- match( Set flags (CmpL src1 src2 ));
- effect( TEMP tmp );
- ins_cost(300);
- format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
- "MOV $tmp,$src1.hi\n\t"
- "SBB $tmp,$src2.hi\t! Compute flags for long compare" %}
- ins_encode( long_cmp_flags2( src1, src2, tmp ) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-// Long compares reg < zero/req OR reg >= zero/req.
-// Just a wrapper for a normal branch, plus the predicate test.
-instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
- expand %{
- jmpCon(cmp,flags,labl); // JLT or JGE...
- %}
-%}
-
-//======
-// Manifest a CmpUL result in the normal flags. Only good for LT or GE
-// compares. Can be used for LE or GT compares by reversing arguments.
-// NOT GOOD FOR EQ/NE tests.
-instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
- match(Set flags (CmpUL src zero));
- ins_cost(100);
- format %{ "TEST $src.hi,$src.hi" %}
- opcode(0x85);
- ins_encode(OpcP, RegReg_Hi2(src, src));
- ins_pipe(ialu_cr_reg_reg);
-%}
-
-// Manifest a CmpUL result in the normal flags. Only good for LT or GE
-// compares. Can be used for LE or GT compares by reversing arguments.
-// NOT GOOD FOR EQ/NE tests.
-instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
- match(Set flags (CmpUL src1 src2));
- effect(TEMP tmp);
- ins_cost(300);
- format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
- "MOV $tmp,$src1.hi\n\t"
- "SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
- ins_encode(long_cmp_flags2(src1, src2, tmp));
- ins_pipe(ialu_cr_reg_reg);
-%}
-
-// Unsigned long compares reg < zero/req OR reg >= zero/req.
-// Just a wrapper for a normal branch, plus the predicate test.
-instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
- expand %{
- jmpCon(cmp, flags, labl); // JLT or JGE...
- %}
-%}
-
-// Compare 2 longs and CMOVE longs.
-instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- ins_cost(400);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovLL_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, load_long_memory src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- ins_cost(500);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src), ClearInstMark );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovLL_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, eRegL src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- ins_cost(400);
- expand %{
- cmovLL_reg_LTGE(cmp, flags, dst, src);
- %}
-%}
-
-instruct cmovLL_mem_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, load_long_memory src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- ins_cost(500);
- expand %{
- cmovLL_mem_LTGE(cmp, flags, dst, src);
- %}
-%}
-
-// Compare 2 longs and CMOVE ints.
-instruct cmovII_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovII_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem( dst, src ), ClearInstMark );
- ins_pipe( pipe_cmov_mem );
-%}
-
-instruct cmovII_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovII_reg_LTGE(cmp, flags, dst, src);
- %}
-%}
-
-instruct cmovII_mem_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- expand %{
- cmovII_mem_LTGE(cmp, flags, dst, src);
- %}
-%}
-
-// Compare 2 longs and CMOVE ptrs.
-instruct cmovPP_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-// Compare 2 unsigned longs and CMOVE ptrs.
-instruct cmovPP_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovPP_reg_LTGE(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDDPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regDPR dst, regDPR src) %{
- predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovDPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDD_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regD dst, regD src) %{
- predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovD_regS(cmp,flags,dst,src);
- %}
-%}
-
-instruct cmovFFPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regFPR dst, regFPR src) %{
- predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovFPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-instruct cmovFF_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regF dst, regF src) %{
- predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovF_regS(cmp,flags,dst,src);
- %}
-%}
-
-//======
-// Manifest a CmpL result in the normal flags. Only good for EQ/NE compares.
-instruct cmpL_zero_flags_EQNE( flagsReg_long_EQNE flags, eRegL src, immL0 zero, rRegI tmp ) %{
- match( Set flags (CmpL src zero ));
- effect(TEMP tmp);
- ins_cost(200);
- format %{ "MOV $tmp,$src.lo\n\t"
- "OR $tmp,$src.hi\t! Long is EQ/NE 0?" %}
- ins_encode( long_cmp_flags0( src, tmp ) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Manifest a CmpL result in the normal flags. Only good for EQ/NE compares.
-instruct cmpL_reg_flags_EQNE( flagsReg_long_EQNE flags, eRegL src1, eRegL src2 ) %{
- match( Set flags (CmpL src1 src2 ));
- ins_cost(200+300);
- format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
- "JNE,s skip\n\t"
- "CMP $src1.hi,$src2.hi\n\t"
- "skip:\t" %}
- ins_encode( long_cmp_flags1( src1, src2 ) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-// Long compare reg == zero/reg OR reg != zero/reg
-// Just a wrapper for a normal branch, plus the predicate test.
-instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
- expand %{
- jmpCon(cmp,flags,labl); // JEQ or JNE...
- %}
-%}
-
-//======
-// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
-instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
- match(Set flags (CmpUL src zero));
- effect(TEMP tmp);
- ins_cost(200);
- format %{ "MOV $tmp,$src.lo\n\t"
- "OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
- ins_encode(long_cmp_flags0(src, tmp));
- ins_pipe(ialu_reg_reg_long);
-%}
-
-// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
-instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
- match(Set flags (CmpUL src1 src2));
- ins_cost(200+300);
- format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
- "JNE,s skip\n\t"
- "CMP $src1.hi,$src2.hi\n\t"
- "skip:\t" %}
- ins_encode(long_cmp_flags1(src1, src2));
- ins_pipe(ialu_cr_reg_reg);
-%}
-
-// Unsigned long compare reg == zero/reg OR reg != zero/reg
-// Just a wrapper for a normal branch, plus the predicate test.
-instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
- expand %{
- jmpCon(cmp, flags, labl); // JEQ or JNE...
- %}
-%}
-
-// Compare 2 longs and CMOVE longs.
-instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- ins_cost(400);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovLL_mem_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, load_long_memory src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- ins_cost(500);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src), ClearInstMark );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-// Compare 2 longs and CMOVE ints.
-instruct cmovII_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovII_mem_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem( dst, src ), ClearInstMark );
- ins_pipe( pipe_cmov_mem );
-%}
-
-instruct cmovII_reg_EQNE_U(cmpOpU cmp, flagsReg_ulong_EQNE flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovII_reg_EQNE(cmp, flags, dst, src);
- %}
-%}
-
-instruct cmovII_mem_EQNE_U(cmpOpU cmp, flagsReg_ulong_EQNE flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- expand %{
- cmovII_mem_EQNE(cmp, flags, dst, src);
- %}
-%}
-
-// Compare 2 longs and CMOVE ptrs.
-instruct cmovPP_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-// Compare 2 unsigned longs and CMOVE ptrs.
-instruct cmovPP_reg_EQNE_U(cmpOpU cmp, flagsReg_ulong_EQNE flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovPP_reg_EQNE(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDDPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regDPR dst, regDPR src) %{
- predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovDPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDD_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regD dst, regD src) %{
- predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovD_regS(cmp,flags,dst,src);
- %}
-%}
-
-instruct cmovFFPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regFPR dst, regFPR src) %{
- predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovFPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-instruct cmovFF_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regF dst, regF src) %{
- predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovF_regS(cmp,flags,dst,src);
- %}
-%}
-
-//======
-// Manifest a CmpL result in the normal flags. Only good for LE or GT compares.
-// Same as cmpL_reg_flags_LEGT except must negate src
-instruct cmpL_zero_flags_LEGT( flagsReg_long_LEGT flags, eRegL src, immL0 zero, rRegI tmp ) %{
- match( Set flags (CmpL src zero ));
- effect( TEMP tmp );
- ins_cost(300);
- format %{ "XOR $tmp,$tmp\t# Long compare for -$src < 0, use commuted test\n\t"
- "CMP $tmp,$src.lo\n\t"
- "SBB $tmp,$src.hi\n\t" %}
- ins_encode( long_cmp_flags3(src, tmp) );
- ins_pipe( ialu_reg_reg_long );
-%}
-
-// Manifest a CmpL result in the normal flags. Only good for LE or GT compares.
-// Same as cmpL_reg_flags_LTGE except operands swapped. Swapping operands
-// requires a commuted test to get the same result.
-instruct cmpL_reg_flags_LEGT( flagsReg_long_LEGT flags, eRegL src1, eRegL src2, rRegI tmp ) %{
- match( Set flags (CmpL src1 src2 ));
- effect( TEMP tmp );
- ins_cost(300);
- format %{ "CMP $src2.lo,$src1.lo\t! Long compare, swapped operands, use with commuted test\n\t"
- "MOV $tmp,$src2.hi\n\t"
- "SBB $tmp,$src1.hi\t! Compute flags for long compare" %}
- ins_encode( long_cmp_flags2( src2, src1, tmp ) );
- ins_pipe( ialu_cr_reg_reg );
-%}
-
-// Long compares reg < zero/req OR reg >= zero/req.
-// Just a wrapper for a normal branch, plus the predicate test
-instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
- ins_cost(300);
- expand %{
- jmpCon(cmp,flags,labl); // JGT or JLE...
- %}
-%}
-
-//======
-// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
-// Same as cmpUL_reg_flags_LEGT except must negate src
-instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
- match(Set flags (CmpUL src zero));
- effect(TEMP tmp);
- ins_cost(300);
- format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
- "CMP $tmp,$src.lo\n\t"
- "SBB $tmp,$src.hi\n\t" %}
- ins_encode(long_cmp_flags3(src, tmp));
- ins_pipe(ialu_reg_reg_long);
-%}
-
-// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
-// Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands
-// requires a commuted test to get the same result.
-instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
- match(Set flags (CmpUL src1 src2));
- effect(TEMP tmp);
- ins_cost(300);
- format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
- "MOV $tmp,$src2.hi\n\t"
- "SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
- ins_encode(long_cmp_flags2( src2, src1, tmp));
- ins_pipe(ialu_cr_reg_reg);
-%}
-
-// Unsigned long compares reg < zero/req OR reg >= zero/req.
-// Just a wrapper for a normal branch, plus the predicate test
-instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
- match(If cmp flags);
- effect(USE labl);
- predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
- ins_cost(300);
- expand %{
- jmpCon(cmp, flags, labl); // JGT or JLE...
- %}
-%}
-
-// Compare 2 longs and CMOVE longs.
-instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- ins_cost(400);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovLL_mem_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, load_long_memory src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- ins_cost(500);
- format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
- "CMOV$cmp $dst.hi,$src.hi+4" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src), ClearInstMark );
- ins_pipe( pipe_cmov_reg_long );
-%}
-
-instruct cmovLL_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegL dst, eRegL src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- ins_cost(400);
- expand %{
- cmovLL_reg_LEGT(cmp, flags, dst, src);
- %}
-%}
-
-instruct cmovLL_mem_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegL dst, load_long_memory src) %{
- match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- ins_cost(500);
- expand %{
- cmovLL_mem_LEGT(cmp, flags, dst, src);
- %}
-%}
-
-// Compare 2 longs and CMOVE ints.
-instruct cmovII_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-instruct cmovII_mem_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( SetInstMark, enc_cmov(cmp), RegMem( dst, src ), ClearInstMark );
- ins_pipe( pipe_cmov_mem );
-%}
-
-instruct cmovII_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, rRegI dst, rRegI src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovII_reg_LEGT(cmp, flags, dst, src);
- %}
-%}
-
-instruct cmovII_mem_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, rRegI dst, memory src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveI (Binary cmp flags) (Binary dst (LoadI src))));
- ins_cost(250);
- expand %{
- cmovII_mem_LEGT(cmp, flags, dst, src);
- %}
-%}
-
-// Compare 2 longs and CMOVE ptrs.
-instruct cmovPP_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- format %{ "CMOV$cmp $dst,$src" %}
- opcode(0x0F,0x40);
- ins_encode( enc_cmov(cmp), RegReg( dst, src ) );
- ins_pipe( pipe_cmov_reg );
-%}
-
-// Compare 2 unsigned longs and CMOVE ptrs.
-instruct cmovPP_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegP dst, eRegP src) %{
- predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveP (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- cmovPP_reg_LEGT(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDDPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regDPR dst, regDPR src) %{
- predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovDPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-// Compare 2 longs and CMOVE doubles
-instruct cmovDD_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regD dst, regD src) %{
- predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveD (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovD_regS(cmp,flags,dst,src);
- %}
-%}
-
-instruct cmovFFPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regFPR dst, regFPR src) %{
- predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovFPR_regS(cmp,flags,dst,src);
- %}
-%}
-
-
-instruct cmovFF_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regF dst, regF src) %{
- predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
- match(Set dst (CMoveF (Binary cmp flags) (Binary dst src)));
- ins_cost(200);
- expand %{
- fcmovF_regS(cmp,flags,dst,src);
- %}
-%}
-
-
-// ============================================================================
-// Procedure Call/Return Instructions
-// Call Java Static Instruction
-// Note: If this code changes, the corresponding ret_addr_offset() and
-// compute_padding() functions will have to be adjusted.
-instruct CallStaticJavaDirect(method meth) %{
- match(CallStaticJava);
- effect(USE meth);
-
- ins_cost(300);
- format %{ "CALL,static " %}
- opcode(0xE8); /* E8 cd */
- ins_encode( pre_call_resets,
- Java_Static_Call( meth ),
- call_epilog,
- post_call_FPU );
- ins_pipe( pipe_slow );
- ins_alignment(4);
-%}
-
-// Call Java Dynamic Instruction
-// Note: If this code changes, the corresponding ret_addr_offset() and
-// compute_padding() functions will have to be adjusted.
-instruct CallDynamicJavaDirect(method meth) %{
- match(CallDynamicJava);
- effect(USE meth);
-
- ins_cost(300);
- format %{ "MOV EAX,(oop)-1\n\t"
- "CALL,dynamic" %}
- opcode(0xE8); /* E8 cd */
- ins_encode( pre_call_resets,
- Java_Dynamic_Call( meth ),
- call_epilog,
- post_call_FPU );
- ins_pipe( pipe_slow );
- ins_alignment(4);
-%}
-
-// Call Runtime Instruction
-instruct CallRuntimeDirect(method meth) %{
- match(CallRuntime );
- effect(USE meth);
-
- ins_cost(300);
- format %{ "CALL,runtime " %}
- opcode(0xE8); /* E8 cd */
- // Use FFREEs to clear entries in float stack
- ins_encode( pre_call_resets,
- FFree_Float_Stack_All,
- Java_To_Runtime( meth ),
- post_call_FPU );
- ins_pipe( pipe_slow );
-%}
-
-// Call runtime without safepoint
-instruct CallLeafDirect(method meth) %{
- match(CallLeaf);
- effect(USE meth);
-
- ins_cost(300);
- format %{ "CALL_LEAF,runtime " %}
- opcode(0xE8); /* E8 cd */
- ins_encode( pre_call_resets,
- FFree_Float_Stack_All,
- Java_To_Runtime( meth ),
- Verify_FPU_For_Leaf, post_call_FPU );
- ins_pipe( pipe_slow );
-%}
-
-instruct CallLeafNoFPDirect(method meth) %{
- match(CallLeafNoFP);
- effect(USE meth);
-
- ins_cost(300);
- format %{ "CALL_LEAF_NOFP,runtime " %}
- opcode(0xE8); /* E8 cd */
- ins_encode(pre_call_resets, Java_To_Runtime(meth));
- ins_pipe( pipe_slow );
-%}
-
-
-// Return Instruction
-// Remove the return address & jump to it.
-instruct Ret() %{
- match(Return);
- format %{ "RET" %}
- opcode(0xC3);
- ins_encode(OpcP);
- ins_pipe( pipe_jmp );
-%}
-
-// Tail Call; Jump from runtime stub to Java code.
-// Also known as an 'interprocedural jump'.
-// Target of jump will eventually return to caller.
-// TailJump below removes the return address.
-// Don't use ebp for 'jump_target' because a MachEpilogNode has already been
-// emitted just above the TailCall which has reset ebp to the caller state.
-instruct TailCalljmpInd(eRegP_no_EBP jump_target, eBXRegP method_ptr) %{
- match(TailCall jump_target method_ptr);
- ins_cost(300);
- format %{ "JMP $jump_target \t# EBX holds method" %}
- opcode(0xFF, 0x4); /* Opcode FF /4 */
- ins_encode( OpcP, RegOpc(jump_target) );
- ins_pipe( pipe_jmp );
-%}
-
-
-// Tail Jump; remove the return address; jump to target.
-// TailCall above leaves the return address around.
-instruct tailjmpInd(eRegP_no_EBP jump_target, eAXRegP ex_oop) %{
- match( TailJump jump_target ex_oop );
- ins_cost(300);
- format %{ "POP EDX\t# pop return address into dummy\n\t"
- "JMP $jump_target " %}
- opcode(0xFF, 0x4); /* Opcode FF /4 */
- ins_encode( enc_pop_rdx,
- OpcP, RegOpc(jump_target) );
- ins_pipe( pipe_jmp );
-%}
-
-// Forward exception.
-instruct ForwardExceptionjmp()
-%{
- match(ForwardException);
-
- format %{ "JMP forward_exception_stub" %}
- ins_encode %{
- __ jump(RuntimeAddress(StubRoutines::forward_exception_entry()), noreg);
- %}
- ins_pipe(pipe_jmp);
-%}
-
-// Create exception oop: created by stack-crawling runtime code.
-// Created exception is now available to this handler, and is setup
-// just prior to jumping to this handler. No code emitted.
-instruct CreateException( eAXRegP ex_oop )
-%{
- match(Set ex_oop (CreateEx));
-
- size(0);
- // use the following format syntax
- format %{ "# exception oop is in EAX; no code emitted" %}
- ins_encode();
- ins_pipe( empty );
-%}
-
-
-// Rethrow exception:
-// The exception oop will come in the first argument position.
-// Then JUMP (not call) to the rethrow stub code.
-instruct RethrowException()
-%{
- match(Rethrow);
-
- // use the following format syntax
- format %{ "JMP rethrow_stub" %}
- ins_encode(enc_rethrow);
- ins_pipe( pipe_jmp );
-%}
-
-// inlined locking and unlocking
-
-instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr, eRegP thread) %{
- predicate(LockingMode != LM_LIGHTWEIGHT);
- match(Set cr (FastLock object box));
- effect(TEMP tmp, TEMP scr, USE_KILL box, TEMP thread);
- ins_cost(300);
- format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr" %}
- ins_encode %{
- __ get_thread($thread$$Register);
- __ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
- $scr$$Register, noreg, noreg, $thread$$Register, nullptr);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
- predicate(LockingMode != LM_LIGHTWEIGHT);
- match(Set cr (FastUnlock object box));
- effect(TEMP tmp, USE_KILL box);
- ins_cost(300);
- format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %}
- ins_encode %{
- __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpFastLockLightweight(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI eax_reg, eRegP tmp, eRegP thread) %{
- predicate(LockingMode == LM_LIGHTWEIGHT);
- match(Set cr (FastLock object box));
- effect(TEMP eax_reg, TEMP tmp, USE_KILL box, TEMP thread);
- ins_cost(300);
- format %{ "FASTLOCK $object,$box\t! kills $box,$eax_reg,$tmp" %}
- ins_encode %{
- __ get_thread($thread$$Register);
- __ fast_lock_lightweight($object$$Register, $box$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpFastUnlockLightweight(eFlagsReg cr, eRegP object, eAXRegP eax_reg, eRegP tmp, eRegP thread) %{
- predicate(LockingMode == LM_LIGHTWEIGHT);
- match(Set cr (FastUnlock object eax_reg));
- effect(TEMP tmp, USE_KILL eax_reg, TEMP thread);
- ins_cost(300);
- format %{ "FASTUNLOCK $object,$eax_reg\t! kills $eax_reg,$tmp" %}
- ins_encode %{
- __ get_thread($thread$$Register);
- __ fast_unlock_lightweight($object$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
- %}
- ins_pipe(pipe_slow);
-%}
-
-instruct mask_all_evexL_LT32(kReg dst, eRegL src) %{
- predicate(Matcher::vector_length(n) <= 32);
- match(Set dst (MaskAll src));
- format %{ "mask_all_evexL_LE32 $dst, $src \t" %}
- ins_encode %{
- int mask_len = Matcher::vector_length(this);
- __ vector_maskall_operation($dst$$KRegister, $src$$Register, mask_len);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct mask_all_evexL_GT32(kReg dst, eRegL src, kReg ktmp) %{
- predicate(Matcher::vector_length(n) > 32);
- match(Set dst (MaskAll src));
- effect(TEMP ktmp);
- format %{ "mask_all_evexL_GT32 $dst, $src \t! using $ktmp as TEMP " %}
- ins_encode %{
- int mask_len = Matcher::vector_length(this);
- __ vector_maskall_operation32($dst$$KRegister, $src$$Register, $ktmp$$KRegister, mask_len);
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct mask_all_evexI_GT32(kReg dst, rRegI src, kReg ktmp) %{
- predicate(Matcher::vector_length(n) > 32);
- match(Set dst (MaskAll src));
- effect(TEMP ktmp);
- format %{ "mask_all_evexI_GT32 $dst, $src \t! using $ktmp as TEMP" %}
- ins_encode %{
- int mask_len = Matcher::vector_length(this);
- __ vector_maskall_operation32($dst$$KRegister, $src$$Register, $ktmp$$KRegister, mask_len);
- %}
- ins_pipe( pipe_slow );
-%}
-
-// ============================================================================
-// Safepoint Instruction
-instruct safePoint_poll_tls(eFlagsReg cr, eRegP_no_EBP poll) %{
- match(SafePoint poll);
- effect(KILL cr, USE poll);
-
- format %{ "TSTL #EAX,[$poll]\t! Safepoint: poll for GC" %}
- ins_cost(125);
- // EBP would need size(3)
- size(2); /* setting an explicit size will cause debug builds to assert if size is incorrect */
- ins_encode %{
- __ set_inst_mark();
- __ relocate(relocInfo::poll_type);
- __ clear_inst_mark();
- address pre_pc = __ pc();
- __ testl(rax, Address($poll$$Register, 0));
- address post_pc = __ pc();
- guarantee(pre_pc[0] == 0x85, "must emit test-ax [reg]");
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-
-// ============================================================================
-// This name is KNOWN by the ADLC and cannot be changed.
-// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
-// for this guy.
-instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
- match(Set dst (ThreadLocal));
- effect(DEF dst, KILL cr);
-
- format %{ "MOV $dst, Thread::current()" %}
- ins_encode %{
- Register dstReg = as_Register($dst$$reg);
- __ get_thread(dstReg);
- %}
- ins_pipe( ialu_reg_fat );
-%}
-
-
-
-//----------PEEPHOLE RULES-----------------------------------------------------
-// These must follow all instruction definitions as they use the names
-// defined in the instructions definitions.
-//
-// peepmatch ( root_instr_name [preceding_instruction]* );
-//
-// peepconstraint %{
-// (instruction_number.operand_name relational_op instruction_number.operand_name
-// [, ...] );
-// // instruction numbers are zero-based using left to right order in peepmatch
-//
-// peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
-// // provide an instruction_number.operand_name for each operand that appears
-// // in the replacement instruction's match rule
-//
-// ---------VM FLAGS---------------------------------------------------------
-//
-// All peephole optimizations can be turned off using -XX:-OptoPeephole
-//
-// Each peephole rule is given an identifying number starting with zero and
-// increasing by one in the order seen by the parser. An individual peephole
-// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
-// on the command-line.
-//
-// ---------CURRENT LIMITATIONS----------------------------------------------
-//
-// Only match adjacent instructions in same basic block
-// Only equality constraints
-// Only constraints between operands, not (0.dest_reg == EAX_enc)
-// Only one replacement instruction
-//
-// ---------EXAMPLE----------------------------------------------------------
-//
-// // pertinent parts of existing instructions in architecture description
-// instruct movI(rRegI dst, rRegI src) %{
-// match(Set dst (CopyI src));
-// %}
-//
-// instruct incI_eReg(rRegI dst, immI_1 src, eFlagsReg cr) %{
-// match(Set dst (AddI dst src));
-// effect(KILL cr);
-// %}
-//
-// // Change (inc mov) to lea
-// peephole %{
-// // increment preceded by register-register move
-// peepmatch ( incI_eReg movI );
-// // require that the destination register of the increment
-// // match the destination register of the move
-// peepconstraint ( 0.dst == 1.dst );
-// // construct a replacement instruction that sets
-// // the destination to ( move's source register + one )
-// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) );
-// %}
-//
-// Implementation no longer uses movX instructions since
-// machine-independent system no longer uses CopyX nodes.
-//
-// peephole %{
-// peepmatch ( incI_eReg movI );
-// peepconstraint ( 0.dst == 1.dst );
-// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) );
-// %}
-//
-// peephole %{
-// peepmatch ( decI_eReg movI );
-// peepconstraint ( 0.dst == 1.dst );
-// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) );
-// %}
-//
-// peephole %{
-// peepmatch ( addI_eReg_imm movI );
-// peepconstraint ( 0.dst == 1.dst );
-// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) );
-// %}
-//
-// peephole %{
-// peepmatch ( addP_eReg_imm movP );
-// peepconstraint ( 0.dst == 1.dst );
-// peepreplace ( leaP_eReg_immI( 0.dst 1.src 0.src ) );
-// %}
-
-// // Change load of spilled value to only a spill
-// instruct storeI(memory mem, rRegI src) %{
-// match(Set mem (StoreI mem src));
-// %}
-//
-// instruct loadI(rRegI dst, memory mem) %{
-// match(Set dst (LoadI mem));
-// %}
-//
-peephole %{
- peepmatch ( loadI storeI );
- peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
- peepreplace ( storeI( 1.mem 1.mem 1.src ) );
-%}
-
-//----------SMARTSPILL RULES---------------------------------------------------
-// These must follow all instruction definitions as they use the names
-// defined in the instructions definitions.
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 8cc4a970bfd9f..b94ff7dbd9e5a 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -818,7 +818,7 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
st->print("# stack alignment check");
#endif
}
- if (C->stub_function() != nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
+ if (C->stub_function() != nullptr) {
st->print("\n\t");
st->print("cmpl [r15_thread + #disarmed_guard_value_offset], #disarmed_guard_value\t");
st->print("\n\t");
@@ -1547,7 +1547,11 @@ void BoxLockNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
uint BoxLockNode::size(PhaseRegAlloc *ra_) const
{
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
- return (offset < 0x80) ? 5 : 8; // REX
+ if (ra_->get_encode(this) > 15) {
+ return (offset < 0x80) ? 6 : 9; // REX2
+ } else {
+ return (offset < 0x80) ? 5 : 8; // REX
+ }
}
//=============================================================================
@@ -4377,16 +4381,21 @@ instruct loadNKlassCompactHeaders(rRegN dst, memory mem, rFlagsReg cr)
predicate(UseCompactObjectHeaders);
match(Set dst (LoadNKlass mem));
effect(KILL cr);
- ins_cost(125); // XXX
+ ins_cost(125);
format %{
"movl $dst, $mem\t# compressed klass ptr, shifted\n\t"
"shrl $dst, markWord::klass_shift_at_offset"
%}
ins_encode %{
- __ movl($dst$$Register, $mem$$Address);
- __ shrl($dst$$Register, markWord::klass_shift_at_offset);
+ if (UseAPX) {
+ __ eshrl($dst$$Register, $mem$$Address, markWord::klass_shift_at_offset, false);
+ }
+ else {
+ __ movl($dst$$Register, $mem$$Address);
+ __ shrl($dst$$Register, markWord::klass_shift_at_offset);
+ }
%}
- ins_pipe(ialu_reg_mem); // XXX
+ ins_pipe(ialu_reg_mem);
%}
// Load Float
@@ -6136,6 +6145,7 @@ instruct cmovI_imm_01(rRegI dst, immI_1 src, rFlagsReg cr, cmpOp cop)
instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6146,6 +6156,19 @@ instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovI_reg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr, cmpOp cop)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovI_imm_01U(rRegI dst, immI_1 src, rFlagsRegU cr, cmpOpU cop)
%{
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
@@ -6161,6 +6184,7 @@ instruct cmovI_imm_01U(rRegI dst, immI_1 src, rFlagsRegU cr, cmpOpU cop)
%}
instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6171,6 +6195,18 @@ instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovI_regU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, rRegI src2) %{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovI_imm_01UCF(rRegI dst, immI_1 src, rFlagsRegUCF cr, cmpOpUCF cop)
%{
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
@@ -6186,6 +6222,7 @@ instruct cmovI_imm_01UCF(rRegI dst, immI_1 src, rFlagsRegUCF cr, cmpOpUCF cop)
%}
instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
@@ -6193,8 +6230,19 @@ instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
%}
%}
+instruct cmovI_regUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, rRegI src2) %{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6207,10 +6255,24 @@ instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovI_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpl $dst, $src1, $src2\n\t"
+ "ecmovnel $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovl(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
// inputs of the CMove
instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
ins_cost(200); // XXX
@@ -6223,8 +6285,25 @@ instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src)
ins_pipe(pipe_cmov_reg);
%}
+// We need this special handling for only eq / neq comparison since NaN == NaN is false,
+// and parity flag bit is set if any of the operand is a NaN.
+instruct cmovI_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpl $dst, $src1, $src2\n\t"
+ "ecmovnel $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovl(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Conditional move
instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250); // XXX
@@ -6235,9 +6314,24 @@ instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
ins_pipe(pipe_cmov_mem);
%}
+// Conditional move
+instruct cmovI_rReg_rReg_mem_ndd(rRegI dst, cmpOp cop, rFlagsReg cr, rRegI src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
+
+ ins_cost(250);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
// Conditional move
instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250); // XXX
@@ -6249,6 +6343,7 @@ instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
%}
instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250);
expand %{
@@ -6256,9 +6351,35 @@ instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
%}
%}
+instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
+
+ ins_cost(250);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
+instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
+ ins_cost(250);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
// Conditional move
instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6269,9 +6390,24 @@ instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
ins_pipe(pipe_cmov_reg);
%}
+// Conditional move ndd
+instruct cmovN_reg_ndd(rRegN dst, rRegN src1, rRegN src2, rFlagsReg cr, cmpOp cop)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, compressed ptr ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Conditional move
instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6283,6 +6419,7 @@ instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
%}
instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
@@ -6290,6 +6427,31 @@ instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
%}
%}
+// Conditional move ndd
+instruct cmovN_regU_ndd(rRegN dst, cmpOpU cop, rFlagsRegU cr, rRegN src1, rRegN src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
+instruct cmovN_regUCF_ndd(rRegN dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegN src1, rRegN src2) %{
+ predicate(UseAPX);
+ match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
+ ins_cost(200);
+ format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
+ ins_encode %{
+ __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovN_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
@@ -6323,6 +6485,7 @@ instruct cmovN_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src)
// Conditional move
instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6333,9 +6496,24 @@ instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
ins_pipe(pipe_cmov_reg); // XXX
%}
+// Conditional move ndd
+instruct cmovP_reg_ndd(rRegP dst, rRegP src1, rRegP src2, rFlagsReg cr, cmpOp cop)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, ptr ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Conditional move
instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6346,6 +6524,20 @@ instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src)
ins_pipe(pipe_cmov_reg); // XXX
%}
+// Conditional move ndd
+instruct cmovP_regU_ndd(rRegP dst, cmpOpU cop, rFlagsRegU cr, rRegP src1, rRegP src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200);
@@ -6354,8 +6546,18 @@ instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
%}
%}
+instruct cmovP_regUCF_ndd(rRegP dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegP src1, rRegP src2) %{
+ match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6368,10 +6570,24 @@ instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovP_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpq $dst, $src1, $src2\n\t"
+ "ecmovneq $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovq(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
// inputs of the CMove
instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
match(Set dst (CMoveP (Binary cop cr) (Binary src dst)));
ins_cost(200); // XXX
@@ -6384,6 +6600,20 @@ instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovP_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpq $dst, $src1, $src2\n\t"
+ "ecmovneq $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovq(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovL_imm_01(rRegL dst, immL1 src, rFlagsReg cr, cmpOp cop)
%{
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
@@ -6400,6 +6630,7 @@ instruct cmovL_imm_01(rRegL dst, immL1 src, rFlagsReg cr, cmpOp cop)
instruct cmovL_reg(cmpOp cop, rFlagsReg cr, rRegL dst, rRegL src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6410,8 +6641,22 @@ instruct cmovL_reg(cmpOp cop, rFlagsReg cr, rRegL dst, rRegL src)
ins_pipe(pipe_cmov_reg); // XXX
%}
+instruct cmovL_reg_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, rRegL src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
ins_cost(200); // XXX
@@ -6422,6 +6667,19 @@ instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src)
ins_pipe(pipe_cmov_mem); // XXX
%}
+instruct cmovL_rReg_rReg_mem_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
instruct cmovL_imm_01U(rRegL dst, immL1 src, rFlagsRegU cr, cmpOpU cop)
%{
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
@@ -6438,6 +6696,7 @@ instruct cmovL_imm_01U(rRegL dst, immL1 src, rFlagsRegU cr, cmpOpU cop)
instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6448,6 +6707,19 @@ instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src)
ins_pipe(pipe_cmov_reg); // XXX
%}
+instruct cmovL_regU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, rRegL src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovL_imm_01UCF(rRegL dst, immL1 src, rFlagsRegUCF cr, cmpOpUCF cop)
%{
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
@@ -6463,6 +6735,7 @@ instruct cmovL_imm_01UCF(rRegL dst, immL1 src, rFlagsRegUCF cr, cmpOpUCF cop)
%}
instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
@@ -6470,8 +6743,20 @@ instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
%}
%}
+instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@@ -6484,10 +6769,24 @@ instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovL_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpq $dst, $src1, $src2\n\t"
+ "ecmovneq $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovq(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
// inputs of the CMove
instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
- predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
ins_cost(200); // XXX
@@ -6500,8 +6799,23 @@ instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovL_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
+ predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
+
+ ins_cost(200);
+ format %{ "ecmovpq $dst, $src1, $src2\n\t"
+ "ecmovneq $dst, $src1, $src2" %}
+ ins_encode %{
+ __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
+ __ ecmovq(Assembler::notEqual, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
+
instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
%{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
ins_cost(200); // XXX
@@ -6513,6 +6827,7 @@ instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
%}
instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
+ predicate(!UseAPX);
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
ins_cost(200);
expand %{
@@ -6520,6 +6835,31 @@ instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
%}
%}
+instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
+
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
+instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
+ ins_cost(200);
+ format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
+ ins_encode %{
+ __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
+ %}
+ ins_pipe(pipe_cmov_mem);
+%}
+
instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src)
%{
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
@@ -6613,6 +6953,7 @@ instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{
instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddI dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6623,8 +6964,23 @@ instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+instruct addI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eaddl($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
instruct addI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddI dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6636,8 +6992,37 @@ instruct addI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
ins_pipe( ialu_reg );
%}
+instruct addI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eaddl($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe( ialu_reg );
+%}
+
+instruct addI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eaddl($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe( ialu_reg );
+%}
+
instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddI dst (LoadI src)));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6650,6 +7035,36 @@ instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct addI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eaddl($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct addI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddI src1 (LoadI src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eaddl($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct addI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
%{
match(Set dst (StoreI dst (AddI (LoadI dst) src)));
@@ -6681,7 +7096,7 @@ instruct addI_mem_imm(memory dst, immI src, rFlagsReg cr)
instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
%{
- predicate(UseIncDec);
+ predicate(!UseAPX && UseIncDec);
match(Set dst (AddI dst src));
effect(KILL cr);
@@ -6692,30 +7107,82 @@ instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
-instruct incI_mem(memory dst, immI_1 src, rFlagsReg cr)
+instruct incI_rReg_ndd(rRegI dst, rRegI src, immI_1 val, rFlagsReg cr)
%{
- predicate(UseIncDec);
- match(Set dst (StoreI dst (AddI (LoadI dst) src)));
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddI src val));
effect(KILL cr);
- ins_cost(125); // XXX
- format %{ "incl $dst\t# int" %}
+ format %{ "eincl $dst, $src\t# int ndd" %}
ins_encode %{
- __ incrementl($dst$$Address);
+ __ eincl($dst$$Register, $src$$Register, false);
%}
- ins_pipe(ialu_mem_imm);
+ ins_pipe(ialu_reg);
%}
-// XXX why does that use AddI
-instruct decI_rReg(rRegI dst, immI_M1 src, rFlagsReg cr)
+instruct incI_rReg_mem_ndd(rRegI dst, memory src, immI_1 val, rFlagsReg cr)
%{
- predicate(UseIncDec);
- match(Set dst (AddI dst src));
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddI (LoadI src) val));
effect(KILL cr);
- format %{ "decl $dst\t# int" %}
+ format %{ "eincl $dst, $src\t# int ndd" %}
ins_encode %{
- __ decrementl($dst$$Register);
+ __ eincl($dst$$Register, $src$$Address, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct incI_mem(memory dst, immI_1 src, rFlagsReg cr)
+%{
+ predicate(UseIncDec);
+ match(Set dst (StoreI dst (AddI (LoadI dst) src)));
+ effect(KILL cr);
+
+ ins_cost(125); // XXX
+ format %{ "incl $dst\t# int" %}
+ ins_encode %{
+ __ incrementl($dst$$Address);
+ %}
+ ins_pipe(ialu_mem_imm);
+%}
+
+// XXX why does that use AddI
+instruct decI_rReg(rRegI dst, immI_M1 src, rFlagsReg cr)
+%{
+ predicate(!UseAPX && UseIncDec);
+ match(Set dst (AddI dst src));
+ effect(KILL cr);
+
+ format %{ "decl $dst\t# int" %}
+ ins_encode %{
+ __ decrementl($dst$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct decI_rReg_ndd(rRegI dst, rRegI src, immI_M1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddI src val));
+ effect(KILL cr);
+
+ format %{ "edecl $dst, $src\t# int ndd" %}
+ ins_encode %{
+ __ edecl($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct decI_rReg_mem_ndd(rRegI dst, memory src, immI_M1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddI (LoadI src) val));
+ effect(KILL cr);
+
+ format %{ "edecl $dst, $src\t# int ndd" %}
+ ins_encode %{
+ __ edecl($dst$$Register, $src$$Address, false);
%}
ins_pipe(ialu_reg);
%}
@@ -6788,6 +7255,7 @@ instruct leaI_rReg_rReg_immI2_immI(rRegI dst, rRegI base, rRegI index, immI2 sca
instruct addL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddL dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6799,8 +7267,23 @@ instruct addL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+instruct addL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eaddq($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
instruct addL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddL dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6812,8 +7295,37 @@ instruct addL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
ins_pipe( ialu_reg );
%}
+instruct addL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eaddq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe( ialu_reg );
+%}
+
+instruct addL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eaddq($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe( ialu_reg );
+%}
+
instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AddL dst (LoadL src)));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -6826,6 +7338,36 @@ instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct addL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddL src1 (LoadL src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eaddq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct addL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AddL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eaddq($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
%{
match(Set dst (StoreL dst (AddL (LoadL dst) src)));
@@ -6856,7 +7398,7 @@ instruct addL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
instruct incL_rReg(rRegI dst, immL1 src, rFlagsReg cr)
%{
- predicate(UseIncDec);
+ predicate(!UseAPX && UseIncDec);
match(Set dst (AddL dst src));
effect(KILL cr);
@@ -6867,6 +7409,32 @@ instruct incL_rReg(rRegI dst, immL1 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct incL_rReg_ndd(rRegI dst, rRegI src, immL1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddL src val));
+ effect(KILL cr);
+
+ format %{ "eincq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ eincq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct incL_rReg_mem_ndd(rRegI dst, memory src, immL1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddL (LoadL src) val));
+ effect(KILL cr);
+
+ format %{ "eincq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ eincq($dst$$Register, $src$$Address, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
instruct incL_mem(memory dst, immL1 src, rFlagsReg cr)
%{
predicate(UseIncDec);
@@ -6884,7 +7452,7 @@ instruct incL_mem(memory dst, immL1 src, rFlagsReg cr)
// XXX why does that use AddL
instruct decL_rReg(rRegL dst, immL_M1 src, rFlagsReg cr)
%{
- predicate(UseIncDec);
+ predicate(!UseAPX && UseIncDec);
match(Set dst (AddL dst src));
effect(KILL cr);
@@ -6895,6 +7463,32 @@ instruct decL_rReg(rRegL dst, immL_M1 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct decL_rReg_ndd(rRegL dst, rRegL src, immL_M1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddL src val));
+ effect(KILL cr);
+
+ format %{ "edecq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ edecq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct decL_rReg_mem_ndd(rRegL dst, memory src, immL_M1 val, rFlagsReg cr)
+%{
+ predicate(UseAPX && UseIncDec);
+ match(Set dst (AddL (LoadL src) val));
+ effect(KILL cr);
+
+ format %{ "edecq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ edecq($dst$$Register, $src$$Address, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// XXX why does that use AddL
instruct decL_mem(memory dst, immL_M1 src, rFlagsReg cr)
%{
@@ -7530,6 +8124,7 @@ instruct absL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
// Integer Subtraction Instructions
instruct subI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubI dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -7541,8 +8136,51 @@ instruct subI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+instruct subI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ esubl($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ esubl($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ esubl($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubI dst (LoadI src)));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -7555,6 +8193,36 @@ instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct subI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI src1 (LoadI src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ esubl($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct subI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ esubl($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
%{
match(Set dst (StoreI dst (SubI (LoadI dst) src)));
@@ -7571,6 +8239,7 @@ instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubL dst src));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -7582,8 +8251,51 @@ instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+instruct subL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ esubq($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ esubq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ esubq($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubL dst (LoadL src)));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
@@ -7596,6 +8308,36 @@ instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct subL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL src1 (LoadL src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ esubq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct subL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
+
+ ins_cost(150);
+ format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ esubq($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct subL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
%{
match(Set dst (StoreL dst (SubL (LoadL dst) src)));
@@ -7626,6 +8368,7 @@ instruct subP_rReg(rRegP dst, rRegI src, immI_0 zero, rFlagsReg cr)
instruct negI_rReg(rRegI dst, immI_0 zero, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubI zero dst));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
@@ -7637,8 +8380,23 @@ instruct negI_rReg(rRegI dst, immI_0 zero, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct negI_rReg_ndd(rRegI dst, rRegI src, immI_0 zero, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubI zero src));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "enegl $dst, $src\t# int ndd" %}
+ ins_encode %{
+ __ enegl($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
instruct negI_rReg_2(rRegI dst, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (NegI dst));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
@@ -7650,6 +8408,20 @@ instruct negI_rReg_2(rRegI dst, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct negI_rReg_2_ndd(rRegI dst, rRegI src, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (NegI src));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "enegl $dst, $src\t# int ndd" %}
+ ins_encode %{
+ __ enegl($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
instruct negI_mem(memory dst, immI_0 zero, rFlagsReg cr)
%{
match(Set dst (StoreI dst (SubI zero (LoadI dst))));
@@ -7665,6 +8437,7 @@ instruct negI_mem(memory dst, immI_0 zero, rFlagsReg cr)
instruct negL_rReg(rRegL dst, immL0 zero, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (SubL zero dst));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
@@ -7676,8 +8449,23 @@ instruct negL_rReg(rRegL dst, immL0 zero, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct negL_rReg_ndd(rRegL dst, rRegL src, immL0 zero, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (SubL zero src));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "enegq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ enegq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
instruct negL_rReg_2(rRegL dst, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (NegL dst));
effect(KILL cr);
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
@@ -7689,6 +8477,20 @@ instruct negL_rReg_2(rRegL dst, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct negL_rReg_2_ndd(rRegL dst, rRegL src, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (NegL src));
+ effect(KILL cr);
+ flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
+
+ format %{ "enegq $dst, $src\t# long ndd" %}
+ ins_encode %{
+ __ enegq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr)
%{
match(Set dst (StoreL dst (SubL zero (LoadL dst))));
@@ -7708,6 +8510,7 @@ instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr)
instruct mulI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulI dst src));
effect(KILL cr);
@@ -7719,8 +8522,23 @@ instruct mulI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg_alu0);
%}
+instruct mulI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulI src1 src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eimull($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulI src imm));
effect(KILL cr);
@@ -7732,8 +8550,23 @@ instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
ins_pipe(ialu_reg_reg_alu0);
%}
+instruct mulI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulI src1 src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eimull($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulI dst (LoadI src)));
effect(KILL cr);
@@ -7745,8 +8578,23 @@ instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem_alu0);
%}
+instruct mulI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulI src1 (LoadI src2)));
+ effect(KILL cr);
+
+ ins_cost(350);
+ format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eimull($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulI (LoadI src) imm));
effect(KILL cr);
@@ -7758,6 +8606,20 @@ instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
ins_pipe(ialu_reg_mem_alu0);
%}
+instruct mulI_rReg_mem_imm(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulI (LoadI src1) src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eimull($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg cr)
%{
match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3)));
@@ -7770,6 +8632,7 @@ instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg
instruct mulL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulL dst src));
effect(KILL cr);
@@ -7781,8 +8644,23 @@ instruct mulL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg_alu0);
%}
+instruct mulL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulL src1 src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eimulq($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulL src imm));
effect(KILL cr);
@@ -7794,8 +8672,23 @@ instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
ins_pipe(ialu_reg_reg_alu0);
%}
+instruct mulL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulL src1 src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eimulq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulL dst (LoadL src)));
effect(KILL cr);
@@ -7807,15 +8700,44 @@ instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem_alu0);
%}
+instruct mulL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulL src1 (LoadL src2)));
+ effect(KILL cr);
+
+ ins_cost(350);
+ format %{ "eimulq $dst, $src1, $src2 \t# long" %}
+ ins_encode %{
+ __ eimulq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (MulL (LoadL src) imm));
effect(KILL cr);
ins_cost(300);
- format %{ "imulq $dst, $src, $imm\t# long" %}
+ format %{ "imulq $dst, $src, $imm\t# long" %}
+ ins_encode %{
+ __ imulq($dst$$Register, $src$$Address, $imm$$constant);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
+instruct mulL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (MulL (LoadL src1) src2));
+ effect(KILL cr);
+
+ ins_cost(300);
+ format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
ins_encode %{
- __ imulq($dst$$Register, $src$$Address, $imm$$constant);
+ __ eimulq($dst$$Register, $src1$$Address, $src2$$constant, false);
%}
ins_pipe(ialu_reg_mem_alu0);
%}
@@ -8055,6 +8977,7 @@ instruct umodL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div, rFlagsReg c
// Shift Left by one, two, three
instruct salI_rReg_immI2(rRegI dst, immI2 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (LShiftI dst shift));
effect(KILL cr);
@@ -8065,9 +8988,24 @@ instruct salI_rReg_immI2(rRegI dst, immI2 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Shift Left by one, two, three
+instruct salI_rReg_immI2_ndd(rRegI dst, rRegI src, immI2 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftI src shift));
+ effect(KILL cr);
+
+ format %{ "esall $dst, $src, $shift\t# int(ndd)" %}
+ ins_encode %{
+ __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Shift Left by 8-bit immediate
instruct salI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (LShiftI dst shift));
effect(KILL cr);
@@ -8078,6 +9016,33 @@ instruct salI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Shift Left by 8-bit immediate
+instruct salI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftI src shift));
+ effect(KILL cr);
+
+ format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
+ ins_encode %{
+ __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct salI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftI (LoadI src) shift));
+ effect(KILL cr);
+
+ format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
+ ins_encode %{
+ __ esall($dst$$Register, $src$$Address, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Shift Left by 8-bit immediate
instruct salI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@@ -8146,6 +9111,7 @@ instruct salI_mem_rReg(rRegI dst, memory src, rRegI shift)
// Arithmetic Shift Right by 8-bit immediate
instruct sarI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (RShiftI dst shift));
effect(KILL cr);
@@ -8156,6 +9122,33 @@ instruct sarI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_mem_imm);
%}
+// Arithmetic Shift Right by 8-bit immediate
+instruct sarI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (RShiftI src shift));
+ effect(KILL cr);
+
+ format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
+ ins_encode %{
+ __ esarl($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_mem_imm);
+%}
+
+instruct sarI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (RShiftI (LoadI src) shift));
+ effect(KILL cr);
+
+ format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
+ ins_encode %{
+ __ esarl($dst$$Register, $src$$Address, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_mem_imm);
+%}
+
// Arithmetic Shift Right by 8-bit immediate
instruct sarI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@@ -8224,6 +9217,7 @@ instruct sarI_mem_rReg(rRegI dst, memory src, rRegI shift)
// Logical Shift Right by 8-bit immediate
instruct shrI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (URShiftI dst shift));
effect(KILL cr);
@@ -8234,6 +9228,33 @@ instruct shrI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Logical Shift Right by 8-bit immediate
+instruct shrI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (URShiftI src shift));
+ effect(KILL cr);
+
+ format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
+ ins_encode %{
+ __ eshrl($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct shrI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (URShiftI (LoadI src) shift));
+ effect(KILL cr);
+
+ format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
+ ins_encode %{
+ __ eshrl($dst$$Register, $src$$Address, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Logical Shift Right by 8-bit immediate
instruct shrI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@@ -8303,6 +9324,7 @@ instruct shrI_mem_rReg(rRegI dst, memory src, rRegI shift)
// Shift Left by one, two, three
instruct salL_rReg_immI2(rRegL dst, immI2 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (LShiftL dst shift));
effect(KILL cr);
@@ -8313,9 +9335,24 @@ instruct salL_rReg_immI2(rRegL dst, immI2 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Shift Left by one, two, three
+instruct salL_rReg_immI2_ndd(rRegL dst, rRegL src, immI2 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftL src shift));
+ effect(KILL cr);
+
+ format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Shift Left by 8-bit immediate
instruct salL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (LShiftL dst shift));
effect(KILL cr);
@@ -8326,6 +9363,33 @@ instruct salL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Shift Left by 8-bit immediate
+instruct salL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftL src shift));
+ effect(KILL cr);
+
+ format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct salL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (LShiftL (LoadL src) shift));
+ effect(KILL cr);
+
+ format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ esalq($dst$$Register, $src$$Address, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Shift Left by 8-bit immediate
instruct salL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@@ -8394,6 +9458,7 @@ instruct salL_mem_rReg(rRegL dst, memory src, rRegI shift)
// Arithmetic Shift Right by 8-bit immediate
instruct sarL_rReg_imm(rRegL dst, immI shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (RShiftL dst shift));
effect(KILL cr);
@@ -8404,6 +9469,33 @@ instruct sarL_rReg_imm(rRegL dst, immI shift, rFlagsReg cr)
ins_pipe(ialu_mem_imm);
%}
+// Arithmetic Shift Right by 8-bit immediate
+instruct sarL_rReg_imm_ndd(rRegL dst, rRegL src, immI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (RShiftL src shift));
+ effect(KILL cr);
+
+ format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ esarq($dst$$Register, $src$$Register, (unsigned char)($shift$$constant & 0x3F), false);
+ %}
+ ins_pipe(ialu_mem_imm);
+%}
+
+instruct sarL_rReg_mem_imm_ndd(rRegL dst, memory src, immI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (RShiftL (LoadL src) shift));
+ effect(KILL cr);
+
+ format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ esarq($dst$$Register, $src$$Address, (unsigned char)($shift$$constant & 0x3F), false);
+ %}
+ ins_pipe(ialu_mem_imm);
+%}
+
// Arithmetic Shift Right by 8-bit immediate
instruct sarL_mem_imm(memory dst, immI shift, rFlagsReg cr)
%{
@@ -8472,6 +9564,7 @@ instruct sarL_mem_rReg(rRegL dst, memory src, rRegI shift)
// Logical Shift Right by 8-bit immediate
instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (URShiftL dst shift));
effect(KILL cr);
@@ -8482,6 +9575,33 @@ instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+// Logical Shift Right by 8-bit immediate
+instruct shrL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (URShiftL src shift));
+ effect(KILL cr);
+
+ format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ eshrq($dst$$Register, $src$$Register, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct shrL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (URShiftL (LoadL src) shift));
+ effect(KILL cr);
+
+ format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
+ ins_encode %{
+ __ eshrq($dst$$Register, $src$$Address, $shift$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Logical Shift Right by 8-bit immediate
instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@@ -8590,7 +9710,7 @@ instruct rolI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
instruct rolI_immI8(rRegI dst, rRegI src, immI8 shift)
%{
- predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
+ predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
match(Set dst (RotateLeft src shift));
format %{ "rolxl $dst, $src, $shift" %}
ins_encode %{
@@ -8616,7 +9736,7 @@ instruct rolI_mem_immI8(rRegI dst, memory src, immI8 shift)
// Rotate Left by variable
instruct rolI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
%{
- predicate(n->bottom_type()->basic_type() == T_INT);
+ predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
match(Set dst (RotateLeft dst shift));
effect(KILL cr);
format %{ "roll $dst, $shift" %}
@@ -8626,6 +9746,20 @@ instruct rolI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Rotate Left by variable
+instruct rolI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
+ match(Set dst (RotateLeft src shift));
+ effect(KILL cr);
+
+ format %{ "eroll $dst, $src, $shift\t# rotate left (int ndd)" %}
+ ins_encode %{
+ __ eroll($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Rotate Right by constant.
instruct rorI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
%{
@@ -8642,7 +9776,7 @@ instruct rorI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
// Rotate Right by constant.
instruct rorI_immI8(rRegI dst, rRegI src, immI8 shift)
%{
- predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
+ predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
match(Set dst (RotateRight src shift));
format %{ "rorxl $dst, $src, $shift" %}
ins_encode %{
@@ -8666,7 +9800,7 @@ instruct rorI_mem_immI8(rRegI dst, memory src, immI8 shift)
// Rotate Right by variable
instruct rorI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
%{
- predicate(n->bottom_type()->basic_type() == T_INT);
+ predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
match(Set dst (RotateRight dst shift));
effect(KILL cr);
format %{ "rorl $dst, $shift" %}
@@ -8676,6 +9810,20 @@ instruct rorI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Rotate Right by variable
+instruct rorI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
+ match(Set dst (RotateRight src shift));
+ effect(KILL cr);
+
+ format %{ "erorl $dst, $src, $shift\t# rotate right(int ndd)" %}
+ ins_encode %{
+ __ erorl($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Rotate Left by constant.
instruct rolL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
%{
@@ -8691,7 +9839,7 @@ instruct rolL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
instruct rolL_immI8(rRegL dst, rRegL src, immI8 shift)
%{
- predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
+ predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
match(Set dst (RotateLeft src shift));
format %{ "rolxq $dst, $src, $shift" %}
ins_encode %{
@@ -8717,7 +9865,7 @@ instruct rolL_mem_immI8(rRegL dst, memory src, immI8 shift)
// Rotate Left by variable
instruct rolL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
%{
- predicate(n->bottom_type()->basic_type() == T_LONG);
+ predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
match(Set dst (RotateLeft dst shift));
effect(KILL cr);
format %{ "rolq $dst, $shift" %}
@@ -8727,6 +9875,20 @@ instruct rolL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Rotate Left by variable
+instruct rolL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
+ match(Set dst (RotateLeft src shift));
+ effect(KILL cr);
+
+ format %{ "erolq $dst, $src, $shift\t# rotate left(long ndd)" %}
+ ins_encode %{
+ __ erolq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Rotate Right by constant.
instruct rorL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
%{
@@ -8767,7 +9929,7 @@ instruct rorL_mem_immI8(rRegL dst, memory src, immI8 shift)
// Rotate Right by variable
instruct rorL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
%{
- predicate(n->bottom_type()->basic_type() == T_LONG);
+ predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
match(Set dst (RotateRight dst shift));
effect(KILL cr);
format %{ "rorq $dst, $shift" %}
@@ -8777,6 +9939,20 @@ instruct rorL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Rotate Right by variable
+instruct rorL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
+%{
+ predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
+ match(Set dst (RotateRight src shift));
+ effect(KILL cr);
+
+ format %{ "erorq $dst, $src, $shift\t# rotate right(long ndd)" %}
+ ins_encode %{
+ __ erorq($dst$$Register, $src$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
//----------------------------- CompressBits/ExpandBits ------------------------
instruct compressBitsL_reg(rRegL dst, rRegL src, rRegL mask) %{
@@ -8828,6 +10004,7 @@ instruct expandBitsL_mem(rRegL dst, rRegL src, memory mask) %{
// And Register with Register
instruct andI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -8839,6 +10016,22 @@ instruct andI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// And Register with Register using New Data Destination (NDD)
+instruct andI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eandl($dst$$Register, $src1$$Register, $src2$$Register, false);
+
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// And Register with Immediate 255
instruct andI_rReg_imm255(rRegI dst, rRegI src, immI_255 mask)
%{
@@ -8905,6 +10098,7 @@ instruct convI2LAndI_reg_immIbitmask(rRegL dst, rRegI src, immI_Pow2M1 mask, rR
// And Register with Immediate
instruct andI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -8916,9 +10110,38 @@ instruct andI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct andI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eandl($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct andI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eandl($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// And Register with Memory
instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndI dst (LoadI src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -8931,6 +10154,21 @@ instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct andI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndI src1 (LoadI src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eandl($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// And Memory with Register
instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
%{
@@ -9103,6 +10341,7 @@ instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
// Or Register with Register
instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (OrI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9114,16 +10353,74 @@ instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Or Register with Register using New Data Destination (NDD)
+instruct orI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eorl($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Or Register with Immediate
instruct orI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
%{
- match(Set dst (OrI dst src));
+ predicate(!UseAPX);
+ match(Set dst (OrI dst src));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "orl $dst, $src\t# int" %}
+ ins_encode %{
+ __ orl($dst$$Register, $src$$constant);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct orI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eorl($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct orI_rReg_imm_rReg_ndd(rRegI dst, immI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorl $dst, $src2, $src1\t# int ndd" %}
+ ins_encode %{
+ __ eorl($dst$$Register, $src2$$Register, $src1$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct orI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrI (LoadI src1) src2));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
- format %{ "orl $dst, $src\t# int" %}
+ format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
ins_encode %{
- __ orl($dst$$Register, $src$$constant);
+ __ eorl($dst$$Register, $src1$$Address, $src2$$constant, false);
%}
ins_pipe(ialu_reg);
%}
@@ -9131,6 +10428,7 @@ instruct orI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
// Or Register with Memory
instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (OrI dst (LoadI src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9143,6 +10441,21 @@ instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct orI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrI src1 (LoadI src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ eorl($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// Or Memory with Register
instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
%{
@@ -9191,6 +10504,7 @@ instruct orI_mem_imm(memory dst, immI src, rFlagsReg cr)
// Xor Register with Register
instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9202,20 +10516,50 @@ instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Xor Register with Register using New Data Destination (NDD)
+instruct xorI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ exorl($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Xor Register with Immediate -1
-instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{
+instruct xorI_rReg_im1(rRegI dst, immI_M1 imm)
+%{
+ predicate(!UseAPX);
match(Set dst (XorI dst imm));
- format %{ "not $dst" %}
+ format %{ "notl $dst" %}
ins_encode %{
__ notl($dst$$Register);
%}
ins_pipe(ialu_reg);
%}
+instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm)
+%{
+ match(Set dst (XorI src imm));
+ predicate(UseAPX);
+
+ format %{ "enotl $dst, $src" %}
+ ins_encode %{
+ __ enotl($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Xor Register with Immediate
instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9227,9 +10571,39 @@ instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorI src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ exorl($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+// Xor Memory with Immediate
+instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ exorl($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Xor Register with Memory
instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorI dst (LoadI src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9242,6 +10616,36 @@ instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct xorI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorI src1 (LoadI src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ exorl($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct xorI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorI (LoadI src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
+ ins_encode %{
+ __ exorl($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// Xor Memory with Register
instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
%{
@@ -9293,6 +10697,7 @@ instruct xorI_mem_imm(memory dst, immI src, rFlagsReg cr)
// And Register with Register
instruct andL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9304,6 +10709,22 @@ instruct andL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// And Register with Register using New Data Destination (NDD)
+instruct andL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eandq($dst$$Register, $src1$$Register, $src2$$Register, false);
+
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// And Register with Immediate 255
instruct andL_rReg_imm255(rRegL dst, rRegL src, immL_255 mask)
%{
@@ -9333,6 +10754,7 @@ instruct andL_rReg_imm65535(rRegL dst, rRegL src, immL_65535 mask)
// And Register with Immediate
instruct andL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9344,9 +10766,38 @@ instruct andL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct andL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eandq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct andL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eandq($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// And Register with Memory
instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (AndL dst (LoadL src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9359,6 +10810,36 @@ instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct andL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndL src1 (LoadL src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eandq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct andL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (AndL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eandq($dst$$Register, $src1$$Address, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// And Memory with Register
instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
%{
@@ -9534,6 +11015,7 @@ instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
// Or Register with Register
instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (OrL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9545,6 +11027,22 @@ instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Or Register with Register using New Data Destination (NDD)
+instruct orL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
+
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Use any_RegP to match R15 (TLS register) without spilling.
instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
match(Set dst (OrL dst (CastP2X src)));
@@ -9558,10 +11056,22 @@ instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
ins_pipe(ialu_reg_reg);
%}
+instruct orL_rReg_castP2X_ndd(rRegL dst, any_RegP src1, any_RegP src2, rFlagsReg cr) %{
+ match(Set dst (OrL src1 (CastP2X src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
// Or Register with Immediate
instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (OrL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9573,9 +11083,53 @@ instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct orL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct orL_rReg_imm_rReg_ndd(rRegL dst, immL32 src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorq $dst, $src2, $src1\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src2$$Register, $src1$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+// Or Memory with Immediate
+instruct orL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Or Register with Memory
instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (OrL dst (LoadL src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9588,6 +11142,21 @@ instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct orL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (OrL src1 (LoadL src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ eorq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// Or Memory with Register
instruct orL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
%{
@@ -9639,6 +11208,7 @@ instruct btsL_mem_imm(memory dst, immL_Pow2 con, rFlagsReg cr)
// Xor Register with Register
instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9650,8 +11220,25 @@ instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
+// Xor Register with Register using New Data Destination (NDD)
+instruct xorL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ exorq($dst$$Register, $src1$$Register, $src2$$Register, false);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
// Xor Register with Immediate -1
-instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{
+instruct xorL_rReg_im1(rRegL dst, immL_M1 imm)
+%{
+ predicate(!UseAPX);
match(Set dst (XorL dst imm));
format %{ "notq $dst" %}
@@ -9661,9 +11248,22 @@ instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{
ins_pipe(ialu_reg);
%}
+instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL src imm));
+
+ format %{ "enotq $dst, $src" %}
+ ins_encode %{
+ __ enotq($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Xor Register with Immediate
instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9675,9 +11275,39 @@ instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
+instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL src1 src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ exorq($dst$$Register, $src1$$Register, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+// Xor Memory with Immediate
+instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ exorq($dst$$Register, $src1$$Address, $src2$$constant, false);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
// Xor Register with Memory
instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
match(Set dst (XorL dst (LoadL src)));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -9690,6 +11320,36 @@ instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
ins_pipe(ialu_reg_mem);
%}
+instruct xorL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL src1 (LoadL src2)));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ exorq($dst$$Register, $src1$$Register, $src2$$Address, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct xorL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ match(Set dst (XorL (LoadL src1) src2));
+ effect(KILL cr);
+ flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
+
+ ins_cost(150);
+ format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
+ ins_encode %{
+ __ exorq($dst$$Register, $src1$$Address, $src1$$Register, false);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
// Xor Memory with Register
instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
%{
@@ -12003,6 +13663,7 @@ instruct testB_mem_imm(rFlagsReg cr, memory mem, immI8 imm, immI_0 zero)
instruct cmovI_reg_g(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
effect(USE_DEF dst, USE src, USE cr);
format %{ "cmovlgt $dst, $src\t# min" %}
@@ -12012,9 +13673,21 @@ instruct cmovI_reg_g(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovI_reg_g_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ effect(DEF dst, USE src1, USE src2, USE cr);
+
+ format %{ "ecmovlgt $dst, $src1, $src2\t# min ndd" %}
+ ins_encode %{
+ __ ecmovl(Assembler::greater, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
instruct minI_rReg(rRegI dst, rRegI src)
%{
+ predicate(!UseAPX);
match(Set dst (MinI dst src));
ins_cost(200);
@@ -12025,8 +13698,23 @@ instruct minI_rReg(rRegI dst, rRegI src)
%}
%}
+instruct minI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (MinI src1 src2));
+ effect(DEF dst, USE src1, USE src2);
+
+ ins_cost(200);
+ expand %{
+ rFlagsReg cr;
+ compI_rReg(cr, src1, src2);
+ cmovI_reg_g_ndd(dst, src1, src2, cr);
+ %}
+%}
+
instruct cmovI_reg_l(rRegI dst, rRegI src, rFlagsReg cr)
%{
+ predicate(!UseAPX);
effect(USE_DEF dst, USE src, USE cr);
format %{ "cmovllt $dst, $src\t# max" %}
@@ -12036,9 +13724,21 @@ instruct cmovI_reg_l(rRegI dst, rRegI src, rFlagsReg cr)
ins_pipe(pipe_cmov_reg);
%}
+instruct cmovI_reg_l_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
+%{
+ predicate(UseAPX);
+ effect(DEF dst, USE src1, USE src2, USE cr);
+
+ format %{ "ecmovllt $dst, $src1, $src2\t# max ndd" %}
+ ins_encode %{
+ __ ecmovl(Assembler::less, $dst$$Register, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_cmov_reg);
+%}
instruct maxI_rReg(rRegI dst, rRegI src)
%{
+ predicate(!UseAPX);
match(Set dst (MaxI dst src));
ins_cost(200);
@@ -12049,6 +13749,20 @@ instruct maxI_rReg(rRegI dst, rRegI src)
%}
%}
+instruct maxI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
+%{
+ predicate(UseAPX);
+ match(Set dst (MaxI src1 src2));
+ effect(DEF dst, USE src1, USE src2);
+
+ ins_cost(200);
+ expand %{
+ rFlagsReg cr;
+ compI_rReg(cr, src1, src2);
+ cmovI_reg_l_ndd(dst, src1, src2, cr);
+ %}
+%}
+
// ============================================================================
// Branch Instructions
diff --git a/src/hotspot/cpu/zero/vmStructs_zero.hpp b/src/hotspot/cpu/zero/vmStructs_zero.hpp
index 64a9300e25ce9..9100c765e7ed2 100644
--- a/src/hotspot/cpu/zero/vmStructs_zero.hpp
+++ b/src/hotspot/cpu/zero/vmStructs_zero.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -30,12 +30,12 @@
// constants required by the Serviceability Agent. This file is
// referenced by vmStructs.cpp.
-#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
+#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field)
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type)
-#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant)
-#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant)
#endif // CPU_ZERO_VMSTRUCTS_ZERO_HPP
diff --git a/src/hotspot/os/aix/loadlib_aix.cpp b/src/hotspot/os/aix/loadlib_aix.cpp
index 2c38e1b637ca7..90a7271ad6d38 100644
--- a/src/hotspot/os/aix/loadlib_aix.cpp
+++ b/src/hotspot/os/aix/loadlib_aix.cpp
@@ -42,6 +42,9 @@
// For loadquery()
#include