Ejemplo n.º 1
0
int fetestexcept(int excepts) {
#if defined(__aarch64__)
  // Fetch exception flags.
  return mrs_fpsr() & excepts;
#elif defined(__x86_64__)
  // Combine the x87 and SSE exception flags.
  return (fnstsw() | stmxcsr()) & excepts;
#else
#error "Unsupported platform"
#endif
}
  address generate_call_stub(address& return_address) {
    StubCodeMark mark(this, "StubRoutines", "call_stub");
    address start = __ pc();

    // stub code parameters / addresses
    assert(frame::entry_frame_call_wrapper_offset == 2, "adjust this code");
    bool  sse_save = false;
    const Address esp_after_call(ebp, -4 * wordSize); // same as in generate_catch_exception()!
    const Address mxcsr_save    (ebp, -4 * wordSize);
    const Address result        (ebp,  3 * wordSize);
    const Address result_type   (ebp,  4 * wordSize);
    const Address method        (ebp,  5 * wordSize);
    const Address entry_point   (ebp,  6 * wordSize);
    const Address parameters    (ebp,  7 * wordSize);
    const Address parameter_size(ebp,  8 * wordSize);
    const Address thread        (ebp,  9 * wordSize); // same as in generate_catch_exception()!
#ifdef COMPILER2
    sse_save =  VM_Version::supports_sse();
#endif

    // stub code
    __ enter();    

    // save edi, esi, & ebx, according to C calling conventions
    __ pushl(edi);
    __ pushl(esi);
    __ pushl(ebx);
    __ subl(esp, wordSize);  // space for %mxcsr save
    // save and initialize %mxcsr
    if (sse_save) {
      __ stmxcsr(mxcsr_save);
      __ ldmxcsr(Address((int) StubRoutines::addr_mxcsr_std(), relocInfo::none));
    }

#ifdef ASSERT
    // make sure we have no pending exceptions
    { Label L;
      __ movl(ecx, thread);
      __ cmpl(Address(ecx, Thread::pending_exception_offset()), (int)NULL);
      __ jcc(Assembler::equal, L);
      __ stop("StubRoutines::call_stub: entered with pending exception");
      __ bind(L);
    }
#endif

    // pass parameters if any
    Label parameters_done;
    __ movl(ecx, parameter_size);  // parameter counter
    __ testl(ecx, ecx);
    __ jcc(Assembler::zero, parameters_done);

    // parameter passing loop

    Label loop;
    __ movl(edx, parameters);	       // parameter pointer
    __ movl(esi, ecx);                 // parameter counter is in esi now
    __ movl(ecx,  Address(edx));       // get first parameter in case it is a receiver

    __ bind(loop);
    __ movl(eax, Address(edx));	       // get parameter
    __ addl(edx, wordSize);            // advance to next parameter
    __ decl(esi);                      // decrement counter
    __ pushl(eax);                     // pass parameter
    __ jcc(Assembler::notZero, loop);

    // call Java function
    __ bind(parameters_done);
    __ movl(ebx, method);              // get methodOop
    __ movl(esi, entry_point);         // get entry_point
    __ call(esi, relocInfo::none);
    return_address = __ pc();

    // store result depending on type
    // (everything that is not T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
    __ movl(edi, result);
    Label is_long, is_float, is_double, exit;
    __ movl(esi, result_type);
    __ cmpl(esi, T_LONG);
    __ jcc(Assembler::equal, is_long);
    __ cmpl(esi, T_FLOAT);
    __ jcc(Assembler::equal, is_float);
    __ cmpl(esi, T_DOUBLE);
    __ jcc(Assembler::equal, is_double);

    // handle T_INT case
    __ movl(Address(edi), eax);
    __ bind(exit);

    // pop parameters
    __ movl(ecx, parameter_size);
    __ leal(esp, Address(esp, ecx, Address::times_4));

    // check if parameters have been popped correctly
#ifdef ASSERT
      Label esp_wrong;
      __ leal(edi, esp_after_call);
      __ cmpl(esp, edi);
      __ jcc(Assembler::notEqual, esp_wrong);
#endif

    // restore %mxcsr
    if (sse_save) {
      __ ldmxcsr(mxcsr_save);
    }
    // restore edi & esi
    __ addl(esp, wordSize);  // remove %mxcsr save area
    __ popl(ebx);
    __ popl(esi);
    __ popl(edi);    

    // return
    __ popl(ebp);
    __ ret(0);

    // handle return types different from T_INT
    __ bind(is_long);
    __ movl(Address(edi, 0 * wordSize), eax);
    __ movl(Address(edi, 1 * wordSize), edx);
    __ jmp(exit);

    __ bind(is_float);
    __ fstp_s(Address(edi));
    __ jmp(exit);

    __ bind(is_double);
    __ fstp_d(Address(edi));
    __ jmp(exit);

#ifdef ASSERT
      // stack pointer misadjusted
      __ bind(esp_wrong);
      __ stop("esp wrong after Java call");
#endif

    return start;
  }