xref: /netbsd-src/external/gpl3/gdb/dist/sim/arm/armsupp.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
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