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