예제 #1
0
 LIR_Opr result()             {
   assert(!_destroys_register || (!_result->is_register() || _result->is_virtual()),
          "shouldn't use set_destroys_register with physical regsiters");
   if (_destroys_register && _result->is_register()) {
     if (_new_result->is_illegal()) {
       _new_result = _gen->new_register(type());
       gen()->lir()->move(_result, _new_result);
     }
     return _new_result;
   } else {
     return _result;
   }
   return _result;
 }
예제 #2
0
void FpuStackAllocator::handle_op2(LIR_Op2* op2) {
  LIR_Opr left  = op2->in_opr1();
  if (!left->is_float_kind()) {
    return;
  }
  if (left->is_xmm_register()) {
    return;
  }

  LIR_Opr right = op2->in_opr2();
  LIR_Opr res   = op2->result_opr();
  LIR_Opr new_left  = left;  // new operands relative to the actual fpu stack top
  LIR_Opr new_right = right;
  LIR_Opr new_res   = res;

  assert(!left->is_xmm_register() && !right->is_xmm_register() && !res->is_xmm_register(), "not for xmm registers");

  switch (op2->code()) {
    case lir_cmp:
    case lir_cmp_fd2i:
    case lir_ucmp_fd2i:
    case lir_assert: {
      assert(left->is_fpu_register(), "invalid LIR");
      assert(right->is_fpu_register(), "invalid LIR");

      // the left-hand side must be on top of stack.
      // the right-hand side is never popped, even if is_last_use is set
      insert_exchange(left);
      new_left = to_fpu_stack_top(left);
      new_right = to_fpu_stack(right);
      pop_if_last_use(op2, left);
      break;
    }

    case lir_mul_strictfp:
    case lir_div_strictfp: {
      assert(op2->tmp1_opr()->is_fpu_register(), "strict operations need temporary fpu stack slot");
      insert_free_if_dead(op2->tmp1_opr());
      assert(sim()->stack_size() <= 7, "at least one stack slot must be free");
      // fall-through: continue with the normal handling of lir_mul and lir_div
    }
    case lir_add:
    case lir_sub:
    case lir_mul:
    case lir_div: {
      assert(left->is_fpu_register(), "must be");
      assert(res->is_fpu_register(), "must be");
      assert(left->is_equal(res), "must be");

      // either the left-hand or the right-hand side must be on top of stack
      // (if right is not a register, left must be on top)
      if (!right->is_fpu_register()) {
        insert_exchange(left);
        new_left = to_fpu_stack_top(left);
      } else {
        // no exchange necessary if right is alredy on top of stack
        if (tos_offset(right) == 0) {
          new_left = to_fpu_stack(left);
          new_right = to_fpu_stack_top(right);
        } else {
          insert_exchange(left);
          new_left = to_fpu_stack_top(left);
          new_right = to_fpu_stack(right);
        }

        if (right->is_last_use()) {
          op2->set_fpu_pop_count(1);

          if (tos_offset(right) == 0) {
            sim()->pop();
          } else {
            // if left is on top of stack, the result is placed in the stack
            // slot of right, so a renaming from right to res is necessary
            assert(tos_offset(left) == 0, "must be");
            sim()->pop();
            do_rename(right, res);
          }
        }
      }
      new_res = to_fpu_stack(res);

      break;
    }

    case lir_rem: {
      assert(left->is_fpu_register(), "must be");
      assert(right->is_fpu_register(), "must be");
      assert(res->is_fpu_register(), "must be");
      assert(left->is_equal(res), "must be");

      // Must bring both operands to top of stack with following operand ordering:
      // * fpu stack before rem: ... right left
      // * fpu stack after rem:  ... left
      if (tos_offset(right) != 1) {
        insert_exchange(right);
        insert_exchange(1);
      }
      insert_exchange(left);
      assert(tos_offset(right) == 1, "check");
      assert(tos_offset(left) == 0, "check");

      new_left = to_fpu_stack_top(left);
      new_right = to_fpu_stack(right);

      op2->set_fpu_pop_count(1);
      sim()->pop();
      do_rename(right, res);

      new_res = to_fpu_stack_top(res);
      break;
    }

    case lir_abs:
    case lir_sqrt: {
      // Right argument appears to be unused
      assert(right->is_illegal(), "must be");
      assert(left->is_fpu_register(), "must be");
      assert(res->is_fpu_register(), "must be");
      assert(left->is_last_use(), "old value gets destroyed");

      insert_free_if_dead(res, left);
      insert_exchange(left);
      do_rename(left, res);

      new_left = to_fpu_stack_top(res);
      new_res = new_left;

      op2->set_fpu_stack_size(sim()->stack_size());
      break;
    }

    default: {
      assert(false, "missed a fpu-operation");
    }
  }

  op2->set_in_opr1(new_left);
  op2->set_in_opr2(new_right);
  op2->set_result_opr(new_res);
}