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