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