src/cpu/x86/vm/x86_32.ad

changeset 2269
ae065c367d93
parent 2103
3e8fbc61cee8
child 2275
2fe998383789
     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) %{

mercurial