home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / CLISP-2.LHA / CLISP960530-ki.lha / ffcall / trampoline / cache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-15  |  4.5 KB  |  163 lines

  1. /* This file is derived from gcc-2.6.3/libgcc2.c, section L_clear_cache */
  2.  
  3. /* Copyright (C) 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* Clear part of an instruction cache. */
  23.  
  24. /* Our emphasis here is _not_ to clear as few cache lines as possible
  25.  * or with as few machine instructions as possible, but to do it _right_.
  26.  */
  27.  
  28.  
  29.  
  30. /* This code is apparently untested!! */
  31.  
  32. #ifdef __m68k__
  33. #ifdef NeXT
  34. #define CLEAR_INSN_CACHE(BEG, END)   \
  35.    asm volatile ("trap #2")
  36. #endif
  37. #endif
  38.  
  39. /* This is from Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>. */
  40. #ifdef __mips__
  41. #ifdef ultrix
  42. #include <mips/cachectl.h>
  43. #else
  44. #include <sys/cachectl.h>
  45. #endif
  46. #define CLEAR_INSN_CACHE(BEG, END)   \
  47.    cacheflush (BEG, END - BEG, BCACHE)
  48. #endif
  49.  
  50. #ifdef __convex__
  51. #define CLEAR_INSN_CACHE(BEG, END)   \
  52.    asm ("pich")
  53. #endif
  54.  
  55. void
  56. __TR_clear_cache (beg, end)
  57.      char *beg, *end;
  58. {
  59. #ifdef CLEAR_INSN_CACHE 
  60.   CLEAR_INSN_CACHE (beg, end);
  61. #else
  62. #ifdef INSN_CACHE_SIZE /* This is actually dead code!! */
  63. #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
  64.   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
  65.   static int initialized = 0;
  66.   int offset;
  67.   void *start_addr;
  68.   void *end_addr;
  69.   typedef (*function_ptr) ();
  70.  
  71. #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
  72.   /* It's cheaper to clear the whole cache.
  73.      Put in a series of jump instructions so that calling the beginning
  74.      of the cache will clear the whole thing.  */
  75.  
  76.   if (! initialized)
  77.     {
  78.       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
  79.          & -INSN_CACHE_LINE_WIDTH);
  80.       int end_ptr = ptr + INSN_CACHE_SIZE;
  81.  
  82.       while (ptr < end_ptr)
  83.     {
  84.       *(INSTRUCTION_TYPE *)ptr
  85.         = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
  86.       ptr += INSN_CACHE_LINE_WIDTH;
  87.     }
  88.       *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
  89.  
  90.       initialized = 1;
  91.     }
  92.  
  93.   /* Call the beginning of the sequence.  */
  94.   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
  95.             & -INSN_CACHE_LINE_WIDTH))
  96.    ());
  97.  
  98. #else /* Cache is large.  */
  99.  
  100.   if (! initialized)
  101.     {
  102.       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
  103.          & -INSN_CACHE_LINE_WIDTH);
  104.  
  105.       while (ptr < (int) array + sizeof array)
  106.     {
  107.       *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
  108.       ptr += INSN_CACHE_LINE_WIDTH;
  109.     }
  110.  
  111.       initialized = 1;
  112.     }
  113.  
  114.   /* Find the location in array that occupies the same cache line as BEG.  */
  115.  
  116.   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
  117.   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
  118.          & -INSN_CACHE_PLANE_SIZE)
  119.         + offset);
  120.  
  121.   /* Compute the cache alignment of the place to stop clearing.  */
  122. #if 0  /* This is not needed for gcc's purposes.  */
  123.   /* If the block to clear is bigger than a cache plane,
  124.      we clear the entire cache, and OFFSET is already correct.  */ 
  125.   if (end < beg + INSN_CACHE_PLANE_SIZE)
  126. #endif
  127.     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
  128.            & -INSN_CACHE_LINE_WIDTH)
  129.           & (INSN_CACHE_PLANE_SIZE - 1));
  130.  
  131. #if INSN_CACHE_DEPTH > 1
  132.   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
  133.   if (end_addr <= start_addr)
  134.     end_addr += INSN_CACHE_PLANE_SIZE;
  135.  
  136.   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
  137.     {
  138.       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
  139.       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
  140.  
  141.       while (addr != stop)
  142.     {
  143.       /* Call the return instruction at ADDR.  */
  144.       ((function_ptr) addr) ();
  145.  
  146.       addr += INSN_CACHE_LINE_WIDTH;
  147.     }
  148.     }
  149. #else /* just one plane */
  150.   do
  151.     {
  152.       /* Call the return instruction at START_ADDR.  */
  153.       ((function_ptr) start_addr) ();
  154.  
  155.       start_addr += INSN_CACHE_LINE_WIDTH;
  156.     }
  157.   while ((start_addr % INSN_CACHE_SIZE) != offset);
  158. #endif /* just one plane */
  159. #endif /* Cache is large */
  160. #endif /* Cache exists */
  161. #endif /* CLEAR_INSN_CACHE */
  162. }
  163.