1.1 --- a/src/cpu/x86/vm/x86_32.ad Sat Oct 30 13:08:23 2010 -0700 1.2 +++ b/src/cpu/x86/vm/x86_32.ad Tue Nov 02 09:00:37 2010 -0700 1.3 @@ -1508,6 +1508,16 @@ 1.4 return can_be_java_arg(reg); 1.5 } 1.6 1.7 +bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1.8 + // Use hardware integer DIV instruction when 1.9 + // it is faster than a code which use multiply. 1.10 + // Only when constant divisor fits into 32 bit 1.11 + // (min_jint is excluded to get only correct 1.12 + // positive 32 bit values from negative). 1.13 + return VM_Version::has_fast_idiv() && 1.14 + (divisor == (int)divisor && divisor != min_jint); 1.15 +} 1.16 + 1.17 // Register for DIVI projection of divmodI 1.18 RegMask Matcher::divI_proj_mask() { 1.19 return EAX_REG_mask; 1.20 @@ -1546,6 +1556,9 @@ 1.21 return true; 1.22 } 1.23 } 1.24 + if (opc == Op_ConL && (n->get_long() & 0xFFFFFFFF00000000LL) == 0LL) { 1.25 + return true; 1.26 + } 1.27 return false; 1.28 } 1.29 1.30 @@ -2309,9 +2322,11 @@ 1.31 enc_class move_long_big_shift_sign( eRegL dst, immI_32_63 cnt ) %{ 1.32 emit_opcode( cbuf, 0x8B ); // Move 1.33 emit_rm(cbuf, 0x3, $dst$$reg, HIGH_FROM_LOW($dst$$reg)); 1.34 - emit_d8(cbuf,$primary); 1.35 - emit_rm(cbuf, 0x3, $secondary, $dst$$reg); 1.36 - emit_d8(cbuf,$cnt$$constant-32); 1.37 + if( $cnt$$constant > 32 ) { // Shift, if not by zero 1.38 + emit_d8(cbuf,$primary); 1.39 + emit_rm(cbuf, 0x3, $secondary, $dst$$reg); 1.40 + emit_d8(cbuf,$cnt$$constant-32); 1.41 + } 1.42 emit_d8(cbuf,$primary); 1.43 emit_rm(cbuf, 0x3, $secondary, HIGH_FROM_LOW($dst$$reg)); 1.44 emit_d8(cbuf,31); 1.45 @@ -8842,6 +8857,103 @@ 1.46 ins_pipe( pipe_slow ); 1.47 %} 1.48 1.49 +// Divide Register Long (no special case since divisor != -1) 1.50 +instruct divL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{ 1.51 + match(Set dst (DivL dst imm)); 1.52 + effect( TEMP tmp, TEMP tmp2, KILL cr ); 1.53 + ins_cost(1000); 1.54 + format %{ "MOV $tmp,abs($imm) # ldiv EDX:EAX,$imm\n\t" 1.55 + "CMP $tmp,EDX\n\t" 1.56 + "JA,s fast\n\t" 1.57 + "MOV $tmp2,EAX\n\t" 1.58 + "MOV EAX,EDX\n\t" 1.59 + "SAR EDX,31\n\t" 1.60 + "IDIV $tmp\n\t" 1.61 + "XCHG EAX,$tmp2 \n\t" 1.62 + "IDIV $tmp\n\t" 1.63 + "CDQ\n\t" 1.64 + "ADD EDX,$tmp2\n\t" 1.65 + "JMP,s done\n" 1.66 + "fast:\n\t" 1.67 + "IDIV $tmp\n\t" 1.68 + "XOR EDX,EDX\n" 1.69 + "done:\n\t" 1.70 + "NEG EDX:EAX # if $imm < 0" %} 1.71 + ins_encode %{ 1.72 + int con = (int)$imm$$constant; 1.73 + assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); 1.74 + int pcon = (con > 0) ? con : -con; 1.75 + Label Lfast, Ldone; 1.76 + 1.77 + __ movl($tmp$$Register, pcon); 1.78 + __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); 1.79 + __ jccb(Assembler::above, Lfast); 1.80 + 1.81 + __ movl($tmp2$$Register, $dst$$Register); // save 1.82 + __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); 1.83 + __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // src sign 1.84 + __ idivl($tmp$$Register); 1.85 + __ xchgl($dst$$Register, $tmp2$$Register); 1.86 + __ idivl($tmp$$Register); 1.87 + __ cdql(); 1.88 + __ addl(HIGH_FROM_LOW($dst$$Register),$tmp2$$Register); 1.89 + __ jmpb(Ldone); 1.90 + 1.91 + __ bind(Lfast); 1.92 + // fast path: src is positive and result fits into 32 bit 1.93 + __ idivl($tmp$$Register); 1.94 + __ xorl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register)); 1.95 + 1.96 + __ bind(Ldone); 1.97 + if (con < 0) { 1.98 + __ lneg(HIGH_FROM_LOW($dst$$Register), $dst$$Register); 1.99 + } 1.100 + %} 1.101 + ins_pipe( pipe_slow ); 1.102 +%} 1.103 + 1.104 +// Remainder Register Long (remainder fit into 32 bits) 1.105 +instruct modL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{ 1.106 + match(Set dst (ModL dst imm)); 1.107 + effect( TEMP tmp, TEMP tmp2, KILL cr ); 1.108 + ins_cost(1000); 1.109 + format %{ "MOV $tmp,abs($imm) # lrem EDX:EAX,$imm\n\t" 1.110 + "CMP $tmp,EDX\n\t" 1.111 + "JA,s fast\n\t" 1.112 + "MOV $tmp2,EAX\n\t" 1.113 + "MOV EAX,EDX\n\t" 1.114 + "SAR EDX,31\n\t" 1.115 + "IDIV $tmp\n\t" 1.116 + "MOV EAX,$tmp2\n" 1.117 + "fast:\n\t" 1.118 + "IDIV $tmp\n\t" 1.119 + "MOV EAX,EDX\n\t" 1.120 + "SAR EDX,31\n\t" %} 1.121 + ins_encode %{ 1.122 + int con = (int)$imm$$constant; 1.123 + assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); 1.124 + int pcon = (con > 0) ? con : -con; 1.125 + Label Lfast; 1.126 + 1.127 + __ movl($tmp$$Register, pcon); 1.128 + __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); 1.129 + __ jccb(Assembler::above, Lfast); // src is positive and result fits into 32 bit 1.130 + 1.131 + __ movl($tmp2$$Register, $dst$$Register); // save 1.132 + __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); 1.133 + __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // src sign 1.134 + __ idivl($tmp$$Register); 1.135 + __ movl($dst$$Register, $tmp2$$Register); 1.136 + 1.137 + __ bind(Lfast); 1.138 + __ idivl($tmp$$Register); 1.139 + __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); 1.140 + __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // result sign 1.141 + 1.142 + %} 1.143 + ins_pipe( pipe_slow ); 1.144 +%} 1.145 + 1.146 // Integer Shift Instructions 1.147 // Shift Left by one 1.148 instruct shlI_eReg_1(eRegI dst, immI1 shift, eFlagsReg cr) %{