1 /*
   2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "interpreter/interp_masm.hpp"
  28 #include "interpreter/interpreter.hpp"
  29 #include "interpreter/interpreterRuntime.hpp"
  30 #include "interpreter/templateInterpreterGenerator.hpp"
  31 #include "runtime/arguments.hpp"
  32 #include "runtime/sharedRuntime.hpp"
  33 
  34 #define __ _masm->
  35 
  36 
  37 address TemplateInterpreterGenerator::generate_slow_signature_handler() {
  38   address entry = __ pc();
  39   // rbx,: method
  40   // rcx: temporary
  41   // rdi: pointer to locals
  42   // rsp: end of copied parameters area
  43   __ mov(rcx, rsp);
  44   __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, rdi, rcx);
  45   __ ret(0);
  46   return entry;
  47 }
  48 
  49 /**
  50  * Method entry for static native methods:
  51  *   int java.util.zip.CRC32.update(int crc, int b)
  52  */
  53 address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
  54   if (UseCRC32Intrinsics) {
  55     address entry = __ pc();
  56 
  57     // rbx: Method*
  58     // rsi: senderSP must preserved for slow path, set SP to it on fast path
  59     // rdx: scratch
  60     // rdi: scratch
  61 
  62     Label slow_path;
  63     // If we need a safepoint check, generate full interpreter entry.
  64     ExternalAddress state(SafepointSynchronize::address_of_state());
  65     __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
  66              SafepointSynchronize::_not_synchronized);
  67     __ jcc(Assembler::notEqual, slow_path);
  68 
  69     // We don't generate local frame and don't align stack because
  70     // we call stub code and there is no safepoint on this path.
  71 
  72     // Load parameters
  73     const Register crc = rax;  // crc
  74     const Register val = rdx;  // source java byte value
  75     const Register tbl = rdi;  // scratch
  76 
  77     // Arguments are reversed on java expression stack
  78     __ movl(val, Address(rsp,   wordSize)); // byte value
  79     __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC
  80 
  81     __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr()));
  82     __ notl(crc); // ~crc
  83     __ update_byte_crc32(crc, val, tbl);
  84     __ notl(crc); // ~crc
  85     // result in rax
  86 
  87     // _areturn
  88     __ pop(rdi);                // get return address
  89     __ mov(rsp, rsi);           // set sp to sender sp
  90     __ jmp(rdi);
  91 
  92     // generate a vanilla native entry as the slow path
  93     __ bind(slow_path);
  94     __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
  95     return entry;
  96   }
  97   return NULL;
  98 }
  99 
 100 /**
 101  * Method entry for static native methods:
 102  *   int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
 103  *   int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
 104  */
 105 address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
 106   if (UseCRC32Intrinsics) {
 107     address entry = __ pc();
 108 
 109     // rbx,: Method*
 110     // rsi: senderSP must preserved for slow path, set SP to it on fast path
 111     // rdx: scratch
 112     // rdi: scratch
 113 
 114     Label slow_path;
 115     // If we need a safepoint check, generate full interpreter entry.
 116     ExternalAddress state(SafepointSynchronize::address_of_state());
 117     __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
 118              SafepointSynchronize::_not_synchronized);
 119     __ jcc(Assembler::notEqual, slow_path);
 120 
 121     // We don't generate local frame and don't align stack because
 122     // we call stub code and there is no safepoint on this path.
 123 
 124     // Load parameters
 125     const Register crc = rax;  // crc
 126     const Register buf = rdx;  // source java byte array address
 127     const Register len = rdi;  // length
 128 
 129     // value              x86_32
 130     // interp. arg ptr    ESP + 4
 131     // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
 132     //                                         3           2      1        0
 133     // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
 134     //                                              4         2,3      1        0
 135 
 136     // Arguments are reversed on java expression stack
 137     __ movl(len,   Address(rsp,   4 + 0)); // Length
 138     // Calculate address of start element
 139     if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) {
 140       __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf
 141       __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
 142       __ movl(crc,   Address(rsp, 4 + 4 * wordSize)); // Initial CRC
 143     } else {
 144       __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
 145       __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
 146       __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
 147       __ movl(crc,   Address(rsp, 4 + 3 * wordSize)); // Initial CRC
 148     }
 149 
 150     __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len);
 151     // result in rax
 152 
 153     // _areturn
 154     __ pop(rdi);                // get return address
 155     __ mov(rsp, rsi);           // set sp to sender sp
 156     __ jmp(rdi);
 157 
 158     // generate a vanilla native entry as the slow path
 159     __ bind(slow_path);
 160     __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
 161     return entry;
 162   }
 163   return NULL;
 164 }
 165 
 166 /**
 167 * Method entry for static native methods:
 168 *   int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
 169 *   int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
 170 */
 171 address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
 172   if (UseCRC32CIntrinsics) {
 173     address entry = __ pc();
 174     // Load parameters
 175     const Register crc = rax;  // crc
 176     const Register buf = rcx;  // source java byte array address
 177     const Register len = rdx;  // length
 178     const Register end = len;
 179 
 180     // value              x86_32
 181     // interp. arg ptr    ESP + 4
 182     // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end)
 183     //                                         3           2      1        0
 184     // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end)
 185     //                                              4         2,3          1        0
 186 
 187     // Arguments are reversed on java expression stack
 188     __ movl(end, Address(rsp, 4 + 0)); // end
 189     __ subl(len, Address(rsp, 4 + 1 * wordSize));  // end - offset == length
 190     // Calculate address of start element
 191     if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
 192       __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address
 193       __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
 194       __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
 195     } else {
 196       __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
 197       __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
 198       __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
 199       __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
 200     }
 201     __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len);
 202     // result in rax
 203     // _areturn
 204     __ pop(rdi);                // get return address
 205     __ mov(rsp, rsi);           // set sp to sender sp
 206     __ jmp(rdi);
 207 
 208     return entry;
 209   }
 210   return NULL;
 211 }
 212 
 213 /**
 214  * Method entry for static native method:
 215  *    java.lang.Float.intBitsToFloat(int bits)
 216  */
 217 address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() {
 218   if (UseSSE >= 1) {
 219     address entry = __ pc();
 220 
 221     // rsi: the sender's SP
 222 
 223     // Skip safepoint check (compiler intrinsic versions of this method
 224     // do not perform safepoint checks either).
 225 
 226     // Load 'bits' into xmm0 (interpreter returns results in xmm0)
 227     __ movflt(xmm0, Address(rsp, wordSize));
 228 
 229     // Return
 230     __ pop(rdi); // get return address
 231     __ mov(rsp, rsi); // set rsp to the sender's SP
 232     __ jmp(rdi);
 233     return entry;
 234   }
 235 
 236   return NULL;
 237 }
 238 
 239 /**
 240  * Method entry for static native method:
 241  *    java.lang.Float.floatToRawIntBits(float value)
 242  */
 243 address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
 244   if (UseSSE >= 1) {
 245     address entry = __ pc();
 246 
 247     // rsi: the sender's SP
 248 
 249     // Skip safepoint check (compiler intrinsic versions of this method
 250     // do not perform safepoint checks either).
 251 
 252     // Load the parameter (a floating-point value) into rax.
 253     __ movl(rax, Address(rsp, wordSize));
 254 
 255     // Return
 256     __ pop(rdi); // get return address
 257     __ mov(rsp, rsi); // set rsp to the sender's SP
 258     __ jmp(rdi);
 259     return entry;
 260   }
 261 
 262   return NULL;
 263 }
 264 
 265 
 266 /**
 267  * Method entry for static native method:
 268  *    java.lang.Double.longBitsToDouble(long bits)
 269  */
 270 address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() {
 271    if (UseSSE >= 2) {
 272      address entry = __ pc();
 273 
 274      // rsi: the sender's SP
 275 
 276      // Skip safepoint check (compiler intrinsic versions of this method
 277      // do not perform safepoint checks either).
 278 
 279      // Load 'bits' into xmm0 (interpreter returns results in xmm0)
 280      __ movdbl(xmm0, Address(rsp, wordSize));
 281 
 282      // Return
 283      __ pop(rdi); // get return address
 284      __ mov(rsp, rsi); // set rsp to the sender's SP
 285      __ jmp(rdi);
 286      return entry;
 287    }
 288 
 289    return NULL;
 290 }
 291 
 292 /**
 293  * Method entry for static native method:
 294  *    java.lang.Double.doubleToRawLongBits(double value)
 295  */
 296 address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() {
 297   if (UseSSE >= 2) {
 298     address entry = __ pc();
 299 
 300     // rsi: the sender's SP
 301 
 302     // Skip safepoint check (compiler intrinsic versions of this method
 303     // do not perform safepoint checks either).
 304 
 305     // Load the parameter (a floating-point value) into rax.
 306     __ movl(rdx, Address(rsp, 2*wordSize));
 307     __ movl(rax, Address(rsp, wordSize));
 308 
 309     // Return
 310     __ pop(rdi); // get return address
 311     __ mov(rsp, rsi); // set rsp to the sender's SP
 312     __ jmp(rdi);
 313     return entry;
 314   }
 315 
 316   return NULL;
 317 }
 318 
 319 address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
 320 
 321   // rbx,: Method*
 322   // rcx: scratrch
 323   // rsi: sender sp
 324 
 325   if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
 326 
 327   address entry_point = __ pc();
 328 
 329   // These don't need a safepoint check because they aren't virtually
 330   // callable. We won't enter these intrinsics from compiled code.
 331   // If in the future we added an intrinsic which was virtually callable
 332   // we'd have to worry about how to safepoint so that this code is used.
 333 
 334   // mathematical functions inlined by compiler
 335   // (interpreter must provide identical implementation
 336   // in order to avoid monotonicity bugs when switching
 337   // from interpreter to compiler in the middle of some
 338   // computation)
 339   //
 340   // stack: [ ret adr ] <-- rsp
 341   //        [ lo(arg) ]
 342   //        [ hi(arg) ]
 343   //
 344 
 345   __ fld_d(Address(rsp, 1*wordSize));
 346   switch (kind) {
 347     case Interpreter::java_lang_math_sin :
 348         __ trigfunc('s');







 349         break;
 350     case Interpreter::java_lang_math_cos :
 351         __ trigfunc('c');







 352         break;
 353     case Interpreter::java_lang_math_tan :
 354         __ trigfunc('t');







 355         break;
 356     case Interpreter::java_lang_math_sqrt:
 357         __ fsqrt();
 358         break;
 359     case Interpreter::java_lang_math_abs:
 360         __ fabs();
 361         break;
 362     case Interpreter::java_lang_math_log:
 363         __ subptr(rsp, 2 * wordSize);
 364         __ fstp_d(Address(rsp, 0));
 365         if (VM_Version::supports_sse2()) {
 366           __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
 367         }
 368         else {
 369           __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
 370         }
 371         __ addptr(rsp, 2 * wordSize);
 372         break;
 373     case Interpreter::java_lang_math_log10:
 374         __ flog10();
 375         // Store to stack to convert 80bit precision back to 64bits
 376         __ push_fTOS();
 377         __ pop_fTOS();




 378         break;
 379     case Interpreter::java_lang_math_pow:
 380       __ fld_d(Address(rsp, 3*wordSize)); // second argument
 381       __ subptr(rsp, 4 * wordSize);
 382       __ fstp_d(Address(rsp, 0));
 383       __ fstp_d(Address(rsp, 2 * wordSize));
 384       if (VM_Version::supports_sse2()) {
 385         __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dpow())));
 386       } else {
 387         __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dpow)));
 388       }
 389       __ addptr(rsp, 4 * wordSize);
 390       break;
 391     case Interpreter::java_lang_math_exp:
 392       __ subptr(rsp, 2*wordSize);
 393       __ fstp_d(Address(rsp, 0));
 394       if (VM_Version::supports_sse2()) {
 395         __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
 396       } else {
 397         __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dexp)));
 398       }
 399       __ addptr(rsp, 2*wordSize);
 400     break;
 401     default                              :
 402         ShouldNotReachHere();
 403   }
 404 
 405   // return double result in xmm0 for interpreter and compilers.
 406   if (UseSSE >= 2) {
 407     __ subptr(rsp, 2*wordSize);
 408     __ fstp_d(Address(rsp, 0));
 409     __ movdbl(xmm0, Address(rsp, 0));
 410     __ addptr(rsp, 2*wordSize);
 411   }
 412 
 413   // done, result in FPU ST(0) or XMM0
 414   __ pop(rdi);                               // get return address
 415   __ mov(rsp, rsi);                          // set sp to sender sp
 416   __ jmp(rdi);
 417 
 418   return entry_point;
 419 }
--- EOF ---