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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [frv/] [memory.c] - Blame information for rev 866

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* frv memory model.
2
   Copyright (C) 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Red Hat
5
 
6
This file is part of the GNU simulators.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#define WANT_CPU frvbf
22
#define WANT_CPU_FRVBF
23
 
24
#include "sim-main.h"
25
#include "cgen-mem.h"
26
#include "bfd.h"
27
 
28
/* Check for alignment and access restrictions.  Return the corrected address.
29
 */
30
static SI
31
fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
32
{
33
  /* Check access restrictions for double word loads only.  */
34
  if (align_mask == 7)
35
    {
36
      if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
37
        frv_queue_data_access_error_interrupt (current_cpu, address);
38
    }
39
  return address;
40
}
41
 
42
static SI
43
fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
44
{
45
  if (address & align_mask)
46
    {
47
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
48
      address &= ~align_mask;
49
    }
50
 
51
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
52
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
53
    frv_queue_data_access_error_interrupt (current_cpu, address);
54
 
55
  return address;
56
}
57
 
58
static SI
59
fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
60
{
61
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
62
      || (align_mask > 0x3
63
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
64
    frv_queue_data_access_error_interrupt (current_cpu, address);
65
 
66
  return address;
67
}
68
 
69
static SI
70
check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
71
{
72
  SIM_DESC sd = CPU_STATE (current_cpu);
73
  switch (STATE_ARCHITECTURE (sd)->mach)
74
    {
75
    case bfd_mach_fr400:
76
    case bfd_mach_fr450:
77
      address = fr400_check_data_read_address (current_cpu, address,
78
                                               align_mask);
79
      break;
80
    case bfd_mach_frvtomcat:
81
    case bfd_mach_fr500:
82
    case bfd_mach_frv:
83
      address = fr500_check_data_read_address (current_cpu, address,
84
                                               align_mask);
85
      break;
86
    case bfd_mach_fr550:
87
      address = fr550_check_data_read_address (current_cpu, address,
88
                                               align_mask);
89
      break;
90
    default:
91
      break;
92
    }
93
 
94
  return address;
95
}
96
 
97
static SI
98
fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
99
{
100
  if (address & align_mask)
101
    {
102
      /* Make sure that this exception is not masked.  */
103
      USI isr = GET_ISR ();
104
      if (! GET_ISR_EMAM (isr))
105
        {
106
          /* Bad alignment causes a data_access_error on fr400.  */
107
          frv_queue_data_access_error_interrupt (current_cpu, address);
108
        }
109
      address &= ~align_mask;
110
    }
111
  /* Nothing to check.  */
112
  return address;
113
}
114
 
115
static SI
116
fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
117
{
118
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff
119
      || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
120
      || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
121
      || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
122
    frv_queue_data_access_exception_interrupt (current_cpu);
123
 
124
  return address;
125
}
126
 
127
static SI
128
fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
129
{
130
  /* No alignment restrictions on fr550 */
131
 
132
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
133
      || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
134
    frv_queue_data_access_exception_interrupt (current_cpu);
135
  else
136
    {
137
      USI hsr0 = GET_HSR0 ();
138
      if (! GET_HSR0_RME (hsr0)
139
          && (USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff)
140
        frv_queue_data_access_exception_interrupt (current_cpu);
141
    }
142
 
143
  return address;
144
}
145
 
146
static SI
147
check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
148
{
149
  SIM_DESC sd = CPU_STATE (current_cpu);
150
  switch (STATE_ARCHITECTURE (sd)->mach)
151
    {
152
    case bfd_mach_fr400:
153
    case bfd_mach_fr450:
154
      address = fr400_check_readwrite_address (current_cpu, address,
155
                                                    align_mask);
156
      break;
157
    case bfd_mach_frvtomcat:
158
    case bfd_mach_fr500:
159
    case bfd_mach_frv:
160
      address = fr500_check_readwrite_address (current_cpu, address,
161
                                                    align_mask);
162
      break;
163
    case bfd_mach_fr550:
164
      address = fr550_check_readwrite_address (current_cpu, address,
165
                                               align_mask);
166
      break;
167
    default:
168
      break;
169
    }
170
 
171
  return address;
172
}
173
 
174
static PCADDR
175
fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
176
                               int align_mask)
177
{
178
  if (address & align_mask)
179
    {
180
      frv_queue_instruction_access_error_interrupt (current_cpu);
181
      address &= ~align_mask;
182
    }
183
  else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
184
    frv_queue_instruction_access_error_interrupt (current_cpu);
185
 
186
  return address;
187
}
188
 
189
static PCADDR
190
fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
191
                               int align_mask)
192
{
193
  if (address & align_mask)
194
    {
195
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
196
      address &= ~align_mask;
197
    }
198
 
199
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
200
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
201
    frv_queue_instruction_access_error_interrupt (current_cpu);
202
  else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
203
           || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
204
           || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
205
    frv_queue_instruction_access_exception_interrupt (current_cpu);
206
  else
207
    {
208
      USI hsr0 = GET_HSR0 ();
209
      if (! GET_HSR0_RME (hsr0)
210
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
211
        frv_queue_instruction_access_exception_interrupt (current_cpu);
212
    }
213
 
214
  return address;
215
}
216
 
217
static PCADDR
218
fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
219
                               int align_mask)
220
{
221
  address &= ~align_mask;
222
 
223
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
224
    frv_queue_instruction_access_error_interrupt (current_cpu);
225
  else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff)
226
    frv_queue_instruction_access_exception_interrupt (current_cpu);
227
  else
228
    {
229
      USI hsr0 = GET_HSR0 ();
230
      if (! GET_HSR0_RME (hsr0)
231
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff)
232
        frv_queue_instruction_access_exception_interrupt (current_cpu);
233
    }
234
 
235
  return address;
236
}
237
 
238
static PCADDR
239
check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
240
{
241
  SIM_DESC sd = CPU_STATE (current_cpu);
242
  switch (STATE_ARCHITECTURE (sd)->mach)
243
    {
244
    case bfd_mach_fr400:
245
    case bfd_mach_fr450:
246
      address = fr400_check_insn_read_address (current_cpu, address,
247
                                               align_mask);
248
      break;
249
    case bfd_mach_frvtomcat:
250
    case bfd_mach_fr500:
251
    case bfd_mach_frv:
252
      address = fr500_check_insn_read_address (current_cpu, address,
253
                                               align_mask);
254
      break;
255
    case bfd_mach_fr550:
256
      address = fr550_check_insn_read_address (current_cpu, address,
257
                                               align_mask);
258
      break;
259
    default:
260
      break;
261
    }
262
 
263
  return address;
264
}
265
 
266
/* Memory reads.  */
267
QI
268
frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
269
{
270
  USI hsr0 = GET_HSR0 ();
271
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
272
 
273
  /* Check for access exceptions.  */
274
  address = check_data_read_address (current_cpu, address, 0);
275
  address = check_readwrite_address (current_cpu, address, 0);
276
 
277
  /* If we need to count cycles, then the cache operation will be
278
     initiated from the model profiling functions.
279
     See frvbf_model_....  */
280
  if (model_insn)
281
    {
282
      CPU_LOAD_ADDRESS (current_cpu) = address;
283
      CPU_LOAD_LENGTH (current_cpu) = 1;
284
      CPU_LOAD_SIGNED (current_cpu) = 1;
285
      return 0xb7; /* any random value */
286
    }
287
 
288
  if (GET_HSR0_DCE (hsr0))
289
    {
290
      int cycles;
291
      cycles = frv_cache_read (cache, 0, address);
292
      if (cycles != 0)
293
        return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
294
    }
295
 
296
  return GETMEMQI (current_cpu, pc, address);
297
}
298
 
299
UQI
300
frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
301
{
302
  USI hsr0 = GET_HSR0 ();
303
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
304
 
305
  /* Check for access exceptions.  */
306
  address = check_data_read_address (current_cpu, address, 0);
307
  address = check_readwrite_address (current_cpu, address, 0);
308
 
309
  /* If we need to count cycles, then the cache operation will be
310
     initiated from the model profiling functions.
311
     See frvbf_model_....  */
312
  if (model_insn)
313
    {
314
      CPU_LOAD_ADDRESS (current_cpu) = address;
315
      CPU_LOAD_LENGTH (current_cpu) = 1;
316
      CPU_LOAD_SIGNED (current_cpu) = 0;
317
      return 0xb7; /* any random value */
318
    }
319
 
320
  if (GET_HSR0_DCE (hsr0))
321
    {
322
      int cycles;
323
      cycles = frv_cache_read (cache, 0, address);
324
      if (cycles != 0)
325
        return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
326
    }
327
 
328
  return GETMEMUQI (current_cpu, pc, address);
329
}
330
 
331
/* Read a HI which spans two cache lines */
332
static HI
333
read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
334
{
335
  HI value = frvbf_read_mem_QI (current_cpu, pc, address);
336
  value <<= 8;
337
  value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
338
  return T2H_2 (value);
339
}
340
 
341
HI
342
frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
343
{
344
  USI hsr0;
345
  FRV_CACHE *cache;
346
 
347
  /* Check for access exceptions.  */
348
  address = check_data_read_address (current_cpu, address, 1);
349
  address = check_readwrite_address (current_cpu, address, 1);
350
 
351
  /* If we need to count cycles, then the cache operation will be
352
     initiated from the model profiling functions.
353
     See frvbf_model_....  */
354
  hsr0 = GET_HSR0 ();
355
  cache = CPU_DATA_CACHE (current_cpu);
356
  if (model_insn)
357
    {
358
      CPU_LOAD_ADDRESS (current_cpu) = address;
359
      CPU_LOAD_LENGTH (current_cpu) = 2;
360
      CPU_LOAD_SIGNED (current_cpu) = 1;
361
      return 0xb711; /* any random value */
362
    }
363
 
364
  if (GET_HSR0_DCE (hsr0))
365
    {
366
      int cycles;
367
      /* Handle access which crosses cache line boundary */
368
      SIM_DESC sd = CPU_STATE (current_cpu);
369
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
370
        {
371
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
372
            return read_mem_unaligned_HI (current_cpu, pc, address);
373
        }
374
      cycles = frv_cache_read (cache, 0, address);
375
      if (cycles != 0)
376
        return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
377
    }
378
 
379
  return GETMEMHI (current_cpu, pc, address);
380
}
381
 
382
UHI
383
frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
384
{
385
  USI hsr0;
386
  FRV_CACHE *cache;
387
 
388
  /* Check for access exceptions.  */
389
  address = check_data_read_address (current_cpu, address, 1);
390
  address = check_readwrite_address (current_cpu, address, 1);
391
 
392
  /* If we need to count cycles, then the cache operation will be
393
     initiated from the model profiling functions.
394
     See frvbf_model_....  */
395
  hsr0 = GET_HSR0 ();
396
  cache = CPU_DATA_CACHE (current_cpu);
397
  if (model_insn)
398
    {
399
      CPU_LOAD_ADDRESS (current_cpu) = address;
400
      CPU_LOAD_LENGTH (current_cpu) = 2;
401
      CPU_LOAD_SIGNED (current_cpu) = 0;
402
      return 0xb711; /* any random value */
403
    }
404
 
405
  if (GET_HSR0_DCE (hsr0))
406
    {
407
      int cycles;
408
      /* Handle access which crosses cache line boundary */
409
      SIM_DESC sd = CPU_STATE (current_cpu);
410
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
411
        {
412
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
413
            return read_mem_unaligned_HI (current_cpu, pc, address);
414
        }
415
      cycles = frv_cache_read (cache, 0, address);
416
      if (cycles != 0)
417
        return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
418
    }
419
 
420
  return GETMEMUHI (current_cpu, pc, address);
421
}
422
 
423
/* Read a SI which spans two cache lines */
424
static SI
425
read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
426
{
427
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
428
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
429
  char valarray[4];
430
  SI SIvalue;
431
  HI HIvalue;
432
 
433
  switch (hi_len)
434
    {
435
    case 1:
436
      valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address);
437
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1);
438
      SIvalue = H2T_4 (SIvalue);
439
      memcpy (valarray + 1, (char*)&SIvalue, 3);
440
      break;
441
    case 2:
442
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address);
443
      HIvalue = H2T_2 (HIvalue);
444
      memcpy (valarray, (char*)&HIvalue, 2);
445
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2);
446
      HIvalue = H2T_2 (HIvalue);
447
      memcpy (valarray + 2, (char*)&HIvalue, 2);
448
      break;
449
    case 3:
450
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1);
451
      SIvalue = H2T_4 (SIvalue);
452
      memcpy (valarray, (char*)&SIvalue, 3);
453
      valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3);
454
      break;
455
    default:
456
      abort (); /* can't happen */
457
    }
458
  return T2H_4 (*(SI*)valarray);
459
}
460
 
461
SI
462
frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
463
{
464
  FRV_CACHE *cache;
465
  USI hsr0;
466
 
467
  /* Check for access exceptions.  */
468
  address = check_data_read_address (current_cpu, address, 3);
469
  address = check_readwrite_address (current_cpu, address, 3);
470
 
471
  hsr0 = GET_HSR0 ();
472
  cache = CPU_DATA_CACHE (current_cpu);
473
  /* If we need to count cycles, then the cache operation will be
474
     initiated from the model profiling functions.
475
     See frvbf_model_....  */
476
  if (model_insn)
477
    {
478
      CPU_LOAD_ADDRESS (current_cpu) = address;
479
      CPU_LOAD_LENGTH (current_cpu) = 4;
480
      return 0x37111319; /* any random value */
481
    }
482
 
483
  if (GET_HSR0_DCE (hsr0))
484
    {
485
      int cycles;
486
      /* Handle access which crosses cache line boundary */
487
      SIM_DESC sd = CPU_STATE (current_cpu);
488
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
489
        {
490
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
491
            return read_mem_unaligned_SI (current_cpu, pc, address);
492
        }
493
      cycles = frv_cache_read (cache, 0, address);
494
      if (cycles != 0)
495
        return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
496
    }
497
 
498
  return GETMEMSI (current_cpu, pc, address);
499
}
500
 
501
SI
502
frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
503
{
504
  return frvbf_read_mem_SI (current_cpu, pc, address);
505
}
506
 
507
/* Read a SI which spans two cache lines */
508
static DI
509
read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
510
{
511
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
512
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
513
  DI value, value1;
514
 
515
  switch (hi_len)
516
    {
517
    case 1:
518
      value = frvbf_read_mem_QI (current_cpu, pc, address);
519
      value <<= 56;
520
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1);
521
      value1 = H2T_8 (value1);
522
      value |= value1 & ((DI)0x00ffffff << 32);
523
      value |= value1 & 0xffffffffu;
524
      break;
525
    case 2:
526
      value = frvbf_read_mem_HI (current_cpu, pc, address);
527
      value = H2T_2 (value);
528
      value <<= 48;
529
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2);
530
      value1 = H2T_8 (value1);
531
      value |= value1 & ((DI)0x0000ffff << 32);
532
      value |= value1 & 0xffffffffu;
533
      break;
534
    case 3:
535
      value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
536
      value = H2T_4 (value);
537
      value <<= 40;
538
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3);
539
      value1 = H2T_8 (value1);
540
      value |= value1 & ((DI)0x000000ff << 32);
541
      value |= value1 & 0xffffffffu;
542
      break;
543
    case 4:
544
      value = frvbf_read_mem_SI (current_cpu, pc, address);
545
      value = H2T_4 (value);
546
      value <<= 32;
547
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
548
      value1 = H2T_4 (value1);
549
      value |= value1 & 0xffffffffu;
550
      break;
551
    case 5:
552
      value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
553
      value = H2T_8 (value);
554
      value <<= 24;
555
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
556
      value1 = H2T_4 (value1);
557
      value |= value1 & 0x00ffffff;
558
      break;
559
    case 6:
560
      value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
561
      value = H2T_8 (value);
562
      value <<= 16;
563
      value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
564
      value1 = H2T_2 (value1);
565
      value |= value1 & 0x0000ffff;
566
      break;
567
    case 7:
568
      value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
569
      value = H2T_8 (value);
570
      value <<= 8;
571
      value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
572
      value |= value1 & 0x000000ff;
573
      break;
574
    default:
575
      abort (); /* can't happen */
576
    }
577
  return T2H_8 (value);
578
}
579
 
580
DI
581
frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
582
{
583
  USI hsr0;
584
  FRV_CACHE *cache;
585
 
586
  /* Check for access exceptions.  */
587
  address = check_data_read_address (current_cpu, address, 7);
588
  address = check_readwrite_address (current_cpu, address, 7);
589
 
590
  /* If we need to count cycles, then the cache operation will be
591
     initiated from the model profiling functions.
592
     See frvbf_model_....  */
593
  hsr0 = GET_HSR0 ();
594
  cache = CPU_DATA_CACHE (current_cpu);
595
  if (model_insn)
596
    {
597
      CPU_LOAD_ADDRESS (current_cpu) = address;
598
      CPU_LOAD_LENGTH (current_cpu) = 8;
599
      return 0x37111319; /* any random value */
600
    }
601
 
602
  if (GET_HSR0_DCE (hsr0))
603
    {
604
      int cycles;
605
      /* Handle access which crosses cache line boundary */
606
      SIM_DESC sd = CPU_STATE (current_cpu);
607
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
608
        {
609
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
610
            return read_mem_unaligned_DI (current_cpu, pc, address);
611
        }
612
      cycles = frv_cache_read (cache, 0, address);
613
      if (cycles != 0)
614
        return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
615
    }
616
 
617
  return GETMEMDI (current_cpu, pc, address);
618
}
619
 
620
DF
621
frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
622
{
623
  USI hsr0;
624
  FRV_CACHE *cache;
625
 
626
  /* Check for access exceptions.  */
627
  address = check_data_read_address (current_cpu, address, 7);
628
  address = check_readwrite_address (current_cpu, address, 7);
629
 
630
  /* If we need to count cycles, then the cache operation will be
631
     initiated from the model profiling functions.
632
     See frvbf_model_....  */
633
  hsr0 = GET_HSR0 ();
634
  cache = CPU_DATA_CACHE (current_cpu);
635
  if (model_insn)
636
    {
637
      CPU_LOAD_ADDRESS (current_cpu) = address;
638
      CPU_LOAD_LENGTH (current_cpu) = 8;
639
      return 0x37111319; /* any random value */
640
    }
641
 
642
  if (GET_HSR0_DCE (hsr0))
643
    {
644
      int cycles;
645
      /* Handle access which crosses cache line boundary */
646
      SIM_DESC sd = CPU_STATE (current_cpu);
647
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
648
        {
649
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
650
            return read_mem_unaligned_DI (current_cpu, pc, address);
651
        }
652
      cycles = frv_cache_read (cache, 0, address);
653
      if (cycles != 0)
654
        return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
655
    }
656
 
657
  return GETMEMDF (current_cpu, pc, address);
658
}
659
 
660
USI
661
frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
662
{
663
  USI hsr0;
664
  vpc = check_insn_read_address (current_cpu, vpc, 3);
665
 
666
  hsr0 = GET_HSR0 ();
667
  if (GET_HSR0_ICE (hsr0))
668
    {
669
      FRV_CACHE *cache;
670
      USI value;
671
 
672
      /* We don't want this to show up in the cache statistics.  That read
673
         is done in frvbf_simulate_insn_prefetch.  So read the cache or memory
674
         passively here.  */
675
      cache = CPU_INSN_CACHE (current_cpu);
676
      if (frv_cache_read_passive_SI (cache, vpc, &value))
677
        return value;
678
    }
679
  return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
680
}
681
 
682
static SI
683
fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
684
{
685
  if (align_mask == 7
686
      && address >= 0xfe800000 && address <= 0xfeffffff)
687
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
688
 
689
  return address;
690
}
691
 
692
static SI
693
fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
694
{
695
  if (address & align_mask)
696
    {
697
      struct frv_interrupt_queue_element *item =
698
        frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
699
      /* Record the correct vliw slot with the interrupt.  */
700
      if (item != NULL)
701
        item->slot = frv_interrupt_state.slot;
702
      address &= ~align_mask;
703
    }
704
  if (address >= 0xfeff0600 && address <= 0xfeff7fff
705
      || address >= 0xfe800000 && address <= 0xfefeffff)
706
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
707
 
708
  return address;
709
}
710
 
711
static SI
712
fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
713
{
714
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
715
      || (align_mask > 0x3
716
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
717
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
718
 
719
  return address;
720
}
721
 
722
static SI
723
check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
724
{
725
  SIM_DESC sd = CPU_STATE (current_cpu);
726
  switch (STATE_ARCHITECTURE (sd)->mach)
727
    {
728
    case bfd_mach_fr400:
729
    case bfd_mach_fr450:
730
      address = fr400_check_write_address (current_cpu, address, align_mask);
731
      break;
732
    case bfd_mach_frvtomcat:
733
    case bfd_mach_fr500:
734
    case bfd_mach_frv:
735
      address = fr500_check_write_address (current_cpu, address, align_mask);
736
      break;
737
    case bfd_mach_fr550:
738
      address = fr550_check_write_address (current_cpu, address, align_mask);
739
      break;
740
    default:
741
      break;
742
    }
743
  return address;
744
}
745
 
746
void
747
frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
748
{
749
  USI hsr0;
750
  hsr0 = GET_HSR0 ();
751
  if (GET_HSR0_DCE (hsr0))
752
    sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
753
  else
754
    sim_queue_mem_qi_write (current_cpu, address, value);
755
  frv_set_write_queue_slot (current_cpu);
756
}
757
 
758
void
759
frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
760
{
761
  frvbf_write_mem_QI (current_cpu, pc, address, value);
762
}
763
 
764
void
765
frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
766
{
767
  USI hsr0;
768
  hsr0 = GET_HSR0 ();
769
  if (GET_HSR0_DCE (hsr0))
770
    sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
771
  else
772
    sim_queue_mem_hi_write (current_cpu, address, value);
773
  frv_set_write_queue_slot (current_cpu);
774
}
775
 
776
void
777
frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
778
{
779
  frvbf_write_mem_HI (current_cpu, pc, address, value);
780
}
781
 
782
void
783
frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
784
{
785
  USI hsr0;
786
  hsr0 = GET_HSR0 ();
787
  if (GET_HSR0_DCE (hsr0))
788
    sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
789
  else
790
    sim_queue_mem_si_write (current_cpu, address, value);
791
  frv_set_write_queue_slot (current_cpu);
792
}
793
 
794
void
795
frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
796
{
797
  frvbf_write_mem_SI (current_cpu, pc, address, value);
798
}
799
 
800
void
801
frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
802
{
803
  USI hsr0;
804
  hsr0 = GET_HSR0 ();
805
  if (GET_HSR0_DCE (hsr0))
806
    sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
807
  else
808
    sim_queue_mem_di_write (current_cpu, address, value);
809
  frv_set_write_queue_slot (current_cpu);
810
}
811
 
812
void
813
frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
814
{
815
  USI hsr0;
816
  hsr0 = GET_HSR0 ();
817
  if (GET_HSR0_DCE (hsr0))
818
    sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
819
  else
820
    sim_queue_mem_df_write (current_cpu, address, value);
821
  frv_set_write_queue_slot (current_cpu);
822
}
823
 
824
/* Memory writes.  These do the actual writing through the cache.  */
825
void
826
frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
827
{
828
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
829
 
830
  /* Check for access errors.  */
831
  address = check_write_address (current_cpu, address, 0);
832
  address = check_readwrite_address (current_cpu, address, 0);
833
 
834
  /* If we need to count cycles, then submit the write request to the cache
835
     and let it prioritize the request.  Otherwise perform the write now.  */
836
  if (model_insn)
837
    {
838
      int slot = UNIT_I0;
839
      frv_cache_request_store (cache, address, slot, (char *)&value,
840
                               sizeof (value));
841
    }
842
  else
843
    frv_cache_write (cache, address, (char *)&value, sizeof (value));
844
}
845
 
846
/* Write a HI which spans two cache lines */
847
static void
848
mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
849
{
850
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
851
  /* value is already in target byte order */
852
  frv_cache_write (cache, address, (char *)&value, 1);
853
  frv_cache_write (cache, address + 1, ((char *)&value + 1), 1);
854
}
855
 
856
void
857
frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
858
{
859
  FRV_CACHE *cache;
860
 
861
  /* Check for access errors.  */
862
  address = check_write_address (current_cpu, address, 1);
863
  address = check_readwrite_address (current_cpu, address, 1);
864
 
865
  /* If we need to count cycles, then submit the write request to the cache
866
     and let it prioritize the request.  Otherwise perform the write now.  */
867
  value = H2T_2 (value);
868
  cache = CPU_DATA_CACHE (current_cpu);
869
  if (model_insn)
870
    {
871
      int slot = UNIT_I0;
872
      frv_cache_request_store (cache, address, slot,
873
                               (char *)&value, sizeof (value));
874
    }
875
  else
876
    {
877
      /* Handle access which crosses cache line boundary */
878
      SIM_DESC sd = CPU_STATE (current_cpu);
879
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
880
        {
881
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
882
            {
883
              mem_set_unaligned_HI (current_cpu, pc, address, value);
884
              return;
885
            }
886
        }
887
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
888
    }
889
}
890
 
891
/* Write a SI which spans two cache lines */
892
static void
893
mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
894
{
895
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
896
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
897
  /* value is already in target byte order */
898
  frv_cache_write (cache, address, (char *)&value, hi_len);
899
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len);
900
}
901
 
902
void
903
frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
904
{
905
  FRV_CACHE *cache;
906
 
907
  /* Check for access errors.  */
908
  address = check_write_address (current_cpu, address, 3);
909
  address = check_readwrite_address (current_cpu, address, 3);
910
 
911
  /* If we need to count cycles, then submit the write request to the cache
912
     and let it prioritize the request.  Otherwise perform the write now.  */
913
  cache = CPU_DATA_CACHE (current_cpu);
914
  value = H2T_4 (value);
915
  if (model_insn)
916
    {
917
      int slot = UNIT_I0;
918
      frv_cache_request_store (cache, address, slot,
919
                               (char *)&value, sizeof (value));
920
    }
921
  else
922
    {
923
      /* Handle access which crosses cache line boundary */
924
      SIM_DESC sd = CPU_STATE (current_cpu);
925
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
926
        {
927
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
928
            {
929
              mem_set_unaligned_SI (current_cpu, pc, address, value);
930
              return;
931
            }
932
        }
933
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
934
    }
935
}
936
 
937
/* Write a DI which spans two cache lines */
938
static void
939
mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
940
{
941
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
942
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
943
  /* value is already in target byte order */
944
  frv_cache_write (cache, address, (char *)&value, hi_len);
945
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len);
946
}
947
 
948
void
949
frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
950
{
951
  FRV_CACHE *cache;
952
 
953
  /* Check for access errors.  */
954
  address = check_write_address (current_cpu, address, 7);
955
  address = check_readwrite_address (current_cpu, address, 7);
956
 
957
  /* If we need to count cycles, then submit the write request to the cache
958
     and let it prioritize the request.  Otherwise perform the write now.  */
959
  value = H2T_8 (value);
960
  cache = CPU_DATA_CACHE (current_cpu);
961
  if (model_insn)
962
    {
963
      int slot = UNIT_I0;
964
      frv_cache_request_store (cache, address, slot,
965
                               (char *)&value, sizeof (value));
966
    }
967
  else
968
    {
969
      /* Handle access which crosses cache line boundary */
970
      SIM_DESC sd = CPU_STATE (current_cpu);
971
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
972
        {
973
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
974
            {
975
              mem_set_unaligned_DI (current_cpu, pc, address, value);
976
              return;
977
            }
978
        }
979
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
980
    }
981
}
982
 
983
void
984
frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
985
{
986
  FRV_CACHE *cache;
987
 
988
  /* Check for access errors.  */
989
  address = check_write_address (current_cpu, address, 7);
990
  address = check_readwrite_address (current_cpu, address, 7);
991
 
992
  /* If we need to count cycles, then submit the write request to the cache
993
     and let it prioritize the request.  Otherwise perform the write now.  */
994
  value = H2T_8 (value);
995
  cache = CPU_DATA_CACHE (current_cpu);
996
  if (model_insn)
997
    {
998
      int slot = UNIT_I0;
999
      frv_cache_request_store (cache, address, slot,
1000
                               (char *)&value, sizeof (value));
1001
    }
1002
  else
1003
    {
1004
      /* Handle access which crosses cache line boundary */
1005
      SIM_DESC sd = CPU_STATE (current_cpu);
1006
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
1007
        {
1008
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
1009
            {
1010
              mem_set_unaligned_DI (current_cpu, pc, address, value);
1011
              return;
1012
            }
1013
        }
1014
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
1015
    }
1016
}
1017
 
1018
void
1019
frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
1020
{
1021
  int i;
1022
  FRV_CACHE *cache;
1023
 
1024
  /* Check for access errors.  */
1025
  address = check_write_address (current_cpu, address, 0xf);
1026
  address = check_readwrite_address (current_cpu, address, 0xf);
1027
 
1028
  /* TODO -- reverse word order as well?  */
1029
  for (i = 0; i < 4; ++i)
1030
    value[i] = H2T_4 (value[i]);
1031
 
1032
  /* If we need to count cycles, then submit the write request to the cache
1033
     and let it prioritize the request.  Otherwise perform the write now.  */
1034
  cache = CPU_DATA_CACHE (current_cpu);
1035
  if (model_insn)
1036
    {
1037
      int slot = UNIT_I0;
1038
      frv_cache_request_store (cache, address, slot, (char*)value, 16);
1039
    }
1040
  else
1041
    frv_cache_write (cache, address, (char*)value, 16);
1042
}
1043
 
1044
/* Record the current VLIW slot on the element at the top of the write queue.
1045
*/
1046
void
1047
frv_set_write_queue_slot (SIM_CPU *current_cpu)
1048
{
1049
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);
1050
  int slot = vliw->next_slot - 1;
1051
  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
1052
  int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
1053
  CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
1054
  CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];
1055
}

powered by: WebSVN 2.1.0

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