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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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