Back to index

plt-scheme  4.2.1
funcs.h
Go to the documentation of this file.
00001 /******************************** -*- C -*- ****************************
00002  *
00003  *     Platform-independent layer inline functions (PowerPC)
00004  *
00005  ***********************************************************************/
00006 
00007 
00008 /***********************************************************************
00009  *
00010  * Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
00011  * Written by Paolo Bonzini.
00012  *
00013  * This file is part of GNU lightning.
00014  *
00015  * GNU lightning is free software; you can redistribute it and/or modify it
00016  * under the terms of the GNU Lesser General Public License as published
00017  * by the Free Software Foundation; either version 2.1, or (at your option)
00018  * any later version.
00019  * 
00020  * GNU lightning is distributed in the hope that it will be useful, but 
00021  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00022  * or  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00023  * License for more details.
00024  * 
00025  * You should have received a copy of the GNU Lesser General Public License
00026  * along with GNU lightning; see the file COPYING.LESSER; if not, write to the
00027  * Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00028  * MA 02111-1307, USA.
00029  *
00030  ***********************************************************************/
00031 
00032 
00033 
00034 #ifndef __lightning_funcs_h
00035 #define __lightning_funcs_h
00036 
00037 static void
00038 jit_notify_freed_code(void)
00039 {
00040 }
00041 
00042 #if !defined(__GNUC__) && !defined(__GNUG__)
00043 #error Go get GNU C, I do not know how to flush the cache
00044 #error with this compiler.
00045 #else
00046 static void
00047 jit_flush_code(void *start, void *end)
00048 {
00049 #ifndef LIGHTNING_CROSS
00050   register char *ddest, *idest;
00051 
00052   static int cache_line_size;
00053   if (cache_line_size == 0) {
00054     char buffer[8192];
00055     int i, probe;
00056 
00057     /* Find out the size of a cache line by zeroing one */
00058     memset(buffer, 0xFF, 8192);
00059     __asm__ __volatile__ ("dcbz 0,%0" : : "r"(buffer + 4096));
00060 
00061     /* Probe for the beginning of the cache line. */
00062     for(i = 0, probe = 4096; probe; probe >>= 1)
00063       if (buffer[i | probe] != 0x00)
00064         i |= probe;
00065 
00066     /* i is now just before the start of the cache line */
00067     i++;
00068     for(cache_line_size = 1; i + cache_line_size < 8192; cache_line_size <<= 1)
00069       if (buffer[i + cache_line_size] != 0x00)
00070         break;
00071   }
00072 
00073   start -= ((long) start) & (cache_line_size - 1);
00074   end -= ((long) end - 1) & (cache_line_size - 1);
00075 
00076   /* Force data cache write-backs */
00077   for (ddest = (char *) start; ddest <= (char *) end; ddest += cache_line_size) {
00078     __asm__ __volatile__ ("dcbst 0,%0" : : "r"(ddest));
00079   }
00080   __asm__ __volatile__ ("sync" : : );
00081 
00082   /* Now invalidate the instruction cache */
00083   for (idest = (char *) start; idest <= (char *) end; idest += cache_line_size) {
00084     __asm__ __volatile__ ("icbi 0,%0" : : "r"(idest));
00085   }
00086   __asm__ __volatile__ ("isync" : : );
00087 #endif /* !LIGHTNING_CROSS */
00088 }
00089 #endif /* __GNUC__ || __GNUG__ */
00090 
00091 #define _jit (*jit)
00092 
00093 static void
00094 _jit_epilog(jit_state *jit)
00095 {
00096   int n = _jitl.nbArgs;
00097   int frame_size, ofs;
00098   int first_saved_reg = JIT_AUX - n;
00099   int num_saved_regs = 32 - first_saved_reg;
00100 
00101   frame_size = 24 + 32 + 12 + num_saved_regs * 4;       /* r24..r31 + args             */
00102   frame_size += 15;                /* the stack must be quad-word     */
00103   frame_size &= ~15;               /* aligned                     */
00104 
00105 #ifdef _CALL_DARWIN
00106   LWZrm(0, frame_size + 8, 1);     /* lwz   r0, x+8(r1)  (ret.addr.)  */
00107 #else
00108   LWZrm(0, frame_size + 4, 1);     /* lwz   r0, x+4(r1)  (ret.addr.)  */
00109 #endif
00110   MTLRr(0);                        /* mtspr LR, r0                       */
00111 
00112   ofs = frame_size - num_saved_regs * 4;
00113   LMWrm(first_saved_reg, ofs, 1);  /* lmw   rI, ofs(r1)           */
00114   ADDIrri(1, 1, frame_size);              /* addi  r1, r1, x             */
00115   BLR();                           /* blr                         */
00116 }
00117 
00118 /* Emit a prolog for a function.
00119    Upon entrance to the trampoline:
00120      - LR      = address where the real code for the function lies
00121      - R3-R8   = parameters
00122    Upon finishing the trampoline:
00123      - R0      = return address for the function
00124      - R25-R20 = parameters (order is reversed, 1st argument is R25)
00125   
00126    The +32 in frame_size computation is to accound for the parameter area of
00127    a function frame. The +12 is to make room for two local variables (a
00128    MzScheme-specific change).
00129 
00130    On PPC the frame must have space to host the arguments of any callee.
00131    However, as it currently stands, the argument to jit_trampoline (n) is
00132    the number of arguments of the caller we generate. Therefore, the
00133    callee can overwrite a part of the stack (saved register area when it
00134    flushes its own parameter on the stack). The addition of a constant 
00135    offset = 32 is enough to hold eight 4 bytes arguments.  This is less
00136    than perfect but is a reasonable work around for now. 
00137    Better solution must be investigated.  */
00138 static void
00139 _jit_prolog(jit_state *jit, int n)
00140 {
00141   int frame_size;
00142   int ofs;
00143   int first_saved_reg = JIT_AUX - n;
00144   int num_saved_regs = 32 - first_saved_reg;
00145 
00146   _jitl.nextarg_geti = 3;
00147   _jitl.nextarg_getd = 1;
00148   _jitl.nbArgs = n;
00149 
00150   frame_size = 24 + 32 + 12 + num_saved_regs * 4;       /* r27..r31 + args             */
00151   frame_size += 15;                /* the stack must be quad-word     */
00152   frame_size &= ~15;               /* aligned                     */
00153 
00154   MFLRr(0);
00155   STWUrm(1, -frame_size, 1);              /* stwu  r1, -x(r1)            */
00156 
00157   ofs = frame_size - num_saved_regs * 4;
00158   STMWrm(first_saved_reg, ofs, 1);        /* stmw  rI, ofs(r1)           */
00159 #ifdef _CALL_DARWIN
00160   STWrm(0, frame_size + 8, 1);            /* stw   r0, x+8(r1)           */
00161 #else
00162   STWrm(0, frame_size + 4, 1);            /* stw   r0, x+4(r1)           */
00163 #endif
00164 
00165 #if 0
00166   for (i = 0; i < n; i++)
00167     MRrr(JIT_AUX-1-i, 3+i);        /* save parameters below r24          */
00168 #endif
00169 }
00170 
00171 #undef _jit
00172 
00173 #endif /* __lightning_funcs_h */