1 /*
  2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2019, Arm Limited. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "asm/macroAssembler.hpp"
 27 #include "code/codeBlob.hpp"
 28 #include "memory/resourceArea.hpp"
 29 #include "prims/universalNativeInvoker.hpp"
 30 
 31 #define __ _masm->
 32 
 33 void ProgrammableInvoker::Generator::generate() {
 34   __ enter();
 35 
 36   // Name registers used in the stub code. These are all caller-save so
 37   // may be clobbered by the call to the native function. Avoid using
 38   // rscratch1 here as it's r8 which is the indirect result register in
 39   // the standard ABI.
 40   Register Rctx = r10, Rstack_size = r11;
 41   Register Rwords = r12, Rtmp = r13;
 42   Register Rsrc_ptr = r14, Rdst_ptr = r15;
 43 
 44   assert_different_registers(Rctx, Rstack_size, rscratch1, rscratch2);
 45 
 46   // TODO: if the callee is not using the standard C ABI then we need to
 47   //       preserve more registers here.
 48 
 49   __ block_comment("init_and_alloc_stack");
 50 
 51   __ mov(Rctx, c_rarg0);
 52   __ str(Rctx, Address(__ pre(sp, -2 * wordSize)));
 53 
 54   assert(_abi->_stack_alignment_bytes % 16 == 0, "stack must be 16 byte aligned");
 55 
 56   __ block_comment("allocate_stack");
 57   __ ldr(Rstack_size, Address(Rctx, (int) _layout->stack_args_bytes));
 58   __ add(rscratch2, Rstack_size, _abi->_stack_alignment_bytes - 1);
 59   __ andr(rscratch2, rscratch2, -_abi->_stack_alignment_bytes);
 60   __ sub(sp, sp, rscratch2);
 61 
 62   __ block_comment("load_arguments");
 63 
 64   __ ldr(Rsrc_ptr, Address(Rctx, (int) _layout->stack_args));
 65   __ lsr(Rwords, Rstack_size, LogBytesPerWord);
 66   __ mov(Rdst_ptr, sp);
 67 
 68   Label Ldone, Lnext;
 69   __ bind(Lnext);
 70   __ cbz(Rwords, Ldone);
 71   __ ldr(Rtmp, __ post(Rsrc_ptr, wordSize));
 72   __ str(Rtmp, __ post(Rdst_ptr, wordSize));
 73   __ sub(Rwords, Rwords, 1);
 74   __ b(Lnext);
 75   __ bind(Ldone);
 76 
 77   for (int i = 0; i < _abi->_vector_argument_registers.length(); i++) {
 78     ssize_t offs = _layout->arguments_vector + i * float_reg_size;
 79     __ ldrq(_abi->_vector_argument_registers.at(i), Address(Rctx, offs));
 80   }
 81 
 82   for (int i = 0; i < _abi->_integer_argument_registers.length(); i++) {
 83     ssize_t offs = _layout->arguments_integer + i * sizeof(uintptr_t);
 84     __ ldr(_abi->_integer_argument_registers.at(i), Address(Rctx, offs));
 85   }
 86 
 87   assert(_abi->_shadow_space_bytes == 0, "shadow space not supported on AArch64");
 88 
 89   // call target function
 90   __ block_comment("call target function");
 91   __ ldr(rscratch2, Address(Rctx, (int) _layout->arguments_next_pc));
 92   __ blr(rscratch2);
 93 
 94   __ ldr(Rctx, Address(rfp, -2 * wordSize));   // Might have clobbered Rctx
 95 
 96   __ block_comment("store_registers");
 97 
 98   for (int i = 0; i < _abi->_integer_return_registers.length(); i++) {
 99     ssize_t offs = _layout->returns_integer + i * sizeof(uintptr_t);
100     __ str(_abi->_integer_return_registers.at(i), Address(Rctx, offs));
101   }
102 
103   for (int i = 0; i < _abi->_vector_return_registers.length(); i++) {
104     ssize_t offs = _layout->returns_vector + i * float_reg_size;
105     __ strq(_abi->_vector_return_registers.at(i), Address(Rctx, offs));
106   }
107 
108   __ leave();
109   __ ret(lr);
110 
111   __ flush();
112 }
113 
114 address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) {
115   ResourceMark rm;
116   const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
117   const BufferLayout layout = ForeignGlobals::parse_buffer_layout(jlayout);
118 
119   BufferBlob* _invoke_native_blob = BufferBlob::create("invoke_native_blob", native_invoker_size);
120 
121   CodeBuffer code2(_invoke_native_blob);
122   ProgrammableInvoker::Generator g2(&code2, &abi, &layout);
123   g2.generate();
124   code2.log_section_sizes("InvokeNativeBlob");
125 
126   return _invoke_native_blob->code_begin();
127 }