summaryrefslogtreecommitdiff
path: root/src/core/arm/interpreter/armsupp.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2015-01-31 20:34:26 -0500
committerGravatar Lioncash2015-01-31 20:43:03 -0500
commitf44781fd7b0c5f99573e917ccdd92716a99a9b0d (patch)
treead31575f5653316488371cd654d961ce803e2c01 /src/core/arm/interpreter/armsupp.cpp
parentMerge pull request #512 from lioncash/assignment (diff)
downloadyuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.gz
yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.xz
yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.zip
arm: Adios armemu
Diffstat (limited to 'src/core/arm/interpreter/armsupp.cpp')
-rw-r--r--src/core/arm/interpreter/armsupp.cpp881
1 files changed, 12 insertions, 869 deletions
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 5a8f09b22..fd90fb0a4 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -20,395 +20,13 @@
20#include "core/arm/disassembler/arm_disasm.h" 20#include "core/arm/disassembler/arm_disasm.h"
21#include "core/mem_map.h" 21#include "core/mem_map.h"
22 22
23 23// Unsigned sum of absolute difference
24static ARMword ModeToBank (ARMword);
25
26/* This routine returns the value of a register from a mode. */
27
28ARMword
29ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
30{
31 mode &= MODEBITS;
32 if (mode != state->Mode)
33 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
34 else
35 return (state->Reg[reg]);
36}
37
38/* This routine sets the value of a register for a mode. */
39
40void
41ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
42{
43 mode &= MODEBITS;
44 if (mode != state->Mode)
45 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
46 else
47 state->Reg[reg] = value;
48}
49
50/* This routine returns the value of the PC, mode independently. */
51
52ARMword
53ARMul_GetPC (ARMul_State * state)
54{
55 if (state->Mode > SVC26MODE)
56 return state->Reg[15];
57 else
58 return R15PC;
59}
60
61/* This routine returns the value of the PC, mode independently. */
62
63ARMword
64ARMul_GetNextPC (ARMul_State * state)
65{
66 if (state->Mode > SVC26MODE)
67 return state->Reg[15] + INSN_SIZE;
68 else
69 return (state->Reg[15] + INSN_SIZE) & R15PCBITS;
70}
71
72/* This routine sets the value of the PC. */
73
74void
75ARMul_SetPC (ARMul_State * state, ARMword value)
76{
77 if (ARMul_MODE32BIT)
78 state->Reg[15] = value & PCBITS;
79 else
80 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
81 FLUSHPIPE;
82}
83
84/* This routine returns the value of register 15, mode independently. */
85
86ARMword
87ARMul_GetR15 (ARMul_State * state)
88{
89 if (state->Mode > SVC26MODE)
90 return (state->Reg[15]);
91 else
92 return (R15PC | ECC | ER15INT | EMODE);
93}
94
95/* This routine sets the value of Register 15. */
96
97void
98ARMul_SetR15 (ARMul_State * state, ARMword value)
99{
100 if (ARMul_MODE32BIT)
101 state->Reg[15] = value & PCBITS;
102 else {
103 state->Reg[15] = value;
104 ARMul_R15Altered (state);
105 }
106 FLUSHPIPE;
107}
108
109/* This routine returns the value of the CPSR. */
110
111ARMword
112ARMul_GetCPSR (ARMul_State * state)
113{
114 //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
115 //return (CPSR | state->Cpsr); for gdb20030716
116 return (CPSR); //had be tested in old skyeye with gdb5.0-5.3
117}
118
119/* This routine sets the value of the CPSR. */
120
121void
122ARMul_SetCPSR (ARMul_State * state, ARMword value)
123{
124 state->Cpsr = value;
125 ARMul_CPSRAltered (state);
126}
127
128/* This routine does all the nasty bits involved in a write to the CPSR,
129 including updating the register bank, given a MSR instruction. */
130
131void
132ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
133{
134 state->Cpsr = ARMul_GetCPSR (state);
135 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
136 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
137 /* In user mode, only write flags. */
138 if (BIT (16))
139 SETPSR_C (state->Cpsr, rhs);
140 if (BIT (17))
141 SETPSR_X (state->Cpsr, rhs);
142 if (BIT (18))
143 SETPSR_S (state->Cpsr, rhs);
144 }
145 if (BIT (19))
146 SETPSR_F (state->Cpsr, rhs);
147 ARMul_CPSRAltered (state);
148}
149
150/* Get an SPSR from the specified mode. */
151
152ARMword
153ARMul_GetSPSR (ARMul_State * state, ARMword mode)
154{
155 ARMword bank = ModeToBank (mode & MODEBITS);
156
157 if (!BANK_CAN_ACCESS_SPSR (bank))
158 return ARMul_GetCPSR (state);
159
160 return state->Spsr[bank];
161}
162
163/* This routine does a write to an SPSR. */
164
165void
166ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
167{
168 ARMword bank = ModeToBank (mode & MODEBITS);
169
170 if (BANK_CAN_ACCESS_SPSR (bank))
171 state->Spsr[bank] = value;
172}
173
174/* This routine does a write to the current SPSR, given an MSR instruction. */
175
176void
177ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
178{
179 if (BANK_CAN_ACCESS_SPSR (state->Bank)) {
180 if (BIT (16))
181 SETPSR_C (state->Spsr[state->Bank], rhs);
182 if (BIT (17))
183 SETPSR_X (state->Spsr[state->Bank], rhs);
184 if (BIT (18))
185 SETPSR_S (state->Spsr[state->Bank], rhs);
186 if (BIT (19))
187 SETPSR_F (state->Spsr[state->Bank], rhs);
188 }
189}
190
191/* This routine updates the state of the emulator after the Cpsr has been
192 changed. Both the processor flags and register bank are updated. */
193
194void
195ARMul_CPSRAltered (ARMul_State * state)
196{
197 ARMword oldmode;
198
199 if (state->prog32Sig == LOW)
200 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
201
202 oldmode = state->Mode;
203
204 /*if (state->Mode != (state->Cpsr & MODEBITS)) {
205 state->Mode =
206 ARMul_SwitchMode (state, state->Mode,
207 state->Cpsr & MODEBITS);
208
209 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
210 }*/
211 //state->Cpsr &= ~MODEBITS;
212
213 ASSIGNINT (state->Cpsr & INTBITS);
214 //state->Cpsr &= ~INTBITS;
215 ASSIGNN ((state->Cpsr & NBIT) != 0);
216 //state->Cpsr &= ~NBIT;
217 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
218 //state->Cpsr &= ~ZBIT;
219 ASSIGNC ((state->Cpsr & CBIT) != 0);
220 //state->Cpsr &= ~CBIT;
221 ASSIGNV ((state->Cpsr & VBIT) != 0);
222 //state->Cpsr &= ~VBIT;
223 ASSIGNQ ((state->Cpsr & QBIT) != 0);
224 //state->Cpsr &= ~QBIT;
225 state->GEFlag = (state->Cpsr & 0x000F0000);
226#ifdef MODET
227 ASSIGNT ((state->Cpsr & TBIT) != 0);
228 //state->Cpsr &= ~TBIT;
229#endif
230
231 if (oldmode > SVC26MODE) {
232 if (state->Mode <= SVC26MODE) {
233 state->Emulate = CHANGEMODE;
234 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
235 }
236 } else {
237 if (state->Mode > SVC26MODE) {
238 state->Emulate = CHANGEMODE;
239 state->Reg[15] = R15PC;
240 } else
241 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
242 }
243}
244
245/* This routine updates the state of the emulator after register 15 has
246 been changed. Both the processor flags and register bank are updated.
247 This routine should only be called from a 26 bit mode. */
248
249void
250ARMul_R15Altered (ARMul_State * state)
251{
252 if (state->Mode != R15MODE) {
253 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
254 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
255 }
256
257 if (state->Mode > SVC26MODE)
258 state->Emulate = CHANGEMODE;
259
260 ASSIGNR15INT (R15INT);
261
262 ASSIGNN ((state->Reg[15] & NBIT) != 0);
263 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
264 ASSIGNC ((state->Reg[15] & CBIT) != 0);
265 ASSIGNV ((state->Reg[15] & VBIT) != 0);
266}
267
268/* This routine controls the saving and restoring of registers across mode
269 changes. The regbank matrix is largely unused, only rows 13 and 14 are
270 used across all modes, 8 to 14 are used for FIQ, all others use the USER
271 column. It's easier this way. old and new parameter are modes numbers.
272 Notice the side effect of changing the Bank variable. */
273
274ARMword
275ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
276{
277 unsigned i;
278 ARMword oldbank;
279 ARMword newbank;
280 static int revision_value = 53;
281
282 oldbank = ModeToBank (oldmode);
283 newbank = state->Bank = ModeToBank (newmode);
284
285 /* Do we really need to do it? */
286 if (oldbank != newbank) {
287 if (oldbank == 3 && newbank == 2) {
288 //printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank);
289 if (state->NumInstrs >= 5832487) {
290// printf("%d, ", state->NumInstrs + revision_value);
291// printf("revision_value : %d\n", revision_value);
292 revision_value ++;
293 }
294 }
295 /* Save away the old registers. */
296 switch (oldbank) {
297 case USERBANK:
298 case IRQBANK:
299 case SVCBANK:
300 case ABORTBANK:
301 case UNDEFBANK:
302 if (newbank == FIQBANK)
303 for (i = 8; i < 13; i++)
304 state->RegBank[USERBANK][i] =
305 state->Reg[i];
306 state->RegBank[oldbank][13] = state->Reg[13];
307 state->RegBank[oldbank][14] = state->Reg[14];
308 break;
309 case FIQBANK:
310 for (i = 8; i < 15; i++)
311 state->RegBank[FIQBANK][i] = state->Reg[i];
312 break;
313 case DUMMYBANK:
314 for (i = 8; i < 15; i++)
315 state->RegBank[DUMMYBANK][i] = 0;
316 break;
317 default:
318 abort ();
319 }
320
321 /* Restore the new registers. */
322 switch (newbank) {
323 case USERBANK:
324 case IRQBANK:
325 case SVCBANK:
326 case ABORTBANK:
327 case UNDEFBANK:
328 if (oldbank == FIQBANK)
329 for (i = 8; i < 13; i++)
330 state->Reg[i] =
331 state->RegBank[USERBANK][i];
332 state->Reg[13] = state->RegBank[newbank][13];
333 state->Reg[14] = state->RegBank[newbank][14];
334 break;
335 case FIQBANK:
336 for (i = 8; i < 15; i++)
337 state->Reg[i] = state->RegBank[FIQBANK][i];
338 break;
339 case DUMMYBANK:
340 for (i = 8; i < 15; i++)
341 state->Reg[i] = 0;
342 break;
343 default:
344 abort ();
345 }
346 }
347
348 return newmode;
349}
350
351/* Given a processor mode, this routine returns the
352 register bank that will be accessed in that mode. */
353
354static ARMword
355ModeToBank (ARMword mode)
356{
357 static ARMword bankofmode[] = {
358 USERBANK, FIQBANK, IRQBANK, SVCBANK,
359 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
360 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
361 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
362 USERBANK, FIQBANK, IRQBANK, SVCBANK,
363 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
364 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
365 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
366 };
367
368 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
369 return DUMMYBANK;
370
371 return bankofmode[mode];
372}
373
374/* Returns the register number of the nth register in a reg list. */
375
376unsigned
377ARMul_NthReg (ARMword instr, unsigned number)
378{
379 unsigned bit, upto;
380
381 for (bit = 0, upto = 0; upto <= number; bit++)
382 if (BIT (bit))
383 upto++;
384
385 return (bit - 1);
386}
387
388/* Unsigned sum of absolute difference */
389u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) 24u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
390{ 25{
391 if (left > right) 26 if (left > right)
392 return left - right; 27 return left - right;
393 28
394 return right - left; 29 return right - left;
395}
396
397/* Assigns the N and Z flags depending on the value of result. */
398
399void
400ARMul_NegZero (ARMul_State * state, ARMword result)
401{
402 if (NEG (result)) {
403 SETN;
404 CLEARZ;
405 } else if (result == 0) {
406 CLEARN;
407 SETZ;
408 } else {
409 CLEARN;
410 CLEARZ;
411 }
412} 30}
413 31
414// Add with carry, indicates if a carry-out or signed overflow occurred. 32// Add with carry, indicates if a carry-out or signed overflow occurred.
@@ -441,23 +59,6 @@ bool SubOverflow(ARMword a, ARMword b, ARMword result)
441 (POS(a) && NEG(b) && NEG(result))); 59 (POS(a) && NEG(b) && NEG(result)));
442} 60}
443 61
444/* Assigns the C flag after an addition of a and b to give result. */
445
446void
447ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
448{
449 ASSIGNC ((NEG (a) && NEG (b)) ||
450 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
451}
452
453/* Assigns the V flag after an addition of a and b to give result. */
454
455void
456ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
457{
458 ASSIGNV (AddOverflow (a, b, result));
459}
460
461// Returns true if the Q flag should be set as a result of overflow. 62// Returns true if the Q flag should be set as a result of overflow.
462bool ARMul_AddOverflowQ(ARMword a, ARMword b) 63bool ARMul_AddOverflowQ(ARMword a, ARMword b)
463{ 64{
@@ -468,24 +69,7 @@ bool ARMul_AddOverflowQ(ARMword a, ARMword b)
468 return false; 69 return false;
469} 70}
470 71
471/* Assigns the C flag after an subtraction of a and b to give result. */ 72// 8-bit signed saturated addition
472
473void
474ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
475{
476 ASSIGNC ((NEG (a) && POS (b)) ||
477 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
478}
479
480/* Assigns the V flag after an subtraction of a and b to give result. */
481
482void
483ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
484{
485 ASSIGNV (SubOverflow (a, b, result));
486}
487
488/* 8-bit signed saturated addition */
489u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) 73u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
490{ 74{
491 u8 result = left + right; 75 u8 result = left + right;
@@ -500,7 +84,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
500 return result; 84 return result;
501} 85}
502 86
503/* 8-bit signed saturated subtraction */ 87// 8-bit signed saturated subtraction
504u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) 88u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
505{ 89{
506 u8 result = left - right; 90 u8 result = left - right;
@@ -515,7 +99,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
515 return result; 99 return result;
516} 100}
517 101
518/* 16-bit signed saturated addition */ 102// 16-bit signed saturated addition
519u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) 103u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
520{ 104{
521 u16 result = left + right; 105 u16 result = left + right;
@@ -530,7 +114,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
530 return result; 114 return result;
531} 115}
532 116
533/* 16-bit signed saturated subtraction */ 117// 16-bit signed saturated subtraction
534u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) 118u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
535{ 119{
536 u16 result = left - right; 120 u16 result = left - right;
@@ -545,7 +129,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
545 return result; 129 return result;
546} 130}
547 131
548/* 8-bit unsigned saturated addition */ 132// 8-bit unsigned saturated addition
549u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) 133u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
550{ 134{
551 u8 result = left + right; 135 u8 result = left + right;
@@ -556,7 +140,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
556 return result; 140 return result;
557} 141}
558 142
559/* 16-bit unsigned saturated addition */ 143// 16-bit unsigned saturated addition
560u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) 144u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
561{ 145{
562 u16 result = left + right; 146 u16 result = left + right;
@@ -567,7 +151,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
567 return result; 151 return result;
568} 152}
569 153
570/* 8-bit unsigned saturated subtraction */ 154// 8-bit unsigned saturated subtraction
571u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) 155u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
572{ 156{
573 if (left <= right) 157 if (left <= right)
@@ -576,7 +160,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
576 return left - right; 160 return left - right;
577} 161}
578 162
579/* 16-bit unsigned saturated subtraction */ 163// 16-bit unsigned saturated subtraction
580u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) 164u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
581{ 165{
582 if (left <= right) 166 if (left <= right)
@@ -620,444 +204,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
620 *saturation_occurred = false; 204 *saturation_occurred = false;
621 return (u32)value; 205 return (u32)value;
622} 206}
623
624/* This function does the work of generating the addresses used in an
625 LDC instruction. The code here is always post-indexed, it's up to the
626 caller to get the input address correct and to handle base register
627 modification. It also handles the Busy-Waiting. */
628
629void
630ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
631{
632 unsigned cpab;
633 ARMword data;
634
635 UNDEF_LSCPCBaseWb;
636 //printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
637 /*chy 2004-05-23 should update this function in the future,should concern dataabort*/
638// chy 2004-05-25 , fix it now,so needn't printf
639// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
640 //exit(-1);
641
642 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
643 if (!state->LDC[CPNum]) {
644 /*
645 printf
646 ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n",
647 CPNum, instr, address);
648 */
649 ARMul_UndefInstr (state, instr);
650 return;
651 }
652
653 /*if (ADDREXCEPT (address))
654 INTERNALABORT (address);*/
655
656 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
657 while (cpab == ARMul_BUSY) {
658 ARMul_Icycles (state, 1, 0);
659
660 if (IntPending (state)) {
661 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT,
662 instr, 0);
663 return;
664 } else
665 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr,
666 0);
667 }
668 if (cpab == ARMul_CANT) {
669 /*
670 printf
671 ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n",
672 CPNum, instr, address);
673 */
674 CPTAKEABORT;
675 return;
676 }
677
678 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
679 data = ARMul_LoadWordN (state, address);
680 //chy 2004-05-25
681 if (state->abortSig || state->Aborted)
682 goto L_ldc_takeabort;
683
684 BUSUSEDINCPCN;
685//chy 2004-05-25
686 /*
687 if (BIT (21))
688 LSBase = state->Base;
689 */
690
691 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
692
693 while (cpab == ARMul_INC) {
694 address += 4;
695 data = ARMul_LoadWordN (state, address);
696 //chy 2004-05-25
697 if (state->abortSig || state->Aborted)
698 goto L_ldc_takeabort;
699
700 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
701 }
702
703//chy 2004-05-25
704L_ldc_takeabort:
705 if (BIT (21)) {
706 if (!
707 ((state->abortSig || state->Aborted)
708 && state->lateabtSig == LOW))
709 LSBase = state->Base;
710 }
711
712 if (state->abortSig || state->Aborted)
713 TAKEABORT;
714}
715
716/* This function does the work of generating the addresses used in an
717 STC instruction. The code here is always post-indexed, it's up to the
718 caller to get the input address correct and to handle base register
719 modification. It also handles the Busy-Waiting. */
720
721void
722ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
723{
724 unsigned cpab;
725 ARMword data;
726
727 UNDEF_LSCPCBaseWb;
728
729 //printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
730 /*chy 2004-05-23 should update this function in the future,should concern dataabort */
731// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n");
732// chy 2004-05-25 , fix it now,so needn't printf
733// printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
734
735 //exit(-1);
736 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
737 if (!state->STC[CPNum]) {
738 /*
739 printf
740 ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n",
741 CPNum, instr, address);
742 */
743 ARMul_UndefInstr (state, instr);
744 return;
745 }
746
747 /*if (ADDREXCEPT (address) || VECTORACCESS (address))
748 INTERNALABORT (address);*/
749
750 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
751 while (cpab == ARMul_BUSY) {
752 ARMul_Icycles (state, 1, 0);
753 if (IntPending (state)) {
754 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT,
755 instr, 0);
756 return;
757 } else
758 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr,
759 &data);
760 }
761
762 if (cpab == ARMul_CANT) {
763 /*
764 printf
765 ("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n",
766 CPNum, instr, address);
767 */
768 CPTAKEABORT;
769 return;
770 }
771 /*#ifndef MODE32
772 if (ADDREXCEPT (address) || VECTORACCESS (address))
773 INTERNALABORT (address);
774 #endif*/
775 BUSUSEDINCPCN;
776//chy 2004-05-25
777 /*
778 if (BIT (21))
779 LSBase = state->Base;
780 */
781 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
782 ARMul_StoreWordN (state, address, data);
783 //chy 2004-05-25
784 if (state->abortSig || state->Aborted)
785 goto L_stc_takeabort;
786
787 while (cpab == ARMul_INC) {
788 address += 4;
789 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
790 ARMul_StoreWordN (state, address, data);
791 //chy 2004-05-25
792 if (state->abortSig || state->Aborted)
793 goto L_stc_takeabort;
794 }
795//chy 2004-05-25
796L_stc_takeabort:
797 if (BIT (21)) {
798 if (!
799 ((state->abortSig || state->Aborted)
800 && state->lateabtSig == LOW))
801 LSBase = state->Base;
802 }
803
804 if (state->abortSig || state->Aborted)
805 TAKEABORT;
806}
807
808/* This function does the Busy-Waiting for an MCR instruction. */
809
810void
811ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
812{
813 unsigned cpab;
814 int cm = BITS(0, 3) & 0xf;
815 int cp = BITS(5, 7) & 0x7;
816 int rd = BITS(12, 15) & 0xf;
817 int cn = BITS(16, 19) & 0xf;
818 int cpopc = BITS(21, 23) & 0x7;
819
820 if (CPNum == 15 && source == 0) //Cache flush
821 {
822 return;
823 }
824
825 //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
826 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
827 if (!state->MCR[CPNum]) {
828 //chy 2004-07-19 should fix in the future ????!!!!
829 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x",CPNum, source);
830 ARMul_UndefInstr (state, instr);
831 return;
832 }
833
834 //DEBUG("SKYEYE ARMul_MCR p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp);
835 //DEBUG("plutoo: MCR not implemented\n");
836 //exit(1);
837 //return;
838
839 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
840
841 while (cpab == ARMul_BUSY) {
842 ARMul_Icycles (state, 1, 0);
843
844 if (IntPending (state)) {
845 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT,
846 instr, 0);
847 return;
848 } else
849 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr,
850 source);
851 }
852
853 if (cpab == ARMul_CANT) {
854 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x", instr, CPNum, source); //ichfly todo
855 //ARMul_Abort (state, ARMul_UndefinedInstrV);
856 } else {
857 BUSUSEDINCPCN;
858 ARMul_Ccycles (state, 1, 0);
859 }
860}
861
862/* This function does the Busy-Waiting for an MCRR instruction. */
863
864void
865ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2)
866{
867 unsigned cpab;
868
869 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
870 if (!state->MCRR[CPNum]) {
871 ARMul_UndefInstr (state, instr);
872 return;
873 }
874
875 cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2);
876
877 while (cpab == ARMul_BUSY) {
878 ARMul_Icycles (state, 1, 0);
879
880 if (IntPending (state)) {
881 cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT,
882 instr, 0, 0);
883 return;
884 } else
885 cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr,
886 source1, source2);
887 }
888 if (cpab == ARMul_CANT) {
889 printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2);
890 ARMul_Abort (state, ARMul_UndefinedInstrV);
891 } else {
892 BUSUSEDINCPCN;
893 ARMul_Ccycles (state, 1, 0);
894 }
895}
896
897/* This function does the Busy-Waiting for an MRC instruction. */
898
899ARMword ARMul_MRC (ARMul_State * state, ARMword instr)
900{
901 int cm = BITS(0, 3) & 0xf;
902 int cp = BITS(5, 7) & 0x7;
903 int rd = BITS(12, 15) & 0xf;
904 int cn = BITS(16, 19) & 0xf;
905 int cpopc = BITS(21, 23) & 0x7;
906
907 if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer
908 ARMword result = Memory::KERNEL_MEMORY_VADDR;
909
910 if (result != -1) {
911 return result;
912 }
913 }
914
915 //DEBUG("SKYEYE ARMul_MRC p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp);
916 //DEBUG("plutoo: MRC not implemented\n");
917 //return;
918
919 unsigned cpab;
920 ARMword result = 0;
921
922 //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
923 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
924 if (!state->MRC[CPNum]) {
925 //chy 2004-07-19 should fix in the future????!!!!
926 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x", CPNum, instr);
927 ARMul_UndefInstr (state, instr);
928 return -1;
929 }
930
931 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
932 while (cpab == ARMul_BUSY) {
933 ARMul_Icycles (state, 1, 0);
934 if (IntPending (state)) {
935 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
936 instr, 0);
937 return (0);
938 } else
939 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
940 &result);
941 }
942 if (cpab == ARMul_CANT) {
943 printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
944 ARMul_Abort (state, ARMul_UndefinedInstrV);
945 /* Parent will destroy the flags otherwise. */
946 result = ECC;
947 } else {
948 BUSUSEDINCPCN;
949 ARMul_Ccycles (state, 1, 0);
950 ARMul_Icycles (state, 1, 0);
951 }
952
953 return result;
954}
955
956/* This function does the Busy-Waiting for an MRRC instruction. (to verify) */
957
958void
959ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2)
960{
961 unsigned cpab;
962 ARMword result1 = 0;
963 ARMword result2 = 0;
964
965 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
966 if (!state->MRRC[CPNum]) {
967 ARMul_UndefInstr (state, instr);
968 return;
969 }
970
971 cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2);
972 while (cpab == ARMul_BUSY) {
973 ARMul_Icycles (state, 1, 0);
974 if (IntPending (state)) {
975 cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT,
976 instr, 0, 0);
977 return;
978 } else
979 cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr,
980 &result1, &result2);
981 }
982 if (cpab == ARMul_CANT) {
983 printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr);
984 ARMul_Abort (state, ARMul_UndefinedInstrV);
985 } else {
986 BUSUSEDINCPCN;
987 ARMul_Ccycles (state, 1, 0);
988 ARMul_Icycles (state, 1, 0);
989 }
990
991 *dest1 = result1;
992 *dest2 = result2;
993}
994
995/* This function does the Busy-Waiting for an CDP instruction. */
996
997void
998ARMul_CDP (ARMul_State * state, ARMword instr)
999{
1000 unsigned cpab;
1001
1002 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
1003 if (!state->CDP[CPNum]) {
1004 ARMul_UndefInstr (state, instr);
1005 return;
1006 }
1007 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
1008 while (cpab == ARMul_BUSY) {
1009 ARMul_Icycles (state, 1, 0);
1010 if (IntPending (state)) {
1011 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT,
1012 instr);
1013 return;
1014 } else
1015 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
1016 }
1017 if (cpab == ARMul_CANT)
1018 ARMul_Abort (state, ARMul_UndefinedInstrV);
1019 else
1020 BUSUSEDN;
1021}
1022
1023/* This function handles Undefined instructions, as CP isntruction. */
1024
1025void
1026ARMul_UndefInstr (ARMul_State * state, ARMword instr)
1027{
1028 std::string disasm = ARM_Disasm::Disassemble(state->pc, instr);
1029 LOG_ERROR(Core_ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr);
1030 ARMul_Abort (state, ARMul_UndefinedInstrV);
1031}
1032
1033/* Return TRUE if an interrupt is pending, FALSE otherwise. */
1034
1035unsigned
1036IntPending (ARMul_State * state)
1037{
1038 /* Any exceptions. */
1039 if (state->NresetSig == LOW) {
1040 ARMul_Abort (state, ARMul_ResetV);
1041 return TRUE;
1042 } else if (!state->NfiqSig && !FFLAG) {
1043 ARMul_Abort (state, ARMul_FIQV);
1044 return TRUE;
1045 } else if (!state->NirqSig && !IFLAG) {
1046 ARMul_Abort (state, ARMul_IRQV);
1047 return TRUE;
1048 }
1049
1050 return FALSE;
1051}
1052
1053/* Align a word access to a non word boundary. */
1054
1055ARMword
1056ARMul_Align (ARMul_State* state, ARMword address, ARMword data)
1057{
1058 /* This code assumes the address is really unaligned,
1059 as a shift by 32 is undefined in C. */
1060
1061 address = (address & 3) << 3; /* Get the word address. */
1062 return ((data >> address) | (data << (32 - address))); /* rot right */
1063}