home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cc-61.0.1 / cc / icache.c < prev    next >
C/C++ Source or Header  |  1990-10-08  |  4KB  |  136 lines

  1. /* Clear part of an instruction cache.  */
  2.  
  3. /* Total number of bytes held in instruction cache.  */
  4.  
  5. #define CACHE_SIZE 256
  6.  
  7. /* Number of consecutive bytes that go into the cache together.  */
  8.  
  9. #define CACHE_LINE_WIDTH 16
  10.  
  11. /* Number of cache planes.  This is the number of different locations
  12.    with the same alignment that can be in the cache at once.  */
  13.  
  14. #define CACHE_DEPTH 1
  15.  
  16. /* This is an integer value for a return instruction.  */
  17.  
  18. #define RETURN_INSTRUCTION 0x4e75
  19.  
  20. /* This is an integer value for an instruction to jump a short distance ahead.
  21.    More precisely, this instruction should jump to itself.
  22.    We add an appropriate offset to it when using it.  */
  23.  
  24. #define JUMP_AHEAD_INSTRUCTION (0x6000 - 2)
  25.  
  26. /* This type specifies the size of those instructions.  */
  27.  
  28. #define INSTRUCTION_TYPE short
  29.  
  30.  
  31. #define CACHE_PLANE_SIZE (CACHE_SIZE / CACHE_DEPTH)
  32.  
  33. void
  34. clear_cache (beg, end)
  35.      char *beg, *end;
  36. {
  37.   static char array[CACHE_SIZE + CACHE_PLANE_SIZE + CACHE_LINE_WIDTH];
  38.   static int initialized = 0;
  39.   int offset;
  40.   unsigned int start_addr, end_addr;
  41.   typedef (*function_ptr) ();
  42.  
  43. #if (CACHE_SIZE / CACHE_LINE_WIDTH) < 16
  44.   /* It's cheaper to clear the whole cache.
  45.      Put in a series of jump instructions so that calling the beginning
  46.      of the cache will clear the whole thing.  */
  47.  
  48.   if (! initialized)
  49.     {
  50.       int ptr = (((int) array + CACHE_LINE_WIDTH - 1)
  51.          & -CACHE_LINE_WIDTH);
  52.       int end_ptr = ptr + CACHE_SIZE;
  53.  
  54.       while (ptr < end_ptr)
  55.     {
  56.       *(INSTRUCTION_TYPE *)ptr = JUMP_AHEAD_INSTRUCTION + CACHE_LINE_WIDTH;
  57.       ptr += CACHE_LINE_WIDTH;
  58.     }
  59.       *(INSTRUCTION_TYPE *)(ptr - CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
  60.  
  61.       initialized = 1;
  62.     }
  63.  
  64.   /* Call the beginning of the sequence.  */
  65.   (((function_ptr) (((int) array + CACHE_LINE_WIDTH - 1) & -CACHE_LINE_WIDTH))
  66.    ());
  67.  
  68. #else /* Cache is large.  */
  69.  
  70.   if (! initialized)
  71.     {
  72.       int ptr = (((int) array + CACHE_LINE_WIDTH - 1)
  73.          & -CACHE_LINE_WIDTH);
  74.  
  75.       while (ptr < (int) array + sizeof array)
  76.     {
  77.       *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
  78.       ptr += CACHE_LINE_WIDTH;
  79.     }
  80.  
  81.       initialized = 1;
  82.     }
  83.  
  84.   /* Find the location in array that occupies the same cache line as BEG.  */
  85.  
  86.   offset = ((int) beg & -CACHE_LINE_WIDTH) & (CACHE_PLANE_SIZE - 1);
  87.   start_addr = (((int) (array + CACHE_PLANE_SIZE - 1) & -CACHE_PLANE_SIZE)
  88.         + offset);
  89.  
  90.   /* Compute the cache alignment of the place to stop clearing.
  91.      If the block to clear is bigger than a cache plane,
  92.      we clear the entire cache, and OFFSET is already correct.  */ 
  93. /*   if (end < beg + CACHE_PLANE_SIZE) */
  94.     offset = (((int) (end + CACHE_LINE_WIDTH - 1) & -CACHE_LINE_WIDTH)
  95.           & (CACHE_PLANE_SIZE - 1));
  96.  
  97. #if CACHE_DEPTH > 1
  98.   end_addr = (start_addr & -CACHE_PLANE_SIZE) + offset;
  99.   if (end_addr <= start_addr)
  100.     end_addr += CACHE_PLANE_SIZE;
  101.  
  102.   for (plane = 0; plane < CACHE_DEPTH; plane++)
  103.     {
  104.       int addr = start_addr + plane * CACHE_PLANE_SIZE;
  105.       int stop = end_addr + plane * CACHE_PLANE_SIZE;
  106.  
  107.       while (addr != stop)
  108.     {
  109.       /* Call the return instruction at ADDR.  */
  110.       ((function_ptr) addr) ();
  111.  
  112.       addr += CACHE_LINE_WIDTH;
  113.     }
  114.     }
  115. #else /* just one plane */
  116.   do
  117.     {
  118.       /* Call the return instruction at START_ADDR.  */
  119.       ((function_ptr) start_addr) ();
  120.  
  121.       start_addr += CACHE_LINE_WIDTH;
  122.     }
  123.   while ((start_addr % CACHE_SIZE) != offset);
  124. #endif /* just one plane */
  125. #endif /* Cache is large */
  126. }
  127.  
  128. #ifdef TEST
  129. main (argc, argv)
  130.      int argc;
  131.      char **argv;
  132. {
  133.   clear_cache (atoi (argv[1]), atoi (argv[2]));
  134. }
  135. #endif
  136.