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