* XScale coprocessor support.
[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"
917bca4f 19#include "armos.h"
c1a72ffd 20#include "armemu.h"
6d358e86 21#include "ansidecl.h"
c906108c 22
f1129fb8 23/* Dummy Co-processors. */
c906108c 24
f1129fb8
NC
25static unsigned
26NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
27 unsigned a ATTRIBUTE_UNUSED,
28 ARMword b ATTRIBUTE_UNUSED)
29{
30 return ARMul_CANT;
31}
c906108c 32
f1129fb8
NC
33static unsigned
34NoCoPro4R (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
42static unsigned
43NoCoPro4W (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}
c906108c 50
f1129fb8 51/* The XScale Co-processors. */
c906108c 52
f1129fb8
NC
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. */
58static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
59static 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. */
62static ARMword XScale_cp15_DBR1;
63static ARMword XScale_cp15_DBCON;
64static ARMword XScale_cp15_IBCR0;
65static ARMword XScale_cp15_IBCR1;
66
67static unsigned
68XScale_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
91static unsigned
92check_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 0 5
134 0 6
135 0 7
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 0 5
157 0 6
158 0 7
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
214void
917bca4f 215write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned CRm, ARMword value)
f1129fb8
NC
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;
c3ae2f98
MG
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 }
f1129fb8
NC
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
917bca4f 337/* Return the value in a cp15 register. */
f1129fb8 338
917bca4f 339ARMword
f1129fb8
NC
340read_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
368static unsigned
369XScale_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)
917bca4f 377 write_cp15_reg (state, reg, 0, 0, data);
f1129fb8
NC
378
379 return result;
380}
381
382static unsigned
383XScale_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
396static unsigned
397XScale_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
415static unsigned
416XScale_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)
917bca4f 429 write_cp15_reg (state, reg, opcode_2, CRm, value);
f1129fb8
NC
430
431 return result;
432}
433
434static unsigned
435XScale_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
446static unsigned
447XScale_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. */
917bca4f 453 write_cp15_reg (state, reg, 0, 0, value);
f1129fb8
NC
454
455 return TRUE;
456}
457
c3ae2f98
MG
458/***************************************************************************\
459* Check for special XScale memory access features *
460\***************************************************************************/
461void
462XScale_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\***************************************************************************/
521void
522XScale_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. */
532int
533XScale_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
f1129fb8
NC
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
561static ARMword XScale_cp13_CR0_Regs[16];
562static ARMword XScale_cp13_CR1_Regs[16];
563
564static unsigned
565XScale_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
578static unsigned
579check_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
617static void
618write_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
687static ARMword
688read_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
698static unsigned
699XScale_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
712static unsigned
713XScale_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
726static unsigned
727XScale_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
744static unsigned
745XScale_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
762static unsigned
763XScale_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
777static unsigned
778XScale_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
795static ARMword XScale_cp14_Regs[16];
796
797static unsigned
798XScale_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
808static unsigned
809check_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
836void
837write_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;
c3ae2f98
MG
844
845 /* Reset the clock counter if necessary */
846 if (value & ARMul_CP14_R0_CLKRST)
847 XScale_cp14_Regs [1] = 0;
f1129fb8
NC
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
900ARMword
901read_cp14_reg (unsigned reg)
902{
903 return XScale_cp14_Regs [reg];
904}
905
906static unsigned
907XScale_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
920static unsigned
921XScale_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
934static unsigned
935XScale_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
954static unsigned
955XScale_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
974static unsigned
975XScale_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
987static unsigned
988XScale_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}
c906108c
SS
999
1000/* Here's ARMulator's MMU definition. A few things to note:
f1129fb8
NC
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. */
c906108c 1007
dfcd3bfb 1008static ARMword MMUReg[8];
c906108c 1009
dfcd3bfb
JM
1010static unsigned
1011MMUInit (ARMul_State * state)
1012{
1013 MMUReg[1] = state->prog32Sig << 4 |
1014 state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
f1129fb8 1015
dfcd3bfb 1016 ARMul_ConsolePrint (state, ", MMU present");
f1129fb8
NC
1017
1018 return TRUE;
dfcd3bfb
JM
1019}
1020
1021static unsigned
f1129fb8
NC
1022MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1023 unsigned type ATTRIBUTE_UNUSED,
1024 ARMword instr,
1025 ARMword * value)
dfcd3bfb
JM
1026{
1027 int reg = BITS (16, 19) & 7;
1028
1029 if (reg == 0)
1030 *value = 0x41440110;
1031 else
1032 *value = MMUReg[reg];
f1129fb8
NC
1033
1034 return ARMul_DONE;
c906108c
SS
1035}
1036
dfcd3bfb 1037static unsigned
f1129fb8
NC
1038MMUMCR (ARMul_State * state,
1039 unsigned type ATTRIBUTE_UNUSED,
1040 ARMword instr,
1041 ARMword value)
dfcd3bfb
JM
1042{
1043 int reg = BITS (16, 19) & 7;
1044
1045 MMUReg[reg] = value;
f1129fb8 1046
dfcd3bfb
JM
1047 if (reg == 1)
1048 {
c1a72ffd
NC
1049 ARMword p,d,l,b;
1050
1051 p = state->prog32Sig;
1052 d = state->data32Sig;
1053 l = state->lateabtSig;
1054 b = state->bigendSig;
1055
f1129fb8
NC
1056 state->prog32Sig = value >> 4 & 1;
1057 state->data32Sig = value >> 5 & 1;
dfcd3bfb 1058 state->lateabtSig = value >> 6 & 1;
f1129fb8 1059 state->bigendSig = value >> 7 & 1;
c1a72ffd 1060
f1129fb8 1061 if ( p != state->prog32Sig
c1a72ffd
NC
1062 || d != state->data32Sig
1063 || l != state->lateabtSig
1064 || b != state->bigendSig)
f1129fb8
NC
1065 /* Force ARMulator to notice these now. */
1066 state->Emulate = CHANGEMODE;
c906108c 1067 }
f1129fb8 1068
c1a72ffd 1069 return ARMul_DONE;
dfcd3bfb
JM
1070}
1071
dfcd3bfb 1072static unsigned
6d358e86 1073MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
dfcd3bfb
JM
1074{
1075 if (reg == 0)
1076 *value = 0x41440110;
1077 else if (reg < 8)
1078 *value = MMUReg[reg];
f1129fb8
NC
1079
1080 return TRUE;
dfcd3bfb
JM
1081}
1082
1083static unsigned
1084MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
1085{
1086 if (reg < 8)
1087 MMUReg[reg] = value;
f1129fb8 1088
dfcd3bfb
JM
1089 if (reg == 1)
1090 {
c1a72ffd
NC
1091 ARMword p,d,l,b;
1092
1093 p = state->prog32Sig;
1094 d = state->data32Sig;
1095 l = state->lateabtSig;
1096 b = state->bigendSig;
1097
f1129fb8
NC
1098 state->prog32Sig = value >> 4 & 1;
1099 state->data32Sig = value >> 5 & 1;
dfcd3bfb 1100 state->lateabtSig = value >> 6 & 1;
f1129fb8 1101 state->bigendSig = value >> 7 & 1;
c1a72ffd 1102
f1129fb8 1103 if ( p != state->prog32Sig
c1a72ffd
NC
1104 || d != state->data32Sig
1105 || l != state->lateabtSig
1106 || b != state->bigendSig)
f1129fb8
NC
1107 /* Force ARMulator to notice these now. */
1108 state->Emulate = CHANGEMODE;
c906108c 1109 }
f1129fb8 1110
c1a72ffd 1111 return TRUE;
dfcd3bfb 1112}
c906108c
SS
1113
1114
1115/* What follows is the Validation Suite Coprocessor. It uses two
f1129fb8
NC
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). */
c906108c 1125
dfcd3bfb 1126static ARMword ValReg[16];
c906108c 1127
dfcd3bfb 1128static unsigned
f1129fb8
NC
1129ValLDC (ARMul_State * state ATTRIBUTE_UNUSED,
1130 unsigned type,
1131 ARMword instr,
1132 ARMword data)
dfcd3bfb
JM
1133{
1134 static unsigned words;
c906108c 1135
dfcd3bfb 1136 if (type != ARMul_DATA)
f1129fb8 1137 words = 0;
dfcd3bfb 1138 else
f1129fb8 1139 {
dfcd3bfb 1140 ValReg[BITS (12, 15)] = data;
f1129fb8
NC
1141
1142 if (BIT (22))
1143 /* It's a long access, get two words. */
1144 if (words++ != 4)
1145 return ARMul_INC;
c906108c 1146 }
f1129fb8
NC
1147
1148 return ARMul_DONE;
dfcd3bfb 1149}
c906108c 1150
dfcd3bfb 1151static unsigned
f1129fb8
NC
1152ValSTC (ARMul_State * state ATTRIBUTE_UNUSED,
1153 unsigned type,
1154 ARMword instr,
1155 ARMword * data)
dfcd3bfb
JM
1156{
1157 static unsigned words;
c906108c 1158
dfcd3bfb 1159 if (type != ARMul_DATA)
f1129fb8 1160 words = 0;
dfcd3bfb 1161 else
f1129fb8
NC
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;
dfcd3bfb 1169 }
f1129fb8
NC
1170
1171 return ARMul_DONE;
dfcd3bfb 1172}
c906108c 1173
dfcd3bfb 1174static unsigned
f1129fb8
NC
1175ValMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1176 unsigned type ATTRIBUTE_UNUSED,
1177 ARMword instr,
1178 ARMword * value)
c906108c 1179{
dfcd3bfb 1180 *value = ValReg[BITS (16, 19)];
f1129fb8
NC
1181
1182 return ARMul_DONE;
dfcd3bfb 1183}
c906108c 1184
dfcd3bfb 1185static unsigned
f1129fb8
NC
1186ValMCR (ARMul_State * state ATTRIBUTE_UNUSED,
1187 unsigned type ATTRIBUTE_UNUSED,
1188 ARMword instr,
1189 ARMword value)
c906108c 1190{
dfcd3bfb 1191 ValReg[BITS (16, 19)] = value;
f1129fb8
NC
1192
1193 return ARMul_DONE;
dfcd3bfb 1194}
c906108c 1195
dfcd3bfb
JM
1196static unsigned
1197ValCDP (ARMul_State * state, unsigned type, ARMword instr)
c906108c 1198{
dfcd3bfb 1199 static unsigned long finish = 0;
dfcd3bfb 1200
f1129fb8
NC
1201 if (BITS (20, 23) != 0)
1202 return ARMul_CANT;
1203
1204 if (type == ARMul_FIRST)
dfcd3bfb 1205 {
f1129fb8
NC
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;
c906108c 1221 }
f1129fb8
NC
1222
1223 return ARMul_CANT;
dfcd3bfb 1224}
c906108c 1225
dfcd3bfb
JM
1226static unsigned
1227DoAFIQ (ARMul_State * state)
1228{
1229 state->NfiqSig = LOW;
1230 state->Exception++;
f1129fb8 1231 return 0;
c906108c
SS
1232}
1233
dfcd3bfb
JM
1234static unsigned
1235DoAIRQ (ARMul_State * state)
1236{
1237 state->NirqSig = LOW;
1238 state->Exception++;
f1129fb8 1239 return 0;
c906108c
SS
1240}
1241
dfcd3bfb
JM
1242static unsigned
1243IntCDP (ARMul_State * state, unsigned type, ARMword instr)
1244{
1245 static unsigned long finish;
1246 ARMword howlong;
1247
1248 howlong = ValReg[BITS (0, 3)];
f1129fb8 1249
dfcd3bfb
JM
1250 switch ((int) BITS (20, 23))
1251 {
1252 case 0:
1253 if (type == ARMul_FIRST)
f1129fb8
NC
1254 {
1255 /* First cycle of a busy wait. */
dfcd3bfb 1256 finish = ARMul_Time (state) + howlong;
f1129fb8
NC
1257
1258 return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
dfcd3bfb
JM
1259 }
1260 else if (type == ARMul_BUSY)
1261 {
1262 if (ARMul_Time (state) >= finish)
f1129fb8 1263 return ARMul_DONE;
dfcd3bfb 1264 else
f1129fb8 1265 return ARMul_BUSY;
dfcd3bfb 1266 }
f1129fb8
NC
1267 return ARMul_DONE;
1268
dfcd3bfb
JM
1269 case 1:
1270 if (howlong == 0)
1271 ARMul_Abort (state, ARMul_FIQV);
1272 else
1273 ARMul_ScheduleEvent (state, howlong, DoAFIQ);
f1129fb8
NC
1274 return ARMul_DONE;
1275
dfcd3bfb
JM
1276 case 2:
1277 if (howlong == 0)
1278 ARMul_Abort (state, ARMul_IRQV);
1279 else
1280 ARMul_ScheduleEvent (state, howlong, DoAIRQ);
f1129fb8
NC
1281 return ARMul_DONE;
1282
dfcd3bfb
JM
1283 case 3:
1284 state->NfiqSig = HIGH;
1285 state->Exception--;
f1129fb8
NC
1286 return ARMul_DONE;
1287
dfcd3bfb
JM
1288 case 4:
1289 state->NirqSig = HIGH;
1290 state->Exception--;
f1129fb8
NC
1291 return ARMul_DONE;
1292
dfcd3bfb
JM
1293 case 5:
1294 ValReg[BITS (0, 3)] = ARMul_Time (state);
f1129fb8 1295 return ARMul_DONE;
c906108c 1296 }
f1129fb8
NC
1297
1298 return ARMul_CANT;
dfcd3bfb 1299}
c906108c
SS
1300
1301/***************************************************************************\
1302* Install co-processor instruction handlers in this routine *
1303\***************************************************************************/
1304
dfcd3bfb
JM
1305unsigned
1306ARMul_CoProInit (ARMul_State * state)
1307{
f1129fb8 1308 unsigned int i;
c906108c 1309
f1129fb8
NC
1310 /* Initialise tham all first. */
1311 for (i = 0; i < 16; i++)
dfcd3bfb 1312 ARMul_CoProDetach (state, i);
c906108c 1313
f1129fb8
NC
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). */
dfcd3bfb
JM
1322 ARMul_CoProAttach (state, 4, NULL, NULL,
1323 ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
c906108c 1324
dfcd3bfb
JM
1325 ARMul_CoProAttach (state, 5, NULL, NULL,
1326 NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL);
c906108c 1327
dfcd3bfb
JM
1328 ARMul_CoProAttach (state, 15, MMUInit, NULL,
1329 NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
c906108c 1330
f1129fb8
NC
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);
c906108c 1344
f1129fb8 1345 /* No handlers below here. */
c906108c 1346
f1129fb8
NC
1347 /* Call all the initialisation routines. */
1348 for (i = 0; i < 16; i++)
dfcd3bfb
JM
1349 if (state->CPInit[i])
1350 (state->CPInit[i]) (state);
f1129fb8
NC
1351
1352 return TRUE;
dfcd3bfb 1353}
c906108c
SS
1354
1355/***************************************************************************\
1356* Install co-processor finalisation routines in this routine *
1357\***************************************************************************/
1358
dfcd3bfb
JM
1359void
1360ARMul_CoProExit (ARMul_State * state)
1361{
1362 register unsigned i;
c906108c 1363
dfcd3bfb 1364 for (i = 0; i < 16; i++)
c906108c 1365 if (state->CPExit[i])
dfcd3bfb 1366 (state->CPExit[i]) (state);
f1129fb8
NC
1367
1368 for (i = 0; i < 16; i++) /* Detach all handlers. */
dfcd3bfb
JM
1369 ARMul_CoProDetach (state, i);
1370}
c906108c
SS
1371
1372/***************************************************************************\
1373* Routines to hook Co-processors into ARMulator *
1374\***************************************************************************/
1375
dfcd3bfb 1376void
f1129fb8
NC
1377ARMul_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)
dfcd3bfb
JM
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;
c906108c
SS
1407}
1408
dfcd3bfb
JM
1409void
1410ARMul_CoProDetach (ARMul_State * state, unsigned number)
1411{
1412 ARMul_CoProAttach (state, number, NULL, NULL,
1413 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
1414 NoCoPro3R, NULL, NULL);
f1129fb8 1415
dfcd3bfb
JM
1416 state->CPInit[number] = NULL;
1417 state->CPExit[number] = NULL;
1418 state->CPRead[number] = NULL;
1419 state->CPWrite[number] = NULL;
c906108c 1420}
This page took 0.163973 seconds and 4 git commands to generate.