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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [arm/] [armcopro.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 578 markom
/*  armcopro.c -- co-processor interface:  ARM6 Instruction Emulator.
2
    Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
3
 
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8
 
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13
 
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
 
18
#include "armdefs.h"
19
#include "armos.h"
20
#include "armemu.h"
21
#include "ansidecl.h"
22
 
23
/* Dummy Co-processors.  */
24
 
25
static unsigned
26
NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
27
           unsigned      a     ATTRIBUTE_UNUSED,
28
           ARMword       b     ATTRIBUTE_UNUSED)
29
{
30
  return ARMul_CANT;
31
}
32
 
33
static unsigned
34
NoCoPro4R (ARMul_State * state ATTRIBUTE_UNUSED,
35
           unsigned      a     ATTRIBUTE_UNUSED,
36
           ARMword       b     ATTRIBUTE_UNUSED,
37
           ARMword       c     ATTRIBUTE_UNUSED)
38
{
39
  return ARMul_CANT;
40
}
41
 
42
static unsigned
43
NoCoPro4W (ARMul_State * state ATTRIBUTE_UNUSED,
44
           unsigned      a     ATTRIBUTE_UNUSED,
45
           ARMword       b     ATTRIBUTE_UNUSED,
46
           ARMword *     c     ATTRIBUTE_UNUSED)
47
{
48
  return ARMul_CANT;
49
}
50
 
51
/* The XScale Co-processors.  */
52
 
53
/* Coprocessor 15:  System Control.  */
54
 
55
/* There are two sets of registers for copro 15.
56
   One set is available when opcode_2 is 0 and
57
   the other set when opcode_2 >= 1.  */
58
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
59
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
60
/* There are also a set of breakpoint registers
61
   which are accessed via CRm instead of opcode_2.  */
62
static ARMword XScale_cp15_DBR1;
63
static ARMword XScale_cp15_DBCON;
64
static ARMword XScale_cp15_IBCR0;
65
static ARMword XScale_cp15_IBCR1;
66
 
67
static unsigned
68
XScale_cp15_init (ARMul_State * state ATTRIBUTE_UNUSED)
69
{
70
  int i;
71
 
72
  for (i = 16; i--;)
73
    {
74
      XScale_cp15_opcode_2_is_0_Regs[i] = 0;
75
      XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
76
    }
77
 
78
  /* Initialise the processor ID.  */
79
  XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
80
 
81
  /* Initialise the cache type.  */
82
  XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
83
 
84
  /* Initialise the ARM Control Register.  */
85
  XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
86
 
87
}
88
 
89
/* Check an access to a register.  */
90
 
91
static unsigned
92
check_cp15_access (ARMul_State * state,
93
                   unsigned      reg,
94
                   unsigned      CRm,
95
                   unsigned      opcode_1,
96
                   unsigned      opcode_2)
97
{
98
  /* Do not allow access to these register in USER mode.  */
99
  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
100
    return ARMul_CANT;
101
 
102
  /* Opcode_1should be zero.  */
103
  if (opcode_1 != 0)
104
    return ARMul_CANT;
105
 
106
  /* Different register have different access requirements.  */
107
  switch (reg)
108
    {
109
    case 0:
110
    case 1:
111
      /* CRm must be 0.  Opcode_2 can be anything.  */
112
      if (CRm != 0)
113
        return ARMul_CANT;
114
      break;
115
    case 2:
116
    case 3:
117
      /* CRm must be 0.  Opcode_2 must be zero.  */
118
      if ((CRm != 0) || (opcode_2 != 0))
119
        return ARMul_CANT;
120
      break;
121
    case 4:
122
      /* Access not allowed.  */
123
      return ARMul_CANT;
124
    case 5:
125
    case 6:
126
      /* Opcode_2 must be zero.  CRm must be 0.  */
127
      if ((CRm != 0) || (opcode_2 != 0))
128
        return ARMul_CANT;
129
      break;
130
    case 7:
131
      /* Permissable combinations:
132
           Opcode_2  CRm
133
 
134
 
135
 
136
              1       5
137
              1       6
138
              1      10
139
              4      10
140
              5       2
141
              6       5  */
142
      switch (opcode_2)
143
        {
144
        default:               return ARMul_CANT;
145
        case 6: if (CRm !=  5) return ARMul_CANT; break;
146
        case 5: if (CRm !=  2) return ARMul_CANT; break;
147
        case 4: if (CRm != 10) return ARMul_CANT; break;
148
        case 1: if ((CRm != 5) && (CRm != 6) && (CRm != 10)) return ARMul_CANT; break;
149
        case 0: if ((CRm < 5) || (CRm > 7)) return ARMul_CANT; break;
150
        }
151
      break;
152
 
153
    case 8:
154
      /* Permissable combinations:
155
           Opcode_2  CRm
156
 
157
 
158
 
159
              1       5
160
              1       6  */
161
      if (opcode_2 > 1)
162
        return ARMul_CANT;
163
      if ((CRm < 5) || (CRm > 7))
164
        return ARMul_CANT;
165
      if (opcode_2 == 1 && CRm == 7)
166
        return ARMul_CANT;
167
      break;
168
    case 9:
169
      /* Opcode_2 must be zero or one.  CRm must be 1 or 2.  */
170
      if (   ((CRm != 0) && (CRm != 1))
171
          || ((opcode_2 != 1) && (opcode_2 != 2)))
172
        return ARMul_CANT;
173
      break;
174
    case 10:
175
      /* Opcode_2 must be zero or one.  CRm must be 4 or 8.  */
176
      if (   ((CRm != 0) && (CRm != 1))
177
          || ((opcode_2 != 4) && (opcode_2 != 8)))
178
        return ARMul_CANT;
179
      break;
180
    case 11:
181
      /* Access not allowed.  */
182
      return ARMul_CANT;
183
    case 12:
184
      /* Access not allowed.  */
185
      return ARMul_CANT;
186
    case 13:
187
      /* Opcode_2 must be zero.  CRm must be 0.  */
188
      if ((CRm != 0) || (opcode_2 != 0))
189
        return ARMul_CANT;
190
      break;
191
    case 14:
192
      /* Opcode_2 must be 0.  CRm must be 0, 3, 4, 8 or 9.  */
193
      if (opcode_2 != 0)
194
        return ARMul_CANT;
195
 
196
      if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) && (CRm != 9))
197
        return ARMul_CANT;
198
      break;
199
    case 15:
200
      /* Opcode_2 must be zero.  CRm must be 1.  */
201
      if ((CRm != 1) || (opcode_2 != 0))
202
        return ARMul_CANT;
203
      break;
204
    default:
205
      /* Should never happen.  */
206
      return ARMul_CANT;
207
    }
208
 
209
  return ARMul_DONE;
210
}
211
 
212
/* Store a value into one of coprocessor 15's registers.  */
213
 
214
void
215
write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned CRm, ARMword value)
216
{
217
  if (opcode_2)
218
    {
219
      switch (reg)
220
        {
221
        case 0: /* Cache Type.  */
222
          /* Writes are not allowed.  */
223
          return;
224
 
225
        case 1: /* Auxillary Control.  */
226
          /* Only BITS (5, 4) and BITS (1, 0) can be written.  */
227
          value &= 0x33;
228
          break;
229
 
230
        default:
231
          return;
232
        }
233
 
234
      XScale_cp15_opcode_2_is_not_0_Regs [reg] = value;
235
    }
236
  else
237
    {
238
      switch (reg)
239
        {
240
        case 0: /* ID.  */
241
          /* Writes are not allowed.  */
242
          return;
243
 
244
        case 1: /* ARM Control.  */
245
          /* Only BITS (13, 11), BITS (9, 7) and BITS (2, 0) can be written.
246
             BITS (31, 14) and BIT (10) write as zero, BITS (6, 3) write as one.  */
247
          value &= 0x00003b87;
248
          value |= 0x00000078;
249
 
250
          /* Change the endianness if necessary */
251
          if ((value & ARMul_CP15_R1_ENDIAN) !=
252
              (XScale_cp15_opcode_2_is_0_Regs [reg] & ARMul_CP15_R1_ENDIAN))
253
            {
254
              state->bigendSig = value & ARMul_CP15_R1_ENDIAN;
255
              /* Force ARMulator to notice these now.  */
256
              state->Emulate = CHANGEMODE;
257
            }
258
          break;
259
 
260
        case 2: /* Translation Table Base.  */
261
          /* Only BITS (31, 14) can be written.  */
262
          value &= 0xffffc000;
263
          break;
264
 
265
        case 3: /* Domain Access Control.  */
266
          /* All bits writable.  */
267
          break;
268
 
269
        case 5: /* Fault Status Register.  */
270
          /* BITS (10, 9) and BITS (7, 0) can be written.  */
271
          value &= 0x000006ff;
272
          break;
273
 
274
        case 6: /* Fault Address Register.  */
275
          /* All bits writable.  */
276
          break;
277
 
278
        case 7: /* Cache Functions.  */
279
        case 8: /* TLB Operations.  */
280
        case 10: /* TLB Lock Down.  */
281
          /* Ignore writes.  */
282
          return;
283
 
284
        case 9: /* Data Cache Lock.  */
285
          /* Only BIT (0) can be written.  */
286
          value &= 0x1;
287
          break;
288
 
289
        case 13: /* Process ID.  */
290
          /* Only BITS (31, 25) are writable.  */
291
          value &= 0xfe000000;
292
          break;
293
 
294
        case 14: /* DBR0, DBR1, DBCON, IBCR0, IBCR1 */
295
          /* All bits can be written.  Which register is accessed is
296
             dependent upon CRm.  */
297
          switch (CRm)
298
            {
299
            case 0: /* DBR0 */
300
              break;
301
            case 3: /* DBR1 */
302
              XScale_cp15_DBR1 = value;
303
              break;
304
            case 4: /* DBCON */
305
              XScale_cp15_DBCON = value;
306
              break;
307
            case 8: /* IBCR0 */
308
              XScale_cp15_IBCR0 = value;
309
              break;
310
            case 9: /* IBCR1 */
311
              XScale_cp15_IBCR1 = value;
312
              break;
313
            default:
314
              return;
315
            }
316
          break;
317
 
318
        case 15: /* Coprpcessor Access Register.  */
319
          /* Access is only valid if CRm == 1.  */
320
          if (CRm != 1)
321
            return;
322
 
323
          /* Only BITS (13, 0) may be written.  */
324
          value &= 0x00003fff;
325
          break;
326
 
327
        default:
328
          return;
329
        }
330
 
331
      XScale_cp15_opcode_2_is_0_Regs [reg] = value;
332
    }
333
 
334
  return;
335
}
336
 
337
/* Return the value in a cp15 register.  */
338
 
339
ARMword
340
read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm)
341
{
342
  if (opcode_2 == 0)
343
    {
344
      if (reg == 15 && CRm != 1)
345
        return 0;
346
 
347
      if (reg == 14)
348
        {
349
          switch (CRm)
350
            {
351
            case 3: return XScale_cp15_DBR1;
352
            case 4: return XScale_cp15_DBCON;
353
            case 8: return XScale_cp15_IBCR0;
354
            case 9: return XScale_cp15_IBCR1;
355
            default:
356
              break;
357
            }
358
        }
359
 
360
      return XScale_cp15_opcode_2_is_0_Regs [reg];
361
    }
362
  else
363
    return XScale_cp15_opcode_2_is_not_0_Regs [reg];
364
 
365
  return 0;
366
}
367
 
368
static unsigned
369
XScale_cp15_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
370
{
371
  unsigned reg = BITS (12, 15);
372
  unsigned result;
373
 
374
  result = check_cp15_access (state, reg, 0, 0, 0);
375
 
376
  if (result == ARMul_DONE && type == ARMul_DATA)
377
    write_cp15_reg (state, reg, 0, 0, data);
378
 
379
  return result;
380
}
381
 
382
static unsigned
383
XScale_cp15_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
384
{
385
  unsigned reg = BITS (12, 15);
386
  unsigned result;
387
 
388
  result = check_cp15_access (state, reg, 0, 0, 0);
389
 
390
  if (result == ARMul_DONE && type == ARMul_DATA)
391
    * data = read_cp15_reg (reg, 0, 0);
392
 
393
  return result;
394
}
395
 
396
static unsigned
397
XScale_cp15_MRC (ARMul_State * state,
398
              unsigned      type ATTRIBUTE_UNUSED,
399
              ARMword       instr,
400
              ARMword *     value)
401
{
402
  unsigned opcode_2 = BITS (5, 7);
403
  unsigned CRm = BITS (0, 3);
404
  unsigned reg = BITS (16, 19);
405
  unsigned result;
406
 
407
  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
408
 
409
  if (result == ARMul_DONE)
410
    * value = read_cp15_reg (reg, opcode_2, CRm);
411
 
412
  return result;
413
}
414
 
415
static unsigned
416
XScale_cp15_MCR (ARMul_State * state,
417
              unsigned      type ATTRIBUTE_UNUSED,
418
              ARMword       instr,
419
              ARMword       value)
420
{
421
  unsigned opcode_2 = BITS (5, 7);
422
  unsigned CRm = BITS (0, 3);
423
  unsigned reg = BITS (16, 19);
424
  unsigned result;
425
 
426
  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
427
 
428
  if (result == ARMul_DONE)
429
    write_cp15_reg (state, reg, opcode_2, CRm, value);
430
 
431
  return result;
432
}
433
 
434
static unsigned
435
XScale_cp15_read_reg (ARMul_State * state ATTRIBUTE_UNUSED,
436
                   unsigned      reg,
437
                   ARMword *     value)
438
{
439
  /* FIXME: Not sure what to do about the alternative register set
440
     here.  For now default to just accessing CRm == 0 registers.  */
441
  * value = read_cp15_reg (reg, 0, 0);
442
 
443
  return TRUE;
444
}
445
 
446
static unsigned
447
XScale_cp15_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
448
                    unsigned      reg,
449
                    ARMword       value)
450
{
451
  /* FIXME: Not sure what to do about the alternative register set
452
     here.  For now default to just accessing CRm == 0 registers.  */
453
  write_cp15_reg (state, reg, 0, 0, value);
454
 
455
  return TRUE;
456
}
457
 
458
/***************************************************************************\
459
*        Check for special XScale memory access features                    *
460
\***************************************************************************/
461
void
462
XScale_check_memacc (ARMul_State * state, ARMword * address, int store)
463
{
464
  ARMword dbcon, r0, r1;
465
  int e1, e0;
466
 
467
  if (!state->is_XScale)
468
    return;
469
 
470
  /* Check for PID-ification.
471
     XXX BTB access support will require this test failing.  */
472
  r0 = (read_cp15_reg (13, 0, 0) & 0xfe000000);
473
  if (r0 && (*address & 0xfe000000) == 0)
474
    *address |= r0;
475
 
476
  /* Check alignment fault enable/disable.  */
477
  if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN) && (*address & 3))
478
    ARMul_Abort (state, ARMul_DataAbortV);
479
 
480
  if (XScale_debug_moe (state, -1))
481
    return;
482
 
483
  /* Check the data breakpoint registers.  */
484
  dbcon = read_cp15_reg (14, 0, 4);
485
  r0 = read_cp15_reg (14, 0, 0);
486
  r1 = read_cp15_reg (14, 0, 3);
487
  e0 = dbcon & ARMul_CP15_DBCON_E0;
488
 
489
  if (dbcon & ARMul_CP15_DBCON_M)
490
    {
491
      /* r1 is a inverse mask.  */
492
      if (e0 != 0 && ((store && e0 != 3) || (!store && e0 != 1))
493
          && ((*address & ~r1) == (r0 & ~r1)))
494
        {
495
          XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
496
          ARMul_OSHandleSWI (state, SWI_Breakpoint);
497
        }
498
    }
499
  else
500
    {
501
      if (e0 != 0 && ((store && e0 != 3) || (!store && e0 != 1))
502
              && ((*address & ~3) == (r0 & ~3)))
503
        {
504
          XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
505
          ARMul_OSHandleSWI (state, SWI_Breakpoint);
506
        }
507
 
508
      e1 = (dbcon & ARMul_CP15_DBCON_E1) >> 2;
509
      if (e1 != 0 && ((store && e1 != 3) || (!store && e1 != 1))
510
              && ((*address & ~3) == (r1 & ~3)))
511
        {
512
          XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
513
          ARMul_OSHandleSWI (state, SWI_Breakpoint);
514
        }
515
    }
516
}
517
 
518
/***************************************************************************\
519
*        Check set
520
\***************************************************************************/
521
void
522
XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword far)
523
{
524
  if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
525
    return;
526
 
527
  write_cp15_reg (state, 5, 0, 0, fsr);
528
  write_cp15_reg (state, 6, 0, 0, far);
529
}
530
 
531
/* Set the XScale debug `method of entry' if it is enabled.  */
532
int
533
XScale_debug_moe (ARMul_State * state, int moe)
534
{
535
  ARMword value;
536
 
537
  if (!state->is_XScale)
538
    return 1;
539
 
540
  value = read_cp14_reg (10);
541
  if (value & (1UL << 31))
542
    {
543
      if (moe != -1)
544
        {
545
          value &= ~0x1c;
546
          value |= moe;
547
 
548
          write_cp14_reg (10, value);
549
        }
550
      return 1;
551
    }
552
  return 0;
553
}
554
 
555
/* Coprocessor 13:  Interrupt Controller and Bus Controller.  */
556
 
557
/* There are two sets of registers for copro 13.
558
   One set (of three registers) is available when CRm is 0
559
   and the other set (of six registers) when CRm is 1.  */
560
 
561
static ARMword XScale_cp13_CR0_Regs[16];
562
static ARMword XScale_cp13_CR1_Regs[16];
563
 
564
static unsigned
565
XScale_cp13_init (ARMul_State * state ATTRIBUTE_UNUSED)
566
{
567
  int i;
568
 
569
  for (i = 16; i--;)
570
    {
571
      XScale_cp13_CR0_Regs[i] = 0;
572
      XScale_cp13_CR1_Regs[i] = 0;
573
    }
574
}
575
 
576
/* Check an access to a register.  */
577
 
578
static unsigned
579
check_cp13_access (ARMul_State * state,
580
                   unsigned      reg,
581
                   unsigned      CRm,
582
                   unsigned      opcode_1,
583
                   unsigned      opcode_2)
584
{
585
  /* Do not allow access to these register in USER mode.  */
586
  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
587
    return ARMul_CANT;
588
 
589
  /* The opcodes should be zero.  */
590
  if ((opcode_1 != 0) || (opcode_2 != 0))
591
    return ARMul_CANT;
592
 
593
  /* Do not allow access to these register if bit 13 of coprocessor
594
     15's register 15 is zero.  */
595
  if ((XScale_cp15_opcode_2_is_0_Regs[15] & (1 << 13)) == 0)
596
    return ARMul_CANT;
597
 
598
  /* Registers 0, 4 and 8 are defined when CRm == 0.
599
     Registers 0, 4, 5, 6, 7, 8 are defined when CRm == 1.
600
     For all other CRm values undefined behaviour results.  */
601
  if (CRm == 0)
602
    {
603
      if (reg == 0 || reg == 4 || reg == 8)
604
        return ARMul_DONE;
605
    }
606
  else if (CRm == 1)
607
    {
608
      if (reg == 0 || (reg >= 4 && reg <= 8))
609
        return ARMul_DONE;
610
    }
611
 
612
  return ARMul_CANT;
613
}
614
 
615
/* Store a value into one of coprocessor 13's registers.  */
616
 
617
static void
618
write_cp13_reg (unsigned reg, unsigned CRm, ARMword value)
619
{
620
  switch (CRm)
621
    {
622
    case 0:
623
      switch (reg)
624
        {
625
        case 0: /* INTCTL */
626
          /* Only BITS (3:0) can be written.  */
627
          value &= 0xf;
628
          break;
629
 
630
        case 4: /* INTSRC */
631
          /* No bits may be written.  */
632
          return;
633
 
634
        case 8: /* INTSTR */
635
          /* Only BITS (1:0) can be written.  */
636
          value &= 0x3;
637
          break;
638
 
639
        default:
640
          /* Should not happen.  Ignore any writes to unimplemented registers.  */
641
          return;
642
        }
643
 
644
      XScale_cp13_CR0_Regs [reg] = value;
645
      break;
646
 
647
    case 1:
648
      switch (reg)
649
        {
650
        case 0: /* BCUCTL */
651
          /* Only BITS (30:28) and BITS (3:0) can be written.
652
             BIT(31) is write ignored.  */
653
          value &= 0x7000000f;
654
          value |= XScale_cp13_CR1_Regs[0] & (1UL << 31);
655
          break;
656
 
657
        case 4: /* ELOG0 */
658
        case 5: /* ELOG1 */
659
        case 6: /* ECAR0 */
660
        case 7: /* ECAR1 */
661
          /* No bits can be written.  */
662
          return;
663
 
664
        case 8: /* ECTST */
665
          /* Only BITS (7:0) can be written.  */
666
          value &= 0xff;
667
          break;
668
 
669
        default:
670
          /* Should not happen.  Ignore any writes to unimplemented registers.  */
671
          return;
672
        }
673
 
674
      XScale_cp13_CR1_Regs [reg] = value;
675
      break;
676
 
677
    default:
678
      /* Should not happen.  */
679
      break;
680
    }
681
 
682
  return;
683
}
684
 
685
/* Return the value in a cp13 register.  */
686
 
687
static ARMword
688
read_cp13_reg (unsigned reg, unsigned CRm)
689
{
690
  if (CRm == 0)
691
    return XScale_cp13_CR0_Regs [reg];
692
  else if (CRm == 1)
693
    return XScale_cp13_CR1_Regs [reg];
694
 
695
  return 0;
696
}
697
 
698
static unsigned
699
XScale_cp13_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
700
{
701
  unsigned reg = BITS (12, 15);
702
  unsigned result;
703
 
704
  result = check_cp13_access (state, reg, 0, 0, 0);
705
 
706
  if (result == ARMul_DONE && type == ARMul_DATA)
707
    write_cp13_reg (reg, 0, data);
708
 
709
  return result;
710
}
711
 
712
static unsigned
713
XScale_cp13_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
714
{
715
  unsigned reg = BITS (12, 15);
716
  unsigned result;
717
 
718
  result = check_cp13_access (state, reg, 0, 0, 0);
719
 
720
  if (result == ARMul_DONE && type == ARMul_DATA)
721
    * data = read_cp13_reg (reg, 0);
722
 
723
  return result;
724
}
725
 
726
static unsigned
727
XScale_cp13_MRC (ARMul_State * state,
728
              unsigned      type ATTRIBUTE_UNUSED,
729
              ARMword       instr,
730
              ARMword *     value)
731
{
732
  unsigned CRm = BITS (0, 3);
733
  unsigned reg = BITS (16, 19);
734
  unsigned result;
735
 
736
  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
737
 
738
  if (result == ARMul_DONE)
739
    * value = read_cp13_reg (reg, CRm);
740
 
741
  return result;
742
}
743
 
744
static unsigned
745
XScale_cp13_MCR (ARMul_State * state,
746
              unsigned      type ATTRIBUTE_UNUSED,
747
              ARMword       instr,
748
              ARMword       value)
749
{
750
  unsigned CRm = BITS (0, 3);
751
  unsigned reg = BITS (16, 19);
752
  unsigned result;
753
 
754
  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
755
 
756
  if (result == ARMul_DONE)
757
    write_cp13_reg (reg, CRm, value);
758
 
759
  return result;
760
}
761
 
762
static unsigned
763
XScale_cp13_read_reg
764
(
765
 ARMul_State * state ATTRIBUTE_UNUSED,
766
 unsigned      reg,
767
 ARMword *     value
768
)
769
{
770
  /* FIXME: Not sure what to do about the alternative register set
771
     here.  For now default to just accessing CRm == 0 registers.  */
772
  * value = read_cp13_reg (reg, 0);
773
 
774
  return TRUE;
775
}
776
 
777
static unsigned
778
XScale_cp13_write_reg
779
(
780
 ARMul_State * state ATTRIBUTE_UNUSED,
781
 unsigned      reg,
782
 ARMword       value
783
)
784
{
785
  /* FIXME: Not sure what to do about the alternative register set
786
     here.  For now default to just accessing CRm == 0 registers.  */
787
  write_cp13_reg (reg, 0, value);
788
 
789
  return TRUE;
790
}
791
 
792
/* Coprocessor 14:  Performance Monitoring,  Clock and Power management,
793
   Software Debug.  */
794
 
795
static ARMword XScale_cp14_Regs[16];
796
 
797
static unsigned
798
XScale_cp14_init (ARMul_State * state ATTRIBUTE_UNUSED)
799
{
800
  int i;
801
 
802
  for (i = 16; i--;)
803
    XScale_cp14_Regs[i] = 0;
804
}
805
 
806
/* Check an access to a register.  */
807
 
808
static unsigned
809
check_cp14_access (ARMul_State * state,
810
                   unsigned      reg,
811
                   unsigned      CRm,
812
                   unsigned      opcode1,
813
                   unsigned      opcode2)
814
{
815
  /* Not allowed to access these register in USER mode.  */
816
  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
817
    return ARMul_CANT;
818
 
819
  /* CRm should be zero.  */
820
  if (CRm != 0)
821
    return ARMul_CANT;
822
 
823
  /* OPcodes should be zero.  */
824
  if (opcode1 != 0 || opcode2 != 0)
825
    return ARMul_CANT;
826
 
827
  /* Accessing registers 4 or 5 has unpredicatable results.  */
828
  if (reg >= 4 && reg <= 5)
829
    return ARMul_CANT;
830
 
831
  return ARMul_DONE;
832
}
833
 
834
/* Store a value into one of coprocessor 14's registers.  */
835
 
836
void
837
write_cp14_reg (unsigned reg, ARMword value)
838
{
839
  switch (reg)
840
    {
841
    case 0: /* PMNC */
842
      /* Only BITS (27:12), BITS (10:8) and BITS (6:0) can be written.  */
843
      value &= 0x0ffff77f;
844
 
845
      /* Reset the clock counter if necessary */
846
      if (value & ARMul_CP14_R0_CLKRST)
847
        XScale_cp14_Regs [1] = 0;
848
      break;
849
 
850
    case 4:
851
    case 5:
852
      /* We should not normally reach this code.  The debugger interface
853
         can bypass the normal checks though, so it could happen.  */
854
      value = 0;
855
      break;
856
 
857
    case 6: /* CCLKCFG */
858
      /* Only BITS (3:0) can be written.  */
859
      value &= 0xf;
860
      break;
861
 
862
    case 7: /* PWRMODE */
863
      /* Although BITS (1:0) can be written with non-zero values, this would
864
         have the side effect of putting the processor to sleep.  Thus in
865
         order for the register to be read again, it would have to go into
866
         ACTIVE mode, which means that any read will see these bits as zero.
867
 
868
         Rather than trying to implement complex reset-to-zero-upon-read logic
869
         we just override the write value with zero.  */
870
      value = 0;
871
      break;
872
 
873
    case 10: /* DCSR */
874
      /* Only BITS (31:30), BITS (23:22), BITS (20:16) and BITS (5:0) can
875
         be written.  */
876
      value &= 0xc0df003f;
877
      break;
878
 
879
    case 11: /* TBREG */
880
      /* No writes are permitted.  */
881
      value = 0;
882
      break;
883
 
884
    case 14: /* TXRXCTRL */
885
      /* Only BITS (31:30) can be written.  */
886
      value &= 0xc0000000;
887
      break;
888
 
889
    default:
890
      /* All bits can be written.  */
891
      break;
892
    }
893
 
894
  XScale_cp14_Regs [reg] = value;
895
}
896
 
897
/* Return the value in a cp14 register.  Not a static function since
898
   it is used by the code to emulate the BKPT instruction in armemu.c.  */
899
 
900
ARMword
901
read_cp14_reg (unsigned reg)
902
{
903
  return XScale_cp14_Regs [reg];
904
}
905
 
906
static unsigned
907
XScale_cp14_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
908
{
909
  unsigned reg = BITS (12, 15);
910
  unsigned result;
911
 
912
  result = check_cp14_access (state, reg, 0, 0, 0);
913
 
914
  if (result == ARMul_DONE && type == ARMul_DATA)
915
    write_cp14_reg (reg, data);
916
 
917
  return result;
918
}
919
 
920
static unsigned
921
XScale_cp14_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
922
{
923
  unsigned reg = BITS (12, 15);
924
  unsigned result;
925
 
926
  result = check_cp14_access (state, reg, 0, 0, 0);
927
 
928
  if (result == ARMul_DONE && type == ARMul_DATA)
929
    * data = read_cp14_reg (reg);
930
 
931
  return result;
932
}
933
 
934
static unsigned
935
XScale_cp14_MRC
936
(
937
 ARMul_State * state,
938
 unsigned      type ATTRIBUTE_UNUSED,
939
 ARMword       instr,
940
 ARMword *     value
941
)
942
{
943
  unsigned reg = BITS (16, 19);
944
  unsigned result;
945
 
946
  result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
947
 
948
  if (result == ARMul_DONE)
949
    * value = read_cp14_reg (reg);
950
 
951
  return result;
952
}
953
 
954
static unsigned
955
XScale_cp14_MCR
956
(
957
 ARMul_State * state,
958
 unsigned      type ATTRIBUTE_UNUSED,
959
 ARMword       instr,
960
 ARMword       value
961
)
962
{
963
  unsigned reg = BITS (16, 19);
964
  unsigned result;
965
 
966
  result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
967
 
968
  if (result == ARMul_DONE)
969
    write_cp14_reg (reg, value);
970
 
971
  return result;
972
}
973
 
974
static unsigned
975
XScale_cp14_read_reg
976
(
977
 ARMul_State * state ATTRIBUTE_UNUSED,
978
 unsigned      reg,
979
 ARMword *     value
980
)
981
{
982
  * value = read_cp14_reg (reg);
983
 
984
  return TRUE;
985
}
986
 
987
static unsigned
988
XScale_cp14_write_reg
989
(
990
 ARMul_State * state ATTRIBUTE_UNUSED,
991
 unsigned      reg,
992
 ARMword       value
993
)
994
{
995
  write_cp14_reg (reg, value);
996
 
997
  return TRUE;
998
}
999
 
1000
/* Here's ARMulator's MMU definition.  A few things to note:
1001
   1) It has eight registers, but only two are defined.
1002
   2) You can only access its registers with MCR and MRC.
1003
   3) MMU Register 0 (ID) returns 0x41440110
1004
   4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
1005
      controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
1006
      bit 6 controls late abort timimg and bit 7 controls big/little endian.  */
1007
 
1008
static ARMword MMUReg[8];
1009
 
1010
static unsigned
1011
MMUInit (ARMul_State * state)
1012
{
1013
  MMUReg[1] = state->prog32Sig << 4 |
1014
    state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
1015
 
1016
  ARMul_ConsolePrint (state, ", MMU present");
1017
 
1018
  return TRUE;
1019
}
1020
 
1021
static unsigned
1022
MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1023
        unsigned      type ATTRIBUTE_UNUSED,
1024
        ARMword       instr,
1025
        ARMword *     value)
1026
{
1027
  int reg = BITS (16, 19) & 7;
1028
 
1029
  if (reg == 0)
1030
    *value = 0x41440110;
1031
  else
1032
    *value = MMUReg[reg];
1033
 
1034
  return ARMul_DONE;
1035
}
1036
 
1037
static unsigned
1038
MMUMCR (ARMul_State * state,
1039
        unsigned      type ATTRIBUTE_UNUSED,
1040
        ARMword       instr,
1041
        ARMword       value)
1042
{
1043
  int reg = BITS (16, 19) & 7;
1044
 
1045
  MMUReg[reg] = value;
1046
 
1047
  if (reg == 1)
1048
    {
1049
      ARMword p,d,l,b;
1050
 
1051
      p = state->prog32Sig;
1052
      d = state->data32Sig;
1053
      l = state->lateabtSig;
1054
      b = state->bigendSig;
1055
 
1056
      state->prog32Sig  = value >> 4 & 1;
1057
      state->data32Sig  = value >> 5 & 1;
1058
      state->lateabtSig = value >> 6 & 1;
1059
      state->bigendSig  = value >> 7 & 1;
1060
 
1061
      if (   p != state->prog32Sig
1062
          || d != state->data32Sig
1063
          || l != state->lateabtSig
1064
          || b != state->bigendSig)
1065
        /* Force ARMulator to notice these now.  */
1066
        state->Emulate = CHANGEMODE;
1067
    }
1068
 
1069
  return ARMul_DONE;
1070
}
1071
 
1072
static unsigned
1073
MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
1074
{
1075
  if (reg == 0)
1076
    *value = 0x41440110;
1077
  else if (reg < 8)
1078
    *value = MMUReg[reg];
1079
 
1080
  return TRUE;
1081
}
1082
 
1083
static unsigned
1084
MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
1085
{
1086
  if (reg < 8)
1087
    MMUReg[reg] = value;
1088
 
1089
  if (reg == 1)
1090
    {
1091
      ARMword p,d,l,b;
1092
 
1093
      p = state->prog32Sig;
1094
      d = state->data32Sig;
1095
      l = state->lateabtSig;
1096
      b = state->bigendSig;
1097
 
1098
      state->prog32Sig  = value >> 4 & 1;
1099
      state->data32Sig  = value >> 5 & 1;
1100
      state->lateabtSig = value >> 6 & 1;
1101
      state->bigendSig  = value >> 7 & 1;
1102
 
1103
      if (   p != state->prog32Sig
1104
          || d != state->data32Sig
1105
          || l != state->lateabtSig
1106
          || b != state->bigendSig)
1107
        /* Force ARMulator to notice these now.  */
1108
        state->Emulate = CHANGEMODE;
1109
    }
1110
 
1111
  return TRUE;
1112
}
1113
 
1114
 
1115
/* What follows is the Validation Suite Coprocessor.  It uses two
1116
   co-processor numbers (4 and 5) and has the follwing functionality.
1117
   Sixteen registers.  Both co-processor nuimbers can be used in an MCR
1118
   and MRC to access these registers.  CP 4 can LDC and STC to and from
1119
   the registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of
1120
   cycles specified by a CP register.  CP 5 CDP 1 issues a FIQ after a
1121
   number of cycles (specified in a CP register), CDP 2 issues an IRQW
1122
   in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
1123
   stores a 32 bit time value in a CP register (actually it's the total
1124
   number of N, S, I, C and F cyles).  */
1125
 
1126
static ARMword ValReg[16];
1127
 
1128
static unsigned
1129
ValLDC (ARMul_State * state ATTRIBUTE_UNUSED,
1130
        unsigned      type,
1131
        ARMword       instr,
1132
        ARMword        data)
1133
{
1134
  static unsigned words;
1135
 
1136
  if (type != ARMul_DATA)
1137
    words = 0;
1138
  else
1139
    {
1140
      ValReg[BITS (12, 15)] = data;
1141
 
1142
      if (BIT (22))
1143
        /* It's a long access, get two words.  */
1144
        if (words++ != 4)
1145
          return ARMul_INC;
1146
    }
1147
 
1148
  return ARMul_DONE;
1149
}
1150
 
1151
static unsigned
1152
ValSTC (ARMul_State * state ATTRIBUTE_UNUSED,
1153
        unsigned      type,
1154
        ARMword       instr,
1155
        ARMword *     data)
1156
{
1157
  static unsigned words;
1158
 
1159
  if (type != ARMul_DATA)
1160
    words = 0;
1161
  else
1162
    {
1163
      * data = ValReg[BITS (12, 15)];
1164
 
1165
      if (BIT (22))
1166
        /* It's a long access, get two words.  */
1167
        if (words++ != 4)
1168
          return ARMul_INC;
1169
    }
1170
 
1171
  return ARMul_DONE;
1172
}
1173
 
1174
static unsigned
1175
ValMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1176
        unsigned      type  ATTRIBUTE_UNUSED,
1177
        ARMword       instr,
1178
        ARMword *     value)
1179
{
1180
  *value = ValReg[BITS (16, 19)];
1181
 
1182
  return ARMul_DONE;
1183
}
1184
 
1185
static unsigned
1186
ValMCR (ARMul_State * state ATTRIBUTE_UNUSED,
1187
        unsigned      type  ATTRIBUTE_UNUSED,
1188
        ARMword       instr,
1189
        ARMword       value)
1190
{
1191
  ValReg[BITS (16, 19)] = value;
1192
 
1193
  return ARMul_DONE;
1194
}
1195
 
1196
static unsigned
1197
ValCDP (ARMul_State * state, unsigned type, ARMword instr)
1198
{
1199
  static unsigned long finish = 0;
1200
 
1201
  if (BITS (20, 23) != 0)
1202
    return ARMul_CANT;
1203
 
1204
  if (type == ARMul_FIRST)
1205
    {
1206
      ARMword howlong;
1207
 
1208
      howlong = ValReg[BITS (0, 3)];
1209
 
1210
      /* First cycle of a busy wait.  */
1211
      finish = ARMul_Time (state) + howlong;
1212
 
1213
      return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
1214
    }
1215
  else if (type == ARMul_BUSY)
1216
    {
1217
      if (ARMul_Time (state) >= finish)
1218
        return ARMul_DONE;
1219
      else
1220
        return ARMul_BUSY;
1221
    }
1222
 
1223
  return ARMul_CANT;
1224
}
1225
 
1226
static unsigned
1227
DoAFIQ (ARMul_State * state)
1228
{
1229
  state->NfiqSig = LOW;
1230
  state->Exception++;
1231
  return 0;
1232
}
1233
 
1234
static unsigned
1235
DoAIRQ (ARMul_State * state)
1236
{
1237
  state->NirqSig = LOW;
1238
  state->Exception++;
1239
  return 0;
1240
}
1241
 
1242
static unsigned
1243
IntCDP (ARMul_State * state, unsigned type, ARMword instr)
1244
{
1245
  static unsigned long finish;
1246
  ARMword howlong;
1247
 
1248
  howlong = ValReg[BITS (0, 3)];
1249
 
1250
  switch ((int) BITS (20, 23))
1251
    {
1252
    case 0:
1253
      if (type == ARMul_FIRST)
1254
        {
1255
          /* First cycle of a busy wait.  */
1256
          finish = ARMul_Time (state) + howlong;
1257
 
1258
          return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
1259
        }
1260
      else if (type == ARMul_BUSY)
1261
        {
1262
          if (ARMul_Time (state) >= finish)
1263
            return ARMul_DONE;
1264
          else
1265
            return ARMul_BUSY;
1266
        }
1267
      return ARMul_DONE;
1268
 
1269
    case 1:
1270
      if (howlong == 0)
1271
        ARMul_Abort (state, ARMul_FIQV);
1272
      else
1273
        ARMul_ScheduleEvent (state, howlong, DoAFIQ);
1274
      return ARMul_DONE;
1275
 
1276
    case 2:
1277
      if (howlong == 0)
1278
        ARMul_Abort (state, ARMul_IRQV);
1279
      else
1280
        ARMul_ScheduleEvent (state, howlong, DoAIRQ);
1281
      return ARMul_DONE;
1282
 
1283
    case 3:
1284
      state->NfiqSig = HIGH;
1285
      state->Exception--;
1286
      return ARMul_DONE;
1287
 
1288
    case 4:
1289
      state->NirqSig = HIGH;
1290
      state->Exception--;
1291
      return ARMul_DONE;
1292
 
1293
    case 5:
1294
      ValReg[BITS (0, 3)] = ARMul_Time (state);
1295
      return ARMul_DONE;
1296
    }
1297
 
1298
  return ARMul_CANT;
1299
}
1300
 
1301
/***************************************************************************\
1302
*         Install co-processor instruction handlers in this routine         *
1303
\***************************************************************************/
1304
 
1305
unsigned
1306
ARMul_CoProInit (ARMul_State * state)
1307
{
1308
  unsigned int i;
1309
 
1310
  /* Initialise tham all first.  */
1311
  for (i = 0; i < 16; i++)
1312
    ARMul_CoProDetach (state, i);
1313
 
1314
  /* Install CoPro Instruction handlers here.
1315
     The format is:
1316
     ARMul_CoProAttach (state, CP Number,
1317
                        Init routine, Exit routine
1318
                        LDC routine, STC routine,
1319
                        MRC routine, MCR routine,
1320
                        CDP routine,
1321
                        Read Reg routine, Write Reg routine).  */
1322
  ARMul_CoProAttach (state, 4, NULL, NULL,
1323
                     ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
1324
 
1325
  ARMul_CoProAttach (state, 5, NULL, NULL,
1326
                     NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL);
1327
 
1328
  ARMul_CoProAttach (state, 15, MMUInit, NULL,
1329
                     NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
1330
 
1331
  ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
1332
                     XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
1333
                     XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
1334
                     XScale_cp13_write_reg);
1335
 
1336
  ARMul_CoProAttach (state, 14, XScale_cp14_init, NULL,
1337
                     XScale_cp14_LDC, XScale_cp14_STC, XScale_cp14_MRC,
1338
                     XScale_cp14_MCR, NULL, XScale_cp14_read_reg,
1339
                     XScale_cp14_write_reg);
1340
 
1341
  ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL,
1342
                     NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR,
1343
                     NULL, XScale_cp15_read_reg, XScale_cp15_write_reg);
1344
 
1345
  /* No handlers below here.  */
1346
 
1347
  /* Call all the initialisation routines.  */
1348
  for (i = 0; i < 16; i++)
1349
    if (state->CPInit[i])
1350
      (state->CPInit[i]) (state);
1351
 
1352
  return TRUE;
1353
}
1354
 
1355
/***************************************************************************\
1356
*         Install co-processor finalisation routines in this routine        *
1357
\***************************************************************************/
1358
 
1359
void
1360
ARMul_CoProExit (ARMul_State * state)
1361
{
1362
  register unsigned i;
1363
 
1364
  for (i = 0; i < 16; i++)
1365
    if (state->CPExit[i])
1366
      (state->CPExit[i]) (state);
1367
 
1368
  for (i = 0; i < 16; i++)       /* Detach all handlers.  */
1369
    ARMul_CoProDetach (state, i);
1370
}
1371
 
1372
/***************************************************************************\
1373
*              Routines to hook Co-processors into ARMulator                 *
1374
\***************************************************************************/
1375
 
1376
void
1377
ARMul_CoProAttach (ARMul_State *    state,
1378
                   unsigned         number,
1379
                   ARMul_CPInits *  init,
1380
                   ARMul_CPExits *  exit,
1381
                   ARMul_LDCs *     ldc,
1382
                   ARMul_STCs *     stc,
1383
                   ARMul_MRCs *     mrc,
1384
                   ARMul_MCRs *     mcr,
1385
                   ARMul_CDPs *     cdp,
1386
                   ARMul_CPReads *  read,
1387
                   ARMul_CPWrites * write)
1388
{
1389
  if (init != NULL)
1390
    state->CPInit[number] = init;
1391
  if (exit != NULL)
1392
    state->CPExit[number] = exit;
1393
  if (ldc != NULL)
1394
    state->LDC[number] = ldc;
1395
  if (stc != NULL)
1396
    state->STC[number] = stc;
1397
  if (mrc != NULL)
1398
    state->MRC[number] = mrc;
1399
  if (mcr != NULL)
1400
    state->MCR[number] = mcr;
1401
  if (cdp != NULL)
1402
    state->CDP[number] = cdp;
1403
  if (read != NULL)
1404
    state->CPRead[number] = read;
1405
  if (write != NULL)
1406
    state->CPWrite[number] = write;
1407
}
1408
 
1409
void
1410
ARMul_CoProDetach (ARMul_State * state, unsigned number)
1411
{
1412
  ARMul_CoProAttach (state, number, NULL, NULL,
1413
                     NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
1414
                     NoCoPro3R, NULL, NULL);
1415
 
1416
  state->CPInit[number] = NULL;
1417
  state->CPExit[number] = NULL;
1418
  state->CPRead[number] = NULL;
1419
  state->CPWrite[number] = NULL;
1420
}

powered by: WebSVN 2.1.0

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