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 */