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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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