Fix compile time warning messages.
[platform/upstream/binutils.git] / sim / arm / armcopro.c
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 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
16     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #include "armdefs.h"
19 #include "ansidecl.h"
20
21 extern unsigned ARMul_CoProInit (ARMul_State * state);
22 extern void ARMul_CoProExit (ARMul_State * state);
23 extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,
24                                ARMul_CPInits * init, ARMul_CPExits * exit,
25                                ARMul_LDCs * ldc, ARMul_STCs * stc,
26                                ARMul_MRCs * mrc, ARMul_MCRs * mcr,
27                                ARMul_CDPs * cdp,
28                                ARMul_CPReads * read, ARMul_CPWrites * write);
29 extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);
30
31
32 /***************************************************************************\
33 *                            Dummy Co-processors                            *
34 \***************************************************************************/
35
36 static unsigned NoCoPro3R (ARMul_State * state, unsigned, ARMword);
37 static unsigned NoCoPro4R (ARMul_State * state, unsigned, ARMword, ARMword);
38 static unsigned NoCoPro4W (ARMul_State * state, unsigned, ARMword, ARMword *);
39
40 /***************************************************************************\
41 *                Define Co-Processor instruction handlers here              *
42 \***************************************************************************/
43
44 /* Here's ARMulator's MMU definition.  A few things to note:
45 1) it has eight registers, but only two are defined.
46 2) you can only access its registers with MCR and MRC.
47 3) MMU Register 0 (ID) returns 0x41440110
48 4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
49 controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
50 bit 6 controls late abort timimg and bit 7 controls big/little endian.
51 */
52
53 static ARMword MMUReg[8];
54
55 static unsigned
56 MMUInit (ARMul_State * state)
57 {
58   MMUReg[1] = state->prog32Sig << 4 |
59     state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
60   ARMul_ConsolePrint (state, ", MMU present");
61   return (TRUE);
62 }
63
64 static unsigned
65 MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
66 {
67   int reg = BITS (16, 19) & 7;
68
69   if (reg == 0)
70     *value = 0x41440110;
71   else
72     *value = MMUReg[reg];
73   return (ARMul_DONE);
74 }
75
76 static unsigned
77 MMUMCR (ARMul_State * state, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
78 {
79   int reg = BITS (16, 19) & 7;
80
81   MMUReg[reg] = value;
82   if (reg == 1)
83     {
84       state->prog32Sig = value >> 4 & 1;
85       state->data32Sig = value >> 5 & 1;
86       state->lateabtSig = value >> 6 & 1;
87       state->bigendSig = value >> 7 & 1;
88       state->Emulate = TRUE;    /* force ARMulator to notice these now ! */
89     }
90   return (ARMul_DONE);
91 }
92
93
94 static unsigned
95 MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
96 {
97   if (reg == 0)
98     *value = 0x41440110;
99   else if (reg < 8)
100     *value = MMUReg[reg];
101   return (TRUE);
102 }
103
104 static unsigned
105 MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
106 {
107   if (reg < 8)
108     MMUReg[reg] = value;
109   if (reg == 1)
110     {
111       state->prog32Sig = value >> 4 & 1;
112       state->data32Sig = value >> 5 & 1;
113       state->lateabtSig = value >> 6 & 1;
114       state->bigendSig = value >> 7 & 1;
115       state->Emulate = TRUE;    /* force ARMulator to notice these now ! */
116     }
117   return (TRUE);
118 }
119
120
121 /* What follows is the Validation Suite Coprocessor.  It uses two
122 co-processor numbers (4 and 5) and has the follwing functionality.
123 Sixteen registers.  Both co-processor nuimbers can be used in an MCR and
124 MRC to access these registers.  CP 4 can LDC and STC to and from the
125 registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of cycles
126 specified by a CP register.  CP 5 CDP 1 issues a FIQ after a number of
127 cycles (specified in a CP register), CDP 2 issues an IRQW in the same
128 way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 stores a 32
129 bit time value in a CP register (actually it's the total number of N, S,
130 I, C and F cyles) */
131
132 static ARMword ValReg[16];
133
134 static unsigned
135 ValLDC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword data)
136 {
137   static unsigned words;
138
139   if (type != ARMul_DATA)
140     {
141       words = 0;
142       return (ARMul_DONE);
143     }
144   if (BIT (22))
145     {                           /* it's a long access, get two words */
146       ValReg[BITS (12, 15)] = data;
147       if (words++ == 4)
148         return (ARMul_DONE);
149       else
150         return (ARMul_INC);
151     }
152   else
153     {                           /* get just one word */
154       ValReg[BITS (12, 15)] = data;
155       return (ARMul_DONE);
156     }
157 }
158
159 static unsigned
160 ValSTC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword * data)
161 {
162   static unsigned words;
163
164   if (type != ARMul_DATA)
165     {
166       words = 0;
167       return (ARMul_DONE);
168     }
169   if (BIT (22))
170     {                           /* it's a long access, get two words */
171       *data = ValReg[BITS (12, 15)];
172       if (words++ == 4)
173         return (ARMul_DONE);
174       else
175         return (ARMul_INC);
176     }
177   else
178     {                           /* get just one word */
179       *data = ValReg[BITS (12, 15)];
180       return (ARMul_DONE);
181     }
182 }
183
184 static unsigned
185 ValMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
186 {
187   *value = ValReg[BITS (16, 19)];
188   return (ARMul_DONE);
189 }
190
191 static unsigned
192 ValMCR (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
193 {
194   ValReg[BITS (16, 19)] = value;
195   return (ARMul_DONE);
196 }
197
198 static unsigned
199 ValCDP (ARMul_State * state, unsigned type, ARMword instr)
200 {
201   static unsigned long finish = 0;
202   ARMword howlong;
203
204   howlong = ValReg[BITS (0, 3)];
205   if (BITS (20, 23) == 0)
206     {
207       if (type == ARMul_FIRST)
208         {                       /* First cycle of a busy wait */
209           finish = ARMul_Time (state) + howlong;
210           if (howlong == 0)
211             return (ARMul_DONE);
212           else
213             return (ARMul_BUSY);
214         }
215       else if (type == ARMul_BUSY)
216         {
217           if (ARMul_Time (state) >= finish)
218             return (ARMul_DONE);
219           else
220             return (ARMul_BUSY);
221         }
222     }
223   return (ARMul_CANT);
224 }
225
226 static unsigned
227 DoAFIQ (ARMul_State * state)
228 {
229   state->NfiqSig = LOW;
230   state->Exception++;
231   return (0);
232 }
233
234 static unsigned
235 DoAIRQ (ARMul_State * state)
236 {
237   state->NirqSig = LOW;
238   state->Exception++;
239   return (0);
240 }
241
242 static unsigned
243 IntCDP (ARMul_State * state, unsigned type, ARMword instr)
244 {
245   static unsigned long finish;
246   ARMword howlong;
247
248   howlong = ValReg[BITS (0, 3)];
249   switch ((int) BITS (20, 23))
250     {
251     case 0:
252       if (type == ARMul_FIRST)
253         {                       /* First cycle of a busy wait */
254           finish = ARMul_Time (state) + howlong;
255           if (howlong == 0)
256             return (ARMul_DONE);
257           else
258             return (ARMul_BUSY);
259         }
260       else if (type == ARMul_BUSY)
261         {
262           if (ARMul_Time (state) >= finish)
263             return (ARMul_DONE);
264           else
265             return (ARMul_BUSY);
266         }
267       return (ARMul_DONE);
268     case 1:
269       if (howlong == 0)
270         ARMul_Abort (state, ARMul_FIQV);
271       else
272         ARMul_ScheduleEvent (state, howlong, DoAFIQ);
273       return (ARMul_DONE);
274     case 2:
275       if (howlong == 0)
276         ARMul_Abort (state, ARMul_IRQV);
277       else
278         ARMul_ScheduleEvent (state, howlong, DoAIRQ);
279       return (ARMul_DONE);
280     case 3:
281       state->NfiqSig = HIGH;
282       state->Exception--;
283       return (ARMul_DONE);
284     case 4:
285       state->NirqSig = HIGH;
286       state->Exception--;
287       return (ARMul_DONE);
288     case 5:
289       ValReg[BITS (0, 3)] = ARMul_Time (state);
290       return (ARMul_DONE);
291     }
292   return (ARMul_CANT);
293 }
294
295 /***************************************************************************\
296 *         Install co-processor instruction handlers in this routine         *
297 \***************************************************************************/
298
299 unsigned
300 ARMul_CoProInit (ARMul_State * state)
301 {
302   register unsigned i;
303
304   for (i = 0; i < 16; i++)      /* initialise tham all first */
305     ARMul_CoProDetach (state, i);
306
307   /* Install CoPro Instruction handlers here
308      The format is
309      ARMul_CoProAttach(state, CP Number, Init routine, Exit routine
310      LDC routine, STC routine, MRC routine, MCR routine,
311      CDP routine, Read Reg routine, Write Reg routine) ;
312    */
313
314   ARMul_CoProAttach (state, 4, NULL, NULL,
315                      ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
316
317   ARMul_CoProAttach (state, 5, NULL, NULL,
318                      NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL);
319
320   ARMul_CoProAttach (state, 15, MMUInit, NULL,
321                      NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
322
323
324   /* No handlers below here */
325
326   for (i = 0; i < 16; i++)      /* Call all the initialisation routines */
327     if (state->CPInit[i])
328       (state->CPInit[i]) (state);
329   return (TRUE);
330 }
331
332 /***************************************************************************\
333 *         Install co-processor finalisation routines in this routine        *
334 \***************************************************************************/
335
336 void
337 ARMul_CoProExit (ARMul_State * state)
338 {
339   register unsigned i;
340
341   for (i = 0; i < 16; i++)
342     if (state->CPExit[i])
343       (state->CPExit[i]) (state);
344   for (i = 0; i < 16; i++)      /* Detach all handlers */
345     ARMul_CoProDetach (state, i);
346 }
347
348 /***************************************************************************\
349 *              Routines to hook Co-processors into ARMulator                 *
350 \***************************************************************************/
351
352 void
353 ARMul_CoProAttach (ARMul_State * state, unsigned number,
354                    ARMul_CPInits * init, ARMul_CPExits * exit,
355                    ARMul_LDCs * ldc, ARMul_STCs * stc,
356                    ARMul_MRCs * mrc, ARMul_MCRs * mcr, ARMul_CDPs * cdp,
357                    ARMul_CPReads * read, ARMul_CPWrites * write)
358 {
359   if (init != NULL)
360     state->CPInit[number] = init;
361   if (exit != NULL)
362     state->CPExit[number] = exit;
363   if (ldc != NULL)
364     state->LDC[number] = ldc;
365   if (stc != NULL)
366     state->STC[number] = stc;
367   if (mrc != NULL)
368     state->MRC[number] = mrc;
369   if (mcr != NULL)
370     state->MCR[number] = mcr;
371   if (cdp != NULL)
372     state->CDP[number] = cdp;
373   if (read != NULL)
374     state->CPRead[number] = read;
375   if (write != NULL)
376     state->CPWrite[number] = write;
377 }
378
379 void
380 ARMul_CoProDetach (ARMul_State * state, unsigned number)
381 {
382   ARMul_CoProAttach (state, number, NULL, NULL,
383                      NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
384                      NoCoPro3R, NULL, NULL);
385   state->CPInit[number] = NULL;
386   state->CPExit[number] = NULL;
387   state->CPRead[number] = NULL;
388   state->CPWrite[number] = NULL;
389 }
390
391 /***************************************************************************\
392 *         There is no CoPro around, so Undefined Instruction trap           *
393 \***************************************************************************/
394
395 static unsigned
396 NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
397            unsigned a ATTRIBUTE_UNUSED,
398            ARMword b ATTRIBUTE_UNUSED)
399 {
400   return (ARMul_CANT);
401 }
402
403 static unsigned
404 NoCoPro4R (
405            ARMul_State * state ATTRIBUTE_UNUSED,
406            unsigned a ATTRIBUTE_UNUSED,
407            ARMword b ATTRIBUTE_UNUSED,
408            ARMword c ATTRIBUTE_UNUSED)
409 {
410   return (ARMul_CANT);
411 }
412
413 static unsigned
414 NoCoPro4W (
415            ARMul_State * state ATTRIBUTE_UNUSED,
416            unsigned a ATTRIBUTE_UNUSED,
417            ARMword b ATTRIBUTE_UNUSED,
418            ARMword * c ATTRIBUTE_UNUSED)
419 {
420   return (ARMul_CANT);
421 }