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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [arm/] [armcopro.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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