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