annotate src/cpu/x86/vm/templateInterpreterGenerator_x86_32.cpp @ 12320:3f551de87e59

8169711: CDS does not patch entry trampoline if intrinsic method is disabled Summary: Always create interpreter method entries for intrinsified methods but replace them with vanilla entries if the intrinsic is disabled at runtime. Reviewed-by: kvn, iklam
author thartmann
date Mon, 21 Nov 2016 08:27:10 +0100
parents ca56c5db7157
children
rev   line source
duke@0 1 /*
coleenp@9933 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation.
duke@0 8 *
duke@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 13 * accompanied this code).
duke@0 14 *
duke@0 15 * You should have received a copy of the GNU General Public License version
duke@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 18 *
trims@1472 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1472 20 * or visit www.oracle.com if you need additional information or have any
trims@1472 21 * questions.
duke@0 22 *
duke@0 23 */
duke@0 24
stefank@1879 25 #include "precompiled.hpp"
twisti@3883 26 #include "asm/macroAssembler.hpp"
coleenp@9879 27 #include "interpreter/interp_masm.hpp"
stefank@1879 28 #include "interpreter/interpreter.hpp"
coleenp@9933 29 #include "interpreter/interpreterRuntime.hpp"
coleenp@9879 30 #include "interpreter/templateInterpreterGenerator.hpp"
stefank@1879 31 #include "runtime/arguments.hpp"
coleenp@9933 32 #include "runtime/sharedRuntime.hpp"
duke@0 33
duke@0 34 #define __ _masm->
duke@0 35
duke@0 36
coleenp@9933 37 address TemplateInterpreterGenerator::generate_slow_signature_handler() {
coleenp@9933 38 address entry = __ pc();
coleenp@9933 39 // rbx,: method
coleenp@9933 40 // rcx: temporary
coleenp@9933 41 // rdi: pointer to locals
coleenp@9933 42 // rsp: end of copied parameters area
coleenp@9933 43 __ mov(rcx, rsp);
coleenp@9933 44 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, rdi, rcx);
coleenp@9933 45 __ ret(0);
coleenp@9933 46 return entry;
coleenp@9933 47 }
coleenp@9933 48
drchase@4918 49 /**
drchase@4918 50 * Method entry for static native methods:
drchase@4918 51 * int java.util.zip.CRC32.update(int crc, int b)
drchase@4918 52 */
coleenp@9879 53 address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
drchase@4918 54 if (UseCRC32Intrinsics) {
drchase@4918 55 address entry = __ pc();
drchase@4918 56
zmajo@8878 57 // rbx: Method*
drchase@4918 58 // rsi: senderSP must preserved for slow path, set SP to it on fast path
drchase@4918 59 // rdx: scratch
drchase@4918 60 // rdi: scratch
drchase@4918 61
drchase@4918 62 Label slow_path;
drchase@4918 63 // If we need a safepoint check, generate full interpreter entry.
drchase@4918 64 ExternalAddress state(SafepointSynchronize::address_of_state());
drchase@4918 65 __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
drchase@4918 66 SafepointSynchronize::_not_synchronized);
drchase@4918 67 __ jcc(Assembler::notEqual, slow_path);
drchase@4918 68
drchase@4918 69 // We don't generate local frame and don't align stack because
drchase@4918 70 // we call stub code and there is no safepoint on this path.
drchase@4918 71
drchase@4918 72 // Load parameters
drchase@4918 73 const Register crc = rax; // crc
drchase@4918 74 const Register val = rdx; // source java byte value
drchase@4918 75 const Register tbl = rdi; // scratch
drchase@4918 76
drchase@4918 77 // Arguments are reversed on java expression stack
drchase@4918 78 __ movl(val, Address(rsp, wordSize)); // byte value
drchase@4918 79 __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC
drchase@4918 80
drchase@4918 81 __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr()));
drchase@4918 82 __ notl(crc); // ~crc
drchase@4918 83 __ update_byte_crc32(crc, val, tbl);
drchase@4918 84 __ notl(crc); // ~crc
drchase@4918 85 // result in rax
drchase@4918 86
drchase@4918 87 // _areturn
drchase@4918 88 __ pop(rdi); // get return address
drchase@4918 89 __ mov(rsp, rsi); // set sp to sender sp
drchase@4918 90 __ jmp(rdi);
drchase@4918 91
drchase@4918 92 // generate a vanilla native entry as the slow path
drchase@4918 93 __ bind(slow_path);
mdoerr@9019 94 __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
drchase@4918 95 return entry;
drchase@4918 96 }
mdoerr@9019 97 return NULL;
drchase@4918 98 }
drchase@4918 99
drchase@4918 100 /**
drchase@4918 101 * Method entry for static native methods:
drchase@4918 102 * int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
drchase@4918 103 * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
drchase@4918 104 */
coleenp@9879 105 address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
drchase@4918 106 if (UseCRC32Intrinsics) {
drchase@4918 107 address entry = __ pc();
drchase@4918 108
drchase@4918 109 // rbx,: Method*
drchase@4918 110 // rsi: senderSP must preserved for slow path, set SP to it on fast path
drchase@4918 111 // rdx: scratch
drchase@4918 112 // rdi: scratch
drchase@4918 113
drchase@4918 114 Label slow_path;
drchase@4918 115 // If we need a safepoint check, generate full interpreter entry.
drchase@4918 116 ExternalAddress state(SafepointSynchronize::address_of_state());
drchase@4918 117 __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
drchase@4918 118 SafepointSynchronize::_not_synchronized);
drchase@4918 119 __ jcc(Assembler::notEqual, slow_path);
drchase@4918 120
drchase@4918 121 // We don't generate local frame and don't align stack because
drchase@4918 122 // we call stub code and there is no safepoint on this path.
drchase@4918 123
drchase@4918 124 // Load parameters
drchase@4918 125 const Register crc = rax; // crc
drchase@4918 126 const Register buf = rdx; // source java byte array address
drchase@4918 127 const Register len = rdi; // length
drchase@4918 128
kvn@9015 129 // value x86_32
kvn@9015 130 // interp. arg ptr ESP + 4
kvn@9015 131 // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
kvn@9015 132 // 3 2 1 0
kvn@9015 133 // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
kvn@9015 134 // 4 2,3 1 0
kvn@9015 135
drchase@4918 136 // Arguments are reversed on java expression stack
kvn@9015 137 __ movl(len, Address(rsp, 4 + 0)); // Length
drchase@4918 138 // Calculate address of start element
drchase@4918 139 if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) {
kvn@9015 140 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf
kvn@9015 141 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
kvn@9015 142 __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
drchase@4918 143 } else {
kvn@9015 144 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
drchase@4918 145 __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
kvn@9015 146 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
kvn@9015 147 __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
drchase@4918 148 }
drchase@4918 149
drchase@4918 150 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len);
drchase@4918 151 // result in rax
drchase@4918 152
drchase@4918 153 // _areturn
drchase@4918 154 __ pop(rdi); // get return address
drchase@4918 155 __ mov(rsp, rsi); // set sp to sender sp
drchase@4918 156 __ jmp(rdi);
drchase@4918 157
drchase@4918 158 // generate a vanilla native entry as the slow path
drchase@4918 159 __ bind(slow_path);
mdoerr@9019 160 __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
drchase@4918 161 return entry;
drchase@4918 162 }
mdoerr@9019 163 return NULL;
drchase@4918 164 }
drchase@4918 165
zmajo@8878 166 /**
kvn@9015 167 * Method entry for static native methods:
kvn@9015 168 * int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
kvn@9015 169 * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
kvn@9015 170 */
coleenp@9879 171 address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
kvn@9015 172 if (UseCRC32CIntrinsics) {
kvn@9015 173 address entry = __ pc();
kvn@9015 174 // Load parameters
kvn@9015 175 const Register crc = rax; // crc
kvn@9015 176 const Register buf = rcx; // source java byte array address
kvn@9015 177 const Register len = rdx; // length
kvn@9015 178 const Register end = len;
kvn@9015 179
kvn@9015 180 // value x86_32
kvn@9015 181 // interp. arg ptr ESP + 4
kvn@9015 182 // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end)
kvn@9015 183 // 3 2 1 0
kvn@9015 184 // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end)
kvn@9015 185 // 4 2,3 1 0
kvn@9015 186
kvn@9015 187 // Arguments are reversed on java expression stack
kvn@9015 188 __ movl(end, Address(rsp, 4 + 0)); // end
kvn@9015 189 __ subl(len, Address(rsp, 4 + 1 * wordSize)); // end - offset == length
kvn@9015 190 // Calculate address of start element
iveresov@9036 191 if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
kvn@9015 192 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address
kvn@9015 193 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
kvn@9015 194 __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
kvn@9015 195 } else {
kvn@9015 196 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
kvn@9015 197 __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
kvn@9015 198 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
kvn@9015 199 __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
kvn@9015 200 }
kvn@9015 201 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len);
kvn@9015 202 // result in rax
kvn@9015 203 // _areturn
kvn@9015 204 __ pop(rdi); // get return address
kvn@9015 205 __ mov(rsp, rsi); // set sp to sender sp
kvn@9015 206 __ jmp(rdi);
kvn@9015 207
kvn@9015 208 return entry;
kvn@9015 209 }
mdoerr@9019 210 return NULL;
kvn@9015 211 }
kvn@9015 212
kvn@9015 213 /**
zmajo@8878 214 * Method entry for static native method:
zmajo@8878 215 * java.lang.Float.intBitsToFloat(int bits)
zmajo@8878 216 */
coleenp@9879 217 address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() {
zmajo@8878 218 if (UseSSE >= 1) {
mdoerr@9019 219 address entry = __ pc();
zmajo@8878 220
zmajo@8878 221 // rsi: the sender's SP
zmajo@8878 222
zmajo@8878 223 // Skip safepoint check (compiler intrinsic versions of this method
zmajo@8878 224 // do not perform safepoint checks either).
zmajo@8878 225
zmajo@8878 226 // Load 'bits' into xmm0 (interpreter returns results in xmm0)
zmajo@8878 227 __ movflt(xmm0, Address(rsp, wordSize));
zmajo@8878 228
zmajo@8878 229 // Return
zmajo@8878 230 __ pop(rdi); // get return address
zmajo@8878 231 __ mov(rsp, rsi); // set rsp to the sender's SP
zmajo@8878 232 __ jmp(rdi);
mdoerr@9019 233 return entry;
zmajo@8878 234 }
zmajo@8878 235
mdoerr@9019 236 return NULL;
zmajo@8878 237 }
zmajo@8878 238
zmajo@8878 239 /**
zmajo@8878 240 * Method entry for static native method:
zmajo@8878 241 * java.lang.Float.floatToRawIntBits(float value)
zmajo@8878 242 */
coleenp@9879 243 address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
zmajo@8878 244 if (UseSSE >= 1) {
mdoerr@9019 245 address entry = __ pc();
zmajo@8878 246
zmajo@8878 247 // rsi: the sender's SP
zmajo@8878 248
zmajo@8878 249 // Skip safepoint check (compiler intrinsic versions of this method
zmajo@8878 250 // do not perform safepoint checks either).
zmajo@8878 251
zmajo@8878 252 // Load the parameter (a floating-point value) into rax.
zmajo@8878 253 __ movl(rax, Address(rsp, wordSize));
zmajo@8878 254
zmajo@8878 255 // Return
zmajo@8878 256 __ pop(rdi); // get return address
zmajo@8878 257 __ mov(rsp, rsi); // set rsp to the sender's SP
zmajo@8878 258 __ jmp(rdi);
mdoerr@9019 259 return entry;
zmajo@8878 260 }
zmajo@8878 261
mdoerr@9019 262 return NULL;
zmajo@8878 263 }
zmajo@8878 264
zmajo@8878 265
zmajo@8878 266 /**
zmajo@8878 267 * Method entry for static native method:
zmajo@8878 268 * java.lang.Double.longBitsToDouble(long bits)
zmajo@8878 269 */
coleenp@9879 270 address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() {
zmajo@8878 271 if (UseSSE >= 2) {
mdoerr@9019 272 address entry = __ pc();
zmajo@8878 273
zmajo@8878 274 // rsi: the sender's SP
zmajo@8878 275
zmajo@8878 276 // Skip safepoint check (compiler intrinsic versions of this method
zmajo@8878 277 // do not perform safepoint checks either).
zmajo@8878 278
zmajo@8878 279 // Load 'bits' into xmm0 (interpreter returns results in xmm0)
zmajo@8878 280 __ movdbl(xmm0, Address(rsp, wordSize));
zmajo@8878 281
zmajo@8878 282 // Return
zmajo@8878 283 __ pop(rdi); // get return address
zmajo@8878 284 __ mov(rsp, rsi); // set rsp to the sender's SP
zmajo@8878 285 __ jmp(rdi);
mdoerr@9019 286 return entry;
zmajo@8878 287 }
zmajo@8878 288
mdoerr@9019 289 return NULL;
zmajo@8878 290 }
zmajo@8878 291
zmajo@8878 292 /**
zmajo@8878 293 * Method entry for static native method:
zmajo@8878 294 * java.lang.Double.doubleToRawLongBits(double value)
zmajo@8878 295 */
coleenp@9879 296 address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() {
zmajo@8878 297 if (UseSSE >= 2) {
mdoerr@9019 298 address entry = __ pc();
zmajo@8878 299
zmajo@8878 300 // rsi: the sender's SP
zmajo@8878 301
zmajo@8878 302 // Skip safepoint check (compiler intrinsic versions of this method
zmajo@8878 303 // do not perform safepoint checks either).
zmajo@8878 304
zmajo@8878 305 // Load the parameter (a floating-point value) into rax.
zmajo@8878 306 __ movl(rdx, Address(rsp, 2*wordSize));
zmajo@8878 307 __ movl(rax, Address(rsp, wordSize));
zmajo@8878 308
zmajo@8878 309 // Return
zmajo@8878 310 __ pop(rdi); // get return address
zmajo@8878 311 __ mov(rsp, rsi); // set rsp to the sender's SP
zmajo@8878 312 __ jmp(rdi);
mdoerr@9019 313 return entry;
zmajo@8878 314 }
zmajo@8878 315
mdoerr@9019 316 return NULL;
zmajo@8878 317 }
coleenp@9933 318
coleenp@9933 319 address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
coleenp@9933 320
coleenp@9933 321 // rbx,: Method*
coleenp@9933 322 // rcx: scratrch
coleenp@9933 323 // rsi: sender sp
coleenp@9933 324
coleenp@9933 325 if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
coleenp@9933 326
coleenp@9933 327 address entry_point = __ pc();
coleenp@9933 328
coleenp@9933 329 // These don't need a safepoint check because they aren't virtually
coleenp@9933 330 // callable. We won't enter these intrinsics from compiled code.
coleenp@9933 331 // If in the future we added an intrinsic which was virtually callable
coleenp@9933 332 // we'd have to worry about how to safepoint so that this code is used.
coleenp@9933 333
coleenp@9933 334 // mathematical functions inlined by compiler
coleenp@9933 335 // (interpreter must provide identical implementation
coleenp@9933 336 // in order to avoid monotonicity bugs when switching
coleenp@9933 337 // from interpreter to compiler in the middle of some
coleenp@9933 338 // computation)
coleenp@9933 339 //
coleenp@9933 340 // stack: [ ret adr ] <-- rsp
coleenp@9933 341 // [ lo(arg) ]
coleenp@9933 342 // [ hi(arg) ]
coleenp@9933 343 //
vdeshpande@12068 344 if (kind == Interpreter::java_lang_math_fmaD) {
thartmann@12320 345 if (!UseFMA) {
thartmann@12320 346 return NULL; // Generate a vanilla entry
thartmann@12320 347 }
vdeshpande@12068 348 __ movdbl(xmm2, Address(rsp, 5 * wordSize));
vdeshpande@12068 349 __ movdbl(xmm1, Address(rsp, 3 * wordSize));
vdeshpande@12068 350 __ movdbl(xmm0, Address(rsp, 1 * wordSize));
vdeshpande@12068 351 __ fmad(xmm0, xmm1, xmm2, xmm0);
vdeshpande@12068 352 __ pop(rdi); // get return address
vdeshpande@12068 353 __ mov(rsp, rsi); // set sp to sender sp
vdeshpande@12068 354 __ jmp(rdi);
vdeshpande@12068 355
vdeshpande@12068 356 return entry_point;
vdeshpande@12068 357 } else if (kind == Interpreter::java_lang_math_fmaF) {
thartmann@12320 358 if (!UseFMA) {
thartmann@12320 359 return NULL; // Generate a vanilla entry
thartmann@12320 360 }
vdeshpande@12068 361 __ movflt(xmm2, Address(rsp, 3 * wordSize));
vdeshpande@12068 362 __ movflt(xmm1, Address(rsp, 2 * wordSize));
vdeshpande@12068 363 __ movflt(xmm0, Address(rsp, 1 * wordSize));
vdeshpande@12068 364 __ fmaf(xmm0, xmm1, xmm2, xmm0);
vdeshpande@12068 365 __ pop(rdi); // get return address
vdeshpande@12068 366 __ mov(rsp, rsi); // set sp to sender sp
vdeshpande@12068 367 __ jmp(rdi);
vdeshpande@12068 368
vdeshpande@12068 369 return entry_point;
vdeshpande@12068 370 }
coleenp@9933 371
coleenp@9933 372 __ fld_d(Address(rsp, 1*wordSize));
coleenp@9933 373 switch (kind) {
coleenp@9933 374 case Interpreter::java_lang_math_sin :
vdeshpande@10963 375 __ subptr(rsp, 2 * wordSize);
vdeshpande@10963 376 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 377 if (VM_Version::supports_sse2() && StubRoutines::dsin() != NULL) {
vdeshpande@10963 378 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dsin())));
vdeshpande@10963 379 } else {
vdeshpande@11332 380 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
vdeshpande@10963 381 }
vdeshpande@10963 382 __ addptr(rsp, 2 * wordSize);
coleenp@9933 383 break;
coleenp@9933 384 case Interpreter::java_lang_math_cos :
vdeshpande@10963 385 __ subptr(rsp, 2 * wordSize);
vdeshpande@10963 386 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 387 if (VM_Version::supports_sse2() && StubRoutines::dcos() != NULL) {
vdeshpande@10963 388 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcos())));
vdeshpande@10963 389 } else {
vdeshpande@11332 390 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
vdeshpande@10963 391 }
vdeshpande@10963 392 __ addptr(rsp, 2 * wordSize);
coleenp@9933 393 break;
coleenp@9933 394 case Interpreter::java_lang_math_tan :
vdeshpande@10963 395 __ subptr(rsp, 2 * wordSize);
vdeshpande@10963 396 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 397 if (StubRoutines::dtan() != NULL) {
vdeshpande@10963 398 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtan())));
vdeshpande@10963 399 } else {
vdeshpande@11332 400 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
vdeshpande@10963 401 }
vdeshpande@10963 402 __ addptr(rsp, 2 * wordSize);
coleenp@9933 403 break;
coleenp@9933 404 case Interpreter::java_lang_math_sqrt:
coleenp@9933 405 __ fsqrt();
coleenp@9933 406 break;
coleenp@9933 407 case Interpreter::java_lang_math_abs:
coleenp@9933 408 __ fabs();
coleenp@9933 409 break;
coleenp@9933 410 case Interpreter::java_lang_math_log:
coleenp@9933 411 __ subptr(rsp, 2 * wordSize);
coleenp@9933 412 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 413 if (StubRoutines::dlog() != NULL) {
coleenp@9933 414 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
vdeshpande@10963 415 } else {
vdeshpande@11332 416 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog));
coleenp@9933 417 }
coleenp@9933 418 __ addptr(rsp, 2 * wordSize);
coleenp@9933 419 break;
coleenp@9933 420 case Interpreter::java_lang_math_log10:
vdeshpande@10963 421 __ subptr(rsp, 2 * wordSize);
vdeshpande@10963 422 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 423 if (StubRoutines::dlog10() != NULL) {
vdeshpande@10963 424 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog10())));
vdeshpande@10963 425 } else {
vdeshpande@11332 426 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10));
vdeshpande@10963 427 }
vdeshpande@10963 428 __ addptr(rsp, 2 * wordSize);
coleenp@9933 429 break;
coleenp@9933 430 case Interpreter::java_lang_math_pow:
coleenp@9933 431 __ fld_d(Address(rsp, 3*wordSize)); // second argument
jwilhelm@9949 432 __ subptr(rsp, 4 * wordSize);
jwilhelm@9949 433 __ fstp_d(Address(rsp, 0));
jwilhelm@9949 434 __ fstp_d(Address(rsp, 2 * wordSize));
vdeshpande@10963 435 if (StubRoutines::dpow() != NULL) {
jwilhelm@9949 436 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dpow())));
jwilhelm@9949 437 } else {
vdeshpande@11332 438 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dpow));
jwilhelm@9949 439 }
jwilhelm@9949 440 __ addptr(rsp, 4 * wordSize);
coleenp@9933 441 break;
coleenp@9933 442 case Interpreter::java_lang_math_exp:
coleenp@9933 443 __ subptr(rsp, 2*wordSize);
coleenp@9933 444 __ fstp_d(Address(rsp, 0));
vdeshpande@10963 445 if (StubRoutines::dexp() != NULL) {
coleenp@9933 446 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
coleenp@9933 447 } else {
vdeshpande@11332 448 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dexp));
coleenp@9933 449 }
coleenp@9933 450 __ addptr(rsp, 2*wordSize);
coleenp@9933 451 break;
coleenp@9933 452 default :
coleenp@9933 453 ShouldNotReachHere();
coleenp@9933 454 }
coleenp@9933 455
coleenp@9933 456 // return double result in xmm0 for interpreter and compilers.
coleenp@9933 457 if (UseSSE >= 2) {
coleenp@9933 458 __ subptr(rsp, 2*wordSize);
coleenp@9933 459 __ fstp_d(Address(rsp, 0));
coleenp@9933 460 __ movdbl(xmm0, Address(rsp, 0));
coleenp@9933 461 __ addptr(rsp, 2*wordSize);
coleenp@9933 462 }
coleenp@9933 463
coleenp@9933 464 // done, result in FPU ST(0) or XMM0
coleenp@9933 465 __ pop(rdi); // get return address
coleenp@9933 466 __ mov(rsp, rsi); // set sp to sender sp
coleenp@9933 467 __ jmp(rdi);
coleenp@9933 468
coleenp@9933 469 return entry_point;
coleenp@9933 470 }