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