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