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