/* * jit-apply-alpha.c - Apply support routines for alpha. * * Copyright (C) 2006 Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "jit-internal.h" #if defined(__alpha) || defined(__alpha__) #include "jit-gen-alpha.h" void _jit_create_closure(unsigned char *buf, void *func, void *closure, void *_type) { alpha_inst inst = (alpha_inst) buf; /* Compute and load the global pointer */ alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0); alpha_lda( inst,ALPHA_GP,ALPHA_GP,0); /* Allocate space for a new stack frame. */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(13*8)); /* Save the return address. */ alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Save integer register arguments as local variables */ alpha_stq(inst,ALPHA_A0,ALPHA_SP,1*8); alpha_stq(inst,ALPHA_A1,ALPHA_SP,2*8); alpha_stq(inst,ALPHA_A2,ALPHA_SP,3*8); alpha_stq(inst,ALPHA_A3,ALPHA_SP,4*8); alpha_stq(inst,ALPHA_A4,ALPHA_SP,5*8); alpha_stq(inst,ALPHA_A5,ALPHA_SP,6*8); /* Save floating-point register arguments as local variables */ alpha_stt(inst,ALPHA_FA0,ALPHA_SP, 7*8); alpha_stt(inst,ALPHA_FA1,ALPHA_SP, 8*8); alpha_stt(inst,ALPHA_FA2,ALPHA_SP, 9*8); alpha_stt(inst,ALPHA_FA3,ALPHA_SP,10*8); alpha_stt(inst,ALPHA_FA4,ALPHA_SP,11*8); alpha_stt(inst,ALPHA_FA5,ALPHA_SP,12*8); /* Call the closure handling function */ alpha_call(inst,func); /* Restore the return address */ alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Restore integer register arguments */ alpha_ldq(inst,ALPHA_A0,ALPHA_SP,1*8); alpha_ldq(inst,ALPHA_A1,ALPHA_SP,2*8); alpha_ldq(inst,ALPHA_A2,ALPHA_SP,3*8); alpha_ldq(inst,ALPHA_A3,ALPHA_SP,4*8); alpha_ldq(inst,ALPHA_A4,ALPHA_SP,5*8); alpha_ldq(inst,ALPHA_A5,ALPHA_SP,6*8); /* Restore floating-point register arguments */ alpha_ldt(inst,ALPHA_FA0,ALPHA_SP, 7*8); alpha_ldt(inst,ALPHA_FA1,ALPHA_SP, 8*8); alpha_ldt(inst,ALPHA_FA2,ALPHA_SP, 9*8); alpha_ldt(inst,ALPHA_FA3,ALPHA_SP,10*8); alpha_ldt(inst,ALPHA_FA4,ALPHA_SP,11*8); alpha_ldt(inst,ALPHA_FA5,ALPHA_SP,12*8); /* restore the stack pointer */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,(13*8)); } void *_jit_create_redirector(unsigned char *buf, void *func, void *user_data, int abi) { alpha_inst inst = (alpha_inst) buf; /* Allocate space for a new stack frame. (1 instruction) */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(16*8)); /* Save the return address. (1 instruction) */ alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Save the frame pointer. (1 instruction) */ alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8); /* Save the integer save registers (6 instructions) */ alpha_stq(inst,ALPHA_S0,ALPHA_SP,2*8); alpha_stq(inst,ALPHA_S1,ALPHA_SP,3*8); alpha_stq(inst,ALPHA_S2,ALPHA_SP,4*8); alpha_stq(inst,ALPHA_S3,ALPHA_SP,5*8); alpha_stq(inst,ALPHA_S4,ALPHA_SP,6*8); alpha_stq(inst,ALPHA_S5,ALPHA_SP,7*8); /* Save the floating point save registers (8 instructions) */ alpha_stt(inst,ALPHA_FS0,ALPHA_SP, 8*8); alpha_stt(inst,ALPHA_FS1,ALPHA_SP, 9*8); alpha_stt(inst,ALPHA_FS2,ALPHA_SP,10*8); alpha_stt(inst,ALPHA_FS3,ALPHA_SP,11*8); alpha_stt(inst,ALPHA_FS4,ALPHA_SP,12*8); alpha_stt(inst,ALPHA_FS5,ALPHA_SP,13*8); alpha_stt(inst,ALPHA_FS6,ALPHA_SP,14*8); alpha_stt(inst,ALPHA_FS7,ALPHA_SP,15*8); /* Set the frame pointer (1 instruction) */ alpha_mov(inst,ALPHA_SP,ALPHA_FP); /* Force any pending hardware exceptions to be raised. (1 instruction) */ alpha_trapb(inst); /* Compute and load the global pointer */ alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0); alpha_lda( inst,ALPHA_GP,ALPHA_GP,0); /* Allocate space for a new stack frame. */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(13*8)); /* Save the return address. */ alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Save integer register arguments as local variables */ alpha_stq(inst,ALPHA_A0,ALPHA_SP,1*8); alpha_stq(inst,ALPHA_A1,ALPHA_SP,2*8); alpha_stq(inst,ALPHA_A2,ALPHA_SP,3*8); alpha_stq(inst,ALPHA_A3,ALPHA_SP,4*8); alpha_stq(inst,ALPHA_A4,ALPHA_SP,5*8); alpha_stq(inst,ALPHA_A5,ALPHA_SP,6*8); /* Save floating-point register arguments as local variables */ alpha_stt(inst,ALPHA_FA0,ALPHA_SP, 7*8); alpha_stt(inst,ALPHA_FA1,ALPHA_SP, 8*8); alpha_stt(inst,ALPHA_FA2,ALPHA_SP, 9*8); alpha_stt(inst,ALPHA_FA3,ALPHA_SP,10*8); alpha_stt(inst,ALPHA_FA4,ALPHA_SP,11*8); alpha_stt(inst,ALPHA_FA5,ALPHA_SP,12*8); /* Call the redirector handling function */ alpha_call(inst, func); /* Restore the return address */ alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Restore integer register arguments */ alpha_ldq(inst,ALPHA_A0,ALPHA_SP,1*8); alpha_ldq(inst,ALPHA_A1,ALPHA_SP,2*8); alpha_ldq(inst,ALPHA_A2,ALPHA_SP,3*8); alpha_ldq(inst,ALPHA_A3,ALPHA_SP,4*8); alpha_ldq(inst,ALPHA_A4,ALPHA_SP,5*8); alpha_ldq(inst,ALPHA_A5,ALPHA_SP,6*8); /* Restore floating-point register arguments */ alpha_ldt(inst,ALPHA_FA0,ALPHA_SP, 7*8); alpha_ldt(inst,ALPHA_FA1,ALPHA_SP, 8*8); alpha_ldt(inst,ALPHA_FA2,ALPHA_SP, 9*8); alpha_ldt(inst,ALPHA_FA3,ALPHA_SP,10*8); alpha_ldt(inst,ALPHA_FA4,ALPHA_SP,11*8); alpha_ldt(inst,ALPHA_FA5,ALPHA_SP,12*8); /* restore the stack pointer */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,(13*8)); /* Set the stack pointer */ alpha_mov(inst,ALPHA_FP,ALPHA_SP); /* Restore the return address. (1 instruction) */ alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8); /* Restore the frame pointer. (1 instruction) */ alpha_ldq(inst,ALPHA_FP,ALPHA_SP,1*8); /* Restore the integer save registers (6 instructions) */ alpha_ldq(inst,ALPHA_S0,ALPHA_SP,2*8); alpha_ldq(inst,ALPHA_S1,ALPHA_SP,3*8); alpha_ldq(inst,ALPHA_S2,ALPHA_SP,4*8); alpha_ldq(inst,ALPHA_S3,ALPHA_SP,5*8); alpha_ldq(inst,ALPHA_S4,ALPHA_SP,6*8); alpha_ldq(inst,ALPHA_S5,ALPHA_SP,7*8); /* Restore the floating point save registers (8 instructions) */ alpha_ldt(inst,ALPHA_FS0,ALPHA_SP, 8*8); alpha_ldt(inst,ALPHA_FS1,ALPHA_SP, 9*8); alpha_ldt(inst,ALPHA_FS2,ALPHA_SP,10*8); alpha_ldt(inst,ALPHA_FS3,ALPHA_SP,11*8); alpha_ldt(inst,ALPHA_FS4,ALPHA_SP,12*8); alpha_ldt(inst,ALPHA_FS5,ALPHA_SP,13*8); alpha_ldt(inst,ALPHA_FS6,ALPHA_SP,14*8); alpha_ldt(inst,ALPHA_FS7,ALPHA_SP,15*8); /* Restore the stack pointer (1 instruction) */ alpha_lda(inst,ALPHA_SP,ALPHA_SP,16*8); /* Force any pending hardware exceptions to be raised. (1 instruction) */ alpha_trapb(inst); /* Jump to the function that the redirector indicated */ alpha_jsr(inst,ALPHA_RA,ALPHA_V0,1); /* Return the start of the buffer as the redirector entry point */ return (void *)buf; } void _jit_pad_buffer(unsigned char *buf, int len) { alpha_inst inst = (alpha_inst) buf; if (len > 0) { do { alpha_nop(inst); } while (--len); } } #endif /* alpha */