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