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