import gdb-2000-02-04 snapshot
[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, NULL_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, NULL_CIA,
175                                        read_map, pAddr);
176       break;
177     case AccessLength_SEPTIBYTE :
178       value = sim_core_read_misaligned_7 (CPU, NULL_CIA,
179                                           read_map, pAddr);
180       break;
181     case AccessLength_SEXTIBYTE :
182       value = sim_core_read_misaligned_6 (CPU, NULL_CIA,
183                                           read_map, pAddr);
184       break;
185     case AccessLength_QUINTIBYTE :
186       value = sim_core_read_misaligned_5 (CPU, NULL_CIA,
187                                           read_map, pAddr);
188       break;
189     case AccessLength_WORD :
190       value = sim_core_read_aligned_4 (CPU, NULL_CIA,
191                                        read_map, pAddr);
192       break;
193     case AccessLength_TRIPLEBYTE :
194       value = sim_core_read_misaligned_3 (CPU, NULL_CIA,
195                                           read_map, pAddr);
196       break;
197     case AccessLength_HALFWORD :
198       value = sim_core_read_aligned_2 (CPU, NULL_CIA,
199                                        read_map, pAddr);
200       break;
201     case AccessLength_BYTE :
202       value = sim_core_read_aligned_1 (CPU, NULL_CIA,
203                                        read_map, pAddr);
204       break;
205     default:
206       abort ();
207     }
208   
209 #ifdef DEBUG
210   printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
211          (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
212 #endif /* DEBUG */
213   
214   /* See also store_memory. Position data in correct byte lanes. */
215   if (AccessLength <= LOADDRMASK)
216     {
217       if (BigEndianMem)
218         /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
219            shifted to the most significant byte position.  */
220         value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
221       else
222         /* For little endian target, byte (pAddr&LOADDRMASK == 0)
223            is already in the correct postition. */
224         value <<= ((pAddr & LOADDRMASK) * 8);
225     }
226   
227 #ifdef DEBUG
228   printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
229          pr_uword64(value1),pr_uword64(value));
230 #endif /* DEBUG */
231   
232   *memvalp = value;
233   if (memval1p) *memval1p = value1;
234 }
235
236
237 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
238    (revision 3.1) */
239 /* Store a value to memory. The specified data is stored into the
240    physical location pAddr using the memory hierarchy (data caches and
241    main memory) as specified by the Cache Coherence Algorithm
242    (CCA). The MemElem contains the data for an aligned, fixed-width
243    memory element (word for 32-bit processors, doubleword for 64-bit
244    processors), though only the bytes that will actually be stored to
245    memory need to be valid. The low-order two (or three) bits of pAddr
246    and the AccessLength field indicates which of the bytes within the
247    MemElem data should actually be stored; only these bytes in memory
248    will be changed. */
249
250 INLINE_SIM_MAIN (void)
251 store_memory (SIM_DESC SD,
252               sim_cpu *CPU,
253               address_word cia,
254               int CCA,
255               unsigned int AccessLength,
256               uword64 MemElem,
257               uword64 MemElem1,   /* High order 64 bits */
258               address_word pAddr,
259               address_word vAddr)
260 {
261 #ifdef DEBUG
262   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));
263 #endif /* DEBUG */
264   
265 #if defined(WARN_MEM)
266   if (CCA != uncached)
267     sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
268 #endif /* WARN_MEM */
269   
270   if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
271     sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
272                   AccessLength,
273                   (LOADDRMASK + 1) << 3,
274                   pr_addr(pAddr));
275   
276 #if defined(TRACE)
277   dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
278 #endif /* TRACE */
279   
280 #ifdef DEBUG
281   printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
282 #endif /* DEBUG */
283   
284   /* See also load_memory. Position data in correct byte lanes. */
285   if (AccessLength <= LOADDRMASK)
286     {
287       if (BigEndianMem)
288         /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
289            shifted to the most significant byte position.  */
290         MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
291       else
292         /* For little endian target, byte (pAddr&LOADDRMASK == 0)
293            is already in the correct postition. */
294         MemElem >>= ((pAddr & LOADDRMASK) * 8);
295     }
296   
297 #ifdef DEBUG
298   printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
299 #endif /* DEBUG */
300   
301   switch (AccessLength)
302     {
303     case AccessLength_QUADWORD :
304       {
305         unsigned_16 val = U16_8 (MemElem1, MemElem);
306         sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val);
307         break;
308       }
309     case AccessLength_DOUBLEWORD :
310       sim_core_write_aligned_8 (CPU, NULL_CIA,
311                                 write_map, pAddr, MemElem);
312       break;
313     case AccessLength_SEPTIBYTE :
314       sim_core_write_misaligned_7 (CPU, NULL_CIA,
315                                    write_map, pAddr, MemElem);
316       break;
317     case AccessLength_SEXTIBYTE :
318       sim_core_write_misaligned_6 (CPU, NULL_CIA,
319                                    write_map, pAddr, MemElem);
320       break;
321     case AccessLength_QUINTIBYTE :
322       sim_core_write_misaligned_5 (CPU, NULL_CIA,
323                                    write_map, pAddr, MemElem);
324       break;
325     case AccessLength_WORD :
326       sim_core_write_aligned_4 (CPU, NULL_CIA,
327                                 write_map, pAddr, MemElem);
328       break;
329     case AccessLength_TRIPLEBYTE :
330       sim_core_write_misaligned_3 (CPU, NULL_CIA,
331                                    write_map, pAddr, MemElem);
332       break;
333     case AccessLength_HALFWORD :
334       sim_core_write_aligned_2 (CPU, NULL_CIA,
335                                 write_map, pAddr, MemElem);
336       break;
337     case AccessLength_BYTE :
338       sim_core_write_aligned_1 (CPU, NULL_CIA,
339                                 write_map, pAddr, MemElem);
340       break;
341     default:
342       abort ();
343     }   
344   
345   return;
346 }
347
348
349 INLINE_SIM_MAIN (unsigned32)
350 ifetch32 (SIM_DESC SD,
351           sim_cpu *CPU,
352           address_word cia,
353           address_word vaddr)
354 {
355   /* Copy the action of the LW instruction */
356   address_word mask = LOADDRMASK;
357   address_word access = AccessLength_WORD;
358   address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
359   address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
360   unsigned int byte;
361   address_word paddr;
362   int uncached;
363   unsigned64 memval;
364
365   if ((vaddr & access) != 0)
366     SignalExceptionInstructionFetch ();
367   AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
368   paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
369   LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
370   byte = ((vaddr & mask) ^ bigendiancpu);
371   return (memval >> (8 * byte));
372 }
373
374
375 INLINE_SIM_MAIN (unsigned16)
376 ifetch16 (SIM_DESC SD,
377           sim_cpu *CPU,
378           address_word cia,
379           address_word vaddr)
380 {
381   /* Copy the action of the LH instruction */
382   address_word mask = LOADDRMASK;
383   address_word access = AccessLength_HALFWORD;
384   address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
385   address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
386   unsigned int byte;
387   address_word paddr;
388   int uncached;
389   unsigned64 memval;
390
391   if ((vaddr & access) != 0)
392     SignalExceptionInstructionFetch ();
393   AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
394   paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
395   LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
396   byte = ((vaddr & mask) ^ bigendiancpu);
397   return (memval >> (8 * byte));
398 }
399
400
401
402 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
403 /* Order loads and stores to synchronise shared memory. Perform the
404    action necessary to make the effects of groups of synchronizable
405    loads and stores indicated by stype occur in the same order for all
406    processors. */
407 INLINE_SIM_MAIN (void)
408 sync_operation (SIM_DESC sd,
409                 sim_cpu *cpu,
410                 address_word cia,
411                 int stype)
412 {
413 #ifdef DEBUG
414   sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
415 #endif /* DEBUG */
416   return;
417 }
418
419 INLINE_SIM_MAIN (void)
420 cache_op (SIM_DESC SD,
421           sim_cpu *CPU,
422           address_word cia,
423           int op,
424           address_word pAddr,
425           address_word vAddr,
426           unsigned int instruction)
427 {
428 #if 1 /* stop warning message being displayed (we should really just remove the code) */
429   static int icache_warning = 1;
430   static int dcache_warning = 1;
431 #else
432   static int icache_warning = 0;
433   static int dcache_warning = 0;
434 #endif
435
436   /* If CP0 is not useable (User or Supervisor mode) and the CP0
437      enable bit in the Status Register is clear - a coprocessor
438      unusable exception is taken. */
439 #if 0
440   sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
441 #endif
442
443   switch (op & 0x3) {
444     case 0: /* instruction cache */
445       switch (op >> 2) {
446         case 0: /* Index Invalidate */
447         case 1: /* Index Load Tag */
448         case 2: /* Index Store Tag */
449         case 4: /* Hit Invalidate */
450         case 5: /* Fill */
451         case 6: /* Hit Writeback */
452           if (!icache_warning)
453             {
454               sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
455               icache_warning = 1;
456             }
457           break;
458
459         default:
460           SignalException(ReservedInstruction,instruction);
461           break;
462       }
463       break;
464
465     case 1: /* data cache */
466     case 3: /* secondary data cache */
467       switch (op >> 2) {
468         case 0: /* Index Writeback Invalidate */
469         case 1: /* Index Load Tag */
470         case 2: /* Index Store Tag */
471         case 3: /* Create Dirty */
472         case 4: /* Hit Invalidate */
473         case 5: /* Hit Writeback Invalidate */
474         case 6: /* Hit Writeback */ 
475           if (!dcache_warning)
476             {
477               sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
478               dcache_warning = 1;
479             }
480           break;
481
482         default:
483           SignalException(ReservedInstruction,instruction);
484           break;
485       }
486       break;
487
488     default: /* unrecognised cache ID */
489       SignalException(ReservedInstruction,instruction);
490       break;
491   }
492
493   return;
494 }
495
496
497 INLINE_SIM_MAIN (void)
498 pending_tick (SIM_DESC SD,
499               sim_cpu *CPU,
500               address_word cia)
501 {
502   if (PENDING_TRACE)                                                    
503     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); 
504   if (PENDING_OUT != PENDING_IN)                                        
505     {                                                                   
506       int loop;                                                 
507       int index = PENDING_OUT;                                  
508       int total = PENDING_TOTAL;                                        
509       if (PENDING_TOTAL == 0)                                           
510         sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n"); 
511       for (loop = 0, index = PENDING_OUT;
512            (loop < total);
513            loop++, index = (index + 1) % PSLOTS)
514         {                                                               
515           if (PENDING_SLOT_DEST[index] != NULL)                 
516             {                                                           
517               PENDING_SLOT_DELAY[index] -= 1;                           
518               if (PENDING_SLOT_DELAY[index] == 0)                       
519                 {                                                       
520                   if (PENDING_TRACE)
521                     sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
522                                     index,
523                                     (unsigned long) PENDING_SLOT_DEST[index],
524                                     PENDING_SLOT_BIT[index],
525                                     (unsigned long) PENDING_SLOT_VALUE[index],
526                                     PENDING_SLOT_SIZE[index]);
527                   if (PENDING_SLOT_BIT[index] >= 0)                     
528                     switch (PENDING_SLOT_SIZE[index])                 
529                       {                                         
530                       case 4:
531                         if (PENDING_SLOT_VALUE[index])          
532                           *(unsigned32*)PENDING_SLOT_DEST[index] |=     
533                             BIT32 (PENDING_SLOT_BIT[index]);            
534                         else                                            
535                           *(unsigned32*)PENDING_SLOT_DEST[index] &=     
536                             BIT32 (PENDING_SLOT_BIT[index]);            
537                         break;                                  
538                       case 8:                                   
539                         if (PENDING_SLOT_VALUE[index])          
540                           *(unsigned64*)PENDING_SLOT_DEST[index] |=     
541                             BIT64 (PENDING_SLOT_BIT[index]);            
542                         else                                            
543                           *(unsigned64*)PENDING_SLOT_DEST[index] &=     
544                             BIT64 (PENDING_SLOT_BIT[index]);            
545                         break;                                  
546                       }
547                   else
548                     switch (PENDING_SLOT_SIZE[index])                 
549                       {                                         
550                       case 4:                                   
551                         *(unsigned32*)PENDING_SLOT_DEST[index] =        
552                           PENDING_SLOT_VALUE[index];                    
553                         break;                                  
554                       case 8:                                   
555                         *(unsigned64*)PENDING_SLOT_DEST[index] =        
556                           PENDING_SLOT_VALUE[index];                    
557                         break;                                  
558                       }                                                 
559                   if (PENDING_OUT == index)
560                     {
561                       PENDING_SLOT_DEST[index] = NULL;
562                       PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
563                       PENDING_TOTAL--;
564                     }
565                 }                                                       
566               else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
567                 sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
568                                 index, PENDING_SLOT_DELAY[index],
569                                 (unsigned long) PENDING_SLOT_DEST[index],
570                                 PENDING_SLOT_BIT[index],
571                                 (unsigned long) PENDING_SLOT_VALUE[index],
572                                 PENDING_SLOT_SIZE[index]);
573
574             }                                                           
575         }                                                               
576     }                                                                   
577 }
578
579
580 #endif