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