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