void _jit_create_closure(unsigned char *buf, void *func, void *closure, void *_type) { arm_inst_buf inst; /* Initialize the instruction buffer */ arm_inst_buf_init(inst, buf, buf + jit_closure_size); /* Set up the local stack frame */ arm_setup_frame(inst, 0); arm_alu_reg_imm8(inst, ARM_SUB, ARM_SP, ARM_SP, 24); /* Create the apply argument block on the stack */ arm_store_membase(inst, ARM_R0, ARM_FP, -28); arm_store_membase(inst, ARM_R1, ARM_FP, -24); arm_store_membase(inst, ARM_R2, ARM_FP, -20); arm_store_membase(inst, ARM_R3, ARM_FP, -16); arm_alu_reg_imm(inst, ARM_ADD, ARM_R3, ARM_FP, 4); arm_store_membase(inst, ARM_R3, ARM_FP, -36); arm_store_membase(inst, ARM_R0, ARM_FP, -32); /* Set up the arguments for calling "func" */ arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)closure); arm_mov_reg_reg(inst, ARM_R1, ARM_SP); /* Call the closure handling function */ arm_call(inst, func); /* Pop the current stack frame and return */ arm_pop_frame(inst, 0); }
void *_jit_create_redirector(unsigned char *buf, void *func, void *user_data, int abi) { arm_inst_buf inst; /* Align "buf" on an appropriate boundary */ if((((jit_nint)buf) % jit_closure_align) != 0) { buf += jit_closure_align - (((jit_nint)buf) % jit_closure_align); } /* Initialize the instruction buffer */ arm_inst_buf_init(inst, buf, buf + jit_redirector_size); /* Set up the local stack frame, and save R0-R3 */ arm_setup_frame(inst, 0x000F); /* Set up the arguments for calling "func" */ arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)user_data); /* Call the redirector handling function */ arm_call(inst, func); /* Shift the result into R12, because we are about to restore R0 */ arm_mov_reg_reg(inst, ARM_R12, ARM_R0); /* Pop the current stack frame, but don't change PC yet */ arm_pop_frame_tail(inst, 0x000F); /* Jump to the function that the redirector indicated */ arm_mov_reg_reg(inst, ARM_PC, ARM_R12); /* Flush the cache lines that we just wrote */ _jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf); /* Return the aligned start of the buffer as the entry point */ return (void *)buf; }
void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(32); if(flush_if_too_far(gen)) { jit_gen_load_inst_ptr(gen, inst); } /* Output an appropriate instruction to spill the value */ if(value->has_global_register) { arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg); } else { _jit_gen_fix_value(value); offset = (int)(value->frame_offset); if(reg < 16) { arm_store_membase(inst, reg, ARM_FP, offset); if(other_reg != -1) { /* Spill the other word register in a pair */ offset += sizeof(void *); arm_store_membase(inst, other_reg, ARM_FP, offset); } } else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32) { arm_store_membase_float32(inst, reg - 16, ARM_FP, offset); } else { arm_store_membase_float64(inst, reg - 16, ARM_FP, offset); } } /* End the code output process */ jit_cache_end_output(); }
/** * Creates the indirector, that is the trampoline that permits the Just In Time * compilation of a method the first time that it is executed and its direct execution * the following times */ void *_jit_create_indirector(unsigned char *buf, void **entry) { arm_inst_buf inst; void *start = (void *)buf; /* Initialize the instruction buffer */ arm_inst_buf_init(inst, buf, buf + jit_indirector_size); //Load the content of memory at address "entry", that is, the entry point of the function arm_mov_reg_imm(inst,ARM_WORK,entry); arm_mov_reg_membase(inst,ARM_WORK,ARM_WORK,0,4); /* Jump to the entry point. */ arm_mov_reg_reg(inst, ARM_PC, ARM_WORK); /* Flush the cache lines that we just wrote */ _jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf); return start; }