OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [mips/] [sim-main.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.