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