OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [sim/] [arm/] [armcopro.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/*  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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.