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