src/cpu/x86/vm/x86_32.ad

changeset 2877
bad7ecd0b6ed
parent 2761
15c9a0e16269
child 3037
3d42f82cd811
     1.1 --- a/src/cpu/x86/vm/x86_32.ad	Wed May 04 03:42:58 2011 -0700
     1.2 +++ b/src/cpu/x86/vm/x86_32.ad	Wed May 04 13:12:42 2011 -0700
     1.3 @@ -12989,6 +12989,53 @@
     1.4  %}
     1.5  
     1.6  // ============================================================================
     1.7 +// Counted Loop limit node which represents exact final iterator value.
     1.8 +// Note: the resulting value should fit into integer range since
     1.9 +// counted loops have limit check on overflow.
    1.10 +instruct loopLimit_eReg(eAXRegI limit, nadxRegI init, immI stride, eDXRegI limit_hi, nadxRegI tmp, eFlagsReg flags) %{
    1.11 +  match(Set limit (LoopLimit (Binary init limit) stride));
    1.12 +  effect(TEMP limit_hi, TEMP tmp, KILL flags);
    1.13 +  ins_cost(300);
    1.14 +
    1.15 +  format %{ "loopLimit $init,$limit,$stride  # $limit = $init + $stride *( $limit - $init + $stride -1)/ $stride, kills $limit_hi" %}
    1.16 +  ins_encode %{
    1.17 +    int strd = (int)$stride$$constant;
    1.18 +    assert(strd != 1 && strd != -1, "sanity");
    1.19 +    int m1 = (strd > 0) ? 1 : -1;
    1.20 +    // Convert limit to long (EAX:EDX)
    1.21 +    __ cdql();
    1.22 +    // Convert init to long (init:tmp)
    1.23 +    __ movl($tmp$$Register, $init$$Register);
    1.24 +    __ sarl($tmp$$Register, 31);
    1.25 +    // $limit - $init
    1.26 +    __ subl($limit$$Register, $init$$Register);
    1.27 +    __ sbbl($limit_hi$$Register, $tmp$$Register);
    1.28 +    // + ($stride - 1)
    1.29 +    if (strd > 0) {
    1.30 +      __ addl($limit$$Register, (strd - 1));
    1.31 +      __ adcl($limit_hi$$Register, 0);
    1.32 +      __ movl($tmp$$Register, strd);
    1.33 +    } else {
    1.34 +      __ addl($limit$$Register, (strd + 1));
    1.35 +      __ adcl($limit_hi$$Register, -1);
    1.36 +      __ lneg($limit_hi$$Register, $limit$$Register);
    1.37 +      __ movl($tmp$$Register, -strd);
    1.38 +    }
    1.39 +    // signed devision: (EAX:EDX) / pos_stride
    1.40 +    __ idivl($tmp$$Register);
    1.41 +    if (strd < 0) {
    1.42 +      // restore sign
    1.43 +      __ negl($tmp$$Register);
    1.44 +    }
    1.45 +    // (EAX) * stride
    1.46 +    __ mull($tmp$$Register);
    1.47 +    // + init (ignore upper bits)
    1.48 +    __ addl($limit$$Register, $init$$Register);
    1.49 +  %}
    1.50 +  ins_pipe( pipe_slow );
    1.51 +%}
    1.52 +
    1.53 +// ============================================================================
    1.54  // Branch Instructions
    1.55  // Jump Table
    1.56  instruct jumpXtnd(eRegI switch_val) %{

mercurial