github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-apply-arm.c (about)

     1  /*
     2   * jit-apply-arm.c - Apply support routines for ARM.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  
    25  #if defined(__arm) || defined(__arm__)
    26  
    27  #include "jit-gen-arm.h"
    28  
    29  void _jit_create_closure(unsigned char *buf, void *func,
    30                           void *closure, void *_type)
    31  {
    32  	arm_inst_buf inst;
    33  
    34  	/* Initialize the instruction buffer */
    35  	arm_inst_buf_init(inst, buf, buf + jit_closure_size);
    36  
    37  	/* Set up the local stack frame */
    38  	arm_setup_frame(inst, 0);
    39  	arm_alu_reg_imm8(inst, ARM_SUB, ARM_SP, ARM_SP, 24);
    40  
    41  	/* Create the apply argument block on the stack */
    42  	arm_store_membase(inst, ARM_R0, ARM_FP, -28);
    43  	arm_store_membase(inst, ARM_R1, ARM_FP, -24);
    44  	arm_store_membase(inst, ARM_R2, ARM_FP, -20);
    45  	arm_store_membase(inst, ARM_R3, ARM_FP, -16);
    46  	arm_alu_reg_imm(inst, ARM_ADD, ARM_R3, ARM_FP, 4);
    47  	arm_store_membase(inst, ARM_R3, ARM_FP, -36);
    48  	arm_store_membase(inst, ARM_R0, ARM_FP, -32);
    49  
    50  	/* Set up the arguments for calling "func" */
    51  	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)closure);
    52  	arm_mov_reg_reg(inst, ARM_R1, ARM_SP);
    53  
    54  	/* Call the closure handling function */
    55  	arm_call(inst, func);
    56  
    57  	/* Pop the current stack frame and return */
    58  	arm_pop_frame(inst, 0);
    59  }
    60  
    61  void *_jit_create_redirector(unsigned char *buf, void *func,
    62  							 void *user_data, int abi)
    63  {
    64  	arm_inst_buf inst;
    65  
    66  	/* Align "buf" on an appropriate boundary */
    67  	if((((jit_nint)buf) % jit_closure_align) != 0)
    68  	{
    69  		buf += jit_closure_align - (((jit_nint)buf) % jit_closure_align);
    70  	}
    71  
    72  	/* Initialize the instruction buffer */
    73  	arm_inst_buf_init(inst, buf, buf + jit_redirector_size);
    74  
    75  	/* Set up the local stack frame, and save R0-R3 */
    76  	arm_setup_frame(inst, 0x000F);
    77  
    78  	/* Set up the arguments for calling "func" */
    79  	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)user_data);
    80  
    81  	/* Call the redirector handling function */
    82  	arm_call(inst, func);
    83  
    84  	/* Shift the result into R12, because we are about to restore R0 */
    85  	arm_mov_reg_reg(inst, ARM_R12, ARM_R0);
    86  
    87  	/* Pop the current stack frame, but don't change PC yet */
    88  	arm_pop_frame_tail(inst, 0x000F);
    89  
    90  	/* Jump to the function that the redirector indicated */
    91  	arm_mov_reg_reg(inst, ARM_PC, ARM_R12);
    92  
    93  	/* Flush the cache lines that we just wrote */
    94  	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
    95  
    96  	/* Return the aligned start of the buffer as the entry point */
    97  	return (void *)buf;
    98  }
    99  
   100  /**
   101   * Creates the indirector, that is the trampoline that permits the Just In Time 
   102   * compilation of a method the first time that it is executed and its direct execution
   103   * the following times
   104   */
   105  void *_jit_create_indirector(unsigned char *buf, void **entry)
   106  {
   107  	arm_inst_buf inst;
   108  	void *start = (void *)buf;
   109  
   110  	/* Initialize the instruction buffer */
   111  	arm_inst_buf_init(inst, buf, buf + jit_indirector_size);
   112  
   113  	//Load the content of memory at address "entry", that is, the entry point of the function
   114  	arm_mov_reg_imm(inst,ARM_WORK,entry);
   115  	arm_mov_reg_membase(inst,ARM_WORK,ARM_WORK,0,4);
   116  	
   117  	/* Jump to the entry point. */
   118  	arm_mov_reg_reg(inst, ARM_PC, ARM_WORK);
   119  
   120  	/* Flush the cache lines that we just wrote */
   121  	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
   122  	
   123  	return start;
   124  }
   125  
   126  void _jit_pad_buffer(unsigned char *buf, int len)
   127  {
   128  	arm_inst_buf inst;
   129  	
   130  	/* Initialize the instruction buffer */
   131  	arm_inst_buf_init(inst, buf, buf + len*4);
   132  	while(len > 0)
   133  	{
   134  		/* Traditional arm NOP */
   135  		arm_nop(inst);
   136  		--len;
   137  	}
   138  	
   139  	/* Flush the cache lines that we just wrote */
   140  	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
   141  }
   142  
   143  #endif /* arm */