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