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