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