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