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