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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.
2
    Copyright (C) 1994 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 "armemu.h"
20
#include "ansidecl.h"
21
 
22
/***************************************************************************\
23
*                    Definitions for the support routines                   *
24
\***************************************************************************/
25
 
26
ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg);
27
void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
28
                   ARMword value);
29
ARMword ARMul_GetPC (ARMul_State * state);
30
ARMword ARMul_GetNextPC (ARMul_State * state);
31
void ARMul_SetPC (ARMul_State * state, ARMword value);
32
ARMword ARMul_GetR15 (ARMul_State * state);
33
void ARMul_SetR15 (ARMul_State * state, ARMword value);
34
 
35
ARMword ARMul_GetCPSR (ARMul_State * state);
36
void ARMul_SetCPSR (ARMul_State * state, ARMword value);
37
ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
38
void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
39
 
40
void ARMul_CPSRAltered (ARMul_State * state);
41
void ARMul_R15Altered (ARMul_State * state);
42
 
43
ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode,
44
                          ARMword newmode);
45
static ARMword ModeToBank (ARMul_State * state, ARMword mode);
46
 
47
unsigned ARMul_NthReg (ARMword instr, unsigned number);
48
 
49
void ARMul_NegZero (ARMul_State * state, ARMword result);
50
void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b,
51
                     ARMword result);
52
void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b,
53
                        ARMword result);
54
void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b,
55
                     ARMword result);
56
void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b,
57
                        ARMword result);
58
 
59
void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address);
60
void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address);
61
void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source);
62
ARMword ARMul_MRC (ARMul_State * state, ARMword instr);
63
void ARMul_CDP (ARMul_State * state, ARMword instr);
64
unsigned IntPending (ARMul_State * state);
65
 
66
ARMword ARMul_Align (ARMul_State * state, ARMword address, ARMword data);
67
 
68
void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
69
                          unsigned (*what) ());
70
void ARMul_EnvokeEvent (ARMul_State * state);
71
unsigned long ARMul_Time (ARMul_State * state);
72
static void EnvokeList (ARMul_State * state, unsigned long from,
73
                        unsigned long to);
74
 
75
struct EventNode
76
{                               /* An event list node */
77
  unsigned (*func) ();          /* The function to call */
78
  struct EventNode *next;
79
};
80
 
81
/***************************************************************************\
82
* This routine returns the value of a register from a mode.                 *
83
\***************************************************************************/
84
 
85
ARMword
86
ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
87
{
88
  mode &= MODEBITS;
89
  if (mode != state->Mode)
90
    return (state->RegBank[ModeToBank (state, (ARMword) mode)][reg]);
91
  else
92
    return (state->Reg[reg]);
93
}
94
 
95
/***************************************************************************\
96
* This routine sets the value of a register for a mode.                     *
97
\***************************************************************************/
98
 
99
void
100
ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
101
{
102
  mode &= MODEBITS;
103
  if (mode != state->Mode)
104
    state->RegBank[ModeToBank (state, (ARMword) mode)][reg] = value;
105
  else
106
    state->Reg[reg] = value;
107
}
108
 
109
/***************************************************************************\
110
* This routine returns the value of the PC, mode independently.             *
111
\***************************************************************************/
112
 
113
ARMword
114
ARMul_GetPC (ARMul_State * state)
115
{
116
  if (state->Mode > SVC26MODE)
117
    return (state->Reg[15]);
118
  else
119
    return (R15PC);
120
}
121
 
122
/***************************************************************************\
123
* This routine returns the value of the PC, mode independently.             *
124
\***************************************************************************/
125
 
126
ARMword
127
ARMul_GetNextPC (ARMul_State * state)
128
{
129
  if (state->Mode > SVC26MODE)
130
    return (state->Reg[15] + isize);
131
  else
132
    return ((state->Reg[15] + isize) & R15PCBITS);
133
}
134
 
135
/***************************************************************************\
136
* This routine sets the value of the PC.                                    *
137
\***************************************************************************/
138
 
139
void
140
ARMul_SetPC (ARMul_State * state, ARMword value)
141
{
142
  if (ARMul_MODE32BIT)
143
    state->Reg[15] = value & PCBITS;
144
  else
145
    state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
146
  FLUSHPIPE;
147
}
148
 
149
/***************************************************************************\
150
* This routine returns the value of register 15, mode independently.        *
151
\***************************************************************************/
152
 
153
ARMword
154
ARMul_GetR15 (ARMul_State * state)
155
{
156
  if (state->Mode > SVC26MODE)
157
    return (state->Reg[15]);
158
  else
159
    return (R15PC | ECC | ER15INT | EMODE);
160
}
161
 
162
/***************************************************************************\
163
* This routine sets the value of Register 15.                               *
164
\***************************************************************************/
165
 
166
void
167
ARMul_SetR15 (ARMul_State * state, ARMword value)
168
{
169
  if (ARMul_MODE32BIT)
170
    state->Reg[15] = value & PCBITS;
171
  else
172
    {
173
      state->Reg[15] = value;
174
      ARMul_R15Altered (state);
175
    }
176
  FLUSHPIPE;
177
}
178
 
179
/***************************************************************************\
180
* This routine returns the value of the CPSR                                *
181
\***************************************************************************/
182
 
183
ARMword
184
ARMul_GetCPSR (ARMul_State * state)
185
{
186
  return (CPSR);
187
}
188
 
189
/***************************************************************************\
190
* This routine sets the value of the CPSR                                   *
191
\***************************************************************************/
192
 
193
void
194
ARMul_SetCPSR (ARMul_State * state, ARMword value)
195
{
196
  state->Cpsr = CPSR;
197
  SETPSR (state->Cpsr, value);
198
  ARMul_CPSRAltered (state);
199
}
200
 
201
/***************************************************************************\
202
* This routine does all the nasty bits involved in a write to the CPSR,     *
203
* including updating the register bank, given a MSR instruction.                    *
204
\***************************************************************************/
205
 
206
void
207
ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
208
{
209
  state->Cpsr = CPSR;
210
  if (state->Bank == USERBANK)
211
    {                           /* Only write flags in user mode */
212
      if (BIT (19))
213
        {
214
          SETCC (state->Cpsr, rhs);
215
        }
216
    }
217
  else
218
    {                           /* Not a user mode */
219
      if (BITS (16, 19) == 9)
220
        SETPSR (state->Cpsr, rhs);
221
      else if (BIT (16))
222
        SETINTMODE (state->Cpsr, rhs);
223
      else if (BIT (19))
224
        SETCC (state->Cpsr, rhs);
225
    }
226
  ARMul_CPSRAltered (state);
227
}
228
 
229
/***************************************************************************\
230
* Get an SPSR from the specified mode                                       *
231
\***************************************************************************/
232
 
233
ARMword
234
ARMul_GetSPSR (ARMul_State * state, ARMword mode)
235
{
236
  ARMword bank = ModeToBank (state, mode & MODEBITS);
237
  if (bank == USERBANK || bank == DUMMYBANK)
238
    return (CPSR);
239
  else
240
    return (state->Spsr[bank]);
241
}
242
 
243
/***************************************************************************\
244
* This routine does a write to an SPSR                                      *
245
\***************************************************************************/
246
 
247
void
248
ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
249
{
250
  ARMword bank = ModeToBank (state, mode & MODEBITS);
251
  if (bank != USERBANK && bank != DUMMYBANK)
252
    state->Spsr[bank] = value;
253
}
254
 
255
/***************************************************************************\
256
* This routine does a write to the current SPSR, given an MSR instruction   *
257
\***************************************************************************/
258
 
259
void
260
ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
261
{
262
  if (state->Bank != USERBANK && state->Bank != DUMMYBANK)
263
    {
264
      if (BITS (16, 19) == 9)
265
        SETPSR (state->Spsr[state->Bank], rhs);
266
      else if (BIT (16))
267
        SETINTMODE (state->Spsr[state->Bank], rhs);
268
      else if (BIT (19))
269
        SETCC (state->Spsr[state->Bank], rhs);
270
    }
271
}
272
 
273
/***************************************************************************\
274
* This routine updates the state of the emulator after the Cpsr has been    *
275
* changed.  Both the processor flags and register bank are updated.         *
276
\***************************************************************************/
277
 
278
void
279
ARMul_CPSRAltered (ARMul_State * state)
280
{
281
  ARMword oldmode;
282
 
283
  if (state->prog32Sig == LOW)
284
    state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
285
  oldmode = state->Mode;
286
  if (state->Mode != (state->Cpsr & MODEBITS))
287
    {
288
      state->Mode =
289
        ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
290
      state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
291
    }
292
 
293
  ASSIGNINT (state->Cpsr & INTBITS);
294
  ASSIGNN ((state->Cpsr & NBIT) != 0);
295
  ASSIGNZ ((state->Cpsr & ZBIT) != 0);
296
  ASSIGNC ((state->Cpsr & CBIT) != 0);
297
  ASSIGNV ((state->Cpsr & VBIT) != 0);
298
#ifdef MODET
299
  ASSIGNT ((state->Cpsr & TBIT) != 0);
300
#endif
301
 
302
  if (oldmode > SVC26MODE)
303
    {
304
      if (state->Mode <= SVC26MODE)
305
        {
306
          state->Emulate = CHANGEMODE;
307
          state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
308
        }
309
    }
310
  else
311
    {
312
      if (state->Mode > SVC26MODE)
313
        {
314
          state->Emulate = CHANGEMODE;
315
          state->Reg[15] = R15PC;
316
        }
317
      else
318
        state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
319
    }
320
 
321
}
322
 
323
/***************************************************************************\
324
* This routine updates the state of the emulator after register 15 has      *
325
* been changed.  Both the processor flags and register bank are updated.    *
326
* This routine should only be called from a 26 bit mode.                    *
327
\***************************************************************************/
328
 
329
void
330
ARMul_R15Altered (ARMul_State * state)
331
{
332
  if (state->Mode != R15MODE)
333
    {
334
      state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
335
      state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
336
    }
337
  if (state->Mode > SVC26MODE)
338
    state->Emulate = CHANGEMODE;
339
  ASSIGNR15INT (R15INT);
340
  ASSIGNN ((state->Reg[15] & NBIT) != 0);
341
  ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
342
  ASSIGNC ((state->Reg[15] & CBIT) != 0);
343
  ASSIGNV ((state->Reg[15] & VBIT) != 0);
344
}
345
 
346
/***************************************************************************\
347
* This routine controls the saving and restoring of registers across mode   *
348
* changes.  The regbank matrix is largely unused, only rows 13 and 14 are   *
349
* used across all modes, 8 to 14 are used for FIQ, all others use the USER  *
350
* column.  It's easier this way.  old and new parameter are modes numbers.  *
351
* Notice the side effect of changing the Bank variable.                     *
352
\***************************************************************************/
353
 
354
ARMword
355
ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
356
{
357
  unsigned i;
358
 
359
  oldmode = ModeToBank (state, oldmode);
360
  state->Bank = ModeToBank (state, newmode);
361
  if (oldmode != state->Bank)
362
    {                           /* really need to do it */
363
      switch (oldmode)
364
        {                       /* save away the old registers */
365
        case USERBANK:
366
        case IRQBANK:
367
        case SVCBANK:
368
        case ABORTBANK:
369
        case UNDEFBANK:
370
          if (state->Bank == FIQBANK)
371
            for (i = 8; i < 13; i++)
372
              state->RegBank[USERBANK][i] = state->Reg[i];
373
          state->RegBank[oldmode][13] = state->Reg[13];
374
          state->RegBank[oldmode][14] = state->Reg[14];
375
          break;
376
        case FIQBANK:
377
          for (i = 8; i < 15; i++)
378
            state->RegBank[FIQBANK][i] = state->Reg[i];
379
          break;
380
        case DUMMYBANK:
381
          for (i = 8; i < 15; i++)
382
            state->RegBank[DUMMYBANK][i] = 0;
383
          break;
384
 
385
        }
386
      switch (state->Bank)
387
        {                       /* restore the new registers */
388
        case USERBANK:
389
        case IRQBANK:
390
        case SVCBANK:
391
        case ABORTBANK:
392
        case UNDEFBANK:
393
          if (oldmode == FIQBANK)
394
            for (i = 8; i < 13; i++)
395
              state->Reg[i] = state->RegBank[USERBANK][i];
396
          state->Reg[13] = state->RegBank[state->Bank][13];
397
          state->Reg[14] = state->RegBank[state->Bank][14];
398
          break;
399
        case FIQBANK:
400
          for (i = 8; i < 15; i++)
401
            state->Reg[i] = state->RegBank[FIQBANK][i];
402
          break;
403
        case DUMMYBANK:
404
          for (i = 8; i < 15; i++)
405
            state->Reg[i] = 0;
406
          break;
407
        }                       /* switch */
408
    }                           /* if */
409
  return (newmode);
410
}
411
 
412
/***************************************************************************\
413
* Given a processor mode, this routine returns the register bank that       *
414
* will be accessed in that mode.                                            *
415
\***************************************************************************/
416
 
417
static ARMword
418
ModeToBank (ARMul_State * state ATTRIBUTE_UNUSED, ARMword mode)
419
{
420
  static ARMword bankofmode[] = { USERBANK, FIQBANK, IRQBANK, SVCBANK,
421
    DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
422
    DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
423
    DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
424
    USERBANK, FIQBANK, IRQBANK, SVCBANK,
425
    DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
426
    DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK
427
  };
428
 
429
  if (mode > UNDEF32MODE)
430
    return (DUMMYBANK);
431
  else
432
    return (bankofmode[mode]);
433
}
434
 
435
/***************************************************************************\
436
* Returns the register number of the nth register in a reg list.            *
437
\***************************************************************************/
438
 
439
unsigned
440
ARMul_NthReg (ARMword instr, unsigned number)
441
{
442
  unsigned bit, upto;
443
 
444
  for (bit = 0, upto = 0; upto <= number; bit++)
445
    if (BIT (bit))
446
      upto++;
447
  return (bit - 1);
448
}
449
 
450
/***************************************************************************\
451
* Assigns the N and Z flags depending on the value of result                *
452
\***************************************************************************/
453
 
454
void
455
ARMul_NegZero (ARMul_State * state, ARMword result)
456
{
457
  if (NEG (result))
458
    {
459
      SETN;
460
      CLEARZ;
461
    }
462
  else if (result == 0)
463
    {
464
      CLEARN;
465
      SETZ;
466
    }
467
  else
468
    {
469
      CLEARN;
470
      CLEARZ;
471
    };
472
}
473
 
474
/* Compute whether an addition of A and B, giving RESULT, overflowed.  */
475
int
476
AddOverflow (ARMword a, ARMword b, ARMword result)
477
{
478
  return ((NEG (a) && NEG (b) && POS (result))
479
          || (POS (a) && POS (b) && NEG (result)));
480
}
481
 
482
/* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */
483
int
484
SubOverflow (ARMword a, ARMword b, ARMword result)
485
{
486
  return ((NEG (a) && POS (b) && POS (result))
487
          || (POS (a) && NEG (b) && NEG (result)));
488
}
489
 
490
/***************************************************************************\
491
* Assigns the C flag after an addition of a and b to give result            *
492
\***************************************************************************/
493
 
494
void
495
ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
496
{
497
  ASSIGNC ((NEG (a) && NEG (b)) ||
498
           (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
499
}
500
 
501
/***************************************************************************\
502
* Assigns the V flag after an addition of a and b to give result            *
503
\***************************************************************************/
504
 
505
void
506
ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
507
{
508
  ASSIGNV (AddOverflow (a, b, result));
509
}
510
 
511
/***************************************************************************\
512
* Assigns the C flag after an subtraction of a and b to give result         *
513
\***************************************************************************/
514
 
515
void
516
ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
517
{
518
  ASSIGNC ((NEG (a) && POS (b)) ||
519
           (NEG (a) && POS (result)) || (POS (b) && POS (result)));
520
}
521
 
522
/***************************************************************************\
523
* Assigns the V flag after an subtraction of a and b to give result         *
524
\***************************************************************************/
525
 
526
void
527
ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
528
{
529
  ASSIGNV (SubOverflow (a, b, result));
530
}
531
 
532
/***************************************************************************\
533
* This function does the work of generating the addresses used in an        *
534
* LDC instruction.  The code here is always post-indexed, it's up to the    *
535
* caller to get the input address correct and to handle base register       *
536
* modification. It also handles the Busy-Waiting.                           *
537
\***************************************************************************/
538
 
539
void
540
ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
541
{
542
  unsigned cpab;
543
  ARMword data;
544
 
545
  UNDEF_LSCPCBaseWb;
546
  if (ADDREXCEPT (address))
547
    {
548
      INTERNALABORT (address);
549
    }
550
  cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
551
  while (cpab == ARMul_BUSY)
552
    {
553
      ARMul_Icycles (state, 1, 0);
554
      if (IntPending (state))
555
        {
556
          cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
557
          return;
558
        }
559
      else
560
        cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
561
    }
562
  if (cpab == ARMul_CANT)
563
    {
564
      CPTAKEABORT;
565
      return;
566
    }
567
  cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
568
  data = ARMul_LoadWordN (state, address);
569
  BUSUSEDINCPCN;
570
  if (BIT (21))
571
    LSBase = state->Base;
572
  cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
573
  while (cpab == ARMul_INC)
574
    {
575
      address += 4;
576
      data = ARMul_LoadWordN (state, address);
577
      cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
578
    }
579
  if (state->abortSig || state->Aborted)
580
    {
581
      TAKEABORT;
582
    }
583
}
584
 
585
/***************************************************************************\
586
* This function does the work of generating the addresses used in an        *
587
* STC instruction.  The code here is always post-indexed, it's up to the    *
588
* caller to get the input address correct and to handle base register       *
589
* modification. It also handles the Busy-Waiting.                           *
590
\***************************************************************************/
591
 
592
void
593
ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
594
{
595
  unsigned cpab;
596
  ARMword data;
597
 
598
  UNDEF_LSCPCBaseWb;
599
  if (ADDREXCEPT (address) || VECTORACCESS (address))
600
    {
601
      INTERNALABORT (address);
602
    }
603
  cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
604
  while (cpab == ARMul_BUSY)
605
    {
606
      ARMul_Icycles (state, 1, 0);
607
      if (IntPending (state))
608
        {
609
          cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
610
          return;
611
        }
612
      else
613
        cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
614
    }
615
  if (cpab == ARMul_CANT)
616
    {
617
      CPTAKEABORT;
618
      return;
619
    }
620
#ifndef MODE32
621
  if (ADDREXCEPT (address) || VECTORACCESS (address))
622
    {
623
      INTERNALABORT (address);
624
    }
625
#endif
626
  BUSUSEDINCPCN;
627
  if (BIT (21))
628
    LSBase = state->Base;
629
  cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
630
  ARMul_StoreWordN (state, address, data);
631
  while (cpab == ARMul_INC)
632
    {
633
      address += 4;
634
      cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
635
      ARMul_StoreWordN (state, address, data);
636
    }
637
  if (state->abortSig || state->Aborted)
638
    {
639
      TAKEABORT;
640
    }
641
}
642
 
643
/***************************************************************************\
644
*        This function does the Busy-Waiting for an MCR instruction.        *
645
\***************************************************************************/
646
 
647
void
648
ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
649
{
650
  unsigned cpab;
651
 
652
  cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
653
  while (cpab == ARMul_BUSY)
654
    {
655
      ARMul_Icycles (state, 1, 0);
656
      if (IntPending (state))
657
        {
658
          cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
659
          return;
660
        }
661
      else
662
        cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
663
    }
664
  if (cpab == ARMul_CANT)
665
    ARMul_Abort (state, ARMul_UndefinedInstrV);
666
  else
667
    {
668
      BUSUSEDINCPCN;
669
      ARMul_Ccycles (state, 1, 0);
670
    }
671
}
672
 
673
/***************************************************************************\
674
*        This function does the Busy-Waiting for an MRC instruction.        *
675
\***************************************************************************/
676
 
677
ARMword
678
ARMul_MRC (ARMul_State * state, ARMword instr)
679
{
680
  unsigned cpab;
681
  ARMword result = 0;
682
 
683
  cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
684
  while (cpab == ARMul_BUSY)
685
    {
686
      ARMul_Icycles (state, 1, 0);
687
      if (IntPending (state))
688
        {
689
          cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
690
          return (0);
691
        }
692
      else
693
        cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
694
    }
695
  if (cpab == ARMul_CANT)
696
    {
697
      ARMul_Abort (state, ARMul_UndefinedInstrV);
698
      result = ECC;             /* Parent will destroy the flags otherwise */
699
    }
700
  else
701
    {
702
      BUSUSEDINCPCN;
703
      ARMul_Ccycles (state, 1, 0);
704
      ARMul_Icycles (state, 1, 0);
705
    }
706
  return (result);
707
}
708
 
709
/***************************************************************************\
710
*        This function does the Busy-Waiting for an CDP instruction.        *
711
\***************************************************************************/
712
 
713
void
714
ARMul_CDP (ARMul_State * state, ARMword instr)
715
{
716
  unsigned cpab;
717
 
718
  cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
719
  while (cpab == ARMul_BUSY)
720
    {
721
      ARMul_Icycles (state, 1, 0);
722
      if (IntPending (state))
723
        {
724
          cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
725
          return;
726
        }
727
      else
728
        cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
729
    }
730
  if (cpab == ARMul_CANT)
731
    ARMul_Abort (state, ARMul_UndefinedInstrV);
732
  else
733
    BUSUSEDN;
734
}
735
 
736
/***************************************************************************\
737
*      This function handles Undefined instructions, as CP isntruction      *
738
\***************************************************************************/
739
 
740
void
741
ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
742
{
743
  ARMul_Abort (state, ARMul_UndefinedInstrV);
744
}
745
 
746
/***************************************************************************\
747
*           Return TRUE if an interrupt is pending, FALSE otherwise.        *
748
\***************************************************************************/
749
 
750
unsigned
751
IntPending (ARMul_State * state)
752
{
753
  if (state->Exception)
754
    {                           /* Any exceptions */
755
      if (state->NresetSig == LOW)
756
        {
757
          ARMul_Abort (state, ARMul_ResetV);
758
          return (TRUE);
759
        }
760
      else if (!state->NfiqSig && !FFLAG)
761
        {
762
          ARMul_Abort (state, ARMul_FIQV);
763
          return (TRUE);
764
        }
765
      else if (!state->NirqSig && !IFLAG)
766
        {
767
          ARMul_Abort (state, ARMul_IRQV);
768
          return (TRUE);
769
        }
770
    }
771
  return (FALSE);
772
}
773
 
774
/***************************************************************************\
775
*               Align a word access to a non word boundary                  *
776
\***************************************************************************/
777
 
778
ARMword
779
ARMul_Align (state, address, data)
780
     ARMul_State * state ATTRIBUTE_UNUSED;
781
     ARMword address;
782
     ARMword data;
783
{
784
  /* This code assumes the address is really unaligned,
785
     as a shift by 32 is undefined in C.  */
786
 
787
  address = (address & 3) << 3; /* get the word address */
788
  return ((data >> address) | (data << (32 - address)));        /* rot right */
789
}
790
 
791
/***************************************************************************\
792
* This routine is used to call another routine after a certain number of    *
793
* cycles have been executed. The first parameter is the number of cycles    *
794
* delay before the function is called, the second argument is a pointer     *
795
* to the function. A delay of zero doesn't work, just call the function.    *
796
\***************************************************************************/
797
 
798
void
799
ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
800
                     unsigned (*what) ())
801
{
802
  unsigned long when;
803
  struct EventNode *event;
804
 
805
  if (state->EventSet++ == 0)
806
    state->Now = ARMul_Time (state);
807
  when = (state->Now + delay) % EVENTLISTSIZE;
808
  event = (struct EventNode *) malloc (sizeof (struct EventNode));
809
  event->func = what;
810
  event->next = *(state->EventPtr + when);
811
  *(state->EventPtr + when) = event;
812
}
813
 
814
/***************************************************************************\
815
* This routine is called at the beginning of every cycle, to envoke         *
816
* scheduled events.                                                         *
817
\***************************************************************************/
818
 
819
void
820
ARMul_EnvokeEvent (ARMul_State * state)
821
{
822
  static unsigned long then;
823
 
824
  then = state->Now;
825
  state->Now = ARMul_Time (state) % EVENTLISTSIZE;
826
  if (then < state->Now)        /* schedule events */
827
    EnvokeList (state, then, state->Now);
828
  else if (then > state->Now)
829
    {                           /* need to wrap around the list */
830
      EnvokeList (state, then, EVENTLISTSIZE - 1L);
831
      EnvokeList (state, 0L, state->Now);
832
    }
833
}
834
 
835
static void
836
EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
837
/* envokes all the entries in a range */
838
{
839
  struct EventNode *anevent;
840
 
841
  for (; from <= to; from++)
842
    {
843
      anevent = *(state->EventPtr + from);
844
      while (anevent)
845
        {
846
          (anevent->func) (state);
847
          state->EventSet--;
848
          anevent = anevent->next;
849
        }
850
      *(state->EventPtr + from) = NULL;
851
    }
852
}
853
 
854
/***************************************************************************\
855
* This routine is returns the number of clock ticks since the last reset.   *
856
\***************************************************************************/
857
 
858
unsigned long
859
ARMul_Time (ARMul_State * state)
860
{
861
  return (state->NumScycles + state->NumNcycles +
862
          state->NumIcycles + state->NumCcycles + state->NumFcycles);
863
}

powered by: WebSVN 2.1.0

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