Home | History | Annotate | Line # | Download | only in mips
sim-main.c revision 1.1
      1  1.1  christos /*  Copyright (C) 1998, Cygnus Solutions
      2  1.1  christos 
      3  1.1  christos     This program is free software; you can redistribute it and/or modify
      4  1.1  christos     it under the terms of the GNU General Public License as published by
      5  1.1  christos     the Free Software Foundation; either version 2 of the License, or
      6  1.1  christos     (at your option) any later version.
      7  1.1  christos 
      8  1.1  christos     This program is distributed in the hope that it will be useful,
      9  1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  1.1  christos     GNU General Public License for more details.
     12  1.1  christos 
     13  1.1  christos     You should have received a copy of the GNU General Public License
     14  1.1  christos     along with this program; if not, write to the Free Software
     15  1.1  christos     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     16  1.1  christos 
     17  1.1  christos     */
     18  1.1  christos 
     19  1.1  christos 
     20  1.1  christos #ifndef SIM_MAIN_C
     21  1.1  christos #define SIM_MAIN_C
     22  1.1  christos 
     23  1.1  christos #include "sim-main.h"
     24  1.1  christos #include "sim-assert.h"
     25  1.1  christos 
     26  1.1  christos 
     27  1.1  christos /*---------------------------------------------------------------------------*/
     28  1.1  christos /*-- simulator engine -------------------------------------------------------*/
     29  1.1  christos /*---------------------------------------------------------------------------*/
     30  1.1  christos 
     31  1.1  christos 
     32  1.1  christos /* Description from page A-22 of the "MIPS IV Instruction Set" manual
     33  1.1  christos    (revision 3.1) */
     34  1.1  christos /* Translate a virtual address to a physical address and cache
     35  1.1  christos    coherence algorithm describing the mechanism used to resolve the
     36  1.1  christos    memory reference. Given the virtual address vAddr, and whether the
     37  1.1  christos    reference is to Instructions ot Data (IorD), find the corresponding
     38  1.1  christos    physical address (pAddr) and the cache coherence algorithm (CCA)
     39  1.1  christos    used to resolve the reference. If the virtual address is in one of
     40  1.1  christos    the unmapped address spaces the physical address and the CCA are
     41  1.1  christos    determined directly by the virtual address. If the virtual address
     42  1.1  christos    is in one of the mapped address spaces then the TLB is used to
     43  1.1  christos    determine the physical address and access type; if the required
     44  1.1  christos    translation is not present in the TLB or the desired access is not
     45  1.1  christos    permitted the function fails and an exception is taken.
     46  1.1  christos 
     47  1.1  christos    NOTE: Normally (RAW == 0), when address translation fails, this
     48  1.1  christos    function raises an exception and does not return. */
     49  1.1  christos 
     50  1.1  christos INLINE_SIM_MAIN
     51  1.1  christos (int)
     52  1.1  christos address_translation (SIM_DESC sd,
     53  1.1  christos 		     sim_cpu * cpu,
     54  1.1  christos 		     address_word cia,
     55  1.1  christos 		     address_word vAddr,
     56  1.1  christos 		     int IorD,
     57  1.1  christos 		     int LorS,
     58  1.1  christos 		     address_word * pAddr,
     59  1.1  christos 		     int *CCA,
     60  1.1  christos 		     int raw)
     61  1.1  christos {
     62  1.1  christos   int res = -1;			/* TRUE : Assume good return */
     63  1.1  christos 
     64  1.1  christos #ifdef DEBUG
     65  1.1  christos   sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
     66  1.1  christos #endif
     67  1.1  christos 
     68  1.1  christos   /* Check that the address is valid for this memory model */
     69  1.1  christos 
     70  1.1  christos   /* For a simple (flat) memory model, we simply pass virtual
     71  1.1  christos      addressess through (mostly) unchanged. */
     72  1.1  christos   vAddr &= 0xFFFFFFFF;
     73  1.1  christos 
     74  1.1  christos   *pAddr = vAddr;		/* default for isTARGET */
     75  1.1  christos   *CCA = Uncached;		/* not used for isHOST */
     76  1.1  christos 
     77  1.1  christos   return (res);
     78  1.1  christos }
     79  1.1  christos 
     80  1.1  christos 
     81  1.1  christos 
     82  1.1  christos /* Description from page A-23 of the "MIPS IV Instruction Set" manual
     83  1.1  christos    (revision 3.1) */
     84  1.1  christos /* Prefetch data from memory. Prefetch is an advisory instruction for
     85  1.1  christos    which an implementation specific action is taken. The action taken
     86  1.1  christos    may increase performance, but must not change the meaning of the
     87  1.1  christos    program, or alter architecturally-visible state. */
     88  1.1  christos 
     89  1.1  christos INLINE_SIM_MAIN (void)
     90  1.1  christos prefetch (SIM_DESC sd,
     91  1.1  christos 	  sim_cpu *cpu,
     92  1.1  christos 	  address_word cia,
     93  1.1  christos 	  int CCA,
     94  1.1  christos 	  address_word pAddr,
     95  1.1  christos 	  address_word vAddr,
     96  1.1  christos 	  int DATA,
     97  1.1  christos 	  int hint)
     98  1.1  christos {
     99  1.1  christos #ifdef DEBUG
    100  1.1  christos   sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
    101  1.1  christos #endif /* DEBUG */
    102  1.1  christos 
    103  1.1  christos   /* For our simple memory model we do nothing */
    104  1.1  christos   return;
    105  1.1  christos }
    106  1.1  christos 
    107  1.1  christos /* Description from page A-22 of the "MIPS IV Instruction Set" manual
    108  1.1  christos    (revision 3.1) */
    109  1.1  christos /* Load a value from memory. Use the cache and main memory as
    110  1.1  christos    specified in the Cache Coherence Algorithm (CCA) and the sort of
    111  1.1  christos    access (IorD) to find the contents of AccessLength memory bytes
    112  1.1  christos    starting at physical location pAddr. The data is returned in the
    113  1.1  christos    fixed width naturally-aligned memory element (MemElem). The
    114  1.1  christos    low-order two (or three) bits of the address and the AccessLength
    115  1.1  christos    indicate which of the bytes within MemElem needs to be given to the
    116  1.1  christos    processor. If the memory access type of the reference is uncached
    117  1.1  christos    then only the referenced bytes are read from memory and valid
    118  1.1  christos    within the memory element. If the access type is cached, and the
    119  1.1  christos    data is not present in cache, an implementation specific size and
    120  1.1  christos    alignment block of memory is read and loaded into the cache to
    121  1.1  christos    satisfy a load reference. At a minimum, the block is the entire
    122  1.1  christos    memory element. */
    123  1.1  christos INLINE_SIM_MAIN (void)
    124  1.1  christos load_memory (SIM_DESC SD,
    125  1.1  christos 	     sim_cpu *CPU,
    126  1.1  christos 	     address_word cia,
    127  1.1  christos 	     uword64* memvalp,
    128  1.1  christos 	     uword64* memval1p,
    129  1.1  christos 	     int CCA,
    130  1.1  christos 	     unsigned int AccessLength,
    131  1.1  christos 	     address_word pAddr,
    132  1.1  christos 	     address_word vAddr,
    133  1.1  christos 	     int IorD)
    134  1.1  christos {
    135  1.1  christos   uword64 value = 0;
    136  1.1  christos   uword64 value1 = 0;
    137  1.1  christos 
    138  1.1  christos #ifdef DEBUG
    139  1.1  christos   sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"));
    140  1.1  christos #endif /* DEBUG */
    141  1.1  christos 
    142  1.1  christos #if defined(WARN_MEM)
    143  1.1  christos   if (CCA != uncached)
    144  1.1  christos     sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
    145  1.1  christos #endif /* WARN_MEM */
    146  1.1  christos 
    147  1.1  christos   if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
    148  1.1  christos     {
    149  1.1  christos       /* In reality this should be a Bus Error */
    150  1.1  christos       sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
    151  1.1  christos 		    AccessLength,
    152  1.1  christos 		    (LOADDRMASK + 1) << 3,
    153  1.1  christos 		    pr_addr (pAddr));
    154  1.1  christos     }
    155  1.1  christos 
    156  1.1  christos #if defined(TRACE)
    157  1.1  christos   dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
    158  1.1  christos #endif /* TRACE */
    159  1.1  christos 
    160  1.1  christos   /* Read the specified number of bytes from memory.  Adjust for
    161  1.1  christos      host/target byte ordering/ Align the least significant byte
    162  1.1  christos      read. */
    163  1.1  christos 
    164  1.1  christos   switch (AccessLength)
    165  1.1  christos     {
    166  1.1  christos     case AccessLength_QUADWORD:
    167  1.1  christos       {
    168  1.1  christos 	unsigned_16 val = sim_core_read_aligned_16 (CPU, cia, read_map, pAddr);
    169  1.1  christos 	value1 = VH8_16 (val);
    170  1.1  christos 	value = VL8_16 (val);
    171  1.1  christos 	break;
    172  1.1  christos       }
    173  1.1  christos     case AccessLength_DOUBLEWORD:
    174  1.1  christos       value = sim_core_read_aligned_8 (CPU, cia, read_map, pAddr);
    175  1.1  christos       break;
    176  1.1  christos     case AccessLength_SEPTIBYTE:
    177  1.1  christos       value = sim_core_read_misaligned_7 (CPU, cia, read_map, pAddr);
    178  1.1  christos       break;
    179  1.1  christos     case AccessLength_SEXTIBYTE:
    180  1.1  christos       value = sim_core_read_misaligned_6 (CPU, cia, read_map, pAddr);
    181  1.1  christos       break;
    182  1.1  christos     case AccessLength_QUINTIBYTE:
    183  1.1  christos       value = sim_core_read_misaligned_5 (CPU, cia, read_map, pAddr);
    184  1.1  christos       break;
    185  1.1  christos     case AccessLength_WORD:
    186  1.1  christos       value = sim_core_read_aligned_4 (CPU, cia, read_map, pAddr);
    187  1.1  christos       break;
    188  1.1  christos     case AccessLength_TRIPLEBYTE:
    189  1.1  christos       value = sim_core_read_misaligned_3 (CPU, cia, read_map, pAddr);
    190  1.1  christos       break;
    191  1.1  christos     case AccessLength_HALFWORD:
    192  1.1  christos       value = sim_core_read_aligned_2 (CPU, cia, read_map, pAddr);
    193  1.1  christos       break;
    194  1.1  christos     case AccessLength_BYTE:
    195  1.1  christos       value = sim_core_read_aligned_1 (CPU, cia, read_map, pAddr);
    196  1.1  christos       break;
    197  1.1  christos     default:
    198  1.1  christos       abort ();
    199  1.1  christos     }
    200  1.1  christos 
    201  1.1  christos #ifdef DEBUG
    202  1.1  christos   printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
    203  1.1  christos 	 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
    204  1.1  christos #endif /* DEBUG */
    205  1.1  christos 
    206  1.1  christos   /* See also store_memory. Position data in correct byte lanes. */
    207  1.1  christos   if (AccessLength <= LOADDRMASK)
    208  1.1  christos     {
    209  1.1  christos       if (BigEndianMem)
    210  1.1  christos 	/* for big endian target, byte (pAddr&LOADDRMASK == 0) is
    211  1.1  christos 	   shifted to the most significant byte position.  */
    212  1.1  christos 	value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
    213  1.1  christos       else
    214  1.1  christos 	/* For little endian target, byte (pAddr&LOADDRMASK == 0)
    215  1.1  christos 	   is already in the correct postition. */
    216  1.1  christos 	value <<= ((pAddr & LOADDRMASK) * 8);
    217  1.1  christos     }
    218  1.1  christos 
    219  1.1  christos #ifdef DEBUG
    220  1.1  christos   printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
    221  1.1  christos 	 pr_uword64(value1),pr_uword64(value));
    222  1.1  christos #endif /* DEBUG */
    223  1.1  christos 
    224  1.1  christos   *memvalp = value;
    225  1.1  christos   if (memval1p) *memval1p = value1;
    226  1.1  christos }
    227  1.1  christos 
    228  1.1  christos 
    229  1.1  christos /* Description from page A-23 of the "MIPS IV Instruction Set" manual
    230  1.1  christos    (revision 3.1) */
    231  1.1  christos /* Store a value to memory. The specified data is stored into the
    232  1.1  christos    physical location pAddr using the memory hierarchy (data caches and
    233  1.1  christos    main memory) as specified by the Cache Coherence Algorithm
    234  1.1  christos    (CCA). The MemElem contains the data for an aligned, fixed-width
    235  1.1  christos    memory element (word for 32-bit processors, doubleword for 64-bit
    236  1.1  christos    processors), though only the bytes that will actually be stored to
    237  1.1  christos    memory need to be valid. The low-order two (or three) bits of pAddr
    238  1.1  christos    and the AccessLength field indicates which of the bytes within the
    239  1.1  christos    MemElem data should actually be stored; only these bytes in memory
    240  1.1  christos    will be changed. */
    241  1.1  christos 
    242  1.1  christos INLINE_SIM_MAIN (void)
    243  1.1  christos store_memory (SIM_DESC SD,
    244  1.1  christos 	      sim_cpu *CPU,
    245  1.1  christos 	      address_word cia,
    246  1.1  christos 	      int CCA,
    247  1.1  christos 	      unsigned int AccessLength,
    248  1.1  christos 	      uword64 MemElem,
    249  1.1  christos 	      uword64 MemElem1,   /* High order 64 bits */
    250  1.1  christos 	      address_word pAddr,
    251  1.1  christos 	      address_word vAddr)
    252  1.1  christos {
    253  1.1  christos #ifdef DEBUG
    254  1.1  christos   sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr));
    255  1.1  christos #endif /* DEBUG */
    256  1.1  christos 
    257  1.1  christos #if defined(WARN_MEM)
    258  1.1  christos   if (CCA != uncached)
    259  1.1  christos     sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
    260  1.1  christos #endif /* WARN_MEM */
    261  1.1  christos 
    262  1.1  christos   if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
    263  1.1  christos     sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
    264  1.1  christos 		  AccessLength,
    265  1.1  christos 		  (LOADDRMASK + 1) << 3,
    266  1.1  christos 		  pr_addr(pAddr));
    267  1.1  christos 
    268  1.1  christos #if defined(TRACE)
    269  1.1  christos   dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
    270  1.1  christos #endif /* TRACE */
    271  1.1  christos 
    272  1.1  christos #ifdef DEBUG
    273  1.1  christos   printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
    274  1.1  christos #endif /* DEBUG */
    275  1.1  christos 
    276  1.1  christos   /* See also load_memory. Position data in correct byte lanes. */
    277  1.1  christos   if (AccessLength <= LOADDRMASK)
    278  1.1  christos     {
    279  1.1  christos       if (BigEndianMem)
    280  1.1  christos 	/* for big endian target, byte (pAddr&LOADDRMASK == 0) is
    281  1.1  christos 	   shifted to the most significant byte position.  */
    282  1.1  christos 	MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
    283  1.1  christos       else
    284  1.1  christos 	/* For little endian target, byte (pAddr&LOADDRMASK == 0)
    285  1.1  christos 	   is already in the correct postition. */
    286  1.1  christos 	MemElem >>= ((pAddr & LOADDRMASK) * 8);
    287  1.1  christos     }
    288  1.1  christos 
    289  1.1  christos #ifdef DEBUG
    290  1.1  christos   printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
    291  1.1  christos #endif /* DEBUG */
    292  1.1  christos 
    293  1.1  christos   switch (AccessLength)
    294  1.1  christos     {
    295  1.1  christos     case AccessLength_QUADWORD:
    296  1.1  christos       {
    297  1.1  christos 	unsigned_16 val = U16_8 (MemElem1, MemElem);
    298  1.1  christos 	sim_core_write_aligned_16 (CPU, cia, write_map, pAddr, val);
    299  1.1  christos 	break;
    300  1.1  christos       }
    301  1.1  christos     case AccessLength_DOUBLEWORD:
    302  1.1  christos       sim_core_write_aligned_8 (CPU, cia, write_map, pAddr, MemElem);
    303  1.1  christos       break;
    304  1.1  christos     case AccessLength_SEPTIBYTE:
    305  1.1  christos       sim_core_write_misaligned_7 (CPU, cia, write_map, pAddr, MemElem);
    306  1.1  christos       break;
    307  1.1  christos     case AccessLength_SEXTIBYTE:
    308  1.1  christos       sim_core_write_misaligned_6 (CPU, cia, write_map, pAddr, MemElem);
    309  1.1  christos       break;
    310  1.1  christos     case AccessLength_QUINTIBYTE:
    311  1.1  christos       sim_core_write_misaligned_5 (CPU, cia, write_map, pAddr, MemElem);
    312  1.1  christos       break;
    313  1.1  christos     case AccessLength_WORD:
    314  1.1  christos       sim_core_write_aligned_4 (CPU, cia, write_map, pAddr, MemElem);
    315  1.1  christos       break;
    316  1.1  christos     case AccessLength_TRIPLEBYTE:
    317  1.1  christos       sim_core_write_misaligned_3 (CPU, cia, write_map, pAddr, MemElem);
    318  1.1  christos       break;
    319  1.1  christos     case AccessLength_HALFWORD:
    320  1.1  christos       sim_core_write_aligned_2 (CPU, cia, write_map, pAddr, MemElem);
    321  1.1  christos       break;
    322  1.1  christos     case AccessLength_BYTE:
    323  1.1  christos       sim_core_write_aligned_1 (CPU, cia, write_map, pAddr, MemElem);
    324  1.1  christos       break;
    325  1.1  christos     default:
    326  1.1  christos       abort ();
    327  1.1  christos     }
    328  1.1  christos 
    329  1.1  christos   return;
    330  1.1  christos }
    331  1.1  christos 
    332  1.1  christos 
    333  1.1  christos INLINE_SIM_MAIN (unsigned32)
    334  1.1  christos ifetch32 (SIM_DESC SD,
    335  1.1  christos 	  sim_cpu *CPU,
    336  1.1  christos 	  address_word cia,
    337  1.1  christos 	  address_word vaddr)
    338  1.1  christos {
    339  1.1  christos   /* Copy the action of the LW instruction */
    340  1.1  christos   address_word mask = LOADDRMASK;
    341  1.1  christos   address_word access = AccessLength_WORD;
    342  1.1  christos   address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
    343  1.1  christos   address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
    344  1.1  christos   unsigned int byte;
    345  1.1  christos   address_word paddr;
    346  1.1  christos   int uncached;
    347  1.1  christos   unsigned64 memval;
    348  1.1  christos 
    349  1.1  christos   if ((vaddr & access) != 0)
    350  1.1  christos     SignalExceptionInstructionFetch ();
    351  1.1  christos   AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
    352  1.1  christos   paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
    353  1.1  christos   LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
    354  1.1  christos   byte = ((vaddr & mask) ^ bigendiancpu);
    355  1.1  christos   return (memval >> (8 * byte));
    356  1.1  christos }
    357  1.1  christos 
    358  1.1  christos 
    359  1.1  christos INLINE_SIM_MAIN (unsigned16)
    360  1.1  christos ifetch16 (SIM_DESC SD,
    361  1.1  christos 	  sim_cpu *CPU,
    362  1.1  christos 	  address_word cia,
    363  1.1  christos 	  address_word vaddr)
    364  1.1  christos {
    365  1.1  christos   /* Copy the action of the LH instruction */
    366  1.1  christos   address_word mask = LOADDRMASK;
    367  1.1  christos   address_word access = AccessLength_HALFWORD;
    368  1.1  christos   address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
    369  1.1  christos   address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
    370  1.1  christos   unsigned int byte;
    371  1.1  christos   address_word paddr;
    372  1.1  christos   int uncached;
    373  1.1  christos   unsigned64 memval;
    374  1.1  christos 
    375  1.1  christos   if ((vaddr & access) != 0)
    376  1.1  christos     SignalExceptionInstructionFetch ();
    377  1.1  christos   AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
    378  1.1  christos   paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
    379  1.1  christos   LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
    380  1.1  christos   byte = ((vaddr & mask) ^ bigendiancpu);
    381  1.1  christos   return (memval >> (8 * byte));
    382  1.1  christos }
    383  1.1  christos 
    384  1.1  christos 
    385  1.1  christos 
    386  1.1  christos /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
    387  1.1  christos /* Order loads and stores to synchronise shared memory. Perform the
    388  1.1  christos    action necessary to make the effects of groups of synchronizable
    389  1.1  christos    loads and stores indicated by stype occur in the same order for all
    390  1.1  christos    processors. */
    391  1.1  christos INLINE_SIM_MAIN (void)
    392  1.1  christos sync_operation (SIM_DESC sd,
    393  1.1  christos 		sim_cpu *cpu,
    394  1.1  christos 		address_word cia,
    395  1.1  christos 		int stype)
    396  1.1  christos {
    397  1.1  christos #ifdef DEBUG
    398  1.1  christos   sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
    399  1.1  christos #endif /* DEBUG */
    400  1.1  christos   return;
    401  1.1  christos }
    402  1.1  christos 
    403  1.1  christos INLINE_SIM_MAIN (void)
    404  1.1  christos cache_op (SIM_DESC SD,
    405  1.1  christos 	  sim_cpu *CPU,
    406  1.1  christos 	  address_word cia,
    407  1.1  christos 	  int op,
    408  1.1  christos 	  address_word pAddr,
    409  1.1  christos 	  address_word vAddr,
    410  1.1  christos 	  unsigned int instruction)
    411  1.1  christos {
    412  1.1  christos #if 1 /* stop warning message being displayed (we should really just remove the code) */
    413  1.1  christos   static int icache_warning = 1;
    414  1.1  christos   static int dcache_warning = 1;
    415  1.1  christos #else
    416  1.1  christos   static int icache_warning = 0;
    417  1.1  christos   static int dcache_warning = 0;
    418  1.1  christos #endif
    419  1.1  christos 
    420  1.1  christos   /* If CP0 is not useable (User or Supervisor mode) and the CP0
    421  1.1  christos      enable bit in the Status Register is clear - a coprocessor
    422  1.1  christos      unusable exception is taken. */
    423  1.1  christos #if 0
    424  1.1  christos   sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
    425  1.1  christos #endif
    426  1.1  christos 
    427  1.1  christos   switch (op & 0x3) {
    428  1.1  christos     case 0: /* instruction cache */
    429  1.1  christos       switch (op >> 2) {
    430  1.1  christos         case 0: /* Index Invalidate */
    431  1.1  christos         case 1: /* Index Load Tag */
    432  1.1  christos         case 2: /* Index Store Tag */
    433  1.1  christos         case 4: /* Hit Invalidate */
    434  1.1  christos         case 5: /* Fill */
    435  1.1  christos         case 6: /* Hit Writeback */
    436  1.1  christos           if (!icache_warning)
    437  1.1  christos             {
    438  1.1  christos               sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
    439  1.1  christos               icache_warning = 1;
    440  1.1  christos             }
    441  1.1  christos           break;
    442  1.1  christos 
    443  1.1  christos         default:
    444  1.1  christos           SignalException(ReservedInstruction,instruction);
    445  1.1  christos           break;
    446  1.1  christos       }
    447  1.1  christos       break;
    448  1.1  christos 
    449  1.1  christos     case 1: /* data cache */
    450  1.1  christos     case 3: /* secondary data cache */
    451  1.1  christos       switch (op >> 2) {
    452  1.1  christos         case 0: /* Index Writeback Invalidate */
    453  1.1  christos         case 1: /* Index Load Tag */
    454  1.1  christos         case 2: /* Index Store Tag */
    455  1.1  christos         case 3: /* Create Dirty */
    456  1.1  christos         case 4: /* Hit Invalidate */
    457  1.1  christos         case 5: /* Hit Writeback Invalidate */
    458  1.1  christos         case 6: /* Hit Writeback */
    459  1.1  christos           if (!dcache_warning)
    460  1.1  christos             {
    461  1.1  christos               sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
    462  1.1  christos               dcache_warning = 1;
    463  1.1  christos             }
    464  1.1  christos           break;
    465  1.1  christos 
    466  1.1  christos         default:
    467  1.1  christos           SignalException(ReservedInstruction,instruction);
    468  1.1  christos           break;
    469  1.1  christos       }
    470  1.1  christos       break;
    471  1.1  christos 
    472  1.1  christos     default: /* unrecognised cache ID */
    473  1.1  christos       SignalException(ReservedInstruction,instruction);
    474  1.1  christos       break;
    475  1.1  christos   }
    476  1.1  christos 
    477  1.1  christos   return;
    478  1.1  christos }
    479  1.1  christos 
    480  1.1  christos 
    481  1.1  christos INLINE_SIM_MAIN (void)
    482  1.1  christos pending_tick (SIM_DESC SD,
    483  1.1  christos 	      sim_cpu *CPU,
    484  1.1  christos 	      address_word cia)
    485  1.1  christos {
    486  1.1  christos   if (PENDING_TRACE)
    487  1.1  christos     sim_io_eprintf (SD, "PENDING_DRAIN - 0x%lx - pending_in = %d, pending_out = %d, pending_total = %d\n", (unsigned long) cia, PENDING_IN, PENDING_OUT, PENDING_TOTAL);
    488  1.1  christos   if (PENDING_OUT != PENDING_IN)
    489  1.1  christos     {
    490  1.1  christos       int loop;
    491  1.1  christos       int index = PENDING_OUT;
    492  1.1  christos       int total = PENDING_TOTAL;
    493  1.1  christos       if (PENDING_TOTAL == 0)
    494  1.1  christos 	sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
    495  1.1  christos       for (loop = 0, index = PENDING_OUT;
    496  1.1  christos 	   (loop < total);
    497  1.1  christos 	   loop++, index = (index + 1) % PSLOTS)
    498  1.1  christos 	{
    499  1.1  christos 	  if (PENDING_SLOT_DEST[index] != NULL)
    500  1.1  christos 	    {
    501  1.1  christos 	      PENDING_SLOT_DELAY[index] -= 1;
    502  1.1  christos 	      if (PENDING_SLOT_DELAY[index] == 0)
    503  1.1  christos 		{
    504  1.1  christos 		  if (PENDING_TRACE)
    505  1.1  christos 		    sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
    506  1.1  christos 				    index,
    507  1.1  christos 				    (unsigned long) PENDING_SLOT_DEST[index],
    508  1.1  christos 				    PENDING_SLOT_BIT[index],
    509  1.1  christos 				    (unsigned long) PENDING_SLOT_VALUE[index],
    510  1.1  christos 				    PENDING_SLOT_SIZE[index]);
    511  1.1  christos 		  if (PENDING_SLOT_BIT[index] >= 0)
    512  1.1  christos 		    switch (PENDING_SLOT_SIZE[index])
    513  1.1  christos 		      {
    514  1.1  christos 		      case 4:
    515  1.1  christos 			if (PENDING_SLOT_VALUE[index])
    516  1.1  christos 			  *(unsigned32*)PENDING_SLOT_DEST[index] |=
    517  1.1  christos 			    BIT32 (PENDING_SLOT_BIT[index]);
    518  1.1  christos 			else
    519  1.1  christos 			  *(unsigned32*)PENDING_SLOT_DEST[index] &=
    520  1.1  christos 			    BIT32 (PENDING_SLOT_BIT[index]);
    521  1.1  christos 			break;
    522  1.1  christos 		      case 8:
    523  1.1  christos 			if (PENDING_SLOT_VALUE[index])
    524  1.1  christos 			  *(unsigned64*)PENDING_SLOT_DEST[index] |=
    525  1.1  christos 			    BIT64 (PENDING_SLOT_BIT[index]);
    526  1.1  christos 			else
    527  1.1  christos 			  *(unsigned64*)PENDING_SLOT_DEST[index] &=
    528  1.1  christos 			    BIT64 (PENDING_SLOT_BIT[index]);
    529  1.1  christos 			break;
    530  1.1  christos 		      }
    531  1.1  christos 		  else
    532  1.1  christos 		    switch (PENDING_SLOT_SIZE[index])
    533  1.1  christos 		      {
    534  1.1  christos 		      case 4:
    535  1.1  christos 			*(unsigned32*)PENDING_SLOT_DEST[index] =
    536  1.1  christos 			  PENDING_SLOT_VALUE[index];
    537  1.1  christos 			break;
    538  1.1  christos 		      case 8:
    539  1.1  christos 			*(unsigned64*)PENDING_SLOT_DEST[index] =
    540  1.1  christos 			  PENDING_SLOT_VALUE[index];
    541  1.1  christos 			break;
    542  1.1  christos 		      }
    543  1.1  christos 		  if (PENDING_OUT == index)
    544  1.1  christos 		    {
    545  1.1  christos 		      PENDING_SLOT_DEST[index] = NULL;
    546  1.1  christos 		      PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
    547  1.1  christos 		      PENDING_TOTAL--;
    548  1.1  christos 		    }
    549  1.1  christos 		}
    550  1.1  christos 	      else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
    551  1.1  christos 		sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
    552  1.1  christos 				index, PENDING_SLOT_DELAY[index],
    553  1.1  christos 				(unsigned long) PENDING_SLOT_DEST[index],
    554  1.1  christos 				PENDING_SLOT_BIT[index],
    555  1.1  christos 				(unsigned long) PENDING_SLOT_VALUE[index],
    556  1.1  christos 				PENDING_SLOT_SIZE[index]);
    557  1.1  christos 
    558  1.1  christos 	    }
    559  1.1  christos 	}
    560  1.1  christos     }
    561  1.1  christos }
    562  1.1  christos 
    563  1.1  christos 
    564  1.1  christos #endif
    565