1 /*
  2  * Copyright (c) 2020, 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 #include "precompiled.hpp"
 25 #include "asm/macroAssembler.hpp"
 26 #include "code/codeBlob.hpp"
 27 #include "memory/resourceArea.hpp"
 28 #include "prims/universalNativeInvoker.hpp"
 29 
 30 #define __ _masm->
 31 
 32 void ProgrammableInvoker::Generator::generate() {
 33   __ enter();
 34 
 35   // Put the context pointer in ebx/rbx - it's going to be heavily used below both before and after the call
 36   Register ctxt_reg = rbx;
 37   Register used_regs[] = { ctxt_reg, rcx, rsi, rdi };
 38   GrowableArray<Register> preserved_regs;
 39 
 40   for (size_t i = 0; i < sizeof(used_regs)/sizeof(Register); i++) {
 41     Register used_reg = used_regs[i];
 42     if (!_abi->is_volatile_reg(used_reg)) {
 43       preserved_regs.push(used_reg);
 44     }
 45   }
 46 
 47   __ block_comment("init_and_alloc_stack");
 48 
 49   for (int i = 0; i < preserved_regs.length(); i++) {
 50     __ push(preserved_regs.at(i));
 51   }
 52 
 53   __ movptr(ctxt_reg, c_rarg0); // FIXME c args? or java?
 54 
 55   __ block_comment("allocate_stack");
 56   __ movptr(rcx, Address(ctxt_reg, (int) _layout->stack_args_bytes));
 57   __ subptr(rsp, rcx);
 58   __ andptr(rsp, -_abi->_stack_alignment_bytes);
 59 
 60   // Note: rcx is used below!
 61 
 62 
 63   __ block_comment("load_arguments");
 64 
 65   __ shrptr(rcx, LogBytesPerWord); // bytes -> words
 66   __ movptr(rsi, Address(ctxt_reg, (int) _layout->stack_args));
 67   __ movptr(rdi, rsp);
 68   __ rep_mov();
 69 
 70 
 71   for (int i = 0; i < _abi->_vector_argument_registers.length(); i++) {
 72     // [1] -> 64 bit -> xmm
 73     // [2] -> 128 bit -> xmm
 74     // [4] -> 256 bit -> ymm
 75     // [8] -> 512 bit -> zmm
 76 
 77     XMMRegister reg = _abi->_vector_argument_registers.at(i);
 78     size_t offs = _layout->arguments_vector + i * xmm_reg_size;
 79     __ movdqu(reg, Address(ctxt_reg, (int)offs));
 80   }
 81 
 82   for (int i = 0; i < _abi->_integer_argument_registers.length(); i++) {
 83     size_t offs = _layout->arguments_integer + i * sizeof(uintptr_t);
 84     __ movptr(_abi->_integer_argument_registers.at(i), Address(ctxt_reg, (int)offs));
 85   }
 86 
 87   if (_abi->_shadow_space_bytes != 0) {
 88     __ block_comment("allocate shadow space for argument register spill");
 89     __ subptr(rsp, _abi->_shadow_space_bytes);
 90   }
 91 
 92   // call target function
 93   __ block_comment("call target function");
 94   __ call(Address(ctxt_reg, (int) _layout->arguments_next_pc));
 95 
 96   if (_abi->_shadow_space_bytes != 0) {
 97     __ block_comment("pop shadow space");
 98     __ addptr(rsp, _abi->_shadow_space_bytes);
 99   }
100 
101   __ block_comment("store_registers");
102   for (int i = 0; i < _abi->_integer_return_registers.length(); i++) {
103     ssize_t offs = _layout->returns_integer + i * sizeof(uintptr_t);
104     __ movptr(Address(ctxt_reg, offs), _abi->_integer_return_registers.at(i));
105   }
106 
107   for (int i = 0; i < _abi->_vector_return_registers.length(); i++) {
108     // [1] -> 64 bit -> xmm
109     // [2] -> 128 bit -> xmm (SSE)
110     // [4] -> 256 bit -> ymm (AVX)
111     // [8] -> 512 bit -> zmm (AVX-512, aka AVX3)
112 
113     XMMRegister reg = _abi->_vector_return_registers.at(i);
114     size_t offs = _layout->returns_vector + i * xmm_reg_size;
115     __ movdqu(Address(ctxt_reg, (int)offs), reg);
116   }
117 
118   for (size_t i = 0; i < _abi->_X87_return_registers_noof; i++) {
119     size_t offs = _layout->returns_x87 + i * (sizeof(long double));
120     __ fstp_x(Address(ctxt_reg, (int)offs)); //pop ST(0)
121   }
122 
123   // Restore backed up preserved register
124   for (int i = 0; i < preserved_regs.length(); i++) {
125     __ movptr(preserved_regs.at(i), Address(rbp, -(int)(sizeof(uintptr_t) * (i + 1))));
126   }
127 
128   __ leave();
129   __ ret(0);
130 
131   __ flush();
132 }
133 
134 address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) {
135   ResourceMark rm;
136   const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
137   const BufferLayout layout = ForeignGlobals::parse_buffer_layout(jlayout);
138 
139   BufferBlob* _invoke_native_blob = BufferBlob::create("invoke_native_blob", native_invoker_size);
140 
141   CodeBuffer code2(_invoke_native_blob);
142   ProgrammableInvoker::Generator g2(&code2, &abi, &layout);
143   g2.generate();
144   code2.log_section_sizes("InvokeNativeBlob");
145 
146   return _invoke_native_blob->code_begin();
147 }