/******************************** -*- C -*- **************************** * * Platform-independent layer inline functions (PowerPC) * ***********************************************************************/ /*********************************************************************** * * Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * Written by Paolo Bonzini. * * This file is part of GNU lightning. * * GNU lightning is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * GNU lightning 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with GNU lightning; see the file COPYING.LESSER; if not, write to the * Free Software Foundation, 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * ***********************************************************************/ #ifndef __lightning_funcs_h #define __lightning_funcs_h #if !defined(__GNUC__) && !defined(__GNUG__) #error Go get GNU C, I do not know how to flush the cache #error with this compiler. #else /* Why doesn't this compile?!? * static void * jit_flush_code(start, end) * void *start; * void *end; */ static void jit_flush_code(void* start, void* end) { #ifndef LIGHTNING_CROSS static int cache_line_size, cache_line_shift; register char *ddest, *idest; register int n, dcache_lines, icache_lines; if (cache_line_size == 0) { char buffer[8192]; int i, probe; /* Find out the size of a cache line by zeroing one */ memset(buffer, 0xFF, 8192); __asm__ __volatile__ ("dcbz 0,%0" : : "r"(buffer + 4096)); /* Probe for the beginning of the cache line. */ for(i = 0, probe = 4096; probe; probe >>= 1) if (buffer[i | probe] != 0x00) i |= probe; /* i is now just before the start of the cache line */ i++; for(cache_line_shift = 0, cache_line_size = 1; i + cache_line_size < 8192; cache_line_shift++, cache_line_size <<= 1) if (buffer[i + cache_line_size] != 0x00) break; } n = ((char *) end) - ((char *)start); dcache_lines = icache_lines = (n + cache_line_size - 1) >> cache_line_shift; /* Force data cache write-backs */ for (ddest = start; dcache_lines--; ddest += cache_line_size) { __asm__ __volatile__ ("dcbst 0,%0" : : "r"(ddest)); } __asm__ __volatile__ ("sync" : : ); /* Now invalidate the instruction cache */ for (idest = start; icache_lines--; idest += cache_line_size) { __asm__ __volatile__ ("icbi 0,%0; isync" : : "r"(idest)); } __asm__ __volatile__ ("isync" : : ); #endif } #endif #define _jit (*jit) /* Emit a trampoline for a function. * Upon entrance to the trampoline: * - R0 = return address for the function * - LR = address where the real code for the function lies * - R3-R8 = parameters * After jumping to the address pointed to by R10: * - LR = address where the epilog lies (the function must return there) * - R25-R20 = parameters (order is reversed, 1st argument is R25) */ static jit_insn * _jit_trampoline(jit, n) register jit_state *jit; register int n; { static jit_insn trampolines[200]; static jit_insn *p_trampolines[6], *free = trampolines; register int i, ofs, frame_size; if (!p_trampolines[n]) { _jit.pc = p_trampolines[n] = free; frame_size = 24 + (6 + n) * 4; /* r26..r31 + args */ frame_size += 15; /* the stack must be quad-word */ frame_size &= ~15; /* aligned */ STWUrm(1, -frame_size, 1); /* stwu r1, -x(r1) */ for (ofs = frame_size - (6 + n) * 4, i = 26 - n; i <= 31; ofs += 4, i++) { STWrm(i, ofs, 1); /* stw rI, ofs(r1) */ } STWrm(0, ofs+4, 1); /* stw r0, x(r1) */ for (i = 0; i < n; i++) { MRrr(25-i, 3+i); /* save parameters in r25..r20 */ } BLRL(); /* blrl */ LWZrm(0, ofs+4, 1); /* lwz r0, x(r1) (ret.addr.) */ MTLRr(0); /* mtspr LR, r0 */ for (ofs = frame_size - (6 + n) * 4, i = 26 - n; i <= 31; ofs += 4, i++) { LWZrm(i, ofs, 1); /* lwz rI, ofs(r1) */ } ADDIrri(1, 1, frame_size); /* addi r1, r1, x */ BLR(); /* blr */ jit_flush_code(p_trampolines[n], _jit.pc); free = _jit.pc; } return p_trampolines[n]; } static void _jit_prolog(jit, n) register jit_state *jit; register int n; { register jit_insn *save_pc, *trampo; save_pc = _jit.pc; trampo = _jit_trampoline(jit, n); _jit.pc = save_pc; _jitl.nextarg_get = 25; MFLRr(0); MOVEIri(10, trampo); MTLRr(10); BLRL(); /* blrl */ MFLRr(31); /* mflr r31 */ } #undef _jit #endif /* __lightning_funcs_h */