Automatic date update in version.in
[deliverable/binutils-gdb.git] / sim / arm / armsupp.c
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 3 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, see <http://www.gnu.org/licenses/>. */
16
17 #include "armdefs.h"
18 #include "armemu.h"
19 #include "ansidecl.h"
20 #include "libiberty.h"
21 #include <math.h>
22
23 /* Definitions for the support routines. */
24
25 static ARMword ModeToBank (ARMword);
26 static void EnvokeList (ARMul_State *, unsigned long, unsigned long);
27
28 struct EventNode
29 { /* An event list node. */
30 unsigned (*func) (ARMul_State *); /* The function to call. */
31 struct EventNode *next;
32 };
33
34 /* This routine returns the value of a register from a mode. */
35
36 ARMword
37 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
38 {
39 mode &= MODEBITS;
40 if (mode != state->Mode)
41 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
42 else
43 return (state->Reg[reg]);
44 }
45
46 /* This routine sets the value of a register for a mode. */
47
48 void
49 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
50 {
51 mode &= MODEBITS;
52 if (mode != state->Mode)
53 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
54 else
55 state->Reg[reg] = value;
56 }
57
58 /* This routine returns the value of the PC, mode independently. */
59
60 ARMword
61 ARMul_GetPC (ARMul_State * state)
62 {
63 if (state->Mode > SVC26MODE)
64 return state->Reg[15];
65 else
66 return R15PC;
67 }
68
69 /* This routine returns the value of the PC, mode independently. */
70
71 ARMword
72 ARMul_GetNextPC (ARMul_State * state)
73 {
74 if (state->Mode > SVC26MODE)
75 return state->Reg[15] + isize;
76 else
77 return (state->Reg[15] + isize) & R15PCBITS;
78 }
79
80 /* This routine sets the value of the PC. */
81
82 void
83 ARMul_SetPC (ARMul_State * state, ARMword value)
84 {
85 if (ARMul_MODE32BIT)
86 state->Reg[15] = value & PCBITS;
87 else
88 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
89 FLUSHPIPE;
90 }
91
92 /* This routine returns the value of register 15, mode independently. */
93
94 ARMword
95 ARMul_GetR15 (ARMul_State * state)
96 {
97 if (state->Mode > SVC26MODE)
98 return (state->Reg[15]);
99 else
100 return (R15PC | ECC | ER15INT | EMODE);
101 }
102
103 /* This routine sets the value of Register 15. */
104
105 void
106 ARMul_SetR15 (ARMul_State * state, ARMword value)
107 {
108 if (ARMul_MODE32BIT)
109 state->Reg[15] = value & PCBITS;
110 else
111 {
112 state->Reg[15] = value;
113 ARMul_R15Altered (state);
114 }
115 FLUSHPIPE;
116 }
117
118 /* This routine returns the value of the CPSR. */
119
120 ARMword
121 ARMul_GetCPSR (ARMul_State * state)
122 {
123 return (CPSR | state->Cpsr);
124 }
125
126 /* This routine sets the value of the CPSR. */
127
128 void
129 ARMul_SetCPSR (ARMul_State * state, ARMword value)
130 {
131 state->Cpsr = value;
132 ARMul_CPSRAltered (state);
133 }
134
135 /* This routine does all the nasty bits involved in a write to the CPSR,
136 including updating the register bank, given a MSR instruction. */
137
138 void
139 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
140 {
141 state->Cpsr = ARMul_GetCPSR (state);
142
143 if (state->Mode != USER26MODE
144 && state->Mode != USER32MODE)
145 {
146 /* In user mode, only write flags. */
147 if (BIT (16))
148 SETPSR_C (state->Cpsr, rhs);
149 if (BIT (17))
150 SETPSR_X (state->Cpsr, rhs);
151 if (BIT (18))
152 SETPSR_S (state->Cpsr, rhs);
153 }
154 if (BIT (19))
155 SETPSR_F (state->Cpsr, rhs);
156 ARMul_CPSRAltered (state);
157 }
158
159 /* Get an SPSR from the specified mode. */
160
161 ARMword
162 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
163 {
164 ARMword bank = ModeToBank (mode & MODEBITS);
165
166 if (! BANK_CAN_ACCESS_SPSR (bank))
167 return ARMul_GetCPSR (state);
168
169 return state->Spsr[bank];
170 }
171
172 /* This routine does a write to an SPSR. */
173
174 void
175 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
176 {
177 ARMword bank = ModeToBank (mode & MODEBITS);
178
179 if (BANK_CAN_ACCESS_SPSR (bank))
180 state->Spsr[bank] = value;
181 }
182
183 /* This routine does a write to the current SPSR, given an MSR instruction. */
184
185 void
186 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
187 {
188 if (BANK_CAN_ACCESS_SPSR (state->Bank))
189 {
190 if (BIT (16))
191 SETPSR_C (state->Spsr[state->Bank], rhs);
192 if (BIT (17))
193 SETPSR_X (state->Spsr[state->Bank], rhs);
194 if (BIT (18))
195 SETPSR_S (state->Spsr[state->Bank], rhs);
196 if (BIT (19))
197 SETPSR_F (state->Spsr[state->Bank], rhs);
198 }
199 }
200
201 /* This routine updates the state of the emulator after the Cpsr has been
202 changed. Both the processor flags and register bank are updated. */
203
204 void
205 ARMul_CPSRAltered (ARMul_State * state)
206 {
207 ARMword oldmode;
208
209 if (state->prog32Sig == LOW)
210 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
211
212 oldmode = state->Mode;
213
214 if (state->Mode != (state->Cpsr & MODEBITS))
215 {
216 state->Mode =
217 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
218
219 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
220 }
221 state->Cpsr &= ~MODEBITS;
222
223 ASSIGNINT (state->Cpsr & INTBITS);
224 state->Cpsr &= ~INTBITS;
225 ASSIGNN ((state->Cpsr & NBIT) != 0);
226 state->Cpsr &= ~NBIT;
227 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
228 state->Cpsr &= ~ZBIT;
229 ASSIGNC ((state->Cpsr & CBIT) != 0);
230 state->Cpsr &= ~CBIT;
231 ASSIGNV ((state->Cpsr & VBIT) != 0);
232 state->Cpsr &= ~VBIT;
233 ASSIGNS ((state->Cpsr & SBIT) != 0);
234 state->Cpsr &= ~SBIT;
235 #ifdef MODET
236 ASSIGNT ((state->Cpsr & TBIT) != 0);
237 state->Cpsr &= ~TBIT;
238 #endif
239
240 if (oldmode > SVC26MODE)
241 {
242 if (state->Mode <= SVC26MODE)
243 {
244 state->Emulate = CHANGEMODE;
245 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
246 }
247 }
248 else
249 {
250 if (state->Mode > SVC26MODE)
251 {
252 state->Emulate = CHANGEMODE;
253 state->Reg[15] = R15PC;
254 }
255 else
256 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
257 }
258 }
259
260 /* This routine updates the state of the emulator after register 15 has
261 been changed. Both the processor flags and register bank are updated.
262 This routine should only be called from a 26 bit mode. */
263
264 void
265 ARMul_R15Altered (ARMul_State * state)
266 {
267 if (state->Mode != R15MODE)
268 {
269 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
270 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
271 }
272
273 if (state->Mode > SVC26MODE)
274 state->Emulate = CHANGEMODE;
275
276 ASSIGNR15INT (R15INT);
277
278 ASSIGNN ((state->Reg[15] & NBIT) != 0);
279 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
280 ASSIGNC ((state->Reg[15] & CBIT) != 0);
281 ASSIGNV ((state->Reg[15] & VBIT) != 0);
282 }
283
284 /* This routine controls the saving and restoring of registers across mode
285 changes. The regbank matrix is largely unused, only rows 13 and 14 are
286 used across all modes, 8 to 14 are used for FIQ, all others use the USER
287 column. It's easier this way. old and new parameter are modes numbers.
288 Notice the side effect of changing the Bank variable. */
289
290 ARMword
291 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
292 {
293 unsigned i;
294 ARMword oldbank;
295 ARMword newbank;
296
297 oldbank = ModeToBank (oldmode);
298 newbank = state->Bank = ModeToBank (newmode);
299
300 /* Do we really need to do it? */
301 if (oldbank != newbank)
302 {
303 /* Save away the old registers. */
304 switch (oldbank)
305 {
306 case USERBANK:
307 case IRQBANK:
308 case SVCBANK:
309 case ABORTBANK:
310 case UNDEFBANK:
311 if (newbank == FIQBANK)
312 for (i = 8; i < 13; i++)
313 state->RegBank[USERBANK][i] = state->Reg[i];
314 state->RegBank[oldbank][13] = state->Reg[13];
315 state->RegBank[oldbank][14] = state->Reg[14];
316 break;
317 case FIQBANK:
318 for (i = 8; i < 15; i++)
319 state->RegBank[FIQBANK][i] = state->Reg[i];
320 break;
321 case DUMMYBANK:
322 for (i = 8; i < 15; i++)
323 state->RegBank[DUMMYBANK][i] = 0;
324 break;
325 default:
326 abort ();
327 }
328
329 /* Restore the new registers. */
330 switch (newbank)
331 {
332 case USERBANK:
333 case IRQBANK:
334 case SVCBANK:
335 case ABORTBANK:
336 case UNDEFBANK:
337 if (oldbank == FIQBANK)
338 for (i = 8; i < 13; i++)
339 state->Reg[i] = state->RegBank[USERBANK][i];
340 state->Reg[13] = state->RegBank[newbank][13];
341 state->Reg[14] = state->RegBank[newbank][14];
342 break;
343 case FIQBANK:
344 for (i = 8; i < 15; i++)
345 state->Reg[i] = state->RegBank[FIQBANK][i];
346 break;
347 case DUMMYBANK:
348 for (i = 8; i < 15; i++)
349 state->Reg[i] = 0;
350 break;
351 default:
352 abort ();
353 }
354 }
355
356 return newmode;
357 }
358
359 /* Given a processor mode, this routine returns the
360 register bank that will be accessed in that mode. */
361
362 static ARMword
363 ModeToBank (ARMword mode)
364 {
365 static ARMword bankofmode[] =
366 {
367 USERBANK, FIQBANK, IRQBANK, SVCBANK,
368 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
369 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
370 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
371 USERBANK, FIQBANK, IRQBANK, SVCBANK,
372 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
373 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
374 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
375 };
376
377 if (mode >= ARRAY_SIZE (bankofmode))
378 return DUMMYBANK;
379
380 return bankofmode[mode];
381 }
382
383 /* Returns the register number of the nth register in a reg list. */
384
385 unsigned
386 ARMul_NthReg (ARMword instr, unsigned number)
387 {
388 unsigned bit, upto;
389
390 for (bit = 0, upto = 0; upto <= number; bit ++)
391 if (BIT (bit))
392 upto ++;
393
394 return (bit - 1);
395 }
396
397 /* Assigns the N and Z flags depending on the value of result. */
398
399 void
400 ARMul_NegZero (ARMul_State * state, ARMword result)
401 {
402 if (NEG (result))
403 {
404 SETN;
405 CLEARZ;
406 }
407 else if (result == 0)
408 {
409 CLEARN;
410 SETZ;
411 }
412 else
413 {
414 CLEARN;
415 CLEARZ;
416 }
417 }
418
419 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
420
421 int
422 AddOverflow (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
430 int
431 SubOverflow (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
439 void
440 ARMul_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
448 void
449 ARMul_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
456 void
457 ARMul_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
465 void
466 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
467 {
468 ASSIGNV (SubOverflow (a, b, result));
469 }
470
471 static void
472 handle_VFP_xfer (ARMul_State * state, ARMword instr)
473 {
474 if (TOPBITS (28) == NV)
475 {
476 fprintf (stderr, "SIM: UNDEFINED VFP instruction\n");
477 return;
478 }
479
480 if (BITS (25, 27) != 0x6)
481 {
482 fprintf (stderr, "SIM: ISE: VFP handler called incorrectly\n");
483 return;
484 }
485
486 switch (BITS (20, 24))
487 {
488 case 0x04:
489 case 0x05:
490 {
491 /* VMOV double precision to/from two ARM registers. */
492 int vm = BITS (0, 3);
493 int rt1 = BITS (12, 15);
494 int rt2 = BITS (16, 19);
495
496 /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */
497 if (BIT (20))
498 {
499 /* Transfer to ARM. */
500 /* FIXME: UPPREDICTABLE if rt1 == rt2. */
501 state->Reg[rt1] = VFP_dword (vm) & 0xffffffff;
502 state->Reg[rt2] = VFP_dword (vm) >> 32;
503 }
504 else
505 {
506 VFP_dword (vm) = state->Reg[rt2];
507 VFP_dword (vm) <<= 32;
508 VFP_dword (vm) |= (state->Reg[rt1] & 0xffffffff);
509 }
510 return;
511 }
512
513 case 0x08:
514 case 0x0A:
515 case 0x0C:
516 case 0x0E:
517 {
518 /* VSTM with PUW=011 or PUW=010. */
519 int n = BITS (16, 19);
520 int imm8 = BITS (0, 7);
521
522 ARMword address = state->Reg[n];
523 if (BIT (21))
524 state->Reg[n] = address + (imm8 << 2);
525
526 if (BIT (8))
527 {
528 int src = (BIT (22) << 4) | BITS (12, 15);
529 imm8 >>= 1;
530 while (imm8--)
531 {
532 if (state->bigendSig)
533 {
534 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
535 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
536 }
537 else
538 {
539 ARMul_StoreWordN (state, address, VFP_dword (src));
540 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
541 }
542 address += 8;
543 src += 1;
544 }
545 }
546 else
547 {
548 int src = (BITS (12, 15) << 1) | BIT (22);
549 while (imm8--)
550 {
551 ARMul_StoreWordN (state, address, VFP_uword (src));
552 address += 4;
553 src += 1;
554 }
555 }
556 }
557 return;
558
559 case 0x10:
560 case 0x14:
561 case 0x18:
562 case 0x1C:
563 {
564 /* VSTR */
565 ARMword imm32 = BITS (0, 7) << 2;
566 int base = state->Reg[LHSReg];
567 ARMword address;
568 int dest;
569
570 if (LHSReg == 15)
571 base = (base + 3) & ~3;
572
573 address = base + (BIT (23) ? imm32 : - imm32);
574
575 if (CPNum == 10)
576 {
577 dest = (DESTReg << 1) + BIT (22);
578
579 ARMul_StoreWordN (state, address, VFP_uword (dest));
580 }
581 else
582 {
583 dest = (BIT (22) << 4) + DESTReg;
584
585 if (state->bigendSig)
586 {
587 ARMul_StoreWordN (state, address, VFP_dword (dest) >> 32);
588 ARMul_StoreWordN (state, address + 4, VFP_dword (dest));
589 }
590 else
591 {
592 ARMul_StoreWordN (state, address, VFP_dword (dest));
593 ARMul_StoreWordN (state, address + 4, VFP_dword (dest) >> 32);
594 }
595 }
596 }
597 return;
598
599 case 0x12:
600 case 0x16:
601 if (BITS (16, 19) == 13)
602 {
603 /* VPUSH */
604 ARMword address = state->Reg[13] - (BITS (0, 7) << 2);
605 state->Reg[13] = address;
606
607 if (BIT (8))
608 {
609 int dreg = (BIT (22) << 4) | BITS (12, 15);
610 int num = BITS (0, 7) >> 1;
611 while (num--)
612 {
613 if (state->bigendSig)
614 {
615 ARMul_StoreWordN (state, address, VFP_dword (dreg) >> 32);
616 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg));
617 }
618 else
619 {
620 ARMul_StoreWordN (state, address, VFP_dword (dreg));
621 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg) >> 32);
622 }
623 address += 8;
624 dreg += 1;
625 }
626 }
627 else
628 {
629 int sreg = (BITS (12, 15) << 1) | BIT (22);
630 int num = BITS (0, 7);
631 while (num--)
632 {
633 ARMul_StoreWordN (state, address, VFP_uword (sreg));
634 address += 4;
635 sreg += 1;
636 }
637 }
638 }
639 else if (BITS (9, 11) != 0x5)
640 break;
641 else
642 {
643 /* VSTM PUW=101 */
644 int n = BITS (16, 19);
645 int imm8 = BITS (0, 7);
646 ARMword address = state->Reg[n] - (imm8 << 2);
647 state->Reg[n] = address;
648
649 if (BIT (8))
650 {
651 int src = (BIT (22) << 4) | BITS (12, 15);
652
653 imm8 >>= 1;
654 while (imm8--)
655 {
656 if (state->bigendSig)
657 {
658 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
659 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
660 }
661 else
662 {
663 ARMul_StoreWordN (state, address, VFP_dword (src));
664 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
665 }
666 address += 8;
667 src += 1;
668 }
669 }
670 else
671 {
672 int src = (BITS (12, 15) << 1) | BIT (22);
673
674 while (imm8--)
675 {
676 ARMul_StoreWordN (state, address, VFP_uword (src));
677 address += 4;
678 src += 1;
679 }
680 }
681 }
682 return;
683
684 case 0x13:
685 case 0x17:
686 /* VLDM PUW=101 */
687 case 0x09:
688 case 0x0D:
689 /* VLDM PUW=010 */
690 {
691 int n = BITS (16, 19);
692 int imm8 = BITS (0, 7);
693
694 ARMword address = state->Reg[n];
695 if (BIT (23) == 0)
696 address -= imm8 << 2;
697 if (BIT (21))
698 state->Reg[n] = BIT (23) ? address + (imm8 << 2) : address;
699
700 if (BIT (8))
701 {
702 int dest = (BIT (22) << 4) | BITS (12, 15);
703 imm8 >>= 1;
704 while (imm8--)
705 {
706 if (state->bigendSig)
707 {
708 VFP_dword (dest) = ARMul_LoadWordN (state, address);
709 VFP_dword (dest) <<= 32;
710 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
711 }
712 else
713 {
714 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
715 VFP_dword (dest) <<= 32;
716 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
717 }
718
719 if (trace)
720 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
721
722 address += 8;
723 dest += 1;
724 }
725 }
726 else
727 {
728 int dest = (BITS (12, 15) << 1) | BIT (22);
729
730 while (imm8--)
731 {
732 VFP_uword (dest) = ARMul_LoadWordN (state, address);
733 address += 4;
734 dest += 1;
735 }
736 }
737 }
738 return;
739
740 case 0x0B:
741 case 0x0F:
742 if (BITS (16, 19) == 13)
743 {
744 /* VPOP */
745 ARMword address = state->Reg[13];
746 state->Reg[13] = address + (BITS (0, 7) << 2);
747
748 if (BIT (8))
749 {
750 int dest = (BIT (22) << 4) | BITS (12, 15);
751 int num = BITS (0, 7) >> 1;
752
753 while (num--)
754 {
755 if (state->bigendSig)
756 {
757 VFP_dword (dest) = ARMul_LoadWordN (state, address);
758 VFP_dword (dest) <<= 32;
759 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
760 }
761 else
762 {
763 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
764 VFP_dword (dest) <<= 32;
765 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
766 }
767
768 if (trace)
769 fprintf (stderr, " VFP: VPOP: D%d = %g\n", dest, VFP_dval (dest));
770
771 address += 8;
772 dest += 1;
773 }
774 }
775 else
776 {
777 int sreg = (BITS (12, 15) << 1) | BIT (22);
778 int num = BITS (0, 7);
779
780 while (num--)
781 {
782 VFP_uword (sreg) = ARMul_LoadWordN (state, address);
783 address += 4;
784 sreg += 1;
785 }
786 }
787 }
788 else if (BITS (9, 11) != 0x5)
789 break;
790 else
791 {
792 /* VLDM PUW=011 */
793 int n = BITS (16, 19);
794 int imm8 = BITS (0, 7);
795 ARMword address = state->Reg[n];
796 state->Reg[n] += imm8 << 2;
797
798 if (BIT (8))
799 {
800 int dest = (BIT (22) << 4) | BITS (12, 15);
801
802 imm8 >>= 1;
803 while (imm8--)
804 {
805 if (state->bigendSig)
806 {
807 VFP_dword (dest) = ARMul_LoadWordN (state, address);
808 VFP_dword (dest) <<= 32;
809 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
810 }
811 else
812 {
813 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
814 VFP_dword (dest) <<= 32;
815 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
816 }
817
818 if (trace)
819 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
820
821 address += 8;
822 dest += 1;
823 }
824 }
825 else
826 {
827 int dest = (BITS (12, 15) << 1) | BIT (22);
828 while (imm8--)
829 {
830 VFP_uword (dest) = ARMul_LoadWordN (state, address);
831 address += 4;
832 dest += 1;
833 }
834 }
835 }
836 return;
837
838 case 0x11:
839 case 0x15:
840 case 0x19:
841 case 0x1D:
842 {
843 /* VLDR */
844 ARMword imm32 = BITS (0, 7) << 2;
845 int base = state->Reg[LHSReg];
846 ARMword address;
847 int dest;
848
849 if (LHSReg == 15)
850 base = (base + 3) & ~3;
851
852 address = base + (BIT (23) ? imm32 : - imm32);
853
854 if (CPNum == 10)
855 {
856 dest = (DESTReg << 1) + BIT (22);
857
858 VFP_uword (dest) = ARMul_LoadWordN (state, address);
859 }
860 else
861 {
862 dest = (BIT (22) << 4) + DESTReg;
863
864 if (state->bigendSig)
865 {
866 VFP_dword (dest) = ARMul_LoadWordN (state, address);
867 VFP_dword (dest) <<= 32;
868 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
869 }
870 else
871 {
872 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
873 VFP_dword (dest) <<= 32;
874 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
875 }
876
877 if (trace)
878 fprintf (stderr, " VFP: VLDR: D%d = %g\n", dest, VFP_dval (dest));
879 }
880 }
881 return;
882 }
883
884 fprintf (stderr, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
885 }
886
887 /* This function does the work of generating the addresses used in an
888 LDC instruction. The code here is always post-indexed, it's up to the
889 caller to get the input address correct and to handle base register
890 modification. It also handles the Busy-Waiting. */
891
892 void
893 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
894 {
895 unsigned cpab;
896 ARMword data;
897
898 if (CPNum == 10 || CPNum == 11)
899 {
900 handle_VFP_xfer (state, instr);
901 return;
902 }
903
904 UNDEF_LSCPCBaseWb;
905
906 if (! CP_ACCESS_ALLOWED (state, CPNum))
907 {
908 ARMul_UndefInstr (state, instr);
909 return;
910 }
911
912 if (ADDREXCEPT (address))
913 INTERNALABORT (address);
914
915 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
916 while (cpab == ARMul_BUSY)
917 {
918 ARMul_Icycles (state, 1, 0);
919
920 if (IntPending (state))
921 {
922 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
923 return;
924 }
925 else
926 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
927 }
928 if (cpab == ARMul_CANT)
929 {
930 CPTAKEABORT;
931 return;
932 }
933
934 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
935 data = ARMul_LoadWordN (state, address);
936 BUSUSEDINCPCN;
937
938 if (BIT (21))
939 LSBase = state->Base;
940 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
941
942 while (cpab == ARMul_INC)
943 {
944 address += 4;
945 data = ARMul_LoadWordN (state, address);
946 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
947 }
948
949 if (state->abortSig || state->Aborted)
950 TAKEABORT;
951 }
952
953 /* This function does the work of generating the addresses used in an
954 STC instruction. The code here is always post-indexed, it's up to the
955 caller to get the input address correct and to handle base register
956 modification. It also handles the Busy-Waiting. */
957
958 void
959 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
960 {
961 unsigned cpab;
962 ARMword data;
963
964 if (CPNum == 10 || CPNum == 11)
965 {
966 handle_VFP_xfer (state, instr);
967 return;
968 }
969
970 UNDEF_LSCPCBaseWb;
971
972 if (! CP_ACCESS_ALLOWED (state, CPNum))
973 {
974 ARMul_UndefInstr (state, instr);
975 return;
976 }
977
978 if (ADDREXCEPT (address) || VECTORACCESS (address))
979 INTERNALABORT (address);
980
981 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
982 while (cpab == ARMul_BUSY)
983 {
984 ARMul_Icycles (state, 1, 0);
985 if (IntPending (state))
986 {
987 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
988 return;
989 }
990 else
991 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
992 }
993
994 if (cpab == ARMul_CANT)
995 {
996 CPTAKEABORT;
997 return;
998 }
999 #ifndef MODE32
1000 if (ADDREXCEPT (address) || VECTORACCESS (address))
1001 INTERNALABORT (address);
1002 #endif
1003 BUSUSEDINCPCN;
1004 if (BIT (21))
1005 LSBase = state->Base;
1006 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
1007 ARMul_StoreWordN (state, address, data);
1008
1009 while (cpab == ARMul_INC)
1010 {
1011 address += 4;
1012 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
1013 ARMul_StoreWordN (state, address, data);
1014 }
1015
1016 if (state->abortSig || state->Aborted)
1017 TAKEABORT;
1018 }
1019
1020 /* This function does the Busy-Waiting for an MCR instruction. */
1021
1022 void
1023 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
1024 {
1025 unsigned cpab;
1026
1027 if (! CP_ACCESS_ALLOWED (state, CPNum))
1028 {
1029 ARMul_UndefInstr (state, instr);
1030 return;
1031 }
1032
1033 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
1034
1035 while (cpab == ARMul_BUSY)
1036 {
1037 ARMul_Icycles (state, 1, 0);
1038
1039 if (IntPending (state))
1040 {
1041 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1042 return;
1043 }
1044 else
1045 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
1046 }
1047
1048 if (cpab == ARMul_CANT)
1049 ARMul_Abort (state, ARMul_UndefinedInstrV);
1050 else
1051 {
1052 BUSUSEDINCPCN;
1053 ARMul_Ccycles (state, 1, 0);
1054 }
1055 }
1056
1057 /* This function does the Busy-Waiting for an MRC instruction. */
1058
1059 ARMword
1060 ARMul_MRC (ARMul_State * state, ARMword instr)
1061 {
1062 unsigned cpab;
1063 ARMword result = 0;
1064
1065 if (! CP_ACCESS_ALLOWED (state, CPNum))
1066 {
1067 ARMul_UndefInstr (state, instr);
1068 return result;
1069 }
1070
1071 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
1072 while (cpab == ARMul_BUSY)
1073 {
1074 ARMul_Icycles (state, 1, 0);
1075 if (IntPending (state))
1076 {
1077 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1078 return (0);
1079 }
1080 else
1081 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
1082 }
1083 if (cpab == ARMul_CANT)
1084 {
1085 ARMul_Abort (state, ARMul_UndefinedInstrV);
1086 /* Parent will destroy the flags otherwise. */
1087 result = ECC;
1088 }
1089 else
1090 {
1091 BUSUSEDINCPCN;
1092 ARMul_Ccycles (state, 1, 0);
1093 ARMul_Icycles (state, 1, 0);
1094 }
1095
1096 return result;
1097 }
1098
1099 static void
1100 handle_VFP_op (ARMul_State * state, ARMword instr)
1101 {
1102 int dest;
1103 int srcN;
1104 int srcM;
1105
1106 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1107 {
1108 fprintf (stderr, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1109 return;
1110 }
1111
1112 if (BIT (8))
1113 {
1114 dest = BITS(12,15) + (BIT (22) << 4);
1115 srcN = LHSReg + (BIT (7) << 4);
1116 srcM = BITS (0,3) + (BIT (5) << 4);
1117 }
1118 else
1119 {
1120 dest = (BITS(12,15) << 1) + BIT (22);
1121 srcN = (LHSReg << 1) + BIT (7);
1122 srcM = (BITS (0,3) << 1) + BIT (5);
1123 }
1124
1125 switch (BITS (20, 27))
1126 {
1127 case 0xE0:
1128 case 0xE4:
1129 /* VMLA VMLS */
1130 if (BIT (8))
1131 {
1132 ARMdval val = VFP_dval (srcN) * VFP_dval (srcM);
1133
1134 if (BIT (6))
1135 {
1136 if (trace)
1137 fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
1138 VFP_dval (dest) - val,
1139 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1140 VFP_dval (dest) -= val;
1141 }
1142 else
1143 {
1144 if (trace)
1145 fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
1146 VFP_dval (dest) + val,
1147 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1148 VFP_dval (dest) += val;
1149 }
1150 }
1151 else
1152 {
1153 ARMfval val = VFP_fval (srcN) * VFP_fval (srcM);
1154
1155 if (BIT (6))
1156 {
1157 if (trace)
1158 fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
1159 VFP_fval (dest) - val,
1160 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
1161 VFP_fval (dest) -= val;
1162 }
1163 else
1164 {
1165 if (trace)
1166 fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
1167 VFP_fval (dest) + val,
1168 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
1169 VFP_fval (dest) += val;
1170 }
1171 }
1172 return;
1173
1174 case 0xE1:
1175 case 0xE5:
1176 if (BIT (8))
1177 {
1178 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1179
1180 if (BIT (6))
1181 {
1182 /* VNMLA */
1183 if (trace)
1184 fprintf (stderr, " VFP: VNMLA: %g = -(%g + (%g * %g))\n",
1185 -(VFP_dval (dest) + product),
1186 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1187 VFP_dval (dest) = -(product + VFP_dval (dest));
1188 }
1189 else
1190 {
1191 /* VNMLS */
1192 if (trace)
1193 fprintf (stderr, " VFP: VNMLS: %g = -(%g + (%g * %g))\n",
1194 -(VFP_dval (dest) + product),
1195 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1196 VFP_dval (dest) = product - VFP_dval (dest);
1197 }
1198 }
1199 else
1200 {
1201 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
1202
1203 if (BIT (6))
1204 /* VNMLA */
1205 VFP_fval (dest) = -(product + VFP_fval (dest));
1206 else
1207 /* VNMLS */
1208 VFP_fval (dest) = product - VFP_fval (dest);
1209 }
1210 return;
1211
1212 case 0xE2:
1213 case 0xE6:
1214 if (BIT (8))
1215 {
1216 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1217
1218 if (BIT (6))
1219 {
1220 if (trace)
1221 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1222 - product, VFP_dval (srcN), VFP_dval (srcM));
1223 /* VNMUL */
1224 VFP_dval (dest) = - product;
1225 }
1226 else
1227 {
1228 if (trace)
1229 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1230 product, VFP_dval (srcN), VFP_dval (srcM));
1231 /* VMUL */
1232 VFP_dval (dest) = product;
1233 }
1234 }
1235 else
1236 {
1237 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
1238
1239 if (BIT (6))
1240 {
1241 if (trace)
1242 fprintf (stderr, " VFP: VNMUL: %g = %g * %g\n",
1243 - product, VFP_fval (srcN), VFP_fval (srcM));
1244
1245 VFP_fval (dest) = - product;
1246 }
1247 else
1248 {
1249 if (trace)
1250 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1251 product, VFP_fval (srcN), VFP_fval (srcM));
1252
1253 VFP_fval (dest) = product;
1254 }
1255 }
1256 return;
1257
1258 case 0xE3:
1259 case 0xE7:
1260 if (BIT (6) == 0)
1261 {
1262 /* VADD */
1263 if (BIT(8))
1264 {
1265 if (trace)
1266 fprintf (stderr, " VFP: VADD %g = %g + %g\n",
1267 VFP_dval (srcN) + VFP_dval (srcM),
1268 VFP_dval (srcN),
1269 VFP_dval (srcM));
1270 VFP_dval (dest) = VFP_dval (srcN) + VFP_dval (srcM);
1271 }
1272 else
1273 VFP_fval (dest) = VFP_fval (srcN) + VFP_fval (srcM);
1274
1275 }
1276 else
1277 {
1278 /* VSUB */
1279 if (BIT(8))
1280 {
1281 if (trace)
1282 fprintf (stderr, " VFP: VSUB %g = %g - %g\n",
1283 VFP_dval (srcN) - VFP_dval (srcM),
1284 VFP_dval (srcN),
1285 VFP_dval (srcM));
1286 VFP_dval (dest) = VFP_dval (srcN) - VFP_dval (srcM);
1287 }
1288 else
1289 VFP_fval (dest) = VFP_fval (srcN) - VFP_fval (srcM);
1290 }
1291 return;
1292
1293 case 0xE8:
1294 case 0xEC:
1295 if (BIT (6) == 1)
1296 break;
1297
1298 /* VDIV */
1299 if (BIT (8))
1300 {
1301 ARMdval res = VFP_dval (srcN) / VFP_dval (srcM);
1302 if (trace)
1303 fprintf (stderr, " VFP: VDIV (64bit): %g = %g / %g\n",
1304 res, VFP_dval (srcN), VFP_dval (srcM));
1305 VFP_dval (dest) = res;
1306 }
1307 else
1308 {
1309 if (trace)
1310 fprintf (stderr, " VFP: VDIV: %g = %g / %g\n",
1311 VFP_fval (srcN) / VFP_fval (srcM),
1312 VFP_fval (srcN), VFP_fval (srcM));
1313
1314 VFP_fval (dest) = VFP_fval (srcN) / VFP_fval (srcM);
1315 }
1316 return;
1317
1318 case 0xEB:
1319 case 0xEF:
1320 if (BIT (6) != 1)
1321 break;
1322
1323 switch (BITS (16, 19))
1324 {
1325 case 0x0:
1326 if (BIT (7) == 0)
1327 {
1328 if (BIT (8))
1329 {
1330 /* VMOV.F64 <Dd>, <Dm>. */
1331 VFP_dval (dest) = VFP_dval (srcM);
1332 if (trace)
1333 fprintf (stderr, " VFP: VMOV d%d, d%d: %g\n", dest, srcM, VFP_dval (srcM));
1334 }
1335 else
1336 {
1337 /* VMOV.F32 <Sd>, <Sm>. */
1338 VFP_fval (dest) = VFP_fval (srcM);
1339 if (trace)
1340 fprintf (stderr, " VFP: VMOV s%d, s%d: %g\n", dest, srcM, VFP_fval (srcM));
1341 }
1342 }
1343 else
1344 {
1345 /* VABS */
1346 if (BIT (8))
1347 {
1348 ARMdval src = VFP_dval (srcM);
1349
1350 VFP_dval (dest) = fabs (src);
1351 if (trace)
1352 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_dval (dest));
1353 }
1354 else
1355 {
1356 ARMfval src = VFP_fval (srcM);
1357
1358 VFP_fval (dest) = fabsf (src);
1359 if (trace)
1360 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_fval (dest));
1361 }
1362 }
1363 return;
1364
1365 case 0x1:
1366 if (BIT (7) == 0)
1367 {
1368 /* VNEG */
1369 if (BIT (8))
1370 VFP_dval (dest) = - VFP_dval (srcM);
1371 else
1372 VFP_fval (dest) = - VFP_fval (srcM);
1373 }
1374 else
1375 {
1376 /* VSQRT */
1377 if (BIT (8))
1378 {
1379 if (trace)
1380 fprintf (stderr, " VFP: %g = root(%g)\n",
1381 sqrt (VFP_dval (srcM)), VFP_dval (srcM));
1382
1383 VFP_dval (dest) = sqrt (VFP_dval (srcM));
1384 }
1385 else
1386 {
1387 if (trace)
1388 fprintf (stderr, " VFP: %g = root(%g)\n",
1389 sqrtf (VFP_fval (srcM)), VFP_fval (srcM));
1390
1391 VFP_fval (dest) = sqrtf (VFP_fval (srcM));
1392 }
1393 }
1394 return;
1395
1396 case 0x4:
1397 case 0x5:
1398 /* VCMP, VCMPE */
1399 if (BIT(8))
1400 {
1401 ARMdval res = VFP_dval (dest);
1402
1403 if (BIT (16) == 0)
1404 {
1405 ARMdval src = VFP_dval (srcM);
1406
1407 if (isinf (res) && isinf (src))
1408 {
1409 if (res > 0.0 && src > 0.0)
1410 res = 0.0;
1411 else if (res < 0.0 && src < 0.0)
1412 res = 0.0;
1413 /* else leave res alone. */
1414 }
1415 else
1416 res -= src;
1417 }
1418
1419 /* FIXME: Add handling of signalling NaNs and the E bit. */
1420
1421 state->FPSCR &= 0x0FFFFFFF;
1422 if (res < 0.0)
1423 state->FPSCR |= NBIT;
1424 else
1425 state->FPSCR |= CBIT;
1426 if (res == 0.0)
1427 state->FPSCR |= ZBIT;
1428 if (isnan (res))
1429 state->FPSCR |= VBIT;
1430
1431 if (trace)
1432 fprintf (stderr, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n",
1433 VFP_dval (dest), BIT (16) ? 0.0 : VFP_dval (srcM), res,
1434 state->FPSCR & NBIT ? 'N' : '-',
1435 state->FPSCR & ZBIT ? 'Z' : '-',
1436 state->FPSCR & CBIT ? 'C' : '-',
1437 state->FPSCR & VBIT ? 'V' : '-');
1438 }
1439 else
1440 {
1441 ARMfval res = VFP_fval (dest);
1442
1443 if (BIT (16) == 0)
1444 {
1445 ARMfval src = VFP_fval (srcM);
1446
1447 if (isinf (res) && isinf (src))
1448 {
1449 if (res > 0.0 && src > 0.0)
1450 res = 0.0;
1451 else if (res < 0.0 && src < 0.0)
1452 res = 0.0;
1453 /* else leave res alone. */
1454 }
1455 else
1456 res -= src;
1457 }
1458
1459 /* FIXME: Add handling of signalling NaNs and the E bit. */
1460
1461 state->FPSCR &= 0x0FFFFFFF;
1462 if (res < 0.0)
1463 state->FPSCR |= NBIT;
1464 else
1465 state->FPSCR |= CBIT;
1466 if (res == 0.0)
1467 state->FPSCR |= ZBIT;
1468 if (isnan (res))
1469 state->FPSCR |= VBIT;
1470
1471 if (trace)
1472 fprintf (stderr, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n",
1473 VFP_fval (dest), BIT (16) ? 0.0 : VFP_fval (srcM), res,
1474 state->FPSCR & NBIT ? 'N' : '-',
1475 state->FPSCR & ZBIT ? 'Z' : '-',
1476 state->FPSCR & CBIT ? 'C' : '-',
1477 state->FPSCR & VBIT ? 'V' : '-');
1478 }
1479 return;
1480
1481 case 0x7:
1482 if (BIT (8))
1483 {
1484 dest = (DESTReg << 1) + BIT (22);
1485 VFP_fval (dest) = VFP_dval (srcM);
1486 }
1487 else
1488 {
1489 dest = DESTReg + (BIT (22) << 4);
1490 VFP_dval (dest) = VFP_fval (srcM);
1491 }
1492 return;
1493
1494 case 0x8:
1495 case 0xC:
1496 case 0xD:
1497 /* VCVT integer <-> FP */
1498 if (BIT (18))
1499 {
1500 /* To integer. */
1501 if (BIT (8))
1502 {
1503 dest = (BITS(12,15) << 1) + BIT (22);
1504 if (BIT (16))
1505 VFP_sword (dest) = VFP_dval (srcM);
1506 else
1507 VFP_uword (dest) = VFP_dval (srcM);
1508 }
1509 else
1510 {
1511 if (BIT (16))
1512 VFP_sword (dest) = VFP_fval (srcM);
1513 else
1514 VFP_uword (dest) = VFP_fval (srcM);
1515 }
1516 }
1517 else
1518 {
1519 /* From integer. */
1520 if (BIT (8))
1521 {
1522 srcM = (BITS (0,3) << 1) + BIT (5);
1523 if (BIT (7))
1524 VFP_dval (dest) = VFP_sword (srcM);
1525 else
1526 VFP_dval (dest) = VFP_uword (srcM);
1527 }
1528 else
1529 {
1530 if (BIT (7))
1531 VFP_fval (dest) = VFP_sword (srcM);
1532 else
1533 VFP_fval (dest) = VFP_uword (srcM);
1534 }
1535 }
1536 return;
1537 }
1538
1539 fprintf (stderr, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1540 return;
1541 }
1542
1543 fprintf (stderr, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1544 return;
1545 }
1546
1547 /* This function does the Busy-Waiting for an CDP instruction. */
1548
1549 void
1550 ARMul_CDP (ARMul_State * state, ARMword instr)
1551 {
1552 unsigned cpab;
1553
1554 if (CPNum == 10 || CPNum == 11)
1555 {
1556 handle_VFP_op (state, instr);
1557 return;
1558 }
1559
1560 if (! CP_ACCESS_ALLOWED (state, CPNum))
1561 {
1562 ARMul_UndefInstr (state, instr);
1563 return;
1564 }
1565
1566 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
1567 while (cpab == ARMul_BUSY)
1568 {
1569 ARMul_Icycles (state, 1, 0);
1570 if (IntPending (state))
1571 {
1572 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
1573 return;
1574 }
1575 else
1576 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
1577 }
1578 if (cpab == ARMul_CANT)
1579 ARMul_Abort (state, ARMul_UndefinedInstrV);
1580 else
1581 BUSUSEDN;
1582 }
1583
1584 /* This function handles Undefined instructions, as CP isntruction. */
1585
1586 void
1587 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
1588 {
1589 ARMul_Abort (state, ARMul_UndefinedInstrV);
1590 }
1591
1592 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
1593
1594 unsigned
1595 IntPending (ARMul_State * state)
1596 {
1597 if (state->Exception)
1598 {
1599 /* Any exceptions. */
1600 if (state->NresetSig == LOW)
1601 {
1602 ARMul_Abort (state, ARMul_ResetV);
1603 return TRUE;
1604 }
1605 else if (!state->NfiqSig && !FFLAG)
1606 {
1607 ARMul_Abort (state, ARMul_FIQV);
1608 return TRUE;
1609 }
1610 else if (!state->NirqSig && !IFLAG)
1611 {
1612 ARMul_Abort (state, ARMul_IRQV);
1613 return TRUE;
1614 }
1615 }
1616
1617 return FALSE;
1618 }
1619
1620 /* Align a word access to a non word boundary. */
1621
1622 ARMword
1623 ARMul_Align (ARMul_State *state ATTRIBUTE_UNUSED, ARMword address, ARMword data)
1624 {
1625 /* This code assumes the address is really unaligned,
1626 as a shift by 32 is undefined in C. */
1627
1628 address = (address & 3) << 3; /* Get the word address. */
1629 return ((data >> address) | (data << (32 - address))); /* rot right */
1630 }
1631
1632 /* This routine is used to call another routine after a certain number of
1633 cycles have been executed. The first parameter is the number of cycles
1634 delay before the function is called, the second argument is a pointer
1635 to the function. A delay of zero doesn't work, just call the function. */
1636
1637 void
1638 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
1639 unsigned (*what) (ARMul_State *))
1640 {
1641 unsigned long when;
1642 struct EventNode *event;
1643
1644 if (state->EventSet++ == 0)
1645 state->Now = ARMul_Time (state);
1646 when = (state->Now + delay) % EVENTLISTSIZE;
1647 event = (struct EventNode *) malloc (sizeof (struct EventNode));
1648 event->func = what;
1649 event->next = *(state->EventPtr + when);
1650 *(state->EventPtr + when) = event;
1651 }
1652
1653 /* This routine is called at the beginning of
1654 every cycle, to envoke scheduled events. */
1655
1656 void
1657 ARMul_EnvokeEvent (ARMul_State * state)
1658 {
1659 static unsigned long then;
1660
1661 then = state->Now;
1662 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
1663 if (then < state->Now)
1664 /* Schedule events. */
1665 EnvokeList (state, then, state->Now);
1666 else if (then > state->Now)
1667 {
1668 /* Need to wrap around the list. */
1669 EnvokeList (state, then, EVENTLISTSIZE - 1L);
1670 EnvokeList (state, 0L, state->Now);
1671 }
1672 }
1673
1674 /* Envokes all the entries in a range. */
1675
1676 static void
1677 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
1678 {
1679 for (; from <= to; from++)
1680 {
1681 struct EventNode *anevent;
1682
1683 anevent = *(state->EventPtr + from);
1684 while (anevent)
1685 {
1686 (anevent->func) (state);
1687 state->EventSet--;
1688 anevent = anevent->next;
1689 }
1690 *(state->EventPtr + from) = NULL;
1691 }
1692 }
1693
1694 /* This routine is returns the number of clock ticks since the last reset. */
1695
1696 unsigned long
1697 ARMul_Time (ARMul_State * state)
1698 {
1699 return (state->NumScycles + state->NumNcycles +
1700 state->NumIcycles + state->NumCcycles + state->NumFcycles);
1701 }
This page took 0.067023 seconds and 4 git commands to generate.