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