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