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
ARMul_GetReg(ARMul_State * state,unsigned mode,unsigned reg)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
ARMul_SetReg(ARMul_State * state,unsigned mode,unsigned reg,ARMword value)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
ARMul_GetPC(ARMul_State * state)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
ARMul_GetNextPC(ARMul_State * state)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
ARMul_SetPC(ARMul_State * state,ARMword value)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
ARMul_GetR15(ARMul_State * state)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
ARMul_SetR15(ARMul_State * state,ARMword value)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
ARMul_GetCPSR(ARMul_State * state)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
ARMul_SetCPSR(ARMul_State * state,ARMword value)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
ARMul_FixCPSR(ARMul_State * state,ARMword instr,ARMword rhs)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
ARMul_GetSPSR(ARMul_State * state,ARMword mode)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
ARMul_SetSPSR(ARMul_State * state,ARMword mode,ARMword value)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
ARMul_FixSPSR(ARMul_State * state,ARMword instr,ARMword rhs)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
ARMul_CPSRAltered(ARMul_State * state)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
ARMul_R15Altered(ARMul_State * state)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
ARMul_SwitchMode(ARMul_State * state,ARMword oldmode,ARMword newmode)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
ModeToBank(ARMword mode)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
ARMul_NthReg(ARMword instr,unsigned number)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
ARMul_NegZero(ARMul_State * state,ARMword result)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
AddOverflow(ARMword a,ARMword b,ARMword result)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
SubOverflow(ARMword a,ARMword b,ARMword result)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
ARMul_AddCarry(ARMul_State * state,ARMword a,ARMword b,ARMword result)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
ARMul_AddOverflow(ARMul_State * state,ARMword a,ARMword b,ARMword result)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
ARMul_SubCarry(ARMul_State * state,ARMword a,ARMword b,ARMword result)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
ARMul_SubOverflow(ARMul_State * state,ARMword a,ARMword b,ARMword result)469 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
470 {
471   ASSIGNV (SubOverflow (a, b, result));
472 }
473 
474 static void
handle_VFP_xfer(ARMul_State * state,ARMword instr)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
ARMul_LDC(ARMul_State * state,ARMword instr,ARMword address)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
ARMul_STC(ARMul_State * state,ARMword instr,ARMword address)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
ARMul_MCR(ARMul_State * state,ARMword instr,ARMword source)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
ARMul_MRC(ARMul_State * state,ARMword instr)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
handle_VFP_op(ARMul_State * state,ARMword instr)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
ARMul_CDP(ARMul_State * state,ARMword instr)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
ARMul_UndefInstr(ARMul_State * state,ARMword instr ATTRIBUTE_UNUSED)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
IntPending(ARMul_State * state)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
ARMul_Align(ARMul_State * state ATTRIBUTE_UNUSED,ARMword address,ARMword data)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
ARMul_ScheduleEvent(ARMul_State * state,unsigned long delay,unsigned (* what)(ARMul_State *))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
ARMul_EnvokeEvent(ARMul_State * state)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
EnvokeList(ARMul_State * state,unsigned long from,unsigned long to)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
ARMul_Time(ARMul_State * state)1700 ARMul_Time (ARMul_State * state)
1701 {
1702   return (state->NumScycles + state->NumNcycles +
1703             state->NumIcycles + state->NumCcycles + state->NumFcycles);
1704 }
1705