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