* Makefile.in (tmp-mach-multi): Exit early when igen fails.
[external/binutils.git] / sim / mips / sim-main.c
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