[PATCH 22/57][Arm][GAS] Add support for MVE instructions: vmlaldav, vmlalv, vmlsldav...
[binutils-gdb.git] / sim / arm / armsupp.c
blob11bb53c5b7049130f201acc581f21db0f51d2765
1 /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
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.
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.
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/>. */
17 #include "armdefs.h"
18 #include "armemu.h"
19 #include "ansidecl.h"
20 #include "libiberty.h"
21 #include <math.h>
23 /* Definitions for the support routines. */
25 static ARMword ModeToBank (ARMword);
26 static void EnvokeList (ARMul_State *, unsigned long, unsigned long);
28 struct EventNode
29 { /* An event list node. */
30 unsigned (*func) (ARMul_State *); /* The function to call. */
31 struct EventNode *next;
34 /* This routine returns the value of a register from a mode. */
36 ARMword
37 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
39 mode &= MODEBITS;
40 if (mode != state->Mode)
41 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
42 else
43 return (state->Reg[reg]);
46 /* This routine sets the value of a register for a mode. */
48 void
49 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
51 mode &= MODEBITS;
52 if (mode != state->Mode)
53 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
54 else
55 state->Reg[reg] = value;
58 /* This routine returns the value of the PC, mode independently. */
60 ARMword
61 ARMul_GetPC (ARMul_State * state)
63 if (state->Mode > SVC26MODE)
64 return state->Reg[15];
65 else
66 return R15PC;
69 /* This routine returns the value of the PC, mode independently. */
71 ARMword
72 ARMul_GetNextPC (ARMul_State * state)
74 if (state->Mode > SVC26MODE)
75 return state->Reg[15] + isize;
76 else
77 return (state->Reg[15] + isize) & R15PCBITS;
80 /* This routine sets the value of the PC. */
82 void
83 ARMul_SetPC (ARMul_State * state, ARMword value)
85 if (ARMul_MODE32BIT)
86 state->Reg[15] = value & PCBITS;
87 else
88 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
89 FLUSHPIPE;
92 /* This routine returns the value of register 15, mode independently. */
94 ARMword
95 ARMul_GetR15 (ARMul_State * state)
97 if (state->Mode > SVC26MODE)
98 return (state->Reg[15]);
99 else
100 return (R15PC | ECC | ER15INT | EMODE);
103 /* This routine sets the value of Register 15. */
105 void
106 ARMul_SetR15 (ARMul_State * state, ARMword value)
108 if (ARMul_MODE32BIT)
109 state->Reg[15] = value & PCBITS;
110 else
112 state->Reg[15] = value;
113 ARMul_R15Altered (state);
115 FLUSHPIPE;
118 /* This routine returns the value of the CPSR. */
120 ARMword
121 ARMul_GetCPSR (ARMul_State * state)
123 return (CPSR | state->Cpsr);
126 /* This routine sets the value of the CPSR. */
128 void
129 ARMul_SetCPSR (ARMul_State * state, ARMword value)
131 state->Cpsr = value;
132 ARMul_CPSRAltered (state);
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. */
138 void
139 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
141 state->Cpsr = ARMul_GetCPSR (state);
143 if (state->Mode != USER26MODE
144 && state->Mode != USER32MODE)
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);
154 if (BIT (19))
155 SETPSR_F (state->Cpsr, rhs);
156 ARMul_CPSRAltered (state);
159 /* Get an SPSR from the specified mode. */
161 ARMword
162 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
164 ARMword bank = ModeToBank (mode & MODEBITS);
166 if (! BANK_CAN_ACCESS_SPSR (bank))
167 return ARMul_GetCPSR (state);
169 return state->Spsr[bank];
172 /* This routine does a write to an SPSR. */
174 void
175 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
177 ARMword bank = ModeToBank (mode & MODEBITS);
179 if (BANK_CAN_ACCESS_SPSR (bank))
180 state->Spsr[bank] = value;
183 /* This routine does a write to the current SPSR, given an MSR instruction. */
185 void
186 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
188 if (BANK_CAN_ACCESS_SPSR (state->Bank))
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);
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. */
204 void
205 ARMul_CPSRAltered (ARMul_State * state)
207 ARMword oldmode;
209 if (state->prog32Sig == LOW)
210 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
212 oldmode = state->Mode;
214 if (state->Mode != (state->Cpsr & MODEBITS))
216 state->Mode =
217 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
219 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
221 state->Cpsr &= ~MODEBITS;
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
240 if (oldmode > SVC26MODE)
242 if (state->Mode <= SVC26MODE)
244 state->Emulate = CHANGEMODE;
245 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
248 else
250 if (state->Mode > SVC26MODE)
252 state->Emulate = CHANGEMODE;
253 state->Reg[15] = R15PC;
255 else
256 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
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. */
264 void
265 ARMul_R15Altered (ARMul_State * state)
267 if (state->Mode != R15MODE)
269 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
270 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
273 if (state->Mode > SVC26MODE)
274 state->Emulate = CHANGEMODE;
276 ASSIGNR15INT (R15INT);
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);
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. */
290 ARMword
291 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
293 unsigned i;
294 ARMword oldbank;
295 ARMword newbank;
297 oldbank = ModeToBank (oldmode);
298 newbank = state->Bank = ModeToBank (newmode);
300 /* Do we really need to do it? */
301 if (oldbank != newbank)
303 /* Save away the old registers. */
304 switch (oldbank)
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 ();
329 /* Restore the new registers. */
330 switch (newbank)
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 ();
356 return newmode;
359 /* Given a processor mode, this routine returns the
360 register bank that will be accessed in that mode. */
362 static ARMword
363 ModeToBank (ARMword mode)
365 static ARMword bankofmode[] =
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
377 if (mode >= ARRAY_SIZE (bankofmode))
378 return DUMMYBANK;
380 return bankofmode[mode];
383 /* Returns the register number of the nth register in a reg list. */
385 unsigned
386 ARMul_NthReg (ARMword instr, unsigned number)
388 unsigned bit, upto;
390 for (bit = 0, upto = 0; upto <= number; bit ++)
391 if (BIT (bit))
392 upto ++;
394 return (bit - 1);
397 /* Assigns the N and Z flags depending on the value of result. */
399 void
400 ARMul_NegZero (ARMul_State * state, ARMword result)
402 if (NEG (result))
404 SETN;
405 CLEARZ;
407 else if (result == 0)
409 CLEARN;
410 SETZ;
412 else
414 CLEARN;
415 CLEARZ;
419 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
422 AddOverflow (ARMword a, ARMword b, ARMword result)
424 return ((NEG (a) && NEG (b) && POS (result))
425 || (POS (a) && POS (b) && NEG (result)));
428 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
431 SubOverflow (ARMword a, ARMword b, ARMword result)
433 return ((NEG (a) && POS (b) && POS (result))
434 || (POS (a) && NEG (b) && NEG (result)));
437 /* Assigns the C flag after an addition of a and b to give result. */
439 void
440 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
442 ASSIGNC ((NEG (a) && NEG (b)) ||
443 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
446 /* Assigns the V flag after an addition of a and b to give result. */
448 void
449 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
451 ASSIGNV (AddOverflow (a, b, result));
454 /* Assigns the C flag after an subtraction of a and b to give result. */
456 void
457 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
459 ASSIGNC ((NEG (a) && POS (b)) ||
460 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
463 /* Assigns the V flag after an subtraction of a and b to give result. */
465 void
466 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
468 ASSIGNV (SubOverflow (a, b, result));
471 static void
472 handle_VFP_xfer (ARMul_State * state, ARMword instr)
474 if (TOPBITS (28) == NV)
476 fprintf (stderr, "SIM: UNDEFINED VFP instruction\n");
477 return;
480 if (BITS (25, 27) != 0x6)
482 fprintf (stderr, "SIM: ISE: VFP handler called incorrectly\n");
483 return;
486 switch (BITS (20, 24))
488 case 0x04:
489 case 0x05:
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);
496 /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */
497 if (BIT (20))
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;
504 else
506 VFP_dword (vm) = state->Reg[rt2];
507 VFP_dword (vm) <<= 32;
508 VFP_dword (vm) |= (state->Reg[rt1] & 0xffffffff);
510 return;
513 case 0x08:
514 case 0x0A:
515 case 0x0C:
516 case 0x0E:
518 /* VSTM with PUW=011 or PUW=010. */
519 int n = BITS (16, 19);
520 int imm8 = BITS (0, 7);
522 ARMword address = state->Reg[n];
523 if (BIT (21))
524 state->Reg[n] = address + (imm8 << 2);
526 if (BIT (8))
528 int src = (BIT (22) << 4) | BITS (12, 15);
529 imm8 >>= 1;
530 while (imm8--)
532 if (state->bigendSig)
534 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
535 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
537 else
539 ARMul_StoreWordN (state, address, VFP_dword (src));
540 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
542 address += 8;
543 src += 1;
546 else
548 int src = (BITS (12, 15) << 1) | BIT (22);
549 while (imm8--)
551 ARMul_StoreWordN (state, address, VFP_uword (src));
552 address += 4;
553 src += 1;
557 return;
559 case 0x10:
560 case 0x14:
561 case 0x18:
562 case 0x1C:
564 /* VSTR */
565 ARMword imm32 = BITS (0, 7) << 2;
566 int base = state->Reg[LHSReg];
567 ARMword address;
568 int dest;
570 if (LHSReg == 15)
571 base = (base + 3) & ~3;
573 address = base + (BIT (23) ? imm32 : - imm32);
575 if (CPNum == 10)
577 dest = (DESTReg << 1) + BIT (22);
579 ARMul_StoreWordN (state, address, VFP_uword (dest));
581 else
583 dest = (BIT (22) << 4) + DESTReg;
585 if (state->bigendSig)
587 ARMul_StoreWordN (state, address, VFP_dword (dest) >> 32);
588 ARMul_StoreWordN (state, address + 4, VFP_dword (dest));
590 else
592 ARMul_StoreWordN (state, address, VFP_dword (dest));
593 ARMul_StoreWordN (state, address + 4, VFP_dword (dest) >> 32);
597 return;
599 case 0x12:
600 case 0x16:
601 if (BITS (16, 19) == 13)
603 /* VPUSH */
604 ARMword address = state->Reg[13] - (BITS (0, 7) << 2);
605 state->Reg[13] = address;
607 if (BIT (8))
609 int dreg = (BIT (22) << 4) | BITS (12, 15);
610 int num = BITS (0, 7) >> 1;
611 while (num--)
613 if (state->bigendSig)
615 ARMul_StoreWordN (state, address, VFP_dword (dreg) >> 32);
616 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg));
618 else
620 ARMul_StoreWordN (state, address, VFP_dword (dreg));
621 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg) >> 32);
623 address += 8;
624 dreg += 1;
627 else
629 int sreg = (BITS (12, 15) << 1) | BIT (22);
630 int num = BITS (0, 7);
631 while (num--)
633 ARMul_StoreWordN (state, address, VFP_uword (sreg));
634 address += 4;
635 sreg += 1;
639 else if (BITS (9, 11) != 0x5)
640 break;
641 else
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;
649 if (BIT (8))
651 int src = (BIT (22) << 4) | BITS (12, 15);
653 imm8 >>= 1;
654 while (imm8--)
656 if (state->bigendSig)
658 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
659 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
661 else
663 ARMul_StoreWordN (state, address, VFP_dword (src));
664 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
666 address += 8;
667 src += 1;
670 else
672 int src = (BITS (12, 15) << 1) | BIT (22);
674 while (imm8--)
676 ARMul_StoreWordN (state, address, VFP_uword (src));
677 address += 4;
678 src += 1;
682 return;
684 case 0x13:
685 case 0x17:
686 /* VLDM PUW=101 */
687 case 0x09:
688 case 0x0D:
689 /* VLDM PUW=010 */
691 int n = BITS (16, 19);
692 int imm8 = BITS (0, 7);
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;
700 if (BIT (8))
702 int dest = (BIT (22) << 4) | BITS (12, 15);
703 imm8 >>= 1;
704 while (imm8--)
706 if (state->bigendSig)
708 VFP_dword (dest) = ARMul_LoadWordN (state, address);
709 VFP_dword (dest) <<= 32;
710 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
712 else
714 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
715 VFP_dword (dest) <<= 32;
716 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
719 if (trace)
720 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
722 address += 8;
723 dest += 1;
726 else
728 int dest = (BITS (12, 15) << 1) | BIT (22);
730 while (imm8--)
732 VFP_uword (dest) = ARMul_LoadWordN (state, address);
733 address += 4;
734 dest += 1;
738 return;
740 case 0x0B:
741 case 0x0F:
742 if (BITS (16, 19) == 13)
744 /* VPOP */
745 ARMword address = state->Reg[13];
746 state->Reg[13] = address + (BITS (0, 7) << 2);
748 if (BIT (8))
750 int dest = (BIT (22) << 4) | BITS (12, 15);
751 int num = BITS (0, 7) >> 1;
753 while (num--)
755 if (state->bigendSig)
757 VFP_dword (dest) = ARMul_LoadWordN (state, address);
758 VFP_dword (dest) <<= 32;
759 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
761 else
763 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
764 VFP_dword (dest) <<= 32;
765 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
768 if (trace)
769 fprintf (stderr, " VFP: VPOP: D%d = %g\n", dest, VFP_dval (dest));
771 address += 8;
772 dest += 1;
775 else
777 int sreg = (BITS (12, 15) << 1) | BIT (22);
778 int num = BITS (0, 7);
780 while (num--)
782 VFP_uword (sreg) = ARMul_LoadWordN (state, address);
783 address += 4;
784 sreg += 1;
788 else if (BITS (9, 11) != 0x5)
789 break;
790 else
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;
798 if (BIT (8))
800 int dest = (BIT (22) << 4) | BITS (12, 15);
802 imm8 >>= 1;
803 while (imm8--)
805 if (state->bigendSig)
807 VFP_dword (dest) = ARMul_LoadWordN (state, address);
808 VFP_dword (dest) <<= 32;
809 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
811 else
813 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
814 VFP_dword (dest) <<= 32;
815 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
818 if (trace)
819 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
821 address += 8;
822 dest += 1;
825 else
827 int dest = (BITS (12, 15) << 1) | BIT (22);
828 while (imm8--)
830 VFP_uword (dest) = ARMul_LoadWordN (state, address);
831 address += 4;
832 dest += 1;
836 return;
838 case 0x11:
839 case 0x15:
840 case 0x19:
841 case 0x1D:
843 /* VLDR */
844 ARMword imm32 = BITS (0, 7) << 2;
845 int base = state->Reg[LHSReg];
846 ARMword address;
847 int dest;
849 if (LHSReg == 15)
850 base = (base + 3) & ~3;
852 address = base + (BIT (23) ? imm32 : - imm32);
854 if (CPNum == 10)
856 dest = (DESTReg << 1) + BIT (22);
858 VFP_uword (dest) = ARMul_LoadWordN (state, address);
860 else
862 dest = (BIT (22) << 4) + DESTReg;
864 if (state->bigendSig)
866 VFP_dword (dest) = ARMul_LoadWordN (state, address);
867 VFP_dword (dest) <<= 32;
868 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
870 else
872 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
873 VFP_dword (dest) <<= 32;
874 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
877 if (trace)
878 fprintf (stderr, " VFP: VLDR: D%d = %g\n", dest, VFP_dval (dest));
881 return;
884 fprintf (stderr, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
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. */
892 void
893 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
895 unsigned cpab;
896 ARMword data;
898 if (CPNum == 10 || CPNum == 11)
900 handle_VFP_xfer (state, instr);
901 return;
904 UNDEF_LSCPCBaseWb;
906 if (! CP_ACCESS_ALLOWED (state, CPNum))
908 ARMul_UndefInstr (state, instr);
909 return;
912 if (ADDREXCEPT (address))
913 INTERNALABORT (address);
915 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
916 while (cpab == ARMul_BUSY)
918 ARMul_Icycles (state, 1, 0);
920 if (IntPending (state))
922 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
923 return;
925 else
926 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
928 if (cpab == ARMul_CANT)
930 CPTAKEABORT;
931 return;
934 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
935 data = ARMul_LoadWordN (state, address);
936 BUSUSEDINCPCN;
938 if (BIT (21))
939 LSBase = state->Base;
940 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
942 while (cpab == ARMul_INC)
944 address += 4;
945 data = ARMul_LoadWordN (state, address);
946 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
949 if (state->abortSig || state->Aborted)
950 TAKEABORT;
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. */
958 void
959 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
961 unsigned cpab;
962 ARMword data;
964 if (CPNum == 10 || CPNum == 11)
966 handle_VFP_xfer (state, instr);
967 return;
970 UNDEF_LSCPCBaseWb;
972 if (! CP_ACCESS_ALLOWED (state, CPNum))
974 ARMul_UndefInstr (state, instr);
975 return;
978 if (ADDREXCEPT (address) || VECTORACCESS (address))
979 INTERNALABORT (address);
981 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
982 while (cpab == ARMul_BUSY)
984 ARMul_Icycles (state, 1, 0);
985 if (IntPending (state))
987 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
988 return;
990 else
991 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
994 if (cpab == ARMul_CANT)
996 CPTAKEABORT;
997 return;
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);
1009 while (cpab == ARMul_INC)
1011 address += 4;
1012 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
1013 ARMul_StoreWordN (state, address, data);
1016 if (state->abortSig || state->Aborted)
1017 TAKEABORT;
1020 /* This function does the Busy-Waiting for an MCR instruction. */
1022 void
1023 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
1025 unsigned cpab;
1027 if (! CP_ACCESS_ALLOWED (state, CPNum))
1029 ARMul_UndefInstr (state, instr);
1030 return;
1033 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
1035 while (cpab == ARMul_BUSY)
1037 ARMul_Icycles (state, 1, 0);
1039 if (IntPending (state))
1041 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1042 return;
1044 else
1045 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
1048 if (cpab == ARMul_CANT)
1049 ARMul_Abort (state, ARMul_UndefinedInstrV);
1050 else
1052 BUSUSEDINCPCN;
1053 ARMul_Ccycles (state, 1, 0);
1057 /* This function does the Busy-Waiting for an MRC instruction. */
1059 ARMword
1060 ARMul_MRC (ARMul_State * state, ARMword instr)
1062 unsigned cpab;
1063 ARMword result = 0;
1065 if (! CP_ACCESS_ALLOWED (state, CPNum))
1067 ARMul_UndefInstr (state, instr);
1068 return result;
1071 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
1072 while (cpab == ARMul_BUSY)
1074 ARMul_Icycles (state, 1, 0);
1075 if (IntPending (state))
1077 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1078 return (0);
1080 else
1081 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
1083 if (cpab == ARMul_CANT)
1085 ARMul_Abort (state, ARMul_UndefinedInstrV);
1086 /* Parent will destroy the flags otherwise. */
1087 result = ECC;
1089 else
1091 BUSUSEDINCPCN;
1092 ARMul_Ccycles (state, 1, 0);
1093 ARMul_Icycles (state, 1, 0);
1096 return result;
1099 static void
1100 handle_VFP_op (ARMul_State * state, ARMword instr)
1102 int dest;
1103 int srcN;
1104 int srcM;
1106 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1108 fprintf (stderr, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1109 return;
1112 if (BIT (8))
1114 dest = BITS(12,15) + (BIT (22) << 4);
1115 srcN = LHSReg + (BIT (7) << 4);
1116 srcM = BITS (0,3) + (BIT (5) << 4);
1118 else
1120 dest = (BITS(12,15) << 1) + BIT (22);
1121 srcN = (LHSReg << 1) + BIT (7);
1122 srcM = (BITS (0,3) << 1) + BIT (5);
1125 switch (BITS (20, 27))
1127 case 0xE0:
1128 case 0xE4:
1129 /* VMLA VMLS */
1130 if (BIT (8))
1132 ARMdval val = VFP_dval (srcN) * VFP_dval (srcM);
1134 if (BIT (6))
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;
1142 else
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;
1151 else
1153 ARMfval val = VFP_fval (srcN) * VFP_fval (srcM);
1155 if (BIT (6))
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;
1163 else
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;
1172 return;
1174 case 0xE1:
1175 case 0xE5:
1176 if (BIT (8))
1178 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1180 if (BIT (6))
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));
1189 else
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);
1199 else
1201 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
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);
1210 return;
1212 case 0xE2:
1213 case 0xE6:
1214 if (BIT (8))
1216 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1218 if (BIT (6))
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;
1226 else
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;
1235 else
1237 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
1239 if (BIT (6))
1241 if (trace)
1242 fprintf (stderr, " VFP: VNMUL: %g = %g * %g\n",
1243 - product, VFP_fval (srcN), VFP_fval (srcM));
1245 VFP_fval (dest) = - product;
1247 else
1249 if (trace)
1250 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1251 product, VFP_fval (srcN), VFP_fval (srcM));
1253 VFP_fval (dest) = product;
1256 return;
1258 case 0xE3:
1259 case 0xE7:
1260 if (BIT (6) == 0)
1262 /* VADD */
1263 if (BIT(8))
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);
1272 else
1273 VFP_fval (dest) = VFP_fval (srcN) + VFP_fval (srcM);
1276 else
1278 /* VSUB */
1279 if (BIT(8))
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);
1288 else
1289 VFP_fval (dest) = VFP_fval (srcN) - VFP_fval (srcM);
1291 return;
1293 case 0xE8:
1294 case 0xEC:
1295 if (BIT (6) == 1)
1296 break;
1298 /* VDIV */
1299 if (BIT (8))
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;
1307 else
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));
1314 VFP_fval (dest) = VFP_fval (srcN) / VFP_fval (srcM);
1316 return;
1318 case 0xEB:
1319 case 0xEF:
1320 if (BIT (6) != 1)
1321 break;
1323 switch (BITS (16, 19))
1325 case 0x0:
1326 if (BIT (7) == 0)
1328 if (BIT (8))
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));
1335 else
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));
1343 else
1345 /* VABS */
1346 if (BIT (8))
1348 ARMdval src = VFP_dval (srcM);
1350 VFP_dval (dest) = fabs (src);
1351 if (trace)
1352 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_dval (dest));
1354 else
1356 ARMfval src = VFP_fval (srcM);
1358 VFP_fval (dest) = fabsf (src);
1359 if (trace)
1360 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_fval (dest));
1363 return;
1365 case 0x1:
1366 if (BIT (7) == 0)
1368 /* VNEG */
1369 if (BIT (8))
1370 VFP_dval (dest) = - VFP_dval (srcM);
1371 else
1372 VFP_fval (dest) = - VFP_fval (srcM);
1374 else
1376 /* VSQRT */
1377 if (BIT (8))
1379 if (trace)
1380 fprintf (stderr, " VFP: %g = root(%g)\n",
1381 sqrt (VFP_dval (srcM)), VFP_dval (srcM));
1383 VFP_dval (dest) = sqrt (VFP_dval (srcM));
1385 else
1387 if (trace)
1388 fprintf (stderr, " VFP: %g = root(%g)\n",
1389 sqrtf (VFP_fval (srcM)), VFP_fval (srcM));
1391 VFP_fval (dest) = sqrtf (VFP_fval (srcM));
1394 return;
1396 case 0x4:
1397 case 0x5:
1398 /* VCMP, VCMPE */
1399 if (BIT(8))
1401 ARMdval res = VFP_dval (dest);
1403 if (BIT (16) == 0)
1405 ARMdval src = VFP_dval (srcM);
1407 if (isinf (res) && isinf (src))
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. */
1415 else
1416 res -= src;
1419 /* FIXME: Add handling of signalling NaNs and the E bit. */
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;
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' : '-');
1439 else
1441 ARMfval res = VFP_fval (dest);
1443 if (BIT (16) == 0)
1445 ARMfval src = VFP_fval (srcM);
1447 if (isinf (res) && isinf (src))
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. */
1455 else
1456 res -= src;
1459 /* FIXME: Add handling of signalling NaNs and the E bit. */
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;
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' : '-');
1479 return;
1481 case 0x7:
1482 if (BIT (8))
1484 dest = (DESTReg << 1) + BIT (22);
1485 VFP_fval (dest) = VFP_dval (srcM);
1487 else
1489 dest = DESTReg + (BIT (22) << 4);
1490 VFP_dval (dest) = VFP_fval (srcM);
1492 return;
1494 case 0x8:
1495 case 0xC:
1496 case 0xD:
1497 /* VCVT integer <-> FP */
1498 if (BIT (18))
1500 /* To integer. */
1501 if (BIT (8))
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);
1509 else
1511 if (BIT (16))
1512 VFP_sword (dest) = VFP_fval (srcM);
1513 else
1514 VFP_uword (dest) = VFP_fval (srcM);
1517 else
1519 /* From integer. */
1520 if (BIT (8))
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);
1528 else
1530 if (BIT (7))
1531 VFP_fval (dest) = VFP_sword (srcM);
1532 else
1533 VFP_fval (dest) = VFP_uword (srcM);
1536 return;
1539 fprintf (stderr, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1540 return;
1543 fprintf (stderr, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1544 return;
1547 /* This function does the Busy-Waiting for an CDP instruction. */
1549 void
1550 ARMul_CDP (ARMul_State * state, ARMword instr)
1552 unsigned cpab;
1554 if (CPNum == 10 || CPNum == 11)
1556 handle_VFP_op (state, instr);
1557 return;
1560 if (! CP_ACCESS_ALLOWED (state, CPNum))
1562 ARMul_UndefInstr (state, instr);
1563 return;
1566 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
1567 while (cpab == ARMul_BUSY)
1569 ARMul_Icycles (state, 1, 0);
1570 if (IntPending (state))
1572 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
1573 return;
1575 else
1576 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
1578 if (cpab == ARMul_CANT)
1579 ARMul_Abort (state, ARMul_UndefinedInstrV);
1580 else
1581 BUSUSEDN;
1584 /* This function handles Undefined instructions, as CP isntruction. */
1586 void
1587 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
1589 ARMul_Abort (state, ARMul_UndefinedInstrV);
1592 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
1594 unsigned
1595 IntPending (ARMul_State * state)
1597 if (state->Exception)
1599 /* Any exceptions. */
1600 if (state->NresetSig == LOW)
1602 ARMul_Abort (state, ARMul_ResetV);
1603 return TRUE;
1605 else if (!state->NfiqSig && !FFLAG)
1607 ARMul_Abort (state, ARMul_FIQV);
1608 return TRUE;
1610 else if (!state->NirqSig && !IFLAG)
1612 ARMul_Abort (state, ARMul_IRQV);
1613 return TRUE;
1617 return FALSE;
1620 /* Align a word access to a non word boundary. */
1622 ARMword
1623 ARMul_Align (ARMul_State *state ATTRIBUTE_UNUSED, ARMword address, ARMword data)
1625 /* This code assumes the address is really unaligned,
1626 as a shift by 32 is undefined in C. */
1628 address = (address & 3) << 3; /* Get the word address. */
1629 return ((data >> address) | (data << (32 - address))); /* rot right */
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. */
1637 void
1638 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
1639 unsigned (*what) (ARMul_State *))
1641 unsigned long when;
1642 struct EventNode *event;
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;
1653 /* This routine is called at the beginning of
1654 every cycle, to envoke scheduled events. */
1656 void
1657 ARMul_EnvokeEvent (ARMul_State * state)
1659 static unsigned long then;
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)
1668 /* Need to wrap around the list. */
1669 EnvokeList (state, then, EVENTLISTSIZE - 1L);
1670 EnvokeList (state, 0L, state->Now);
1674 /* Envokes all the entries in a range. */
1676 static void
1677 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
1679 for (; from <= to; from++)
1681 struct EventNode *anevent;
1683 anevent = *(state->EventPtr + from);
1684 while (anevent)
1686 (anevent->func) (state);
1687 state->EventSet--;
1688 anevent = anevent->next;
1690 *(state->EventPtr + from) = NULL;
1694 /* This routine is returns the number of clock ticks since the last reset. */
1696 unsigned long
1697 ARMul_Time (ARMul_State * state)
1699 return (state->NumScycles + state->NumNcycles +
1700 state->NumIcycles + state->NumCcycles + state->NumFcycles);