PR ld/15323
[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
3fd725ef 6 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
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
51b318de 15 along with this program; if not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
16
17#include "armdefs.h"
917bca4f 18#include "armos.h"
c1a72ffd 19#include "armemu.h"
6d358e86 20#include "ansidecl.h"
0f026fd0 21#include "iwmmxt.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 53/* Coprocessor 15: System Control. */
ff44f8e3
NC
54static void write_cp14_reg (unsigned, ARMword);
55static ARMword read_cp14_reg (unsigned);
f1129fb8
NC
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. */
60static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
61static 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. */
64static ARMword XScale_cp15_DBR1;
65static ARMword XScale_cp15_DBCON;
66static ARMword XScale_cp15_IBCR0;
67static ARMword XScale_cp15_IBCR1;
68
69static unsigned
70XScale_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;
f1129fb8
NC
88}
89
90/* Check an access to a register. */
91
92static unsigned
93check_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;
ff44f8e3 106
f1129fb8
NC
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 0 5
135 0 6
136 0 7
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;
ff44f8e3 153
f1129fb8
NC
154 case 8:
155 /* Permissable combinations:
156 Opcode_2 CRm
157 0 5
158 0 6
159 0 7
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 }
ff44f8e3 209
f1129fb8
NC
210 return ARMul_DONE;
211}
212
213/* Store a value into one of coprocessor 15's registers. */
214
ff44f8e3
NC
215static void
216write_cp15_reg (ARMul_State * state,
217 unsigned reg,
218 unsigned opcode_2,
219 unsigned CRm,
220 ARMword value)
f1129fb8
NC
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;
ff44f8e3 234
f1129fb8
NC
235 default:
236 return;
237 }
ff44f8e3 238
f1129fb8
NC
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;
c3ae2f98 254
10b57fcb 255 /* Change the endianness if necessary. */
c3ae2f98
MG
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 }
f1129fb8
NC
263 break;
264
265 case 2: /* Translation Table Base. */
266 /* Only BITS (31, 14) can be written. */
267 value &= 0xffffc000;
268 break;
ff44f8e3 269
f1129fb8
NC
270 case 3: /* Domain Access Control. */
271 /* All bits writable. */
272 break;
ff44f8e3 273
f1129fb8
NC
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;
ff44f8e3 327
f1129fb8
NC
328 /* Only BITS (13, 0) may be written. */
329 value &= 0x00003fff;
330 break;
ff44f8e3 331
f1129fb8
NC
332 default:
333 return;
334 }
335
336 XScale_cp15_opcode_2_is_0_Regs [reg] = value;
337 }
ff44f8e3 338
f1129fb8
NC
339 return;
340}
341
917bca4f 342/* Return the value in a cp15 register. */
f1129fb8 343
917bca4f 344ARMword
f1129fb8
NC
345read_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 }
ff44f8e3 364
f1129fb8
NC
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
373static unsigned
374XScale_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);
ff44f8e3 380
f1129fb8 381 if (result == ARMul_DONE && type == ARMul_DATA)
917bca4f 382 write_cp15_reg (state, reg, 0, 0, data);
f1129fb8
NC
383
384 return result;
385}
386
387static unsigned
388XScale_cp15_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
389{
390 unsigned reg = BITS (12, 15);
391 unsigned result;
ff44f8e3 392
f1129fb8 393 result = check_cp15_access (state, reg, 0, 0, 0);
ff44f8e3 394
f1129fb8
NC
395 if (result == ARMul_DONE && type == ARMul_DATA)
396 * data = read_cp15_reg (reg, 0, 0);
ff44f8e3 397
f1129fb8
NC
398 return result;
399}
400
401static unsigned
402XScale_cp15_MRC (ARMul_State * state,
ff44f8e3
NC
403 unsigned type ATTRIBUTE_UNUSED,
404 ARMword instr,
405 ARMword * value)
f1129fb8
NC
406{
407 unsigned opcode_2 = BITS (5, 7);
408 unsigned CRm = BITS (0, 3);
409 unsigned reg = BITS (16, 19);
410 unsigned result;
ff44f8e3 411
f1129fb8 412 result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
ff44f8e3 413
f1129fb8
NC
414 if (result == ARMul_DONE)
415 * value = read_cp15_reg (reg, opcode_2, CRm);
ff44f8e3 416
f1129fb8
NC
417 return result;
418}
419
420static unsigned
421XScale_cp15_MCR (ARMul_State * state,
ff44f8e3
NC
422 unsigned type ATTRIBUTE_UNUSED,
423 ARMword instr,
424 ARMword value)
f1129fb8
NC
425{
426 unsigned opcode_2 = BITS (5, 7);
427 unsigned CRm = BITS (0, 3);
428 unsigned reg = BITS (16, 19);
429 unsigned result;
ff44f8e3 430
f1129fb8 431 result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
ff44f8e3 432
f1129fb8 433 if (result == ARMul_DONE)
917bca4f 434 write_cp15_reg (state, reg, opcode_2, CRm, value);
ff44f8e3 435
f1129fb8
NC
436 return result;
437}
438
439static unsigned
440XScale_cp15_read_reg (ARMul_State * state ATTRIBUTE_UNUSED,
ff44f8e3
NC
441 unsigned reg,
442 ARMword * value)
f1129fb8
NC
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);
ff44f8e3 447
f1129fb8
NC
448 return TRUE;
449}
450
451static unsigned
452XScale_cp15_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
ff44f8e3
NC
453 unsigned reg,
454 ARMword value)
f1129fb8
NC
455{
456 /* FIXME: Not sure what to do about the alternative register set
457 here. For now default to just accessing CRm == 0 registers. */
917bca4f 458 write_cp15_reg (state, reg, 0, 0, value);
ff44f8e3 459
f1129fb8
NC
460 return TRUE;
461}
462
ff44f8e3
NC
463/* Check for special XScale memory access features. */
464
c3ae2f98
MG
465void
466XScale_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);
10b57fcb
NC
477 if (r0 && (* address & 0xfe000000) == 0)
478 * address |= r0;
c3ae2f98
MG
479
480 /* Check alignment fault enable/disable. */
10b57fcb 481 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN) && (* address & 3))
5aa682b2
NC
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 }
c3ae2f98
MG
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))
10b57fcb 504 && ((* address & ~r1) == (r0 & ~r1)))
c3ae2f98
MG
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))
10b57fcb 513 && ((* address & ~3) == (r0 & ~3)))
c3ae2f98
MG
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))
10b57fcb 521 && ((* address & ~3) == (r1 & ~3)))
c3ae2f98
MG
522 {
523 XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
524 ARMul_OSHandleSWI (state, SWI_Breakpoint);
525 }
526 }
527}
528
10b57fcb 529/* Set the XScale FSR and FAR registers. */
ff44f8e3 530
c3ae2f98 531void
ff44f8e3 532XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword far)
c3ae2f98
MG
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. */
ff44f8e3 542
c3ae2f98
MG
543int
544XScale_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
f1129fb8
NC
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
572static ARMword XScale_cp13_CR0_Regs[16];
573static ARMword XScale_cp13_CR1_Regs[16];
574
575static unsigned
576XScale_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
589static unsigned
590check_cp13_access (ARMul_State * state,
591 unsigned reg,
592 unsigned CRm,
593 unsigned opcode_1,
594 unsigned opcode_2)
595{
8b2440b7 596 /* Do not allow access to these registers in USER mode. */
f1129fb8
NC
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;
ff44f8e3
NC
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))
f1129fb8 607 return ARMul_CANT;
ff44f8e3 608
f1129fb8 609 /* Registers 0, 4 and 8 are defined when CRm == 0.
8b2440b7 610 Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
f1129fb8
NC
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 {
8b2440b7 619 if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
f1129fb8
NC
620 return ARMul_DONE;
621 }
622
623 return ARMul_CANT;
624}
625
626/* Store a value into one of coprocessor 13's registers. */
627
628static void
629write_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;
ff44f8e3 640
f1129fb8
NC
641 case 4: /* INTSRC */
642 /* No bits may be written. */
643 return;
ff44f8e3 644
f1129fb8
NC
645 case 8: /* INTSTR */
646 /* Only BITS (1:0) can be written. */
647 value &= 0x3;
648 break;
ff44f8e3 649
f1129fb8
NC
650 default:
651 /* Should not happen. Ignore any writes to unimplemented registers. */
652 return;
653 }
ff44f8e3 654
f1129fb8
NC
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;
ff44f8e3 667
8b2440b7
NC
668 case 1: /* BCUMOD */
669 /* Only bit 0 is accecssible. */
670 value &= 1;
671 value |= XScale_cp13_CR1_Regs[1] & ~ 1;
672 break;
673
f1129fb8
NC
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;
ff44f8e3 685
f1129fb8
NC
686 default:
687 /* Should not happen. Ignore any writes to unimplemented registers. */
688 return;
689 }
ff44f8e3 690
f1129fb8
NC
691 XScale_cp13_CR1_Regs [reg] = value;
692 break;
693
694 default:
695 /* Should not happen. */
696 break;
697 }
ff44f8e3 698
f1129fb8
NC
699 return;
700}
701
702/* Return the value in a cp13 register. */
703
704static ARMword
705read_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
715static unsigned
716XScale_cp13_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
717{
718 unsigned reg = BITS (12, 15);
719 unsigned result;
ff44f8e3 720
f1129fb8 721 result = check_cp13_access (state, reg, 0, 0, 0);
ff44f8e3 722
f1129fb8
NC
723 if (result == ARMul_DONE && type == ARMul_DATA)
724 write_cp13_reg (reg, 0, data);
725
726 return result;
727}
728
729static unsigned
730XScale_cp13_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
731{
732 unsigned reg = BITS (12, 15);
733 unsigned result;
ff44f8e3 734
f1129fb8 735 result = check_cp13_access (state, reg, 0, 0, 0);
ff44f8e3 736
f1129fb8
NC
737 if (result == ARMul_DONE && type == ARMul_DATA)
738 * data = read_cp13_reg (reg, 0);
ff44f8e3 739
f1129fb8
NC
740 return result;
741}
742
743static unsigned
744XScale_cp13_MRC (ARMul_State * state,
ff44f8e3
NC
745 unsigned type ATTRIBUTE_UNUSED,
746 ARMword instr,
747 ARMword * value)
f1129fb8
NC
748{
749 unsigned CRm = BITS (0, 3);
750 unsigned reg = BITS (16, 19);
751 unsigned result;
ff44f8e3 752
f1129fb8 753 result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
ff44f8e3 754
f1129fb8
NC
755 if (result == ARMul_DONE)
756 * value = read_cp13_reg (reg, CRm);
ff44f8e3 757
f1129fb8
NC
758 return result;
759}
760
761static unsigned
762XScale_cp13_MCR (ARMul_State * state,
ff44f8e3
NC
763 unsigned type ATTRIBUTE_UNUSED,
764 ARMword instr,
765 ARMword value)
f1129fb8
NC
766{
767 unsigned CRm = BITS (0, 3);
768 unsigned reg = BITS (16, 19);
769 unsigned result;
ff44f8e3 770
f1129fb8 771 result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
ff44f8e3 772
f1129fb8
NC
773 if (result == ARMul_DONE)
774 write_cp13_reg (reg, CRm, value);
ff44f8e3 775
f1129fb8
NC
776 return result;
777}
778
779static unsigned
ff44f8e3
NC
780XScale_cp13_read_reg (ARMul_State * state ATTRIBUTE_UNUSED,
781 unsigned reg,
782 ARMword * value)
f1129fb8
NC
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);
ff44f8e3 787
f1129fb8
NC
788 return TRUE;
789}
790
791static unsigned
ff44f8e3
NC
792XScale_cp13_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
793 unsigned reg,
794 ARMword value)
f1129fb8
NC
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);
ff44f8e3 799
f1129fb8
NC
800 return TRUE;
801}
802
803/* Coprocessor 14: Performance Monitoring, Clock and Power management,
804 Software Debug. */
805
806static ARMword XScale_cp14_Regs[16];
807
808static unsigned
809XScale_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
819static unsigned
820check_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;
ff44f8e3 837
f1129fb8
NC
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
ff44f8e3 847static void
f1129fb8
NC
848write_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;
c3ae2f98 855
10b57fcb 856 /* Reset the clock counter if necessary. */
c3ae2f98
MG
857 if (value & ARMul_CP14_R0_CLKRST)
858 XScale_cp14_Regs [1] = 0;
f1129fb8
NC
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;
ff44f8e3 867
f1129fb8
NC
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.
ff44f8e3 878
f1129fb8
NC
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;
ff44f8e3 894
f1129fb8
NC
895 case 14: /* TXRXCTRL */
896 /* Only BITS (31:30) can be written. */
897 value &= 0xc0000000;
898 break;
ff44f8e3 899
f1129fb8
NC
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
911ARMword
912read_cp14_reg (unsigned reg)
913{
914 return XScale_cp14_Regs [reg];
915}
916
917static unsigned
918XScale_cp14_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
919{
920 unsigned reg = BITS (12, 15);
921 unsigned result;
ff44f8e3 922
f1129fb8 923 result = check_cp14_access (state, reg, 0, 0, 0);
ff44f8e3 924
f1129fb8
NC
925 if (result == ARMul_DONE && type == ARMul_DATA)
926 write_cp14_reg (reg, data);
927
928 return result;
929}
930
931static unsigned
932XScale_cp14_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
933{
934 unsigned reg = BITS (12, 15);
935 unsigned result;
ff44f8e3 936
f1129fb8 937 result = check_cp14_access (state, reg, 0, 0, 0);
ff44f8e3 938
f1129fb8
NC
939 if (result == ARMul_DONE && type == ARMul_DATA)
940 * data = read_cp14_reg (reg);
ff44f8e3 941
f1129fb8
NC
942 return result;
943}
944
945static unsigned
946XScale_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;
ff44f8e3 956
f1129fb8 957 result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
ff44f8e3 958
f1129fb8
NC
959 if (result == ARMul_DONE)
960 * value = read_cp14_reg (reg);
ff44f8e3 961
f1129fb8
NC
962 return result;
963}
964
965static unsigned
966XScale_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;
ff44f8e3 976
f1129fb8 977 result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
ff44f8e3 978
f1129fb8
NC
979 if (result == ARMul_DONE)
980 write_cp14_reg (reg, value);
ff44f8e3 981
f1129fb8
NC
982 return result;
983}
984
985static unsigned
986XScale_cp14_read_reg
987(
988 ARMul_State * state ATTRIBUTE_UNUSED,
989 unsigned reg,
990 ARMword * value
991)
992{
993 * value = read_cp14_reg (reg);
ff44f8e3 994
f1129fb8
NC
995 return TRUE;
996}
997
998static unsigned
999XScale_cp14_write_reg
1000(
1001 ARMul_State * state ATTRIBUTE_UNUSED,
1002 unsigned reg,
1003 ARMword value
1004)
1005{
1006 write_cp14_reg (reg, value);
ff44f8e3 1007
f1129fb8
NC
1008 return TRUE;
1009}
c906108c
SS
1010
1011/* Here's ARMulator's MMU definition. A few things to note:
f1129fb8
NC
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. */
c906108c 1018
dfcd3bfb 1019static ARMword MMUReg[8];
c906108c 1020
dfcd3bfb
JM
1021static unsigned
1022MMUInit (ARMul_State * state)
1023{
1024 MMUReg[1] = state->prog32Sig << 4 |
1025 state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
f1129fb8 1026
dfcd3bfb 1027 ARMul_ConsolePrint (state, ", MMU present");
f1129fb8
NC
1028
1029 return TRUE;
dfcd3bfb
JM
1030}
1031
1032static unsigned
f1129fb8
NC
1033MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1034 unsigned type ATTRIBUTE_UNUSED,
1035 ARMword instr,
1036 ARMword * value)
dfcd3bfb
JM
1037{
1038 int reg = BITS (16, 19) & 7;
1039
1040 if (reg == 0)
1041 *value = 0x41440110;
1042 else
1043 *value = MMUReg[reg];
f1129fb8
NC
1044
1045 return ARMul_DONE;
c906108c
SS
1046}
1047
dfcd3bfb 1048static unsigned
f1129fb8
NC
1049MMUMCR (ARMul_State * state,
1050 unsigned type ATTRIBUTE_UNUSED,
1051 ARMword instr,
1052 ARMword value)
dfcd3bfb
JM
1053{
1054 int reg = BITS (16, 19) & 7;
1055
1056 MMUReg[reg] = value;
f1129fb8 1057
dfcd3bfb
JM
1058 if (reg == 1)
1059 {
c1a72ffd
NC
1060 ARMword p,d,l,b;
1061
1062 p = state->prog32Sig;
1063 d = state->data32Sig;
1064 l = state->lateabtSig;
1065 b = state->bigendSig;
ff44f8e3 1066
f1129fb8
NC
1067 state->prog32Sig = value >> 4 & 1;
1068 state->data32Sig = value >> 5 & 1;
dfcd3bfb 1069 state->lateabtSig = value >> 6 & 1;
f1129fb8 1070 state->bigendSig = value >> 7 & 1;
c1a72ffd 1071
f1129fb8 1072 if ( p != state->prog32Sig
c1a72ffd
NC
1073 || d != state->data32Sig
1074 || l != state->lateabtSig
1075 || b != state->bigendSig)
f1129fb8
NC
1076 /* Force ARMulator to notice these now. */
1077 state->Emulate = CHANGEMODE;
c906108c 1078 }
f1129fb8 1079
c1a72ffd 1080 return ARMul_DONE;
dfcd3bfb
JM
1081}
1082
dfcd3bfb 1083static unsigned
6d358e86 1084MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
dfcd3bfb
JM
1085{
1086 if (reg == 0)
1087 *value = 0x41440110;
1088 else if (reg < 8)
1089 *value = MMUReg[reg];
f1129fb8
NC
1090
1091 return TRUE;
dfcd3bfb
JM
1092}
1093
1094static unsigned
1095MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
1096{
1097 if (reg < 8)
1098 MMUReg[reg] = value;
f1129fb8 1099
dfcd3bfb
JM
1100 if (reg == 1)
1101 {
c1a72ffd
NC
1102 ARMword p,d,l,b;
1103
1104 p = state->prog32Sig;
1105 d = state->data32Sig;
1106 l = state->lateabtSig;
1107 b = state->bigendSig;
ff44f8e3 1108
f1129fb8
NC
1109 state->prog32Sig = value >> 4 & 1;
1110 state->data32Sig = value >> 5 & 1;
dfcd3bfb 1111 state->lateabtSig = value >> 6 & 1;
f1129fb8 1112 state->bigendSig = value >> 7 & 1;
ff44f8e3 1113
f1129fb8 1114 if ( p != state->prog32Sig
c1a72ffd
NC
1115 || d != state->data32Sig
1116 || l != state->lateabtSig
1117 || b != state->bigendSig)
f1129fb8
NC
1118 /* Force ARMulator to notice these now. */
1119 state->Emulate = CHANGEMODE;
c906108c 1120 }
f1129fb8 1121
c1a72ffd 1122 return TRUE;
dfcd3bfb 1123}
c906108c
SS
1124
1125
1126/* What follows is the Validation Suite Coprocessor. It uses two
f1129fb8
NC
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). */
c906108c 1136
dfcd3bfb 1137static ARMword ValReg[16];
c906108c 1138
dfcd3bfb 1139static unsigned
f1129fb8
NC
1140ValLDC (ARMul_State * state ATTRIBUTE_UNUSED,
1141 unsigned type,
1142 ARMword instr,
1143 ARMword data)
dfcd3bfb
JM
1144{
1145 static unsigned words;
c906108c 1146
dfcd3bfb 1147 if (type != ARMul_DATA)
f1129fb8 1148 words = 0;
dfcd3bfb 1149 else
f1129fb8 1150 {
dfcd3bfb 1151 ValReg[BITS (12, 15)] = data;
f1129fb8
NC
1152
1153 if (BIT (22))
1154 /* It's a long access, get two words. */
1155 if (words++ != 4)
1156 return ARMul_INC;
c906108c 1157 }
ff44f8e3 1158
f1129fb8 1159 return ARMul_DONE;
dfcd3bfb 1160}
c906108c 1161
dfcd3bfb 1162static unsigned
f1129fb8
NC
1163ValSTC (ARMul_State * state ATTRIBUTE_UNUSED,
1164 unsigned type,
1165 ARMword instr,
1166 ARMword * data)
dfcd3bfb
JM
1167{
1168 static unsigned words;
c906108c 1169
dfcd3bfb 1170 if (type != ARMul_DATA)
f1129fb8 1171 words = 0;
dfcd3bfb 1172 else
f1129fb8
NC
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;
dfcd3bfb 1180 }
f1129fb8
NC
1181
1182 return ARMul_DONE;
dfcd3bfb 1183}
c906108c 1184
dfcd3bfb 1185static unsigned
f1129fb8
NC
1186ValMRC (ARMul_State * state ATTRIBUTE_UNUSED,
1187 unsigned type ATTRIBUTE_UNUSED,
1188 ARMword instr,
1189 ARMword * value)
c906108c 1190{
dfcd3bfb 1191 *value = ValReg[BITS (16, 19)];
f1129fb8
NC
1192
1193 return ARMul_DONE;
dfcd3bfb 1194}
c906108c 1195
dfcd3bfb 1196static unsigned
f1129fb8
NC
1197ValMCR (ARMul_State * state ATTRIBUTE_UNUSED,
1198 unsigned type ATTRIBUTE_UNUSED,
1199 ARMword instr,
1200 ARMword value)
c906108c 1201{
dfcd3bfb 1202 ValReg[BITS (16, 19)] = value;
f1129fb8
NC
1203
1204 return ARMul_DONE;
dfcd3bfb 1205}
c906108c 1206
dfcd3bfb
JM
1207static unsigned
1208ValCDP (ARMul_State * state, unsigned type, ARMword instr)
c906108c 1209{
dfcd3bfb 1210 static unsigned long finish = 0;
dfcd3bfb 1211
f1129fb8
NC
1212 if (BITS (20, 23) != 0)
1213 return ARMul_CANT;
1214
1215 if (type == ARMul_FIRST)
dfcd3bfb 1216 {
f1129fb8 1217 ARMword howlong;
ff44f8e3 1218
f1129fb8 1219 howlong = ValReg[BITS (0, 3)];
ff44f8e3 1220
f1129fb8
NC
1221 /* First cycle of a busy wait. */
1222 finish = ARMul_Time (state) + howlong;
ff44f8e3 1223
f1129fb8
NC
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;
c906108c 1232 }
ff44f8e3 1233
f1129fb8 1234 return ARMul_CANT;
dfcd3bfb 1235}
c906108c 1236
dfcd3bfb
JM
1237static unsigned
1238DoAFIQ (ARMul_State * state)
1239{
1240 state->NfiqSig = LOW;
1241 state->Exception++;
f1129fb8 1242 return 0;
c906108c
SS
1243}
1244
dfcd3bfb
JM
1245static unsigned
1246DoAIRQ (ARMul_State * state)
1247{
1248 state->NirqSig = LOW;
1249 state->Exception++;
f1129fb8 1250 return 0;
c906108c
SS
1251}
1252
dfcd3bfb
JM
1253static unsigned
1254IntCDP (ARMul_State * state, unsigned type, ARMword instr)
1255{
1256 static unsigned long finish;
1257 ARMword howlong;
1258
1259 howlong = ValReg[BITS (0, 3)];
f1129fb8 1260
dfcd3bfb
JM
1261 switch ((int) BITS (20, 23))
1262 {
1263 case 0:
1264 if (type == ARMul_FIRST)
f1129fb8
NC
1265 {
1266 /* First cycle of a busy wait. */
dfcd3bfb 1267 finish = ARMul_Time (state) + howlong;
f1129fb8
NC
1268
1269 return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
dfcd3bfb
JM
1270 }
1271 else if (type == ARMul_BUSY)
1272 {
1273 if (ARMul_Time (state) >= finish)
f1129fb8 1274 return ARMul_DONE;
dfcd3bfb 1275 else
f1129fb8 1276 return ARMul_BUSY;
dfcd3bfb 1277 }
f1129fb8 1278 return ARMul_DONE;
ff44f8e3 1279
dfcd3bfb
JM
1280 case 1:
1281 if (howlong == 0)
1282 ARMul_Abort (state, ARMul_FIQV);
1283 else
1284 ARMul_ScheduleEvent (state, howlong, DoAFIQ);
f1129fb8 1285 return ARMul_DONE;
ff44f8e3 1286
dfcd3bfb
JM
1287 case 2:
1288 if (howlong == 0)
1289 ARMul_Abort (state, ARMul_IRQV);
1290 else
1291 ARMul_ScheduleEvent (state, howlong, DoAIRQ);
f1129fb8 1292 return ARMul_DONE;
ff44f8e3 1293
dfcd3bfb
JM
1294 case 3:
1295 state->NfiqSig = HIGH;
1296 state->Exception--;
f1129fb8 1297 return ARMul_DONE;
ff44f8e3 1298
dfcd3bfb
JM
1299 case 4:
1300 state->NirqSig = HIGH;
1301 state->Exception--;
f1129fb8 1302 return ARMul_DONE;
ff44f8e3 1303
dfcd3bfb
JM
1304 case 5:
1305 ValReg[BITS (0, 3)] = ARMul_Time (state);
f1129fb8 1306 return ARMul_DONE;
c906108c 1307 }
ff44f8e3 1308
f1129fb8 1309 return ARMul_CANT;
dfcd3bfb 1310}
c906108c 1311
ff44f8e3 1312/* Install co-processor instruction handlers in this routine. */
c906108c 1313
dfcd3bfb
JM
1314unsigned
1315ARMul_CoProInit (ARMul_State * state)
1316{
f1129fb8 1317 unsigned int i;
c906108c 1318
f1129fb8
NC
1319 /* Initialise tham all first. */
1320 for (i = 0; i < 16; i++)
dfcd3bfb 1321 ARMul_CoProDetach (state, i);
c906108c 1322
f1129fb8
NC
1323 /* Install CoPro Instruction handlers here.
1324 The format is:
f603c8fe
NC
1325 ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
1326 LDC routine, STC routine, MRC routine, MCR routine,
1327 CDP routine, Read Reg routine, Write Reg routine). */
1328 if (state->is_ep9312)
1329 {
1330 ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
1331 DSPMRC4, DSPMCR4, DSPCDP4, NULL, NULL);
1332 ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
1333 DSPMRC5, DSPMCR5, DSPCDP5, NULL, NULL);
1334 ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
1335 DSPMRC6, DSPMCR6, DSPCDP6, NULL, NULL);
1336 }
1337 else
1338 {
1339 ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
1340 ValMRC, ValMCR, ValCDP, NULL, NULL);
1341
1342 ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
1343 ValMRC, ValMCR, IntCDP, NULL, NULL);
1344 }
1345
1346 if (state->is_XScale)
1347 {
1348 ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
1349 XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
1350 XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
1351 XScale_cp13_write_reg);
1352
1353 ARMul_CoProAttach (state, 14, XScale_cp14_init, NULL,
1354 XScale_cp14_LDC, XScale_cp14_STC, XScale_cp14_MRC,
1355 XScale_cp14_MCR, NULL, XScale_cp14_read_reg,
1356 XScale_cp14_write_reg);
1357
1358 ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL,
1359 NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR,
1360 NULL, XScale_cp15_read_reg, XScale_cp15_write_reg);
1361 }
1362 else
1363 {
1364 ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
1365 MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
1366 }
c906108c 1367
0f026fd0
NC
1368 if (state->is_iWMMXt)
1369 {
1370 ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
1371 NULL, NULL, IwmmxtCDP, NULL, NULL);
1372
1373 ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
1374 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, NULL);
1375 }
3a3d6f65 1376
f1129fb8 1377 /* No handlers below here. */
c906108c 1378
f1129fb8
NC
1379 /* Call all the initialisation routines. */
1380 for (i = 0; i < 16; i++)
dfcd3bfb
JM
1381 if (state->CPInit[i])
1382 (state->CPInit[i]) (state);
f1129fb8
NC
1383
1384 return TRUE;
dfcd3bfb 1385}
c906108c 1386
ff44f8e3 1387/* Install co-processor finalisation routines in this routine. */
c906108c 1388
dfcd3bfb
JM
1389void
1390ARMul_CoProExit (ARMul_State * state)
1391{
1392 register unsigned i;
c906108c 1393
dfcd3bfb 1394 for (i = 0; i < 16; i++)
c906108c 1395 if (state->CPExit[i])
dfcd3bfb 1396 (state->CPExit[i]) (state);
f1129fb8
NC
1397
1398 for (i = 0; i < 16; i++) /* Detach all handlers. */
dfcd3bfb
JM
1399 ARMul_CoProDetach (state, i);
1400}
c906108c 1401
ff44f8e3 1402/* Routines to hook Co-processors into ARMulator. */
c906108c 1403
dfcd3bfb 1404void
f1129fb8
NC
1405ARMul_CoProAttach (ARMul_State * state,
1406 unsigned number,
1407 ARMul_CPInits * init,
1408 ARMul_CPExits * exit,
1409 ARMul_LDCs * ldc,
1410 ARMul_STCs * stc,
1411 ARMul_MRCs * mrc,
1412 ARMul_MCRs * mcr,
1413 ARMul_CDPs * cdp,
1414 ARMul_CPReads * read,
1415 ARMul_CPWrites * write)
dfcd3bfb
JM
1416{
1417 if (init != NULL)
1418 state->CPInit[number] = init;
1419 if (exit != NULL)
1420 state->CPExit[number] = exit;
1421 if (ldc != NULL)
1422 state->LDC[number] = ldc;
1423 if (stc != NULL)
1424 state->STC[number] = stc;
1425 if (mrc != NULL)
1426 state->MRC[number] = mrc;
1427 if (mcr != NULL)
1428 state->MCR[number] = mcr;
1429 if (cdp != NULL)
1430 state->CDP[number] = cdp;
1431 if (read != NULL)
1432 state->CPRead[number] = read;
1433 if (write != NULL)
1434 state->CPWrite[number] = write;
c906108c
SS
1435}
1436
dfcd3bfb
JM
1437void
1438ARMul_CoProDetach (ARMul_State * state, unsigned number)
1439{
1440 ARMul_CoProAttach (state, number, NULL, NULL,
1441 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
1442 NoCoPro3R, NULL, NULL);
f1129fb8 1443
dfcd3bfb
JM
1444 state->CPInit[number] = NULL;
1445 state->CPExit[number] = NULL;
1446 state->CPRead[number] = NULL;
1447 state->CPWrite[number] = NULL;
c906108c 1448}
This page took 0.6098 seconds and 4 git commands to generate.