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