Update base address register after restoring register bank.
[deliverable/binutils-gdb.git] / sim / arm / armemu.c
1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #include "armdefs.h"
20 #include "armemu.h"
21 #include "armos.h"
22
23 static ARMword GetDPRegRHS (ARMul_State * state, ARMword instr);
24 static ARMword GetDPSRegRHS (ARMul_State * state, ARMword instr);
25 static void WriteR15 (ARMul_State * state, ARMword src);
26 static void WriteSR15 (ARMul_State * state, ARMword src);
27 static void WriteR15Branch (ARMul_State * state, ARMword src);
28 static ARMword GetLSRegRHS (ARMul_State * state, ARMword instr);
29 static ARMword GetLS7RHS (ARMul_State * state, ARMword instr);
30 static unsigned LoadWord (ARMul_State * state, ARMword instr,
31 ARMword address);
32 static unsigned LoadHalfWord (ARMul_State * state, ARMword instr,
33 ARMword address, int signextend);
34 static unsigned LoadByte (ARMul_State * state, ARMword instr, ARMword address,
35 int signextend);
36 static unsigned StoreWord (ARMul_State * state, ARMword instr,
37 ARMword address);
38 static unsigned StoreHalfWord (ARMul_State * state, ARMword instr,
39 ARMword address);
40 static unsigned StoreByte (ARMul_State * state, ARMword instr,
41 ARMword address);
42 static void LoadMult (ARMul_State * state, ARMword address, ARMword instr,
43 ARMword WBBase);
44 static void StoreMult (ARMul_State * state, ARMword address, ARMword instr,
45 ARMword WBBase);
46 static void LoadSMult (ARMul_State * state, ARMword address, ARMword instr,
47 ARMword WBBase);
48 static void StoreSMult (ARMul_State * state, ARMword address, ARMword instr,
49 ARMword WBBase);
50 static unsigned Multiply64 (ARMul_State * state, ARMword instr,
51 int signextend, int scc);
52 static unsigned MultiplyAdd64 (ARMul_State * state, ARMword instr,
53 int signextend, int scc);
54 static void Handle_Load_Double (ARMul_State * state, ARMword instr);
55 static void Handle_Store_Double (ARMul_State * state, ARMword instr);
56
57 #define LUNSIGNED (0) /* unsigned operation */
58 #define LSIGNED (1) /* signed operation */
59 #define LDEFAULT (0) /* default : do nothing */
60 #define LSCC (1) /* set condition codes on result */
61
62 #ifdef NEED_UI_LOOP_HOOK
63 /* How often to run the ui_loop update, when in use */
64 #define UI_LOOP_POLL_INTERVAL 0x32000
65
66 /* Counter for the ui_loop_hook update */
67 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
68
69 /* Actual hook to call to run through gdb's gui event loop */
70 extern int (*ui_loop_hook) (int);
71 #endif /* NEED_UI_LOOP_HOOK */
72
73 extern int stop_simulator;
74
75 /***************************************************************************\
76 * short-hand macros for LDR/STR *
77 \***************************************************************************/
78
79 /* store post decrement writeback */
80 #define SHDOWNWB() \
81 lhs = LHS ; \
82 if (StoreHalfWord(state, instr, lhs)) \
83 LSBase = lhs - GetLS7RHS(state, instr) ;
84
85 /* store post increment writeback */
86 #define SHUPWB() \
87 lhs = LHS ; \
88 if (StoreHalfWord(state, instr, lhs)) \
89 LSBase = lhs + GetLS7RHS(state, instr) ;
90
91 /* store pre decrement */
92 #define SHPREDOWN() \
93 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
94
95 /* store pre decrement writeback */
96 #define SHPREDOWNWB() \
97 temp = LHS - GetLS7RHS(state, instr) ; \
98 if (StoreHalfWord(state, instr, temp)) \
99 LSBase = temp ;
100
101 /* store pre increment */
102 #define SHPREUP() \
103 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
104
105 /* store pre increment writeback */
106 #define SHPREUPWB() \
107 temp = LHS + GetLS7RHS(state, instr) ; \
108 if (StoreHalfWord(state, instr, temp)) \
109 LSBase = temp ;
110
111 /* Load post decrement writeback. */
112 #define LHPOSTDOWN() \
113 { \
114 int done = 1; \
115 lhs = LHS; \
116 temp = lhs - GetLS7RHS (state, instr); \
117 \
118 switch (BITS (5, 6)) \
119 { \
120 case 1: /* H */ \
121 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
122 LSBase = temp; \
123 break; \
124 case 2: /* SB */ \
125 if (LoadByte (state, instr, lhs, LSIGNED)) \
126 LSBase = temp; \
127 break; \
128 case 3: /* SH */ \
129 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
130 LSBase = temp; \
131 break; \
132 case 0: /* SWP handled elsewhere. */ \
133 default: \
134 done = 0; \
135 break; \
136 } \
137 if (done) \
138 break; \
139 }
140
141 /* Load post increment writeback. */
142 #define LHPOSTUP() \
143 { \
144 int done = 1; \
145 lhs = LHS; \
146 temp = lhs + GetLS7RHS (state, instr); \
147 \
148 switch (BITS (5, 6)) \
149 { \
150 case 1: /* H */ \
151 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
152 LSBase = temp; \
153 break; \
154 case 2: /* SB */ \
155 if (LoadByte (state, instr, lhs, LSIGNED)) \
156 LSBase = temp; \
157 break; \
158 case 3: /* SH */ \
159 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
160 LSBase = temp; \
161 break; \
162 case 0: /* SWP handled elsewhere. */ \
163 default: \
164 done = 0; \
165 break; \
166 } \
167 if (done) \
168 break; \
169 }
170
171
172 /* load pre decrement */
173 #define LHPREDOWN() \
174 { \
175 int done = 1 ; \
176 temp = LHS - GetLS7RHS(state,instr) ; \
177 switch (BITS(5,6)) { \
178 case 1: /* H */ \
179 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
180 break ; \
181 case 2: /* SB */ \
182 (void)LoadByte(state,instr,temp,LSIGNED) ; \
183 break ; \
184 case 3: /* SH */ \
185 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
186 break ; \
187 case 0: /* SWP handled elsewhere */ \
188 default: \
189 done = 0 ; \
190 break ; \
191 } \
192 if (done) \
193 break ; \
194 }
195
196 /* load pre decrement writeback */
197 #define LHPREDOWNWB() \
198 { \
199 int done = 1 ; \
200 temp = LHS - GetLS7RHS(state, instr) ; \
201 switch (BITS(5,6)) { \
202 case 1: /* H */ \
203 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
204 LSBase = temp ; \
205 break ; \
206 case 2: /* SB */ \
207 if (LoadByte(state,instr,temp,LSIGNED)) \
208 LSBase = temp ; \
209 break ; \
210 case 3: /* SH */ \
211 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
212 LSBase = temp ; \
213 break ; \
214 case 0: /* SWP handled elsewhere */ \
215 default: \
216 done = 0 ; \
217 break ; \
218 } \
219 if (done) \
220 break ; \
221 }
222
223 /* load pre increment */
224 #define LHPREUP() \
225 { \
226 int done = 1 ; \
227 temp = LHS + GetLS7RHS(state,instr) ; \
228 switch (BITS(5,6)) { \
229 case 1: /* H */ \
230 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
231 break ; \
232 case 2: /* SB */ \
233 (void)LoadByte(state,instr,temp,LSIGNED) ; \
234 break ; \
235 case 3: /* SH */ \
236 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
237 break ; \
238 case 0: /* SWP handled elsewhere */ \
239 default: \
240 done = 0 ; \
241 break ; \
242 } \
243 if (done) \
244 break ; \
245 }
246
247 /* load pre increment writeback */
248 #define LHPREUPWB() \
249 { \
250 int done = 1 ; \
251 temp = LHS + GetLS7RHS(state, instr) ; \
252 switch (BITS(5,6)) { \
253 case 1: /* H */ \
254 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
255 LSBase = temp ; \
256 break ; \
257 case 2: /* SB */ \
258 if (LoadByte(state,instr,temp,LSIGNED)) \
259 LSBase = temp ; \
260 break ; \
261 case 3: /* SH */ \
262 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
263 LSBase = temp ; \
264 break ; \
265 case 0: /* SWP handled elsewhere */ \
266 default: \
267 done = 0 ; \
268 break ; \
269 } \
270 if (done) \
271 break ; \
272 }
273
274 /***************************************************************************\
275 * EMULATION of ARM6 *
276 \***************************************************************************/
277
278 /* The PC pipeline value depends on whether ARM or Thumb instructions
279 are being executed: */
280 ARMword isize;
281
282 #ifdef MODE32
283 ARMword
284 ARMul_Emulate32 (register ARMul_State * state)
285 {
286 #else
287 ARMword
288 ARMul_Emulate26 (register ARMul_State * state)
289 {
290 #endif
291 register ARMword instr, /* the current instruction */
292 dest = 0, /* almost the DestBus */
293 temp, /* ubiquitous third hand */
294 pc = 0; /* the address of the current instruction */
295 ARMword lhs, rhs; /* almost the ABus and BBus */
296 ARMword decoded = 0, loaded = 0; /* instruction pipeline */
297
298 /***************************************************************************\
299 * Execute the next instruction *
300 \***************************************************************************/
301
302 if (state->NextInstr < PRIMEPIPE)
303 {
304 decoded = state->decoded;
305 loaded = state->loaded;
306 pc = state->pc;
307 }
308
309 do
310 { /* just keep going */
311 isize = INSN_SIZE;
312 switch (state->NextInstr)
313 {
314 case SEQ:
315 state->Reg[15] += isize; /* Advance the pipeline, and an S cycle */
316 pc += isize;
317 instr = decoded;
318 decoded = loaded;
319 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
320 break;
321
322 case NONSEQ:
323 state->Reg[15] += isize; /* Advance the pipeline, and an N cycle */
324 pc += isize;
325 instr = decoded;
326 decoded = loaded;
327 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
328 NORMALCYCLE;
329 break;
330
331 case PCINCEDSEQ:
332 pc += isize; /* Program counter advanced, and an S cycle */
333 instr = decoded;
334 decoded = loaded;
335 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
336 NORMALCYCLE;
337 break;
338
339 case PCINCEDNONSEQ:
340 pc += isize; /* Program counter advanced, and an N cycle */
341 instr = decoded;
342 decoded = loaded;
343 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
344 NORMALCYCLE;
345 break;
346
347 case RESUME: /* The program counter has been changed */
348 pc = state->Reg[15];
349 #ifndef MODE32
350 pc = pc & R15PCBITS;
351 #endif
352 state->Reg[15] = pc + (isize * 2);
353 state->Aborted = 0;
354 instr = ARMul_ReLoadInstr (state, pc, isize);
355 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
356 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
357 NORMALCYCLE;
358 break;
359
360 default: /* The program counter has been changed */
361 pc = state->Reg[15];
362 #ifndef MODE32
363 pc = pc & R15PCBITS;
364 #endif
365 state->Reg[15] = pc + (isize * 2);
366 state->Aborted = 0;
367 instr = ARMul_LoadInstrN (state, pc, isize);
368 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
369 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
370 NORMALCYCLE;
371 break;
372 }
373 if (state->EventSet)
374 ARMul_EnvokeEvent (state);
375
376 #if 0
377 /* Enable this for a helpful bit of debugging when tracing is needed. */
378 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
379 if (instr == 0)
380 abort ();
381 #endif
382
383 if (state->Exception)
384 { /* Any exceptions */
385 if (state->NresetSig == LOW)
386 {
387 ARMul_Abort (state, ARMul_ResetV);
388 break;
389 }
390 else if (!state->NfiqSig && !FFLAG)
391 {
392 ARMul_Abort (state, ARMul_FIQV);
393 break;
394 }
395 else if (!state->NirqSig && !IFLAG)
396 {
397 ARMul_Abort (state, ARMul_IRQV);
398 break;
399 }
400 }
401
402 if (state->CallDebug > 0)
403 {
404 instr = ARMul_Debug (state, pc, instr);
405 if (state->Emulate < ONCE)
406 {
407 state->NextInstr = RESUME;
408 break;
409 }
410 if (state->Debug)
411 {
412 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
413 state->Mode);
414 (void) fgetc (stdin);
415 }
416 }
417 else if (state->Emulate < ONCE)
418 {
419 state->NextInstr = RESUME;
420 break;
421 }
422
423 state->NumInstrs++;
424
425 #ifdef MODET
426 /* Provide Thumb instruction decoding. If the processor is in Thumb
427 mode, then we can simply decode the Thumb instruction, and map it
428 to the corresponding ARM instruction (by directly loading the
429 instr variable, and letting the normal ARM simulator
430 execute). There are some caveats to ensure that the correct
431 pipelined PC value is used when executing Thumb code, and also for
432 dealing with the BL instruction. */
433 if (TFLAG)
434 { /* check if in Thumb mode */
435 ARMword new;
436 switch (ARMul_ThumbDecode (state, pc, instr, &new))
437 {
438 case t_undefined:
439 ARMul_UndefInstr (state, instr); /* This is a Thumb instruction */
440 goto donext;
441
442 case t_branch: /* already processed */
443 goto donext;
444
445 case t_decoded: /* ARM instruction available */
446 instr = new; /* so continue instruction decoding */
447 break;
448 }
449 }
450 #endif
451
452 /***************************************************************************\
453 * Check the condition codes *
454 \***************************************************************************/
455 if ((temp = TOPBITS (28)) == AL)
456 goto mainswitch; /* vile deed in the need for speed */
457
458 switch ((int) TOPBITS (28))
459 { /* check the condition code */
460 case AL:
461 temp = TRUE;
462 break;
463 case NV:
464 if (state->is_v5)
465 {
466 if (BITS (25, 27) == 5) /* BLX(1) */
467 {
468 ARMword dest;
469
470 state->Reg[14] = pc + 4;
471
472 dest = pc + 8 + 1; /* Force entry into Thumb mode. */
473 if (BIT (23))
474 dest += (NEGBRANCH + (BIT (24) << 1));
475 else
476 dest += POSBRANCH + (BIT (24) << 1);
477
478 WriteR15Branch (state, dest);
479 goto donext;
480 }
481 else if ((instr & 0xFC70F000) == 0xF450F000)
482 /* The PLD instruction. Ignored. */
483 goto donext;
484 else
485 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
486 ARMul_UndefInstr (state, instr);
487 }
488 temp = FALSE;
489 break;
490 case EQ:
491 temp = ZFLAG;
492 break;
493 case NE:
494 temp = !ZFLAG;
495 break;
496 case VS:
497 temp = VFLAG;
498 break;
499 case VC:
500 temp = !VFLAG;
501 break;
502 case MI:
503 temp = NFLAG;
504 break;
505 case PL:
506 temp = !NFLAG;
507 break;
508 case CS:
509 temp = CFLAG;
510 break;
511 case CC:
512 temp = !CFLAG;
513 break;
514 case HI:
515 temp = (CFLAG && !ZFLAG);
516 break;
517 case LS:
518 temp = (!CFLAG || ZFLAG);
519 break;
520 case GE:
521 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
522 break;
523 case LT:
524 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
525 break;
526 case GT:
527 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
528 break;
529 case LE:
530 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
531 break;
532 } /* cc check */
533
534 /***************************************************************************\
535 * Actual execution of instructions begins here *
536 \***************************************************************************/
537
538 if (temp)
539 { /* if the condition codes don't match, stop here */
540 mainswitch:
541
542 if (state->is_XScale)
543 {
544 if (BIT (20) == 0 && BITS (25, 27) == 0)
545 {
546 if (BITS (4, 7) == 0xD)
547 {
548 /* XScale Load Consecutive insn. */
549 ARMword temp = GetLS7RHS (state, instr);
550 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
551 ARMword addr = BIT (24) ? temp2 : temp;
552
553 if (BIT (12))
554 ARMul_UndefInstr (state, instr);
555 else if (addr & 7)
556 /* Alignment violation. */
557 ARMul_Abort (state, ARMul_DataAbortV);
558 else
559 {
560 int wb = BIT (24) && BIT (21);
561
562 state->Reg[BITS (12, 15)] =
563 ARMul_LoadWordN (state, addr);
564 state->Reg[BITS (12, 15) + 1] =
565 ARMul_LoadWordN (state, addr + 4);
566 if (wb)
567 LSBase = addr;
568 }
569
570 goto donext;
571 }
572 else if (BITS (4, 7) == 0xF)
573 {
574 /* XScale Store Consecutive insn. */
575 ARMword temp = GetLS7RHS (state, instr);
576 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
577 ARMword addr = BIT (24) ? temp2 : temp;
578
579 if (BIT (12))
580 ARMul_UndefInstr (state, instr);
581 else if (addr & 7)
582 /* Alignment violation. */
583 ARMul_Abort (state, ARMul_DataAbortV);
584 else
585 {
586 ARMul_StoreWordN (state, addr,
587 state->Reg[BITS (12, 15)]);
588 ARMul_StoreWordN (state, addr + 4,
589 state->Reg[BITS (12, 15) + 1]);
590
591 if (BIT (21))
592 LSBase = addr;
593 }
594
595 goto donext;
596 }
597 }
598 }
599
600 switch ((int) BITS (20, 27))
601 {
602
603 /***************************************************************************\
604 * Data Processing Register RHS Instructions *
605 \***************************************************************************/
606
607 case 0x00: /* AND reg and MUL */
608 #ifdef MODET
609 if (BITS (4, 11) == 0xB)
610 {
611 /* STRH register offset, no write-back, down, post indexed */
612 SHDOWNWB ();
613 break;
614 }
615 if (BITS (4, 7) == 0xD)
616 {
617 Handle_Load_Double (state, instr);
618 break;
619 }
620 if (BITS (4, 7) == 0xF)
621 {
622 Handle_Store_Double (state, instr);
623 break;
624 }
625 #endif
626 if (BITS (4, 7) == 9)
627 { /* MUL */
628 rhs = state->Reg[MULRHSReg];
629 if (MULLHSReg == MULDESTReg)
630 {
631 UNDEF_MULDestEQOp1;
632 state->Reg[MULDESTReg] = 0;
633 }
634 else if (MULDESTReg != 15)
635 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
636 else
637 {
638 UNDEF_MULPCDest;
639 }
640 for (dest = 0, temp = 0; dest < 32; dest++)
641 if (rhs & (1L << dest))
642 temp = dest; /* mult takes this many/2 I cycles */
643 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
644 }
645 else
646 { /* AND reg */
647 rhs = DPRegRHS;
648 dest = LHS & rhs;
649 WRITEDEST (dest);
650 }
651 break;
652
653 case 0x01: /* ANDS reg and MULS */
654 #ifdef MODET
655 if ((BITS (4, 11) & 0xF9) == 0x9)
656 {
657 /* LDR register offset, no write-back, down, post indexed */
658 LHPOSTDOWN ();
659 /* fall through to rest of decoding */
660 }
661 #endif
662 if (BITS (4, 7) == 9)
663 { /* MULS */
664 rhs = state->Reg[MULRHSReg];
665 if (MULLHSReg == MULDESTReg)
666 {
667 UNDEF_MULDestEQOp1;
668 state->Reg[MULDESTReg] = 0;
669 CLEARN;
670 SETZ;
671 }
672 else if (MULDESTReg != 15)
673 {
674 dest = state->Reg[MULLHSReg] * rhs;
675 ARMul_NegZero (state, dest);
676 state->Reg[MULDESTReg] = dest;
677 }
678 else
679 {
680 UNDEF_MULPCDest;
681 }
682 for (dest = 0, temp = 0; dest < 32; dest++)
683 if (rhs & (1L << dest))
684 temp = dest; /* mult takes this many/2 I cycles */
685 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
686 }
687 else
688 { /* ANDS reg */
689 rhs = DPSRegRHS;
690 dest = LHS & rhs;
691 WRITESDEST (dest);
692 }
693 break;
694
695 case 0x02: /* EOR reg and MLA */
696 #ifdef MODET
697 if (BITS (4, 11) == 0xB)
698 {
699 /* STRH register offset, write-back, down, post indexed */
700 SHDOWNWB ();
701 break;
702 }
703 #endif
704 if (BITS (4, 7) == 9)
705 { /* MLA */
706 rhs = state->Reg[MULRHSReg];
707 if (MULLHSReg == MULDESTReg)
708 {
709 UNDEF_MULDestEQOp1;
710 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
711 }
712 else if (MULDESTReg != 15)
713 state->Reg[MULDESTReg] =
714 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
715 else
716 {
717 UNDEF_MULPCDest;
718 }
719 for (dest = 0, temp = 0; dest < 32; dest++)
720 if (rhs & (1L << dest))
721 temp = dest; /* mult takes this many/2 I cycles */
722 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
723 }
724 else
725 {
726 rhs = DPRegRHS;
727 dest = LHS ^ rhs;
728 WRITEDEST (dest);
729 }
730 break;
731
732 case 0x03: /* EORS reg and MLAS */
733 #ifdef MODET
734 if ((BITS (4, 11) & 0xF9) == 0x9)
735 {
736 /* LDR register offset, write-back, down, post-indexed */
737 LHPOSTDOWN ();
738 /* fall through to rest of the decoding */
739 }
740 #endif
741 if (BITS (4, 7) == 9)
742 { /* MLAS */
743 rhs = state->Reg[MULRHSReg];
744 if (MULLHSReg == MULDESTReg)
745 {
746 UNDEF_MULDestEQOp1;
747 dest = state->Reg[MULACCReg];
748 ARMul_NegZero (state, dest);
749 state->Reg[MULDESTReg] = dest;
750 }
751 else if (MULDESTReg != 15)
752 {
753 dest =
754 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
755 ARMul_NegZero (state, dest);
756 state->Reg[MULDESTReg] = dest;
757 }
758 else
759 {
760 UNDEF_MULPCDest;
761 }
762 for (dest = 0, temp = 0; dest < 32; dest++)
763 if (rhs & (1L << dest))
764 temp = dest; /* mult takes this many/2 I cycles */
765 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
766 }
767 else
768 { /* EORS Reg */
769 rhs = DPSRegRHS;
770 dest = LHS ^ rhs;
771 WRITESDEST (dest);
772 }
773 break;
774
775 case 0x04: /* SUB reg */
776 #ifdef MODET
777 if (BITS (4, 7) == 0xB)
778 {
779 /* STRH immediate offset, no write-back, down, post indexed */
780 SHDOWNWB ();
781 break;
782 }
783 if (BITS (4, 7) == 0xD)
784 {
785 Handle_Load_Double (state, instr);
786 break;
787 }
788 if (BITS (4, 7) == 0xF)
789 {
790 Handle_Store_Double (state, instr);
791 break;
792 }
793 #endif
794 rhs = DPRegRHS;
795 dest = LHS - rhs;
796 WRITEDEST (dest);
797 break;
798
799 case 0x05: /* SUBS reg */
800 #ifdef MODET
801 if ((BITS (4, 7) & 0x9) == 0x9)
802 {
803 /* LDR immediate offset, no write-back, down, post indexed */
804 LHPOSTDOWN ();
805 /* fall through to the rest of the instruction decoding */
806 }
807 #endif
808 lhs = LHS;
809 rhs = DPRegRHS;
810 dest = lhs - rhs;
811 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
812 {
813 ARMul_SubCarry (state, lhs, rhs, dest);
814 ARMul_SubOverflow (state, lhs, rhs, dest);
815 }
816 else
817 {
818 CLEARC;
819 CLEARV;
820 }
821 WRITESDEST (dest);
822 break;
823
824 case 0x06: /* RSB reg */
825 #ifdef MODET
826 if (BITS (4, 7) == 0xB)
827 {
828 /* STRH immediate offset, write-back, down, post indexed */
829 SHDOWNWB ();
830 break;
831 }
832 #endif
833 rhs = DPRegRHS;
834 dest = rhs - LHS;
835 WRITEDEST (dest);
836 break;
837
838 case 0x07: /* RSBS reg */
839 #ifdef MODET
840 if ((BITS (4, 7) & 0x9) == 0x9)
841 {
842 /* LDR immediate offset, write-back, down, post indexed */
843 LHPOSTDOWN ();
844 /* fall through to remainder of instruction decoding */
845 }
846 #endif
847 lhs = LHS;
848 rhs = DPRegRHS;
849 dest = rhs - lhs;
850 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
851 {
852 ARMul_SubCarry (state, rhs, lhs, dest);
853 ARMul_SubOverflow (state, rhs, lhs, dest);
854 }
855 else
856 {
857 CLEARC;
858 CLEARV;
859 }
860 WRITESDEST (dest);
861 break;
862
863 case 0x08: /* ADD reg */
864 #ifdef MODET
865 if (BITS (4, 11) == 0xB)
866 {
867 /* STRH register offset, no write-back, up, post indexed */
868 SHUPWB ();
869 break;
870 }
871 if (BITS (4, 7) == 0xD)
872 {
873 Handle_Load_Double (state, instr);
874 break;
875 }
876 if (BITS (4, 7) == 0xF)
877 {
878 Handle_Store_Double (state, instr);
879 break;
880 }
881 #endif
882 #ifdef MODET
883 if (BITS (4, 7) == 0x9)
884 { /* MULL */
885 /* 32x32 = 64 */
886 ARMul_Icycles (state,
887 Multiply64 (state, instr, LUNSIGNED,
888 LDEFAULT), 0L);
889 break;
890 }
891 #endif
892 rhs = DPRegRHS;
893 dest = LHS + rhs;
894 WRITEDEST (dest);
895 break;
896
897 case 0x09: /* ADDS reg */
898 #ifdef MODET
899 if ((BITS (4, 11) & 0xF9) == 0x9)
900 {
901 /* LDR register offset, no write-back, up, post indexed */
902 LHPOSTUP ();
903 /* fall through to remaining instruction decoding */
904 }
905 #endif
906 #ifdef MODET
907 if (BITS (4, 7) == 0x9)
908 { /* MULL */
909 /* 32x32=64 */
910 ARMul_Icycles (state,
911 Multiply64 (state, instr, LUNSIGNED, LSCC),
912 0L);
913 break;
914 }
915 #endif
916 lhs = LHS;
917 rhs = DPRegRHS;
918 dest = lhs + rhs;
919 ASSIGNZ (dest == 0);
920 if ((lhs | rhs) >> 30)
921 { /* possible C,V,N to set */
922 ASSIGNN (NEG (dest));
923 ARMul_AddCarry (state, lhs, rhs, dest);
924 ARMul_AddOverflow (state, lhs, rhs, dest);
925 }
926 else
927 {
928 CLEARN;
929 CLEARC;
930 CLEARV;
931 }
932 WRITESDEST (dest);
933 break;
934
935 case 0x0a: /* ADC reg */
936 #ifdef MODET
937 if (BITS (4, 11) == 0xB)
938 {
939 /* STRH register offset, write-back, up, post-indexed */
940 SHUPWB ();
941 break;
942 }
943 #endif
944 #ifdef MODET
945 if (BITS (4, 7) == 0x9)
946 { /* MULL */
947 /* 32x32=64 */
948 ARMul_Icycles (state,
949 MultiplyAdd64 (state, instr, LUNSIGNED,
950 LDEFAULT), 0L);
951 break;
952 }
953 #endif
954 rhs = DPRegRHS;
955 dest = LHS + rhs + CFLAG;
956 WRITEDEST (dest);
957 break;
958
959 case 0x0b: /* ADCS reg */
960 #ifdef MODET
961 if ((BITS (4, 11) & 0xF9) == 0x9)
962 {
963 /* LDR register offset, write-back, up, post indexed */
964 LHPOSTUP ();
965 /* fall through to remaining instruction decoding */
966 }
967 #endif
968 #ifdef MODET
969 if (BITS (4, 7) == 0x9)
970 { /* MULL */
971 /* 32x32=64 */
972 ARMul_Icycles (state,
973 MultiplyAdd64 (state, instr, LUNSIGNED,
974 LSCC), 0L);
975 break;
976 }
977 #endif
978 lhs = LHS;
979 rhs = DPRegRHS;
980 dest = lhs + rhs + CFLAG;
981 ASSIGNZ (dest == 0);
982 if ((lhs | rhs) >> 30)
983 { /* possible C,V,N to set */
984 ASSIGNN (NEG (dest));
985 ARMul_AddCarry (state, lhs, rhs, dest);
986 ARMul_AddOverflow (state, lhs, rhs, dest);
987 }
988 else
989 {
990 CLEARN;
991 CLEARC;
992 CLEARV;
993 }
994 WRITESDEST (dest);
995 break;
996
997 case 0x0c: /* SBC reg */
998 #ifdef MODET
999 if (BITS (4, 7) == 0xB)
1000 {
1001 /* STRH immediate offset, no write-back, up post indexed */
1002 SHUPWB ();
1003 break;
1004 }
1005 if (BITS (4, 7) == 0xD)
1006 {
1007 Handle_Load_Double (state, instr);
1008 break;
1009 }
1010 if (BITS (4, 7) == 0xF)
1011 {
1012 Handle_Store_Double (state, instr);
1013 break;
1014 }
1015 #endif
1016 #ifdef MODET
1017 if (BITS (4, 7) == 0x9)
1018 { /* MULL */
1019 /* 32x32=64 */
1020 ARMul_Icycles (state,
1021 Multiply64 (state, instr, LSIGNED, LDEFAULT),
1022 0L);
1023 break;
1024 }
1025 #endif
1026 rhs = DPRegRHS;
1027 dest = LHS - rhs - !CFLAG;
1028 WRITEDEST (dest);
1029 break;
1030
1031 case 0x0d: /* SBCS reg */
1032 #ifdef MODET
1033 if ((BITS (4, 7) & 0x9) == 0x9)
1034 {
1035 /* LDR immediate offset, no write-back, up, post indexed */
1036 LHPOSTUP ();
1037 }
1038 #endif
1039 #ifdef MODET
1040 if (BITS (4, 7) == 0x9)
1041 { /* MULL */
1042 /* 32x32=64 */
1043 ARMul_Icycles (state,
1044 Multiply64 (state, instr, LSIGNED, LSCC),
1045 0L);
1046 break;
1047 }
1048 #endif
1049 lhs = LHS;
1050 rhs = DPRegRHS;
1051 dest = lhs - rhs - !CFLAG;
1052 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1053 {
1054 ARMul_SubCarry (state, lhs, rhs, dest);
1055 ARMul_SubOverflow (state, lhs, rhs, dest);
1056 }
1057 else
1058 {
1059 CLEARC;
1060 CLEARV;
1061 }
1062 WRITESDEST (dest);
1063 break;
1064
1065 case 0x0e: /* RSC reg */
1066 #ifdef MODET
1067 if (BITS (4, 7) == 0xB)
1068 {
1069 /* STRH immediate offset, write-back, up, post indexed */
1070 SHUPWB ();
1071 break;
1072 }
1073 #endif
1074 #ifdef MODET
1075 if (BITS (4, 7) == 0x9)
1076 { /* MULL */
1077 /* 32x32=64 */
1078 ARMul_Icycles (state,
1079 MultiplyAdd64 (state, instr, LSIGNED,
1080 LDEFAULT), 0L);
1081 break;
1082 }
1083 #endif
1084 rhs = DPRegRHS;
1085 dest = rhs - LHS - !CFLAG;
1086 WRITEDEST (dest);
1087 break;
1088
1089 case 0x0f: /* RSCS reg */
1090 #ifdef MODET
1091 if ((BITS (4, 7) & 0x9) == 0x9)
1092 {
1093 /* LDR immediate offset, write-back, up, post indexed */
1094 LHPOSTUP ();
1095 /* fall through to remaining instruction decoding */
1096 }
1097 #endif
1098 #ifdef MODET
1099 if (BITS (4, 7) == 0x9)
1100 { /* MULL */
1101 /* 32x32=64 */
1102 ARMul_Icycles (state,
1103 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
1104 0L);
1105 break;
1106 }
1107 #endif
1108 lhs = LHS;
1109 rhs = DPRegRHS;
1110 dest = rhs - lhs - !CFLAG;
1111 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1112 {
1113 ARMul_SubCarry (state, rhs, lhs, dest);
1114 ARMul_SubOverflow (state, rhs, lhs, dest);
1115 }
1116 else
1117 {
1118 CLEARC;
1119 CLEARV;
1120 }
1121 WRITESDEST (dest);
1122 break;
1123
1124 case 0x10: /* TST reg and MRS CPSR and SWP word */
1125 if (state->is_v5e)
1126 {
1127 if (BIT (4) == 0 && BIT (7) == 1)
1128 {
1129 /* ElSegundo SMLAxy insn. */
1130 ARMword op1 = state->Reg[BITS (0, 3)];
1131 ARMword op2 = state->Reg[BITS (8, 11)];
1132 ARMword Rn = state->Reg[BITS (12, 15)];
1133
1134 if (BIT (5))
1135 op1 >>= 16;
1136 if (BIT (6))
1137 op2 >>= 16;
1138 op1 &= 0xFFFF;
1139 op2 &= 0xFFFF;
1140 if (op1 & 0x8000)
1141 op1 -= 65536;
1142 if (op2 & 0x8000)
1143 op2 -= 65536;
1144 op1 *= op2;
1145
1146 if (AddOverflow (op1, Rn, op1 + Rn))
1147 SETS;
1148 state->Reg[BITS (16, 19)] = op1 + Rn;
1149 break;
1150 }
1151
1152 if (BITS (4, 11) == 5)
1153 {
1154 /* ElSegundo QADD insn. */
1155 ARMword op1 = state->Reg[BITS (0, 3)];
1156 ARMword op2 = state->Reg[BITS (16, 19)];
1157 ARMword result = op1 + op2;
1158 if (AddOverflow (op1, op2, result))
1159 {
1160 result = POS (result) ? 0x80000000 : 0x7fffffff;
1161 SETS;
1162 }
1163 state->Reg[BITS (12, 15)] = result;
1164 break;
1165 }
1166 }
1167 #ifdef MODET
1168 if (BITS (4, 11) == 0xB)
1169 {
1170 /* STRH register offset, no write-back, down, pre indexed */
1171 SHPREDOWN ();
1172 break;
1173 }
1174 if (BITS (4, 7) == 0xD)
1175 {
1176 Handle_Load_Double (state, instr);
1177 break;
1178 }
1179 if (BITS (4, 7) == 0xF)
1180 {
1181 Handle_Store_Double (state, instr);
1182 break;
1183 }
1184 #endif
1185 if (BITS (4, 11) == 9)
1186 { /* SWP */
1187 UNDEF_SWPPC;
1188 temp = LHS;
1189 BUSUSEDINCPCS;
1190 #ifndef MODE32
1191 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1192 {
1193 INTERNALABORT (temp);
1194 (void) ARMul_LoadWordN (state, temp);
1195 (void) ARMul_LoadWordN (state, temp);
1196 }
1197 else
1198 #endif
1199 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1200 if (temp & 3)
1201 DEST = ARMul_Align (state, temp, dest);
1202 else
1203 DEST = dest;
1204 if (state->abortSig || state->Aborted)
1205 {
1206 TAKEABORT;
1207 }
1208 }
1209 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1210 { /* MRS CPSR */
1211 UNDEF_MRSPC;
1212 DEST = ECC | EINT | EMODE;
1213 }
1214 else
1215 {
1216 UNDEF_Test;
1217 }
1218 break;
1219
1220 case 0x11: /* TSTP reg */
1221 #ifdef MODET
1222 if ((BITS (4, 11) & 0xF9) == 0x9)
1223 {
1224 /* LDR register offset, no write-back, down, pre indexed */
1225 LHPREDOWN ();
1226 /* continue with remaining instruction decode */
1227 }
1228 #endif
1229 if (DESTReg == 15)
1230 { /* TSTP reg */
1231 #ifdef MODE32
1232 state->Cpsr = GETSPSR (state->Bank);
1233 ARMul_CPSRAltered (state);
1234 #else
1235 rhs = DPRegRHS;
1236 temp = LHS & rhs;
1237 SETR15PSR (temp);
1238 #endif
1239 }
1240 else
1241 { /* TST reg */
1242 rhs = DPSRegRHS;
1243 dest = LHS & rhs;
1244 ARMul_NegZero (state, dest);
1245 }
1246 break;
1247
1248 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1249 if (state->is_v5)
1250 {
1251 if (BITS (4, 7) == 3)
1252 {
1253 /* BLX(2) */
1254 ARMword temp;
1255
1256 if (TFLAG)
1257 temp = (pc + 2) | 1;
1258 else
1259 temp = pc + 4;
1260
1261 WriteR15Branch (state, state->Reg[RHSReg]);
1262 state->Reg[14] = temp;
1263 break;
1264 }
1265 }
1266
1267 if (state->is_v5e)
1268 {
1269 if (BIT (4) == 0 && BIT (7) == 1
1270 && (BIT (5) == 0 || BITS (12, 15) == 0))
1271 {
1272 /* ElSegundo SMLAWy/SMULWy insn. */
1273 unsigned long long op1 = state->Reg[BITS (0, 3)];
1274 unsigned long long op2 = state->Reg[BITS (8, 11)];
1275 unsigned long long result;
1276
1277 if (BIT (6))
1278 op2 >>= 16;
1279 if (op1 & 0x80000000)
1280 op1 -= 1ULL << 32;
1281 op2 &= 0xFFFF;
1282 if (op2 & 0x8000)
1283 op2 -= 65536;
1284 result = (op1 * op2) >> 16;
1285
1286 if (BIT (5) == 0)
1287 {
1288 ARMword Rn = state->Reg[BITS (12, 15)];
1289
1290 if (AddOverflow (result, Rn, result + Rn))
1291 SETS;
1292 result += Rn;
1293 }
1294 state->Reg[BITS (16, 19)] = result;
1295 break;
1296 }
1297
1298 if (BITS (4, 11) == 5)
1299 {
1300 /* ElSegundo QSUB insn. */
1301 ARMword op1 = state->Reg[BITS (0, 3)];
1302 ARMword op2 = state->Reg[BITS (16, 19)];
1303 ARMword result = op1 - op2;
1304
1305 if (SubOverflow (op1, op2, result))
1306 {
1307 result = POS (result) ? 0x80000000 : 0x7fffffff;
1308 SETS;
1309 }
1310
1311 state->Reg[BITS (12, 15)] = result;
1312 break;
1313 }
1314 }
1315 #ifdef MODET
1316 if (BITS (4, 11) == 0xB)
1317 {
1318 /* STRH register offset, write-back, down, pre indexed */
1319 SHPREDOWNWB ();
1320 break;
1321 }
1322 if (BITS (4, 27) == 0x12FFF1)
1323 {
1324 /* BX */
1325 WriteR15Branch (state, state->Reg[RHSReg]);
1326 break;
1327 }
1328 if (BITS (4, 7) == 0xD)
1329 {
1330 Handle_Load_Double (state, instr);
1331 break;
1332 }
1333 if (BITS (4, 7) == 0xF)
1334 {
1335 Handle_Store_Double (state, instr);
1336 break;
1337 }
1338 #endif
1339 if (state->is_v5)
1340 {
1341 if (BITS (4, 7) == 0x7)
1342 {
1343 ARMword value;
1344 extern int SWI_vector_installed;
1345
1346 /* Hardware is allowed to optionally override this
1347 instruction and treat it as a breakpoint. Since
1348 this is a simulator not hardware, we take the position
1349 that if a SWI vector was not installed, then an Abort
1350 vector was probably not installed either, and so
1351 normally this instruction would be ignored, even if an
1352 Abort is generated. This is a bad thing, since GDB
1353 uses this instruction for its breakpoints (at least in
1354 Thumb mode it does). So intercept the instruction here
1355 and generate a breakpoint SWI instead. */
1356 if (! SWI_vector_installed)
1357 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1358 else
1359
1360 /* BKPT - normally this will cause an abort, but for the
1361 XScale if bit 31 in register 10 of coprocessor 14 is
1362 clear, then this is treated as a no-op. */
1363 if (state->is_XScale)
1364 {
1365 if (read_cp14_reg (10) & (1UL << 31))
1366 {
1367 ARMword value;
1368
1369 value = read_cp14_reg (10);
1370 value &= ~0x1c;
1371 value |= 0xc;
1372
1373 write_cp14_reg (10, value);
1374 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1375 write_cp15_reg (6, 0, 0, pc); /* Set FAR. */
1376 }
1377 else
1378 break;
1379 }
1380
1381 ARMul_Abort (state, ARMul_PrefetchAbortV);
1382 break;
1383 }
1384 }
1385 if (DESTReg == 15)
1386 {
1387 /* MSR reg to CPSR */
1388 UNDEF_MSRPC;
1389 temp = DPRegRHS;
1390 #ifdef MODET
1391 /* Don't allow TBIT to be set by MSR. */
1392 temp &= ~ TBIT;
1393 #endif
1394 ARMul_FixCPSR (state, instr, temp);
1395 }
1396 else
1397 {
1398 UNDEF_Test;
1399 }
1400 break;
1401
1402 case 0x13: /* TEQP reg */
1403 #ifdef MODET
1404 if ((BITS (4, 11) & 0xF9) == 0x9)
1405 {
1406 /* LDR register offset, write-back, down, pre indexed */
1407 LHPREDOWNWB ();
1408 /* continue with remaining instruction decode */
1409 }
1410 #endif
1411 if (DESTReg == 15)
1412 { /* TEQP reg */
1413 #ifdef MODE32
1414 state->Cpsr = GETSPSR (state->Bank);
1415 ARMul_CPSRAltered (state);
1416 #else
1417 rhs = DPRegRHS;
1418 temp = LHS ^ rhs;
1419 SETR15PSR (temp);
1420 #endif
1421 }
1422 else
1423 { /* TEQ Reg */
1424 rhs = DPSRegRHS;
1425 dest = LHS ^ rhs;
1426 ARMul_NegZero (state, dest);
1427 }
1428 break;
1429
1430 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1431 if (state->is_v5e)
1432 {
1433 if (BIT (4) == 0 && BIT (7) == 1)
1434 {
1435 /* ElSegundo SMLALxy insn. */
1436 unsigned long long op1 = state->Reg[BITS (0, 3)];
1437 unsigned long long op2 = state->Reg[BITS (8, 11)];
1438 unsigned long long dest;
1439 unsigned long long result;
1440
1441 if (BIT (5))
1442 op1 >>= 16;
1443 if (BIT (6))
1444 op2 >>= 16;
1445 op1 &= 0xFFFF;
1446 if (op1 & 0x8000)
1447 op1 -= 65536;
1448 op2 &= 0xFFFF;
1449 if (op2 & 0x8000)
1450 op2 -= 65536;
1451
1452 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1453 dest |= state->Reg[BITS (12, 15)];
1454 dest += op1 * op2;
1455 state->Reg[BITS (12, 15)] = dest;
1456 state->Reg[BITS (16, 19)] = dest >> 32;
1457 break;
1458 }
1459
1460 if (BITS (4, 11) == 5)
1461 {
1462 /* ElSegundo QDADD insn. */
1463 ARMword op1 = state->Reg[BITS (0, 3)];
1464 ARMword op2 = state->Reg[BITS (16, 19)];
1465 ARMword op2d = op2 + op2;
1466 ARMword result;
1467
1468 if (AddOverflow (op2, op2, op2d))
1469 {
1470 SETS;
1471 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1472 }
1473
1474 result = op1 + op2d;
1475 if (AddOverflow (op1, op2d, result))
1476 {
1477 SETS;
1478 result = POS (result) ? 0x80000000 : 0x7fffffff;
1479 }
1480
1481 state->Reg[BITS (12, 15)] = result;
1482 break;
1483 }
1484 }
1485 #ifdef MODET
1486 if (BITS (4, 7) == 0xB)
1487 {
1488 /* STRH immediate offset, no write-back, down, pre indexed */
1489 SHPREDOWN ();
1490 break;
1491 }
1492 if (BITS (4, 7) == 0xD)
1493 {
1494 Handle_Load_Double (state, instr);
1495 break;
1496 }
1497 if (BITS (4, 7) == 0xF)
1498 {
1499 Handle_Store_Double (state, instr);
1500 break;
1501 }
1502 #endif
1503 if (BITS (4, 11) == 9)
1504 { /* SWP */
1505 UNDEF_SWPPC;
1506 temp = LHS;
1507 BUSUSEDINCPCS;
1508 #ifndef MODE32
1509 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1510 {
1511 INTERNALABORT (temp);
1512 (void) ARMul_LoadByte (state, temp);
1513 (void) ARMul_LoadByte (state, temp);
1514 }
1515 else
1516 #endif
1517 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1518 if (state->abortSig || state->Aborted)
1519 {
1520 TAKEABORT;
1521 }
1522 }
1523 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1524 { /* MRS SPSR */
1525 UNDEF_MRSPC;
1526 DEST = GETSPSR (state->Bank);
1527 }
1528 else
1529 {
1530 UNDEF_Test;
1531 }
1532 break;
1533
1534 case 0x15: /* CMPP reg */
1535 #ifdef MODET
1536 if ((BITS (4, 7) & 0x9) == 0x9)
1537 {
1538 /* LDR immediate offset, no write-back, down, pre indexed */
1539 LHPREDOWN ();
1540 /* continue with remaining instruction decode */
1541 }
1542 #endif
1543 if (DESTReg == 15)
1544 { /* CMPP reg */
1545 #ifdef MODE32
1546 state->Cpsr = GETSPSR (state->Bank);
1547 ARMul_CPSRAltered (state);
1548 #else
1549 rhs = DPRegRHS;
1550 temp = LHS - rhs;
1551 SETR15PSR (temp);
1552 #endif
1553 }
1554 else
1555 { /* CMP reg */
1556 lhs = LHS;
1557 rhs = DPRegRHS;
1558 dest = lhs - rhs;
1559 ARMul_NegZero (state, dest);
1560 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1561 {
1562 ARMul_SubCarry (state, lhs, rhs, dest);
1563 ARMul_SubOverflow (state, lhs, rhs, dest);
1564 }
1565 else
1566 {
1567 CLEARC;
1568 CLEARV;
1569 }
1570 }
1571 break;
1572
1573 case 0x16: /* CMN reg and MSR reg to SPSR */
1574 if (state->is_v5e)
1575 {
1576 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1577 {
1578 /* ElSegundo SMULxy insn. */
1579 ARMword op1 = state->Reg[BITS (0, 3)];
1580 ARMword op2 = state->Reg[BITS (8, 11)];
1581 ARMword Rn = state->Reg[BITS (12, 15)];
1582
1583 if (BIT (5))
1584 op1 >>= 16;
1585 if (BIT (6))
1586 op2 >>= 16;
1587 op1 &= 0xFFFF;
1588 op2 &= 0xFFFF;
1589 if (op1 & 0x8000)
1590 op1 -= 65536;
1591 if (op2 & 0x8000)
1592 op2 -= 65536;
1593
1594 state->Reg[BITS (16, 19)] = op1 * op2;
1595 break;
1596 }
1597
1598 if (BITS (4, 11) == 5)
1599 {
1600 /* ElSegundo QDSUB insn. */
1601 ARMword op1 = state->Reg[BITS (0, 3)];
1602 ARMword op2 = state->Reg[BITS (16, 19)];
1603 ARMword op2d = op2 + op2;
1604 ARMword result;
1605
1606 if (AddOverflow (op2, op2, op2d))
1607 {
1608 SETS;
1609 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1610 }
1611
1612 result = op1 - op2d;
1613 if (SubOverflow (op1, op2d, result))
1614 {
1615 SETS;
1616 result = POS (result) ? 0x80000000 : 0x7fffffff;
1617 }
1618
1619 state->Reg[BITS (12, 15)] = result;
1620 break;
1621 }
1622 }
1623
1624 if (state->is_v5)
1625 {
1626 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1627 {
1628 /* ARM5 CLZ insn. */
1629 ARMword op1 = state->Reg[BITS (0, 3)];
1630 int result = 32;
1631
1632 if (op1)
1633 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1634 result++;
1635
1636 state->Reg[BITS (12, 15)] = result;
1637 break;
1638 }
1639 }
1640 #ifdef MODET
1641 if (BITS (4, 7) == 0xB)
1642 {
1643 /* STRH immediate offset, write-back, down, pre indexed */
1644 SHPREDOWNWB ();
1645 break;
1646 }
1647 if (BITS (4, 7) == 0xD)
1648 {
1649 Handle_Load_Double (state, instr);
1650 break;
1651 }
1652 if (BITS (4, 7) == 0xF)
1653 {
1654 Handle_Store_Double (state, instr);
1655 break;
1656 }
1657 #endif
1658 if (DESTReg == 15)
1659 { /* MSR */
1660 UNDEF_MSRPC;
1661 ARMul_FixSPSR (state, instr, DPRegRHS);
1662 }
1663 else
1664 {
1665 UNDEF_Test;
1666 }
1667 break;
1668
1669 case 0x17: /* CMNP reg */
1670 #ifdef MODET
1671 if ((BITS (4, 7) & 0x9) == 0x9)
1672 {
1673 /* LDR immediate offset, write-back, down, pre indexed */
1674 LHPREDOWNWB ();
1675 /* continue with remaining instruction decoding */
1676 }
1677 #endif
1678 if (DESTReg == 15)
1679 {
1680 #ifdef MODE32
1681 state->Cpsr = GETSPSR (state->Bank);
1682 ARMul_CPSRAltered (state);
1683 #else
1684 rhs = DPRegRHS;
1685 temp = LHS + rhs;
1686 SETR15PSR (temp);
1687 #endif
1688 break;
1689 }
1690 else
1691 { /* CMN reg */
1692 lhs = LHS;
1693 rhs = DPRegRHS;
1694 dest = lhs + rhs;
1695 ASSIGNZ (dest == 0);
1696 if ((lhs | rhs) >> 30)
1697 { /* possible C,V,N to set */
1698 ASSIGNN (NEG (dest));
1699 ARMul_AddCarry (state, lhs, rhs, dest);
1700 ARMul_AddOverflow (state, lhs, rhs, dest);
1701 }
1702 else
1703 {
1704 CLEARN;
1705 CLEARC;
1706 CLEARV;
1707 }
1708 }
1709 break;
1710
1711 case 0x18: /* ORR reg */
1712 #ifdef MODET
1713 if (BITS (4, 11) == 0xB)
1714 {
1715 /* STRH register offset, no write-back, up, pre indexed */
1716 SHPREUP ();
1717 break;
1718 }
1719 if (BITS (4, 7) == 0xD)
1720 {
1721 Handle_Load_Double (state, instr);
1722 break;
1723 }
1724 if (BITS (4, 7) == 0xF)
1725 {
1726 Handle_Store_Double (state, instr);
1727 break;
1728 }
1729 #endif
1730 rhs = DPRegRHS;
1731 dest = LHS | rhs;
1732 WRITEDEST (dest);
1733 break;
1734
1735 case 0x19: /* ORRS reg */
1736 #ifdef MODET
1737 if ((BITS (4, 11) & 0xF9) == 0x9)
1738 {
1739 /* LDR register offset, no write-back, up, pre indexed */
1740 LHPREUP ();
1741 /* continue with remaining instruction decoding */
1742 }
1743 #endif
1744 rhs = DPSRegRHS;
1745 dest = LHS | rhs;
1746 WRITESDEST (dest);
1747 break;
1748
1749 case 0x1a: /* MOV reg */
1750 #ifdef MODET
1751 if (BITS (4, 11) == 0xB)
1752 {
1753 /* STRH register offset, write-back, up, pre indexed */
1754 SHPREUPWB ();
1755 break;
1756 }
1757 if (BITS (4, 7) == 0xD)
1758 {
1759 Handle_Load_Double (state, instr);
1760 break;
1761 }
1762 if (BITS (4, 7) == 0xF)
1763 {
1764 Handle_Store_Double (state, instr);
1765 break;
1766 }
1767 #endif
1768 dest = DPRegRHS;
1769 WRITEDEST (dest);
1770 break;
1771
1772 case 0x1b: /* MOVS reg */
1773 #ifdef MODET
1774 if ((BITS (4, 11) & 0xF9) == 0x9)
1775 {
1776 /* LDR register offset, write-back, up, pre indexed */
1777 LHPREUPWB ();
1778 /* continue with remaining instruction decoding */
1779 }
1780 #endif
1781 dest = DPSRegRHS;
1782 WRITESDEST (dest);
1783 break;
1784
1785 case 0x1c: /* BIC reg */
1786 #ifdef MODET
1787 if (BITS (4, 7) == 0xB)
1788 {
1789 /* STRH immediate offset, no write-back, up, pre indexed */
1790 SHPREUP ();
1791 break;
1792 }
1793 if (BITS (4, 7) == 0xD)
1794 {
1795 Handle_Load_Double (state, instr);
1796 break;
1797 }
1798 else if (BITS (4, 7) == 0xF)
1799 {
1800 Handle_Store_Double (state, instr);
1801 break;
1802 }
1803 #endif
1804 rhs = DPRegRHS;
1805 dest = LHS & ~rhs;
1806 WRITEDEST (dest);
1807 break;
1808
1809 case 0x1d: /* BICS reg */
1810 #ifdef MODET
1811 if ((BITS (4, 7) & 0x9) == 0x9)
1812 {
1813 /* LDR immediate offset, no write-back, up, pre indexed */
1814 LHPREUP ();
1815 /* continue with instruction decoding */
1816 }
1817 #endif
1818 rhs = DPSRegRHS;
1819 dest = LHS & ~rhs;
1820 WRITESDEST (dest);
1821 break;
1822
1823 case 0x1e: /* MVN reg */
1824 #ifdef MODET
1825 if (BITS (4, 7) == 0xB)
1826 {
1827 /* STRH immediate offset, write-back, up, pre indexed */
1828 SHPREUPWB ();
1829 break;
1830 }
1831 if (BITS (4, 7) == 0xD)
1832 {
1833 Handle_Load_Double (state, instr);
1834 break;
1835 }
1836 if (BITS (4, 7) == 0xF)
1837 {
1838 Handle_Store_Double (state, instr);
1839 break;
1840 }
1841 #endif
1842 dest = ~DPRegRHS;
1843 WRITEDEST (dest);
1844 break;
1845
1846 case 0x1f: /* MVNS reg */
1847 #ifdef MODET
1848 if ((BITS (4, 7) & 0x9) == 0x9)
1849 {
1850 /* LDR immediate offset, write-back, up, pre indexed */
1851 LHPREUPWB ();
1852 /* continue instruction decoding */
1853 }
1854 #endif
1855 dest = ~DPSRegRHS;
1856 WRITESDEST (dest);
1857 break;
1858
1859 /***************************************************************************\
1860 * Data Processing Immediate RHS Instructions *
1861 \***************************************************************************/
1862
1863 case 0x20: /* AND immed */
1864 dest = LHS & DPImmRHS;
1865 WRITEDEST (dest);
1866 break;
1867
1868 case 0x21: /* ANDS immed */
1869 DPSImmRHS;
1870 dest = LHS & rhs;
1871 WRITESDEST (dest);
1872 break;
1873
1874 case 0x22: /* EOR immed */
1875 dest = LHS ^ DPImmRHS;
1876 WRITEDEST (dest);
1877 break;
1878
1879 case 0x23: /* EORS immed */
1880 DPSImmRHS;
1881 dest = LHS ^ rhs;
1882 WRITESDEST (dest);
1883 break;
1884
1885 case 0x24: /* SUB immed */
1886 dest = LHS - DPImmRHS;
1887 WRITEDEST (dest);
1888 break;
1889
1890 case 0x25: /* SUBS immed */
1891 lhs = LHS;
1892 rhs = DPImmRHS;
1893 dest = lhs - rhs;
1894 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1895 {
1896 ARMul_SubCarry (state, lhs, rhs, dest);
1897 ARMul_SubOverflow (state, lhs, rhs, dest);
1898 }
1899 else
1900 {
1901 CLEARC;
1902 CLEARV;
1903 }
1904 WRITESDEST (dest);
1905 break;
1906
1907 case 0x26: /* RSB immed */
1908 dest = DPImmRHS - LHS;
1909 WRITEDEST (dest);
1910 break;
1911
1912 case 0x27: /* RSBS immed */
1913 lhs = LHS;
1914 rhs = DPImmRHS;
1915 dest = rhs - lhs;
1916 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1917 {
1918 ARMul_SubCarry (state, rhs, lhs, dest);
1919 ARMul_SubOverflow (state, rhs, lhs, dest);
1920 }
1921 else
1922 {
1923 CLEARC;
1924 CLEARV;
1925 }
1926 WRITESDEST (dest);
1927 break;
1928
1929 case 0x28: /* ADD immed */
1930 dest = LHS + DPImmRHS;
1931 WRITEDEST (dest);
1932 break;
1933
1934 case 0x29: /* ADDS immed */
1935 lhs = LHS;
1936 rhs = DPImmRHS;
1937 dest = lhs + rhs;
1938 ASSIGNZ (dest == 0);
1939 if ((lhs | rhs) >> 30)
1940 { /* possible C,V,N to set */
1941 ASSIGNN (NEG (dest));
1942 ARMul_AddCarry (state, lhs, rhs, dest);
1943 ARMul_AddOverflow (state, lhs, rhs, dest);
1944 }
1945 else
1946 {
1947 CLEARN;
1948 CLEARC;
1949 CLEARV;
1950 }
1951 WRITESDEST (dest);
1952 break;
1953
1954 case 0x2a: /* ADC immed */
1955 dest = LHS + DPImmRHS + CFLAG;
1956 WRITEDEST (dest);
1957 break;
1958
1959 case 0x2b: /* ADCS immed */
1960 lhs = LHS;
1961 rhs = DPImmRHS;
1962 dest = lhs + rhs + CFLAG;
1963 ASSIGNZ (dest == 0);
1964 if ((lhs | rhs) >> 30)
1965 { /* possible C,V,N to set */
1966 ASSIGNN (NEG (dest));
1967 ARMul_AddCarry (state, lhs, rhs, dest);
1968 ARMul_AddOverflow (state, lhs, rhs, dest);
1969 }
1970 else
1971 {
1972 CLEARN;
1973 CLEARC;
1974 CLEARV;
1975 }
1976 WRITESDEST (dest);
1977 break;
1978
1979 case 0x2c: /* SBC immed */
1980 dest = LHS - DPImmRHS - !CFLAG;
1981 WRITEDEST (dest);
1982 break;
1983
1984 case 0x2d: /* SBCS immed */
1985 lhs = LHS;
1986 rhs = DPImmRHS;
1987 dest = lhs - rhs - !CFLAG;
1988 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1989 {
1990 ARMul_SubCarry (state, lhs, rhs, dest);
1991 ARMul_SubOverflow (state, lhs, rhs, dest);
1992 }
1993 else
1994 {
1995 CLEARC;
1996 CLEARV;
1997 }
1998 WRITESDEST (dest);
1999 break;
2000
2001 case 0x2e: /* RSC immed */
2002 dest = DPImmRHS - LHS - !CFLAG;
2003 WRITEDEST (dest);
2004 break;
2005
2006 case 0x2f: /* RSCS immed */
2007 lhs = LHS;
2008 rhs = DPImmRHS;
2009 dest = rhs - lhs - !CFLAG;
2010 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2011 {
2012 ARMul_SubCarry (state, rhs, lhs, dest);
2013 ARMul_SubOverflow (state, rhs, lhs, dest);
2014 }
2015 else
2016 {
2017 CLEARC;
2018 CLEARV;
2019 }
2020 WRITESDEST (dest);
2021 break;
2022
2023 case 0x30: /* TST immed */
2024 UNDEF_Test;
2025 break;
2026
2027 case 0x31: /* TSTP immed */
2028 if (DESTReg == 15)
2029 { /* TSTP immed */
2030 #ifdef MODE32
2031 state->Cpsr = GETSPSR (state->Bank);
2032 ARMul_CPSRAltered (state);
2033 #else
2034 temp = LHS & DPImmRHS;
2035 SETR15PSR (temp);
2036 #endif
2037 }
2038 else
2039 {
2040 DPSImmRHS; /* TST immed */
2041 dest = LHS & rhs;
2042 ARMul_NegZero (state, dest);
2043 }
2044 break;
2045
2046 case 0x32: /* TEQ immed and MSR immed to CPSR */
2047 if (DESTReg == 15)
2048 { /* MSR immed to CPSR */
2049 ARMul_FixCPSR (state, instr, DPImmRHS);
2050 }
2051 else
2052 {
2053 UNDEF_Test;
2054 }
2055 break;
2056
2057 case 0x33: /* TEQP immed */
2058 if (DESTReg == 15)
2059 { /* TEQP immed */
2060 #ifdef MODE32
2061 state->Cpsr = GETSPSR (state->Bank);
2062 ARMul_CPSRAltered (state);
2063 #else
2064 temp = LHS ^ DPImmRHS;
2065 SETR15PSR (temp);
2066 #endif
2067 }
2068 else
2069 {
2070 DPSImmRHS; /* TEQ immed */
2071 dest = LHS ^ rhs;
2072 ARMul_NegZero (state, dest);
2073 }
2074 break;
2075
2076 case 0x34: /* CMP immed */
2077 UNDEF_Test;
2078 break;
2079
2080 case 0x35: /* CMPP immed */
2081 if (DESTReg == 15)
2082 { /* CMPP immed */
2083 #ifdef MODE32
2084 state->Cpsr = GETSPSR (state->Bank);
2085 ARMul_CPSRAltered (state);
2086 #else
2087 temp = LHS - DPImmRHS;
2088 SETR15PSR (temp);
2089 #endif
2090 break;
2091 }
2092 else
2093 {
2094 lhs = LHS; /* CMP immed */
2095 rhs = DPImmRHS;
2096 dest = lhs - rhs;
2097 ARMul_NegZero (state, dest);
2098 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2099 {
2100 ARMul_SubCarry (state, lhs, rhs, dest);
2101 ARMul_SubOverflow (state, lhs, rhs, dest);
2102 }
2103 else
2104 {
2105 CLEARC;
2106 CLEARV;
2107 }
2108 }
2109 break;
2110
2111 case 0x36: /* CMN immed and MSR immed to SPSR */
2112 if (DESTReg == 15) /* MSR */
2113 ARMul_FixSPSR (state, instr, DPImmRHS);
2114 else
2115 {
2116 UNDEF_Test;
2117 }
2118 break;
2119
2120 case 0x37: /* CMNP immed */
2121 if (DESTReg == 15)
2122 { /* CMNP immed */
2123 #ifdef MODE32
2124 state->Cpsr = GETSPSR (state->Bank);
2125 ARMul_CPSRAltered (state);
2126 #else
2127 temp = LHS + DPImmRHS;
2128 SETR15PSR (temp);
2129 #endif
2130 break;
2131 }
2132 else
2133 {
2134 lhs = LHS; /* CMN immed */
2135 rhs = DPImmRHS;
2136 dest = lhs + rhs;
2137 ASSIGNZ (dest == 0);
2138 if ((lhs | rhs) >> 30)
2139 { /* possible C,V,N to set */
2140 ASSIGNN (NEG (dest));
2141 ARMul_AddCarry (state, lhs, rhs, dest);
2142 ARMul_AddOverflow (state, lhs, rhs, dest);
2143 }
2144 else
2145 {
2146 CLEARN;
2147 CLEARC;
2148 CLEARV;
2149 }
2150 }
2151 break;
2152
2153 case 0x38: /* ORR immed */
2154 dest = LHS | DPImmRHS;
2155 WRITEDEST (dest);
2156 break;
2157
2158 case 0x39: /* ORRS immed */
2159 DPSImmRHS;
2160 dest = LHS | rhs;
2161 WRITESDEST (dest);
2162 break;
2163
2164 case 0x3a: /* MOV immed */
2165 dest = DPImmRHS;
2166 WRITEDEST (dest);
2167 break;
2168
2169 case 0x3b: /* MOVS immed */
2170 DPSImmRHS;
2171 WRITESDEST (rhs);
2172 break;
2173
2174 case 0x3c: /* BIC immed */
2175 dest = LHS & ~DPImmRHS;
2176 WRITEDEST (dest);
2177 break;
2178
2179 case 0x3d: /* BICS immed */
2180 DPSImmRHS;
2181 dest = LHS & ~rhs;
2182 WRITESDEST (dest);
2183 break;
2184
2185 case 0x3e: /* MVN immed */
2186 dest = ~DPImmRHS;
2187 WRITEDEST (dest);
2188 break;
2189
2190 case 0x3f: /* MVNS immed */
2191 DPSImmRHS;
2192 WRITESDEST (~rhs);
2193 break;
2194
2195 /***************************************************************************\
2196 * Single Data Transfer Immediate RHS Instructions *
2197 \***************************************************************************/
2198
2199 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2200 lhs = LHS;
2201 if (StoreWord (state, instr, lhs))
2202 LSBase = lhs - LSImmRHS;
2203 break;
2204
2205 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2206 lhs = LHS;
2207 if (LoadWord (state, instr, lhs))
2208 LSBase = lhs - LSImmRHS;
2209 break;
2210
2211 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2212 UNDEF_LSRBaseEQDestWb;
2213 UNDEF_LSRPCBaseWb;
2214 lhs = LHS;
2215 temp = lhs - LSImmRHS;
2216 state->NtransSig = LOW;
2217 if (StoreWord (state, instr, lhs))
2218 LSBase = temp;
2219 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2220 break;
2221
2222 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2223 UNDEF_LSRBaseEQDestWb;
2224 UNDEF_LSRPCBaseWb;
2225 lhs = LHS;
2226 state->NtransSig = LOW;
2227 if (LoadWord (state, instr, lhs))
2228 LSBase = lhs - LSImmRHS;
2229 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2230 break;
2231
2232 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2233 lhs = LHS;
2234 if (StoreByte (state, instr, lhs))
2235 LSBase = lhs - LSImmRHS;
2236 break;
2237
2238 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2239 lhs = LHS;
2240 if (LoadByte (state, instr, lhs, LUNSIGNED))
2241 LSBase = lhs - LSImmRHS;
2242 break;
2243
2244 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2245 UNDEF_LSRBaseEQDestWb;
2246 UNDEF_LSRPCBaseWb;
2247 lhs = LHS;
2248 state->NtransSig = LOW;
2249 if (StoreByte (state, instr, lhs))
2250 LSBase = lhs - LSImmRHS;
2251 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2252 break;
2253
2254 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2255 UNDEF_LSRBaseEQDestWb;
2256 UNDEF_LSRPCBaseWb;
2257 lhs = LHS;
2258 state->NtransSig = LOW;
2259 if (LoadByte (state, instr, lhs, LUNSIGNED))
2260 LSBase = lhs - LSImmRHS;
2261 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2262 break;
2263
2264 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2265 lhs = LHS;
2266 if (StoreWord (state, instr, lhs))
2267 LSBase = lhs + LSImmRHS;
2268 break;
2269
2270 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2271 lhs = LHS;
2272 if (LoadWord (state, instr, lhs))
2273 LSBase = lhs + LSImmRHS;
2274 break;
2275
2276 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2277 UNDEF_LSRBaseEQDestWb;
2278 UNDEF_LSRPCBaseWb;
2279 lhs = LHS;
2280 state->NtransSig = LOW;
2281 if (StoreWord (state, instr, lhs))
2282 LSBase = lhs + LSImmRHS;
2283 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2284 break;
2285
2286 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2287 UNDEF_LSRBaseEQDestWb;
2288 UNDEF_LSRPCBaseWb;
2289 lhs = LHS;
2290 state->NtransSig = LOW;
2291 if (LoadWord (state, instr, lhs))
2292 LSBase = lhs + LSImmRHS;
2293 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2294 break;
2295
2296 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2297 lhs = LHS;
2298 if (StoreByte (state, instr, lhs))
2299 LSBase = lhs + LSImmRHS;
2300 break;
2301
2302 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2303 lhs = LHS;
2304 if (LoadByte (state, instr, lhs, LUNSIGNED))
2305 LSBase = lhs + LSImmRHS;
2306 break;
2307
2308 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2309 UNDEF_LSRBaseEQDestWb;
2310 UNDEF_LSRPCBaseWb;
2311 lhs = LHS;
2312 state->NtransSig = LOW;
2313 if (StoreByte (state, instr, lhs))
2314 LSBase = lhs + LSImmRHS;
2315 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2316 break;
2317
2318 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2319 UNDEF_LSRBaseEQDestWb;
2320 UNDEF_LSRPCBaseWb;
2321 lhs = LHS;
2322 state->NtransSig = LOW;
2323 if (LoadByte (state, instr, lhs, LUNSIGNED))
2324 LSBase = lhs + LSImmRHS;
2325 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2326 break;
2327
2328
2329 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2330 (void) StoreWord (state, instr, LHS - LSImmRHS);
2331 break;
2332
2333 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2334 (void) LoadWord (state, instr, LHS - LSImmRHS);
2335 break;
2336
2337 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2338 UNDEF_LSRBaseEQDestWb;
2339 UNDEF_LSRPCBaseWb;
2340 temp = LHS - LSImmRHS;
2341 if (StoreWord (state, instr, temp))
2342 LSBase = temp;
2343 break;
2344
2345 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2346 UNDEF_LSRBaseEQDestWb;
2347 UNDEF_LSRPCBaseWb;
2348 temp = LHS - LSImmRHS;
2349 if (LoadWord (state, instr, temp))
2350 LSBase = temp;
2351 break;
2352
2353 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2354 (void) StoreByte (state, instr, LHS - LSImmRHS);
2355 break;
2356
2357 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2358 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2359 break;
2360
2361 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2362 UNDEF_LSRBaseEQDestWb;
2363 UNDEF_LSRPCBaseWb;
2364 temp = LHS - LSImmRHS;
2365 if (StoreByte (state, instr, temp))
2366 LSBase = temp;
2367 break;
2368
2369 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2370 UNDEF_LSRBaseEQDestWb;
2371 UNDEF_LSRPCBaseWb;
2372 temp = LHS - LSImmRHS;
2373 if (LoadByte (state, instr, temp, LUNSIGNED))
2374 LSBase = temp;
2375 break;
2376
2377 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2378 (void) StoreWord (state, instr, LHS + LSImmRHS);
2379 break;
2380
2381 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2382 (void) LoadWord (state, instr, LHS + LSImmRHS);
2383 break;
2384
2385 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2386 UNDEF_LSRBaseEQDestWb;
2387 UNDEF_LSRPCBaseWb;
2388 temp = LHS + LSImmRHS;
2389 if (StoreWord (state, instr, temp))
2390 LSBase = temp;
2391 break;
2392
2393 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2394 UNDEF_LSRBaseEQDestWb;
2395 UNDEF_LSRPCBaseWb;
2396 temp = LHS + LSImmRHS;
2397 if (LoadWord (state, instr, temp))
2398 LSBase = temp;
2399 break;
2400
2401 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2402 (void) StoreByte (state, instr, LHS + LSImmRHS);
2403 break;
2404
2405 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2406 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2407 break;
2408
2409 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2410 UNDEF_LSRBaseEQDestWb;
2411 UNDEF_LSRPCBaseWb;
2412 temp = LHS + LSImmRHS;
2413 if (StoreByte (state, instr, temp))
2414 LSBase = temp;
2415 break;
2416
2417 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2418 UNDEF_LSRBaseEQDestWb;
2419 UNDEF_LSRPCBaseWb;
2420 temp = LHS + LSImmRHS;
2421 if (LoadByte (state, instr, temp, LUNSIGNED))
2422 LSBase = temp;
2423 break;
2424
2425 /***************************************************************************\
2426 * Single Data Transfer Register RHS Instructions *
2427 \***************************************************************************/
2428
2429 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2430 if (BIT (4))
2431 {
2432 ARMul_UndefInstr (state, instr);
2433 break;
2434 }
2435 UNDEF_LSRBaseEQOffWb;
2436 UNDEF_LSRBaseEQDestWb;
2437 UNDEF_LSRPCBaseWb;
2438 UNDEF_LSRPCOffWb;
2439 lhs = LHS;
2440 if (StoreWord (state, instr, lhs))
2441 LSBase = lhs - LSRegRHS;
2442 break;
2443
2444 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2445 if (BIT (4))
2446 {
2447 ARMul_UndefInstr (state, instr);
2448 break;
2449 }
2450 UNDEF_LSRBaseEQOffWb;
2451 UNDEF_LSRBaseEQDestWb;
2452 UNDEF_LSRPCBaseWb;
2453 UNDEF_LSRPCOffWb;
2454 lhs = LHS;
2455 temp = lhs - LSRegRHS;
2456 if (LoadWord (state, instr, lhs))
2457 LSBase = temp;
2458 break;
2459
2460 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2461 if (BIT (4))
2462 {
2463 ARMul_UndefInstr (state, instr);
2464 break;
2465 }
2466 UNDEF_LSRBaseEQOffWb;
2467 UNDEF_LSRBaseEQDestWb;
2468 UNDEF_LSRPCBaseWb;
2469 UNDEF_LSRPCOffWb;
2470 lhs = LHS;
2471 state->NtransSig = LOW;
2472 if (StoreWord (state, instr, lhs))
2473 LSBase = lhs - LSRegRHS;
2474 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2475 break;
2476
2477 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2478 if (BIT (4))
2479 {
2480 ARMul_UndefInstr (state, instr);
2481 break;
2482 }
2483 UNDEF_LSRBaseEQOffWb;
2484 UNDEF_LSRBaseEQDestWb;
2485 UNDEF_LSRPCBaseWb;
2486 UNDEF_LSRPCOffWb;
2487 lhs = LHS;
2488 temp = lhs - LSRegRHS;
2489 state->NtransSig = LOW;
2490 if (LoadWord (state, instr, lhs))
2491 LSBase = temp;
2492 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2493 break;
2494
2495 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2496 if (BIT (4))
2497 {
2498 ARMul_UndefInstr (state, instr);
2499 break;
2500 }
2501 UNDEF_LSRBaseEQOffWb;
2502 UNDEF_LSRBaseEQDestWb;
2503 UNDEF_LSRPCBaseWb;
2504 UNDEF_LSRPCOffWb;
2505 lhs = LHS;
2506 if (StoreByte (state, instr, lhs))
2507 LSBase = lhs - LSRegRHS;
2508 break;
2509
2510 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2511 if (BIT (4))
2512 {
2513 ARMul_UndefInstr (state, instr);
2514 break;
2515 }
2516 UNDEF_LSRBaseEQOffWb;
2517 UNDEF_LSRBaseEQDestWb;
2518 UNDEF_LSRPCBaseWb;
2519 UNDEF_LSRPCOffWb;
2520 lhs = LHS;
2521 temp = lhs - LSRegRHS;
2522 if (LoadByte (state, instr, lhs, LUNSIGNED))
2523 LSBase = temp;
2524 break;
2525
2526 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2527 if (BIT (4))
2528 {
2529 ARMul_UndefInstr (state, instr);
2530 break;
2531 }
2532 UNDEF_LSRBaseEQOffWb;
2533 UNDEF_LSRBaseEQDestWb;
2534 UNDEF_LSRPCBaseWb;
2535 UNDEF_LSRPCOffWb;
2536 lhs = LHS;
2537 state->NtransSig = LOW;
2538 if (StoreByte (state, instr, lhs))
2539 LSBase = lhs - LSRegRHS;
2540 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2541 break;
2542
2543 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2544 if (BIT (4))
2545 {
2546 ARMul_UndefInstr (state, instr);
2547 break;
2548 }
2549 UNDEF_LSRBaseEQOffWb;
2550 UNDEF_LSRBaseEQDestWb;
2551 UNDEF_LSRPCBaseWb;
2552 UNDEF_LSRPCOffWb;
2553 lhs = LHS;
2554 temp = lhs - LSRegRHS;
2555 state->NtransSig = LOW;
2556 if (LoadByte (state, instr, lhs, LUNSIGNED))
2557 LSBase = temp;
2558 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2559 break;
2560
2561 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2562 if (BIT (4))
2563 {
2564 ARMul_UndefInstr (state, instr);
2565 break;
2566 }
2567 UNDEF_LSRBaseEQOffWb;
2568 UNDEF_LSRBaseEQDestWb;
2569 UNDEF_LSRPCBaseWb;
2570 UNDEF_LSRPCOffWb;
2571 lhs = LHS;
2572 if (StoreWord (state, instr, lhs))
2573 LSBase = lhs + LSRegRHS;
2574 break;
2575
2576 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2577 if (BIT (4))
2578 {
2579 ARMul_UndefInstr (state, instr);
2580 break;
2581 }
2582 UNDEF_LSRBaseEQOffWb;
2583 UNDEF_LSRBaseEQDestWb;
2584 UNDEF_LSRPCBaseWb;
2585 UNDEF_LSRPCOffWb;
2586 lhs = LHS;
2587 temp = lhs + LSRegRHS;
2588 if (LoadWord (state, instr, lhs))
2589 LSBase = temp;
2590 break;
2591
2592 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2593 if (BIT (4))
2594 {
2595 ARMul_UndefInstr (state, instr);
2596 break;
2597 }
2598 UNDEF_LSRBaseEQOffWb;
2599 UNDEF_LSRBaseEQDestWb;
2600 UNDEF_LSRPCBaseWb;
2601 UNDEF_LSRPCOffWb;
2602 lhs = LHS;
2603 state->NtransSig = LOW;
2604 if (StoreWord (state, instr, lhs))
2605 LSBase = lhs + LSRegRHS;
2606 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2607 break;
2608
2609 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2610 if (BIT (4))
2611 {
2612 ARMul_UndefInstr (state, instr);
2613 break;
2614 }
2615 UNDEF_LSRBaseEQOffWb;
2616 UNDEF_LSRBaseEQDestWb;
2617 UNDEF_LSRPCBaseWb;
2618 UNDEF_LSRPCOffWb;
2619 lhs = LHS;
2620 temp = lhs + LSRegRHS;
2621 state->NtransSig = LOW;
2622 if (LoadWord (state, instr, lhs))
2623 LSBase = temp;
2624 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2625 break;
2626
2627 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2628 if (BIT (4))
2629 {
2630 ARMul_UndefInstr (state, instr);
2631 break;
2632 }
2633 UNDEF_LSRBaseEQOffWb;
2634 UNDEF_LSRBaseEQDestWb;
2635 UNDEF_LSRPCBaseWb;
2636 UNDEF_LSRPCOffWb;
2637 lhs = LHS;
2638 if (StoreByte (state, instr, lhs))
2639 LSBase = lhs + LSRegRHS;
2640 break;
2641
2642 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2643 if (BIT (4))
2644 {
2645 ARMul_UndefInstr (state, instr);
2646 break;
2647 }
2648 UNDEF_LSRBaseEQOffWb;
2649 UNDEF_LSRBaseEQDestWb;
2650 UNDEF_LSRPCBaseWb;
2651 UNDEF_LSRPCOffWb;
2652 lhs = LHS;
2653 temp = lhs + LSRegRHS;
2654 if (LoadByte (state, instr, lhs, LUNSIGNED))
2655 LSBase = temp;
2656 break;
2657
2658 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2659 if (BIT (4))
2660 {
2661 ARMul_UndefInstr (state, instr);
2662 break;
2663 }
2664 UNDEF_LSRBaseEQOffWb;
2665 UNDEF_LSRBaseEQDestWb;
2666 UNDEF_LSRPCBaseWb;
2667 UNDEF_LSRPCOffWb;
2668 lhs = LHS;
2669 state->NtransSig = LOW;
2670 if (StoreByte (state, instr, lhs))
2671 LSBase = lhs + LSRegRHS;
2672 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2673 break;
2674
2675 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2676 if (BIT (4))
2677 {
2678 ARMul_UndefInstr (state, instr);
2679 break;
2680 }
2681 UNDEF_LSRBaseEQOffWb;
2682 UNDEF_LSRBaseEQDestWb;
2683 UNDEF_LSRPCBaseWb;
2684 UNDEF_LSRPCOffWb;
2685 lhs = LHS;
2686 temp = lhs + LSRegRHS;
2687 state->NtransSig = LOW;
2688 if (LoadByte (state, instr, lhs, LUNSIGNED))
2689 LSBase = temp;
2690 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2691 break;
2692
2693
2694 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2695 if (BIT (4))
2696 {
2697 ARMul_UndefInstr (state, instr);
2698 break;
2699 }
2700 (void) StoreWord (state, instr, LHS - LSRegRHS);
2701 break;
2702
2703 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2704 if (BIT (4))
2705 {
2706 ARMul_UndefInstr (state, instr);
2707 break;
2708 }
2709 (void) LoadWord (state, instr, LHS - LSRegRHS);
2710 break;
2711
2712 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2713 if (BIT (4))
2714 {
2715 ARMul_UndefInstr (state, instr);
2716 break;
2717 }
2718 UNDEF_LSRBaseEQOffWb;
2719 UNDEF_LSRBaseEQDestWb;
2720 UNDEF_LSRPCBaseWb;
2721 UNDEF_LSRPCOffWb;
2722 temp = LHS - LSRegRHS;
2723 if (StoreWord (state, instr, temp))
2724 LSBase = temp;
2725 break;
2726
2727 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2728 if (BIT (4))
2729 {
2730 ARMul_UndefInstr (state, instr);
2731 break;
2732 }
2733 UNDEF_LSRBaseEQOffWb;
2734 UNDEF_LSRBaseEQDestWb;
2735 UNDEF_LSRPCBaseWb;
2736 UNDEF_LSRPCOffWb;
2737 temp = LHS - LSRegRHS;
2738 if (LoadWord (state, instr, temp))
2739 LSBase = temp;
2740 break;
2741
2742 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2743 if (BIT (4))
2744 {
2745 ARMul_UndefInstr (state, instr);
2746 break;
2747 }
2748 (void) StoreByte (state, instr, LHS - LSRegRHS);
2749 break;
2750
2751 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2752 if (BIT (4))
2753 {
2754 ARMul_UndefInstr (state, instr);
2755 break;
2756 }
2757 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2758 break;
2759
2760 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2761 if (BIT (4))
2762 {
2763 ARMul_UndefInstr (state, instr);
2764 break;
2765 }
2766 UNDEF_LSRBaseEQOffWb;
2767 UNDEF_LSRBaseEQDestWb;
2768 UNDEF_LSRPCBaseWb;
2769 UNDEF_LSRPCOffWb;
2770 temp = LHS - LSRegRHS;
2771 if (StoreByte (state, instr, temp))
2772 LSBase = temp;
2773 break;
2774
2775 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2776 if (BIT (4))
2777 {
2778 ARMul_UndefInstr (state, instr);
2779 break;
2780 }
2781 UNDEF_LSRBaseEQOffWb;
2782 UNDEF_LSRBaseEQDestWb;
2783 UNDEF_LSRPCBaseWb;
2784 UNDEF_LSRPCOffWb;
2785 temp = LHS - LSRegRHS;
2786 if (LoadByte (state, instr, temp, LUNSIGNED))
2787 LSBase = temp;
2788 break;
2789
2790 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2791 if (BIT (4))
2792 {
2793 ARMul_UndefInstr (state, instr);
2794 break;
2795 }
2796 (void) StoreWord (state, instr, LHS + LSRegRHS);
2797 break;
2798
2799 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2800 if (BIT (4))
2801 {
2802 ARMul_UndefInstr (state, instr);
2803 break;
2804 }
2805 (void) LoadWord (state, instr, LHS + LSRegRHS);
2806 break;
2807
2808 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2809 if (BIT (4))
2810 {
2811 ARMul_UndefInstr (state, instr);
2812 break;
2813 }
2814 UNDEF_LSRBaseEQOffWb;
2815 UNDEF_LSRBaseEQDestWb;
2816 UNDEF_LSRPCBaseWb;
2817 UNDEF_LSRPCOffWb;
2818 temp = LHS + LSRegRHS;
2819 if (StoreWord (state, instr, temp))
2820 LSBase = temp;
2821 break;
2822
2823 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2824 if (BIT (4))
2825 {
2826 ARMul_UndefInstr (state, instr);
2827 break;
2828 }
2829 UNDEF_LSRBaseEQOffWb;
2830 UNDEF_LSRBaseEQDestWb;
2831 UNDEF_LSRPCBaseWb;
2832 UNDEF_LSRPCOffWb;
2833 temp = LHS + LSRegRHS;
2834 if (LoadWord (state, instr, temp))
2835 LSBase = temp;
2836 break;
2837
2838 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2839 if (BIT (4))
2840 {
2841 ARMul_UndefInstr (state, instr);
2842 break;
2843 }
2844 (void) StoreByte (state, instr, LHS + LSRegRHS);
2845 break;
2846
2847 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2848 if (BIT (4))
2849 {
2850 ARMul_UndefInstr (state, instr);
2851 break;
2852 }
2853 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2854 break;
2855
2856 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2857 if (BIT (4))
2858 {
2859 ARMul_UndefInstr (state, instr);
2860 break;
2861 }
2862 UNDEF_LSRBaseEQOffWb;
2863 UNDEF_LSRBaseEQDestWb;
2864 UNDEF_LSRPCBaseWb;
2865 UNDEF_LSRPCOffWb;
2866 temp = LHS + LSRegRHS;
2867 if (StoreByte (state, instr, temp))
2868 LSBase = temp;
2869 break;
2870
2871 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2872 if (BIT (4))
2873 {
2874 /* Check for the special breakpoint opcode.
2875 This value should correspond to the value defined
2876 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2877 if (BITS (0, 19) == 0xfdefe)
2878 {
2879 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2880 ARMul_Abort (state, ARMul_SWIV);
2881 }
2882 else
2883 ARMul_UndefInstr (state, instr);
2884 break;
2885 }
2886 UNDEF_LSRBaseEQOffWb;
2887 UNDEF_LSRBaseEQDestWb;
2888 UNDEF_LSRPCBaseWb;
2889 UNDEF_LSRPCOffWb;
2890 temp = LHS + LSRegRHS;
2891 if (LoadByte (state, instr, temp, LUNSIGNED))
2892 LSBase = temp;
2893 break;
2894
2895 /***************************************************************************\
2896 * Multiple Data Transfer Instructions *
2897 \***************************************************************************/
2898
2899 case 0x80: /* Store, No WriteBack, Post Dec */
2900 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2901 break;
2902
2903 case 0x81: /* Load, No WriteBack, Post Dec */
2904 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2905 break;
2906
2907 case 0x82: /* Store, WriteBack, Post Dec */
2908 temp = LSBase - LSMNumRegs;
2909 STOREMULT (instr, temp + 4L, temp);
2910 break;
2911
2912 case 0x83: /* Load, WriteBack, Post Dec */
2913 temp = LSBase - LSMNumRegs;
2914 LOADMULT (instr, temp + 4L, temp);
2915 break;
2916
2917 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2918 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2919 break;
2920
2921 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2922 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2923 break;
2924
2925 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2926 temp = LSBase - LSMNumRegs;
2927 STORESMULT (instr, temp + 4L, temp);
2928 break;
2929
2930 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2931 temp = LSBase - LSMNumRegs;
2932 LOADSMULT (instr, temp + 4L, temp);
2933 break;
2934
2935 case 0x88: /* Store, No WriteBack, Post Inc */
2936 STOREMULT (instr, LSBase, 0L);
2937 break;
2938
2939 case 0x89: /* Load, No WriteBack, Post Inc */
2940 LOADMULT (instr, LSBase, 0L);
2941 break;
2942
2943 case 0x8a: /* Store, WriteBack, Post Inc */
2944 temp = LSBase;
2945 STOREMULT (instr, temp, temp + LSMNumRegs);
2946 break;
2947
2948 case 0x8b: /* Load, WriteBack, Post Inc */
2949 temp = LSBase;
2950 LOADMULT (instr, temp, temp + LSMNumRegs);
2951 break;
2952
2953 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2954 STORESMULT (instr, LSBase, 0L);
2955 break;
2956
2957 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2958 LOADSMULT (instr, LSBase, 0L);
2959 break;
2960
2961 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2962 temp = LSBase;
2963 STORESMULT (instr, temp, temp + LSMNumRegs);
2964 break;
2965
2966 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2967 temp = LSBase;
2968 LOADSMULT (instr, temp, temp + LSMNumRegs);
2969 break;
2970
2971 case 0x90: /* Store, No WriteBack, Pre Dec */
2972 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
2973 break;
2974
2975 case 0x91: /* Load, No WriteBack, Pre Dec */
2976 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
2977 break;
2978
2979 case 0x92: /* Store, WriteBack, Pre Dec */
2980 temp = LSBase - LSMNumRegs;
2981 STOREMULT (instr, temp, temp);
2982 break;
2983
2984 case 0x93: /* Load, WriteBack, Pre Dec */
2985 temp = LSBase - LSMNumRegs;
2986 LOADMULT (instr, temp, temp);
2987 break;
2988
2989 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2990 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
2991 break;
2992
2993 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2994 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
2995 break;
2996
2997 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2998 temp = LSBase - LSMNumRegs;
2999 STORESMULT (instr, temp, temp);
3000 break;
3001
3002 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3003 temp = LSBase - LSMNumRegs;
3004 LOADSMULT (instr, temp, temp);
3005 break;
3006
3007 case 0x98: /* Store, No WriteBack, Pre Inc */
3008 STOREMULT (instr, LSBase + 4L, 0L);
3009 break;
3010
3011 case 0x99: /* Load, No WriteBack, Pre Inc */
3012 LOADMULT (instr, LSBase + 4L, 0L);
3013 break;
3014
3015 case 0x9a: /* Store, WriteBack, Pre Inc */
3016 temp = LSBase;
3017 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3018 break;
3019
3020 case 0x9b: /* Load, WriteBack, Pre Inc */
3021 temp = LSBase;
3022 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3023 break;
3024
3025 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3026 STORESMULT (instr, LSBase + 4L, 0L);
3027 break;
3028
3029 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3030 LOADSMULT (instr, LSBase + 4L, 0L);
3031 break;
3032
3033 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3034 temp = LSBase;
3035 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3036 break;
3037
3038 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3039 temp = LSBase;
3040 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3041 break;
3042
3043 /***************************************************************************\
3044 * Branch forward *
3045 \***************************************************************************/
3046
3047 case 0xa0:
3048 case 0xa1:
3049 case 0xa2:
3050 case 0xa3:
3051 case 0xa4:
3052 case 0xa5:
3053 case 0xa6:
3054 case 0xa7:
3055 state->Reg[15] = pc + 8 + POSBRANCH;
3056 FLUSHPIPE;
3057 break;
3058
3059 /***************************************************************************\
3060 * Branch backward *
3061 \***************************************************************************/
3062
3063 case 0xa8:
3064 case 0xa9:
3065 case 0xaa:
3066 case 0xab:
3067 case 0xac:
3068 case 0xad:
3069 case 0xae:
3070 case 0xaf:
3071 state->Reg[15] = pc + 8 + NEGBRANCH;
3072 FLUSHPIPE;
3073 break;
3074
3075 /***************************************************************************\
3076 * Branch and Link forward *
3077 \***************************************************************************/
3078
3079 case 0xb0:
3080 case 0xb1:
3081 case 0xb2:
3082 case 0xb3:
3083 case 0xb4:
3084 case 0xb5:
3085 case 0xb6:
3086 case 0xb7:
3087 #ifdef MODE32
3088 state->Reg[14] = pc + 4; /* put PC into Link */
3089 #else
3090 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
3091 #endif
3092 state->Reg[15] = pc + 8 + POSBRANCH;
3093 FLUSHPIPE;
3094 break;
3095
3096 /***************************************************************************\
3097 * Branch and Link backward *
3098 \***************************************************************************/
3099
3100 case 0xb8:
3101 case 0xb9:
3102 case 0xba:
3103 case 0xbb:
3104 case 0xbc:
3105 case 0xbd:
3106 case 0xbe:
3107 case 0xbf:
3108 #ifdef MODE32
3109 state->Reg[14] = pc + 4; /* put PC into Link */
3110 #else
3111 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
3112 #endif
3113 state->Reg[15] = pc + 8 + NEGBRANCH;
3114 FLUSHPIPE;
3115 break;
3116
3117 /***************************************************************************\
3118 * Co-Processor Data Transfers *
3119 \***************************************************************************/
3120
3121 case 0xc4:
3122 if (state->is_XScale)
3123 {
3124 if (BITS (4, 7) != 0x00)
3125 ARMul_UndefInstr (state, instr);
3126
3127 if (BITS (8, 11) != 0x00)
3128 ARMul_UndefInstr (state, instr); /* Not CP0. */
3129
3130 /* XScale MAR insn. Move two registers into accumulator. */
3131 if (BITS (0, 3) == 0x00)
3132 {
3133 state->Accumulator = state->Reg[BITS (12, 15)];
3134 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3135 break;
3136 }
3137 /* Access to any other acc is unpredicatable. */
3138 break;
3139 }
3140 /* Drop through. */
3141
3142 case 0xc0: /* Store , No WriteBack , Post Dec */
3143 ARMul_STC (state, instr, LHS);
3144 break;
3145
3146 case 0xc5:
3147 if (state->is_XScale)
3148 {
3149 if (BITS (4, 7) != 0x00)
3150 ARMul_UndefInstr (state, instr);
3151
3152 if (BITS (8, 11) != 0x00)
3153 ARMul_UndefInstr (state, instr); /* Not CP0. */
3154
3155 /* XScale MRA insn. Move accumulator into two registers. */
3156 if (BITS (0, 3) == 0x00)
3157 {
3158 ARMword t1 = (state->Accumulator >> 32) & 255;
3159
3160 if (t1 & 128)
3161 t1 -= 256;
3162
3163 state->Reg[BITS (12, 15)] = state->Accumulator;
3164 state->Reg[BITS (16, 19)] = t1;
3165 break;
3166 }
3167 /* Access to any other acc is unpredicatable. */
3168 break;
3169 }
3170 /* Drop through. */
3171
3172 case 0xc1: /* Load , No WriteBack , Post Dec */
3173 ARMul_LDC (state, instr, LHS);
3174 break;
3175
3176 case 0xc2:
3177 case 0xc6: /* Store , WriteBack , Post Dec */
3178 lhs = LHS;
3179 state->Base = lhs - LSCOff;
3180 ARMul_STC (state, instr, lhs);
3181 break;
3182
3183 case 0xc3:
3184 case 0xc7: /* Load , WriteBack , Post Dec */
3185 lhs = LHS;
3186 state->Base = lhs - LSCOff;
3187 ARMul_LDC (state, instr, lhs);
3188 break;
3189
3190 case 0xc8:
3191 case 0xcc: /* Store , No WriteBack , Post Inc */
3192 ARMul_STC (state, instr, LHS);
3193 break;
3194
3195 case 0xc9:
3196 case 0xcd: /* Load , No WriteBack , Post Inc */
3197 ARMul_LDC (state, instr, LHS);
3198 break;
3199
3200 case 0xca:
3201 case 0xce: /* Store , WriteBack , Post Inc */
3202 lhs = LHS;
3203 state->Base = lhs + LSCOff;
3204 ARMul_STC (state, instr, LHS);
3205 break;
3206
3207 case 0xcb:
3208 case 0xcf: /* Load , WriteBack , Post Inc */
3209 lhs = LHS;
3210 state->Base = lhs + LSCOff;
3211 ARMul_LDC (state, instr, LHS);
3212 break;
3213
3214
3215 case 0xd0:
3216 case 0xd4: /* Store , No WriteBack , Pre Dec */
3217 ARMul_STC (state, instr, LHS - LSCOff);
3218 break;
3219
3220 case 0xd1:
3221 case 0xd5: /* Load , No WriteBack , Pre Dec */
3222 ARMul_LDC (state, instr, LHS - LSCOff);
3223 break;
3224
3225 case 0xd2:
3226 case 0xd6: /* Store , WriteBack , Pre Dec */
3227 lhs = LHS - LSCOff;
3228 state->Base = lhs;
3229 ARMul_STC (state, instr, lhs);
3230 break;
3231
3232 case 0xd3:
3233 case 0xd7: /* Load , WriteBack , Pre Dec */
3234 lhs = LHS - LSCOff;
3235 state->Base = lhs;
3236 ARMul_LDC (state, instr, lhs);
3237 break;
3238
3239 case 0xd8:
3240 case 0xdc: /* Store , No WriteBack , Pre Inc */
3241 ARMul_STC (state, instr, LHS + LSCOff);
3242 break;
3243
3244 case 0xd9:
3245 case 0xdd: /* Load , No WriteBack , Pre Inc */
3246 ARMul_LDC (state, instr, LHS + LSCOff);
3247 break;
3248
3249 case 0xda:
3250 case 0xde: /* Store , WriteBack , Pre Inc */
3251 lhs = LHS + LSCOff;
3252 state->Base = lhs;
3253 ARMul_STC (state, instr, lhs);
3254 break;
3255
3256 case 0xdb:
3257 case 0xdf: /* Load , WriteBack , Pre Inc */
3258 lhs = LHS + LSCOff;
3259 state->Base = lhs;
3260 ARMul_LDC (state, instr, lhs);
3261 break;
3262
3263 /***************************************************************************\
3264 * Co-Processor Register Transfers (MCR) and Data Ops *
3265 \***************************************************************************/
3266
3267 case 0xe2:
3268 if (state->is_XScale)
3269 switch (BITS (18, 19))
3270 {
3271 case 0x0:
3272 {
3273 /* XScale MIA instruction. Signed multiplication of two 32 bit
3274 values and addition to 40 bit accumulator. */
3275 long long Rm = state->Reg[MULLHSReg];
3276 long long Rs = state->Reg[MULACCReg];
3277
3278 if (Rm & (1 << 31))
3279 Rm -= 1ULL << 32;
3280 if (Rs & (1 << 31))
3281 Rs -= 1ULL << 32;
3282 state->Accumulator += Rm * Rs;
3283 }
3284 goto donext;
3285
3286 case 0x2:
3287 {
3288 /* XScale MIAPH instruction. */
3289 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3290 ARMword t2 = state->Reg[MULACCReg] >> 16;
3291 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3292 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3293 long long t5;
3294
3295 if (t1 & (1 << 15))
3296 t1 -= 1 << 16;
3297 if (t2 & (1 << 15))
3298 t2 -= 1 << 16;
3299 if (t3 & (1 << 15))
3300 t3 -= 1 << 16;
3301 if (t4 & (1 << 15))
3302 t4 -= 1 << 16;
3303 t1 *= t2;
3304 t5 = t1;
3305 if (t5 & (1 << 31))
3306 t5 -= 1ULL << 32;
3307 state->Accumulator += t5;
3308 t3 *= t4;
3309 t5 = t3;
3310 if (t5 & (1 << 31))
3311 t5 -= 1ULL << 32;
3312 state->Accumulator += t5;
3313 }
3314 goto donext;
3315
3316 case 0x3:
3317 {
3318 /* XScale MIAxy instruction. */
3319 ARMword t1;
3320 ARMword t2;
3321 long long t5;
3322
3323 if (BIT (17))
3324 t1 = state->Reg[MULLHSReg] >> 16;
3325 else
3326 t1 = state->Reg[MULLHSReg] & 0xffff;
3327
3328 if (BIT (16))
3329 t2 = state->Reg[MULACCReg] >> 16;
3330 else
3331 t2 = state->Reg[MULACCReg] & 0xffff;
3332
3333 if (t1 & (1 << 15))
3334 t1 -= 1 << 16;
3335 if (t2 & (1 << 15))
3336 t2 -= 1 << 16;
3337 t1 *= t2;
3338 t5 = t1;
3339 if (t5 & (1 << 31))
3340 t5 -= 1ULL << 32;
3341 state->Accumulator += t5;
3342 }
3343 goto donext;
3344
3345 default:
3346 break;
3347 }
3348 /* Drop through. */
3349
3350 case 0xe0:
3351 case 0xe4:
3352 case 0xe6:
3353 case 0xe8:
3354 case 0xea:
3355 case 0xec:
3356 case 0xee:
3357 if (BIT (4))
3358 { /* MCR */
3359 if (DESTReg == 15)
3360 {
3361 UNDEF_MCRPC;
3362 #ifdef MODE32
3363 ARMul_MCR (state, instr, state->Reg[15] + isize);
3364 #else
3365 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3366 ((state->Reg[15] + isize) & R15PCBITS));
3367 #endif
3368 }
3369 else
3370 ARMul_MCR (state, instr, DEST);
3371 }
3372 else /* CDP Part 1 */
3373 ARMul_CDP (state, instr);
3374 break;
3375
3376 /***************************************************************************\
3377 * Co-Processor Register Transfers (MRC) and Data Ops *
3378 \***************************************************************************/
3379
3380 case 0xe1:
3381 case 0xe3:
3382 case 0xe5:
3383 case 0xe7:
3384 case 0xe9:
3385 case 0xeb:
3386 case 0xed:
3387 case 0xef:
3388 if (BIT (4))
3389 { /* MRC */
3390 temp = ARMul_MRC (state, instr);
3391 if (DESTReg == 15)
3392 {
3393 ASSIGNN ((temp & NBIT) != 0);
3394 ASSIGNZ ((temp & ZBIT) != 0);
3395 ASSIGNC ((temp & CBIT) != 0);
3396 ASSIGNV ((temp & VBIT) != 0);
3397 }
3398 else
3399 DEST = temp;
3400 }
3401 else /* CDP Part 2 */
3402 ARMul_CDP (state, instr);
3403 break;
3404
3405 /***************************************************************************\
3406 * SWI instruction *
3407 \***************************************************************************/
3408
3409 case 0xf0:
3410 case 0xf1:
3411 case 0xf2:
3412 case 0xf3:
3413 case 0xf4:
3414 case 0xf5:
3415 case 0xf6:
3416 case 0xf7:
3417 case 0xf8:
3418 case 0xf9:
3419 case 0xfa:
3420 case 0xfb:
3421 case 0xfc:
3422 case 0xfd:
3423 case 0xfe:
3424 case 0xff:
3425 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3426 { /* a prefetch abort */
3427 ARMul_Abort (state, ARMul_PrefetchAbortV);
3428 break;
3429 }
3430
3431 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3432 {
3433 ARMul_Abort (state, ARMul_SWIV);
3434 }
3435 break;
3436 } /* 256 way main switch */
3437 } /* if temp */
3438
3439 #ifdef MODET
3440 donext:
3441 #endif
3442
3443 #ifdef NEED_UI_LOOP_HOOK
3444 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3445 {
3446 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3447 ui_loop_hook (0);
3448 }
3449 #endif /* NEED_UI_LOOP_HOOK */
3450
3451 if (state->Emulate == ONCE)
3452 state->Emulate = STOP;
3453 /* If we have changed mode, allow the PC to advance before stopping. */
3454 else if (state->Emulate == CHANGEMODE)
3455 continue;
3456 else if (state->Emulate != RUN)
3457 break;
3458 }
3459 while (!stop_simulator); /* do loop */
3460
3461 state->decoded = decoded;
3462 state->loaded = loaded;
3463 state->pc = pc;
3464
3465 return pc;
3466 } /* Emulate 26/32 in instruction based mode */
3467
3468
3469 /***************************************************************************\
3470 * This routine evaluates most Data Processing register RHS's with the S *
3471 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3472 * filters the common case of an unshifted register with in line code *
3473 \***************************************************************************/
3474
3475 static ARMword
3476 GetDPRegRHS (ARMul_State * state, ARMword instr)
3477 {
3478 ARMword shamt, base;
3479
3480 base = RHSReg;
3481 if (BIT (4))
3482 { /* shift amount in a register */
3483 UNDEF_Shift;
3484 INCPC;
3485 #ifndef MODE32
3486 if (base == 15)
3487 base = ECC | ER15INT | R15PC | EMODE;
3488 else
3489 #endif
3490 base = state->Reg[base];
3491 ARMul_Icycles (state, 1, 0L);
3492 shamt = state->Reg[BITS (8, 11)] & 0xff;
3493 switch ((int) BITS (5, 6))
3494 {
3495 case LSL:
3496 if (shamt == 0)
3497 return (base);
3498 else if (shamt >= 32)
3499 return (0);
3500 else
3501 return (base << shamt);
3502 case LSR:
3503 if (shamt == 0)
3504 return (base);
3505 else if (shamt >= 32)
3506 return (0);
3507 else
3508 return (base >> shamt);
3509 case ASR:
3510 if (shamt == 0)
3511 return (base);
3512 else if (shamt >= 32)
3513 return ((ARMword) ((long int) base >> 31L));
3514 else
3515 return ((ARMword) ((long int) base >> (int) shamt));
3516 case ROR:
3517 shamt &= 0x1f;
3518 if (shamt == 0)
3519 return (base);
3520 else
3521 return ((base << (32 - shamt)) | (base >> shamt));
3522 }
3523 }
3524 else
3525 { /* shift amount is a constant */
3526 #ifndef MODE32
3527 if (base == 15)
3528 base = ECC | ER15INT | R15PC | EMODE;
3529 else
3530 #endif
3531 base = state->Reg[base];
3532 shamt = BITS (7, 11);
3533 switch ((int) BITS (5, 6))
3534 {
3535 case LSL:
3536 return (base << shamt);
3537 case LSR:
3538 if (shamt == 0)
3539 return (0);
3540 else
3541 return (base >> shamt);
3542 case ASR:
3543 if (shamt == 0)
3544 return ((ARMword) ((long int) base >> 31L));
3545 else
3546 return ((ARMword) ((long int) base >> (int) shamt));
3547 case ROR:
3548 if (shamt == 0) /* its an RRX */
3549 return ((base >> 1) | (CFLAG << 31));
3550 else
3551 return ((base << (32 - shamt)) | (base >> shamt));
3552 }
3553 }
3554 return (0); /* just to shut up lint */
3555 }
3556
3557 /***************************************************************************\
3558 * This routine evaluates most Logical Data Processing register RHS's *
3559 * with the S bit set. It is intended to be called from the macro *
3560 * DPSRegRHS, which filters the common case of an unshifted register *
3561 * with in line code *
3562 \***************************************************************************/
3563
3564 static ARMword
3565 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3566 {
3567 ARMword shamt, base;
3568
3569 base = RHSReg;
3570 if (BIT (4))
3571 { /* shift amount in a register */
3572 UNDEF_Shift;
3573 INCPC;
3574 #ifndef MODE32
3575 if (base == 15)
3576 base = ECC | ER15INT | R15PC | EMODE;
3577 else
3578 #endif
3579 base = state->Reg[base];
3580 ARMul_Icycles (state, 1, 0L);
3581 shamt = state->Reg[BITS (8, 11)] & 0xff;
3582 switch ((int) BITS (5, 6))
3583 {
3584 case LSL:
3585 if (shamt == 0)
3586 return (base);
3587 else if (shamt == 32)
3588 {
3589 ASSIGNC (base & 1);
3590 return (0);
3591 }
3592 else if (shamt > 32)
3593 {
3594 CLEARC;
3595 return (0);
3596 }
3597 else
3598 {
3599 ASSIGNC ((base >> (32 - shamt)) & 1);
3600 return (base << shamt);
3601 }
3602 case LSR:
3603 if (shamt == 0)
3604 return (base);
3605 else if (shamt == 32)
3606 {
3607 ASSIGNC (base >> 31);
3608 return (0);
3609 }
3610 else if (shamt > 32)
3611 {
3612 CLEARC;
3613 return (0);
3614 }
3615 else
3616 {
3617 ASSIGNC ((base >> (shamt - 1)) & 1);
3618 return (base >> shamt);
3619 }
3620 case ASR:
3621 if (shamt == 0)
3622 return (base);
3623 else if (shamt >= 32)
3624 {
3625 ASSIGNC (base >> 31L);
3626 return ((ARMword) ((long int) base >> 31L));
3627 }
3628 else
3629 {
3630 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3631 return ((ARMword) ((long int) base >> (int) shamt));
3632 }
3633 case ROR:
3634 if (shamt == 0)
3635 return (base);
3636 shamt &= 0x1f;
3637 if (shamt == 0)
3638 {
3639 ASSIGNC (base >> 31);
3640 return (base);
3641 }
3642 else
3643 {
3644 ASSIGNC ((base >> (shamt - 1)) & 1);
3645 return ((base << (32 - shamt)) | (base >> shamt));
3646 }
3647 }
3648 }
3649 else
3650 { /* shift amount is a constant */
3651 #ifndef MODE32
3652 if (base == 15)
3653 base = ECC | ER15INT | R15PC | EMODE;
3654 else
3655 #endif
3656 base = state->Reg[base];
3657 shamt = BITS (7, 11);
3658 switch ((int) BITS (5, 6))
3659 {
3660 case LSL:
3661 ASSIGNC ((base >> (32 - shamt)) & 1);
3662 return (base << shamt);
3663 case LSR:
3664 if (shamt == 0)
3665 {
3666 ASSIGNC (base >> 31);
3667 return (0);
3668 }
3669 else
3670 {
3671 ASSIGNC ((base >> (shamt - 1)) & 1);
3672 return (base >> shamt);
3673 }
3674 case ASR:
3675 if (shamt == 0)
3676 {
3677 ASSIGNC (base >> 31L);
3678 return ((ARMword) ((long int) base >> 31L));
3679 }
3680 else
3681 {
3682 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3683 return ((ARMword) ((long int) base >> (int) shamt));
3684 }
3685 case ROR:
3686 if (shamt == 0)
3687 { /* its an RRX */
3688 shamt = CFLAG;
3689 ASSIGNC (base & 1);
3690 return ((base >> 1) | (shamt << 31));
3691 }
3692 else
3693 {
3694 ASSIGNC ((base >> (shamt - 1)) & 1);
3695 return ((base << (32 - shamt)) | (base >> shamt));
3696 }
3697 }
3698 }
3699 return (0); /* just to shut up lint */
3700 }
3701
3702 /***************************************************************************\
3703 * This routine handles writes to register 15 when the S bit is not set. *
3704 \***************************************************************************/
3705
3706 static void
3707 WriteR15 (ARMul_State * state, ARMword src)
3708 {
3709 /* The ARM documentation states that the two least significant bits
3710 are discarded when setting PC, except in the cases handled by
3711 WriteR15Branch() below. It's probably an oversight: in THUMB
3712 mode, the second least significant bit should probably not be
3713 discarded. */
3714 #ifdef MODET
3715 if (TFLAG)
3716 src &= 0xfffffffe;
3717 else
3718 #endif
3719 src &= 0xfffffffc;
3720 #ifdef MODE32
3721 state->Reg[15] = src & PCBITS;
3722 #else
3723 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3724 ARMul_R15Altered (state);
3725 #endif
3726 FLUSHPIPE;
3727 }
3728
3729 /***************************************************************************\
3730 * This routine handles writes to register 15 when the S bit is set. *
3731 \***************************************************************************/
3732
3733 static void
3734 WriteSR15 (ARMul_State * state, ARMword src)
3735 {
3736 #ifdef MODE32
3737 if (state->Bank > 0)
3738 {
3739 state->Cpsr = state->Spsr[state->Bank];
3740 ARMul_CPSRAltered (state);
3741 }
3742 #ifdef MODET
3743 if (TFLAG)
3744 src &= 0xfffffffe;
3745 else
3746 #endif
3747 src &= 0xfffffffc;
3748 state->Reg[15] = src & PCBITS;
3749 #else
3750 #ifdef MODET
3751 if (TFLAG)
3752 abort (); /* ARMul_R15Altered would have to support it. */
3753 else
3754 #endif
3755 src &= 0xfffffffc;
3756 if (state->Bank == USERBANK)
3757 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3758 else
3759 state->Reg[15] = src;
3760 ARMul_R15Altered (state);
3761 #endif
3762 FLUSHPIPE;
3763 }
3764
3765 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3766 will switch to Thumb mode if the least significant bit is set. */
3767
3768 static void
3769 WriteR15Branch (ARMul_State * state, ARMword src)
3770 {
3771 #ifdef MODET
3772 if (src & 1)
3773 { /* Thumb bit */
3774 SETT;
3775 state->Reg[15] = src & 0xfffffffe;
3776 }
3777 else
3778 {
3779 CLEART;
3780 state->Reg[15] = src & 0xfffffffc;
3781 }
3782 FLUSHPIPE;
3783 #else
3784 WriteR15 (state, src);
3785 #endif
3786 }
3787
3788 /***************************************************************************\
3789 * This routine evaluates most Load and Store register RHS's. It is *
3790 * intended to be called from the macro LSRegRHS, which filters the *
3791 * common case of an unshifted register with in line code *
3792 \***************************************************************************/
3793
3794 static ARMword
3795 GetLSRegRHS (ARMul_State * state, ARMword instr)
3796 {
3797 ARMword shamt, base;
3798
3799 base = RHSReg;
3800 #ifndef MODE32
3801 if (base == 15)
3802 base = ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but .... */
3803 else
3804 #endif
3805 base = state->Reg[base];
3806
3807 shamt = BITS (7, 11);
3808 switch ((int) BITS (5, 6))
3809 {
3810 case LSL:
3811 return (base << shamt);
3812 case LSR:
3813 if (shamt == 0)
3814 return (0);
3815 else
3816 return (base >> shamt);
3817 case ASR:
3818 if (shamt == 0)
3819 return ((ARMword) ((long int) base >> 31L));
3820 else
3821 return ((ARMword) ((long int) base >> (int) shamt));
3822 case ROR:
3823 if (shamt == 0) /* its an RRX */
3824 return ((base >> 1) | (CFLAG << 31));
3825 else
3826 return ((base << (32 - shamt)) | (base >> shamt));
3827 }
3828 return (0); /* just to shut up lint */
3829 }
3830
3831 /***************************************************************************\
3832 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3833 \***************************************************************************/
3834
3835 static ARMword
3836 GetLS7RHS (ARMul_State * state, ARMword instr)
3837 {
3838 if (BIT (22) == 0)
3839 { /* register */
3840 #ifndef MODE32
3841 if (RHSReg == 15)
3842 return ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but ... */
3843 #endif
3844 return state->Reg[RHSReg];
3845 }
3846
3847 /* else immediate */
3848 return BITS (0, 3) | (BITS (8, 11) << 4);
3849 }
3850
3851 /***************************************************************************\
3852 * This function does the work of loading a word for a LDR instruction. *
3853 \***************************************************************************/
3854
3855 static unsigned
3856 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3857 {
3858 ARMword dest;
3859
3860 BUSUSEDINCPCS;
3861 #ifndef MODE32
3862 if (ADDREXCEPT (address))
3863 {
3864 INTERNALABORT (address);
3865 }
3866 #endif
3867 dest = ARMul_LoadWordN (state, address);
3868 if (state->Aborted)
3869 {
3870 TAKEABORT;
3871 return (state->lateabtSig);
3872 }
3873 if (address & 3)
3874 dest = ARMul_Align (state, address, dest);
3875 WRITEDESTB (dest);
3876 ARMul_Icycles (state, 1, 0L);
3877
3878 return (DESTReg != LHSReg);
3879 }
3880
3881 #ifdef MODET
3882 /***************************************************************************\
3883 * This function does the work of loading a halfword. *
3884 \***************************************************************************/
3885
3886 static unsigned
3887 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3888 int signextend)
3889 {
3890 ARMword dest;
3891
3892 BUSUSEDINCPCS;
3893 #ifndef MODE32
3894 if (ADDREXCEPT (address))
3895 {
3896 INTERNALABORT (address);
3897 }
3898 #endif
3899 dest = ARMul_LoadHalfWord (state, address);
3900 if (state->Aborted)
3901 {
3902 TAKEABORT;
3903 return (state->lateabtSig);
3904 }
3905 UNDEF_LSRBPC;
3906 if (signextend)
3907 {
3908 if (dest & 1 << (16 - 1))
3909 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
3910 }
3911 WRITEDEST (dest);
3912 ARMul_Icycles (state, 1, 0L);
3913 return (DESTReg != LHSReg);
3914 }
3915
3916 #endif /* MODET */
3917
3918 /***************************************************************************\
3919 * This function does the work of loading a byte for a LDRB instruction. *
3920 \***************************************************************************/
3921
3922 static unsigned
3923 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
3924 {
3925 ARMword dest;
3926
3927 BUSUSEDINCPCS;
3928 #ifndef MODE32
3929 if (ADDREXCEPT (address))
3930 {
3931 INTERNALABORT (address);
3932 }
3933 #endif
3934 dest = ARMul_LoadByte (state, address);
3935 if (state->Aborted)
3936 {
3937 TAKEABORT;
3938 return (state->lateabtSig);
3939 }
3940 UNDEF_LSRBPC;
3941 if (signextend)
3942 {
3943 if (dest & 1 << (8 - 1))
3944 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
3945 }
3946 WRITEDEST (dest);
3947 ARMul_Icycles (state, 1, 0L);
3948 return (DESTReg != LHSReg);
3949 }
3950
3951 /***************************************************************************\
3952 * This function does the work of loading two words for a LDRD instruction. *
3953 \***************************************************************************/
3954
3955 static void
3956 Handle_Load_Double (ARMul_State * state, ARMword instr)
3957 {
3958 ARMword dest_reg;
3959 ARMword addr_reg;
3960 ARMword write_back = BIT (21);
3961 ARMword immediate = BIT (22);
3962 ARMword add_to_base = BIT (23);
3963 ARMword pre_indexed = BIT (24);
3964 ARMword offset;
3965 ARMword addr;
3966 ARMword sum;
3967 ARMword base;
3968 ARMword value1;
3969 ARMword value2;
3970
3971 BUSUSEDINCPCS;
3972
3973 /* If the writeback bit is set, the pre-index bit must be clear. */
3974 if (write_back && ! pre_indexed)
3975 {
3976 ARMul_UndefInstr (state, instr);
3977 return;
3978 }
3979
3980 /* Extract the base address register. */
3981 addr_reg = LHSReg;
3982
3983 /* Extract the destination register and check it. */
3984 dest_reg = DESTReg;
3985
3986 /* Destination register must be even. */
3987 if ((dest_reg & 1)
3988 /* Destination register cannot be LR. */
3989 || (dest_reg == 14))
3990 {
3991 ARMul_UndefInstr (state, instr);
3992 return;
3993 }
3994
3995 /* Compute the base address. */
3996 base = state->Reg[addr_reg];
3997
3998 /* Compute the offset. */
3999 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4000
4001 /* Compute the sum of the two. */
4002 if (add_to_base)
4003 sum = base + offset;
4004 else
4005 sum = base - offset;
4006
4007 /* If this is a pre-indexed mode use the sum. */
4008 if (pre_indexed)
4009 addr = sum;
4010 else
4011 addr = base;
4012
4013 /* The address must be aligned on a 8 byte boundary. */
4014 if (addr & 0x7)
4015 {
4016 #ifdef ABORTS
4017 ARMul_DATAABORT (addr);
4018 #else
4019 ARMul_UndefInstr (state, instr);
4020 #endif
4021 return;
4022 }
4023
4024 /* For pre indexed or post indexed addressing modes,
4025 check that the destination registers do not overlap
4026 the address registers. */
4027 if ((! pre_indexed || write_back)
4028 && ( addr_reg == dest_reg
4029 || addr_reg == dest_reg + 1))
4030 {
4031 ARMul_UndefInstr (state, instr);
4032 return;
4033 }
4034
4035 /* Load the words. */
4036 value1 = ARMul_LoadWordN (state, addr);
4037 value2 = ARMul_LoadWordN (state, addr + 4);
4038
4039 /* Check for data aborts. */
4040 if (state->Aborted)
4041 {
4042 TAKEABORT;
4043 return;
4044 }
4045
4046 ARMul_Icycles (state, 2, 0L);
4047
4048 /* Store the values. */
4049 state->Reg[dest_reg] = value1;
4050 state->Reg[dest_reg + 1] = value2;
4051
4052 /* Do the post addressing and writeback. */
4053 if (! pre_indexed)
4054 addr = sum;
4055
4056 if (! pre_indexed || write_back)
4057 state->Reg[addr_reg] = addr;
4058 }
4059
4060 /***************************************************************************\
4061 * This function does the work of storing two words for a STRD instruction. *
4062 \***************************************************************************/
4063
4064 static void
4065 Handle_Store_Double (ARMul_State * state, ARMword instr)
4066 {
4067 ARMword src_reg;
4068 ARMword addr_reg;
4069 ARMword write_back = BIT (21);
4070 ARMword immediate = BIT (22);
4071 ARMword add_to_base = BIT (23);
4072 ARMword pre_indexed = BIT (24);
4073 ARMword offset;
4074 ARMword addr;
4075 ARMword sum;
4076 ARMword base;
4077
4078 BUSUSEDINCPCS;
4079
4080 /* If the writeback bit is set, the pre-index bit must be clear. */
4081 if (write_back && ! pre_indexed)
4082 {
4083 ARMul_UndefInstr (state, instr);
4084 return;
4085 }
4086
4087 /* Extract the base address register. */
4088 addr_reg = LHSReg;
4089
4090 /* Base register cannot be PC. */
4091 if (addr_reg == 15)
4092 {
4093 ARMul_UndefInstr (state, instr);
4094 return;
4095 }
4096
4097 /* Extract the source register. */
4098 src_reg = DESTReg;
4099
4100 /* Source register must be even. */
4101 if (src_reg & 1)
4102 {
4103 ARMul_UndefInstr (state, instr);
4104 return;
4105 }
4106
4107 /* Compute the base address. */
4108 base = state->Reg[addr_reg];
4109
4110 /* Compute the offset. */
4111 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4112
4113 /* Compute the sum of the two. */
4114 if (add_to_base)
4115 sum = base + offset;
4116 else
4117 sum = base - offset;
4118
4119 /* If this is a pre-indexed mode use the sum. */
4120 if (pre_indexed)
4121 addr = sum;
4122 else
4123 addr = base;
4124
4125 /* The address must be aligned on a 8 byte boundary. */
4126 if (addr & 0x7)
4127 {
4128 #ifdef ABORTS
4129 ARMul_DATAABORT (addr);
4130 #else
4131 ARMul_UndefInstr (state, instr);
4132 #endif
4133 return;
4134 }
4135
4136 /* For pre indexed or post indexed addressing modes,
4137 check that the destination registers do not overlap
4138 the address registers. */
4139 if ((! pre_indexed || write_back)
4140 && ( addr_reg == src_reg
4141 || addr_reg == src_reg + 1))
4142 {
4143 ARMul_UndefInstr (state, instr);
4144 return;
4145 }
4146
4147 /* Load the words. */
4148 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4149 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4150
4151 if (state->Aborted)
4152 {
4153 TAKEABORT;
4154 return;
4155 }
4156
4157 /* Do the post addressing and writeback. */
4158 if (! pre_indexed)
4159 addr = sum;
4160
4161 if (! pre_indexed || write_back)
4162 state->Reg[addr_reg] = addr;
4163 }
4164
4165 /***************************************************************************\
4166 * This function does the work of storing a word from a STR instruction. *
4167 \***************************************************************************/
4168
4169 static unsigned
4170 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4171 {
4172 BUSUSEDINCPCN;
4173 #ifndef MODE32
4174 if (DESTReg == 15)
4175 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4176 #endif
4177 #ifdef MODE32
4178 ARMul_StoreWordN (state, address, DEST);
4179 #else
4180 if (VECTORACCESS (address) || ADDREXCEPT (address))
4181 {
4182 INTERNALABORT (address);
4183 (void) ARMul_LoadWordN (state, address);
4184 }
4185 else
4186 ARMul_StoreWordN (state, address, DEST);
4187 #endif
4188 if (state->Aborted)
4189 {
4190 TAKEABORT;
4191 return (state->lateabtSig);
4192 }
4193 return (TRUE);
4194 }
4195
4196 #ifdef MODET
4197 /***************************************************************************\
4198 * This function does the work of storing a byte for a STRH instruction. *
4199 \***************************************************************************/
4200
4201 static unsigned
4202 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4203 {
4204 BUSUSEDINCPCN;
4205
4206 #ifndef MODE32
4207 if (DESTReg == 15)
4208 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4209 #endif
4210
4211 #ifdef MODE32
4212 ARMul_StoreHalfWord (state, address, DEST);
4213 #else
4214 if (VECTORACCESS (address) || ADDREXCEPT (address))
4215 {
4216 INTERNALABORT (address);
4217 (void) ARMul_LoadHalfWord (state, address);
4218 }
4219 else
4220 ARMul_StoreHalfWord (state, address, DEST);
4221 #endif
4222
4223 if (state->Aborted)
4224 {
4225 TAKEABORT;
4226 return (state->lateabtSig);
4227 }
4228
4229 return (TRUE);
4230 }
4231
4232 #endif /* MODET */
4233
4234 /***************************************************************************\
4235 * This function does the work of storing a byte for a STRB instruction. *
4236 \***************************************************************************/
4237
4238 static unsigned
4239 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4240 {
4241 BUSUSEDINCPCN;
4242 #ifndef MODE32
4243 if (DESTReg == 15)
4244 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4245 #endif
4246 #ifdef MODE32
4247 ARMul_StoreByte (state, address, DEST);
4248 #else
4249 if (VECTORACCESS (address) || ADDREXCEPT (address))
4250 {
4251 INTERNALABORT (address);
4252 (void) ARMul_LoadByte (state, address);
4253 }
4254 else
4255 ARMul_StoreByte (state, address, DEST);
4256 #endif
4257 if (state->Aborted)
4258 {
4259 TAKEABORT;
4260 return (state->lateabtSig);
4261 }
4262 UNDEF_LSRBPC;
4263 return (TRUE);
4264 }
4265
4266 /***************************************************************************\
4267 * This function does the work of loading the registers listed in an LDM *
4268 * instruction, when the S bit is clear. The code here is always increment *
4269 * after, it's up to the caller to get the input address correct and to *
4270 * handle base register modification. *
4271 \***************************************************************************/
4272
4273 static void
4274 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4275 {
4276 ARMword dest, temp;
4277
4278 UNDEF_LSMNoRegs;
4279 UNDEF_LSMPCBase;
4280 UNDEF_LSMBaseInListWb;
4281 BUSUSEDINCPCS;
4282 #ifndef MODE32
4283 if (ADDREXCEPT (address))
4284 {
4285 INTERNALABORT (address);
4286 }
4287 #endif
4288 if (BIT (21) && LHSReg != 15)
4289 LSBase = WBBase;
4290
4291 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
4292 dest = ARMul_LoadWordN (state, address);
4293 if (!state->abortSig && !state->Aborted)
4294 state->Reg[temp++] = dest;
4295 else if (!state->Aborted)
4296 state->Aborted = ARMul_DataAbortV;
4297
4298 for (; temp < 16; temp++) /* S cycles from here on */
4299 if (BIT (temp))
4300 { /* load this register */
4301 address += 4;
4302 dest = ARMul_LoadWordS (state, address);
4303 if (!state->abortSig && !state->Aborted)
4304 state->Reg[temp] = dest;
4305 else if (!state->Aborted)
4306 state->Aborted = ARMul_DataAbortV;
4307 }
4308
4309 if (BIT (15) && !state->Aborted)
4310 { /* PC is in the reg list */
4311 WriteR15Branch(state, PC);
4312 }
4313
4314 ARMul_Icycles (state, 1, 0L); /* to write back the final register */
4315
4316 if (state->Aborted)
4317 {
4318 if (BIT (21) && LHSReg != 15)
4319 LSBase = WBBase;
4320 TAKEABORT;
4321 }
4322 }
4323
4324 /***************************************************************************\
4325 * This function does the work of loading the registers listed in an LDM *
4326 * instruction, when the S bit is set. The code here is always increment *
4327 * after, it's up to the caller to get the input address correct and to *
4328 * handle base register modification. *
4329 \***************************************************************************/
4330
4331 static void
4332 LoadSMult (ARMul_State * state, ARMword instr,
4333 ARMword address, ARMword WBBase)
4334 {
4335 ARMword dest, temp;
4336
4337 UNDEF_LSMNoRegs;
4338 UNDEF_LSMPCBase;
4339 UNDEF_LSMBaseInListWb;
4340
4341 BUSUSEDINCPCS;
4342
4343 #ifndef MODE32
4344 if (ADDREXCEPT (address))
4345 {
4346 INTERNALABORT (address);
4347 }
4348 #endif
4349
4350 if (BIT (21) && LHSReg != 15)
4351 LSBase = WBBase;
4352
4353 if (!BIT (15) && state->Bank != USERBANK)
4354 {
4355 /* Temporary reg bank switch. */
4356 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4357 UNDEF_LSMUserBankWb;
4358 }
4359
4360 for (temp = 0; !BIT (temp); temp ++)
4361 ; /* N cycle first. */
4362
4363 dest = ARMul_LoadWordN (state, address);
4364
4365 if (!state->abortSig)
4366 state->Reg[temp++] = dest;
4367 else if (!state->Aborted)
4368 state->Aborted = ARMul_DataAbortV;
4369
4370 for (; temp < 16; temp++)
4371 /* S cycles from here on. */
4372 if (BIT (temp))
4373 {
4374 /* Load this register. */
4375 address += 4;
4376 dest = ARMul_LoadWordS (state, address);
4377
4378 if (!state->abortSig && !state->Aborted)
4379 state->Reg[temp] = dest;
4380 else if (!state->Aborted)
4381 state->Aborted = ARMul_DataAbortV;
4382 }
4383
4384 if (BIT (15) && !state->Aborted)
4385 {
4386 /* PC is in the reg list. */
4387 #ifdef MODE32
4388 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4389 {
4390 state->Cpsr = GETSPSR (state->Bank);
4391 ARMul_CPSRAltered (state);
4392 }
4393
4394 WriteR15 (state, PC);
4395 #else
4396 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4397 {
4398 /* Protect bits in user mode. */
4399 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4400 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4401 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4402 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4403 }
4404 else
4405 ARMul_R15Altered (state);
4406 FLUSHPIPE;
4407 #endif
4408 }
4409
4410 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4411 /* Restore the correct bank. */
4412 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4413
4414 /* To write back the final register. */
4415 ARMul_Icycles (state, 1, 0L);
4416
4417 if (state->Aborted)
4418 {
4419 if (BIT (21) && LHSReg != 15)
4420 LSBase = WBBase;
4421 TAKEABORT;
4422 }
4423 }
4424
4425 /***************************************************************************\
4426 * This function does the work of storing the registers listed in an STM *
4427 * instruction, when the S bit is clear. The code here is always increment *
4428 * after, it's up to the caller to get the input address correct and to *
4429 * handle base register modification. *
4430 \***************************************************************************/
4431
4432 static void
4433 StoreMult (ARMul_State * state, ARMword instr,
4434 ARMword address, ARMword WBBase)
4435 {
4436 ARMword temp;
4437
4438 UNDEF_LSMNoRegs;
4439 UNDEF_LSMPCBase;
4440 UNDEF_LSMBaseInListWb;
4441 if (!TFLAG)
4442 {
4443 BUSUSEDINCPCN; /* N-cycle, increment the PC and update the NextInstr state */
4444 }
4445
4446 #ifndef MODE32
4447 if (VECTORACCESS (address) || ADDREXCEPT (address))
4448 {
4449 INTERNALABORT (address);
4450 }
4451 if (BIT (15))
4452 PATCHR15;
4453 #endif
4454
4455 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
4456 #ifdef MODE32
4457 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4458 #else
4459 if (state->Aborted)
4460 {
4461 (void) ARMul_LoadWordN (state, address);
4462 for (; temp < 16; temp++) /* Fake the Stores as Loads */
4463 if (BIT (temp))
4464 { /* save this register */
4465 address += 4;
4466 (void) ARMul_LoadWordS (state, address);
4467 }
4468 if (BIT (21) && LHSReg != 15)
4469 LSBase = WBBase;
4470 TAKEABORT;
4471 return;
4472 }
4473 else
4474 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4475 #endif
4476 if (state->abortSig && !state->Aborted)
4477 state->Aborted = ARMul_DataAbortV;
4478
4479 if (BIT (21) && LHSReg != 15)
4480 LSBase = WBBase;
4481
4482 for (; temp < 16; temp++) /* S cycles from here on */
4483 if (BIT (temp))
4484 { /* save this register */
4485 address += 4;
4486 ARMul_StoreWordS (state, address, state->Reg[temp]);
4487 if (state->abortSig && !state->Aborted)
4488 state->Aborted = ARMul_DataAbortV;
4489 }
4490 if (state->Aborted)
4491 {
4492 TAKEABORT;
4493 }
4494 }
4495
4496 /***************************************************************************\
4497 * This function does the work of storing the registers listed in an STM *
4498 * instruction when the S bit is set. The code here is always increment *
4499 * after, it's up to the caller to get the input address correct and to *
4500 * handle base register modification. *
4501 \***************************************************************************/
4502
4503 static void
4504 StoreSMult (
4505 ARMul_State * state,
4506 ARMword instr,
4507 ARMword address,
4508 ARMword WBBase)
4509 {
4510 ARMword temp;
4511
4512 UNDEF_LSMNoRegs;
4513 UNDEF_LSMPCBase;
4514 UNDEF_LSMBaseInListWb;
4515
4516 BUSUSEDINCPCN;
4517
4518 #ifndef MODE32
4519 if (VECTORACCESS (address) || ADDREXCEPT (address))
4520 {
4521 INTERNALABORT (address);
4522 }
4523
4524 if (BIT (15))
4525 PATCHR15;
4526 #endif
4527
4528 if (state->Bank != USERBANK)
4529 {
4530 /* Force User Bank. */
4531 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4532 UNDEF_LSMUserBankWb;
4533 }
4534
4535 for (temp = 0; !BIT (temp); temp++)
4536 ; /* N cycle first. */
4537
4538 #ifdef MODE32
4539 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4540 #else
4541 if (state->Aborted)
4542 {
4543 (void) ARMul_LoadWordN (state, address);
4544
4545 for (; temp < 16; temp++)
4546 /* Fake the Stores as Loads. */
4547 if (BIT (temp))
4548 {
4549 /* Save this register. */
4550 address += 4;
4551 (void) ARMul_LoadWordS (state, address);
4552 }
4553
4554 if (BIT (21) && LHSReg != 15)
4555 LSBase = WBBase;
4556
4557 TAKEABORT;
4558
4559 return;
4560 }
4561 else
4562 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4563 #endif
4564
4565 if (state->abortSig && !state->Aborted)
4566 state->Aborted = ARMul_DataAbortV;
4567
4568 for (; temp < 16; temp++)
4569 /* S cycles from here on. */
4570 if (BIT (temp))
4571 {
4572 /* Save this register. */
4573 address += 4;
4574
4575 ARMul_StoreWordS (state, address, state->Reg[temp]);
4576
4577 if (state->abortSig && !state->Aborted)
4578 state->Aborted = ARMul_DataAbortV;
4579 }
4580
4581 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4582 /* Restore the correct bank. */
4583 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4584
4585 if (BIT (21) && LHSReg != 15)
4586 LSBase = WBBase;
4587
4588 if (state->Aborted)
4589 {
4590 TAKEABORT;
4591 }
4592 }
4593
4594 /***************************************************************************\
4595 * This function does the work of adding two 32bit values together, and *
4596 * calculating if a carry has occurred. *
4597 \***************************************************************************/
4598
4599 static ARMword
4600 Add32 (ARMword a1, ARMword a2, int *carry)
4601 {
4602 ARMword result = (a1 + a2);
4603 unsigned int uresult = (unsigned int) result;
4604 unsigned int ua1 = (unsigned int) a1;
4605
4606 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4607 or (result > RdLo) then we have no carry: */
4608 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4609 *carry = 1;
4610 else
4611 *carry = 0;
4612
4613 return (result);
4614 }
4615
4616 /***************************************************************************\
4617 * This function does the work of multiplying two 32bit values to give a *
4618 * 64bit result. *
4619 \***************************************************************************/
4620
4621 static unsigned
4622 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4623 {
4624 int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */
4625 ARMword RdHi = 0, RdLo = 0, Rm;
4626 int scount; /* cycle count */
4627
4628 nRdHi = BITS (16, 19);
4629 nRdLo = BITS (12, 15);
4630 nRs = BITS (8, 11);
4631 nRm = BITS (0, 3);
4632
4633 /* Needed to calculate the cycle count: */
4634 Rm = state->Reg[nRm];
4635
4636 /* Check for illegal operand combinations first: */
4637 if (nRdHi != 15
4638 && nRdLo != 15
4639 && nRs != 15
4640 && nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm)
4641 {
4642 ARMword lo, mid1, mid2, hi; /* intermediate results */
4643 int carry;
4644 ARMword Rs = state->Reg[nRs];
4645 int sign = 0;
4646
4647 if (msigned)
4648 {
4649 /* Compute sign of result and adjust operands if necessary. */
4650
4651 sign = (Rm ^ Rs) & 0x80000000;
4652
4653 if (((signed long) Rm) < 0)
4654 Rm = -Rm;
4655
4656 if (((signed long) Rs) < 0)
4657 Rs = -Rs;
4658 }
4659
4660 /* We can split the 32x32 into four 16x16 operations. This ensures
4661 that we do not lose precision on 32bit only hosts: */
4662 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4663 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4664 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4665 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4666
4667 /* We now need to add all of these results together, taking care
4668 to propogate the carries from the additions: */
4669 RdLo = Add32 (lo, (mid1 << 16), &carry);
4670 RdHi = carry;
4671 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4672 RdHi +=
4673 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
4674
4675 if (sign)
4676 {
4677 /* Negate result if necessary. */
4678
4679 RdLo = ~RdLo;
4680 RdHi = ~RdHi;
4681 if (RdLo == 0xFFFFFFFF)
4682 {
4683 RdLo = 0;
4684 RdHi += 1;
4685 }
4686 else
4687 RdLo += 1;
4688 }
4689
4690 state->Reg[nRdLo] = RdLo;
4691 state->Reg[nRdHi] = RdHi;
4692 } /* else undefined result */
4693 else
4694 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4695
4696 if (scc)
4697 {
4698 /* Ensure that both RdHi and RdLo are used to compute Z, but
4699 don't let RdLo's sign bit make it to N. */
4700 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4701 }
4702
4703 /* The cycle count depends on whether the instruction is a signed or
4704 unsigned multiply, and what bits are clear in the multiplier: */
4705 if (msigned && (Rm & ((unsigned) 1 << 31)))
4706 Rm = ~Rm; /* invert the bits to make the check against zero */
4707
4708 if ((Rm & 0xFFFFFF00) == 0)
4709 scount = 1;
4710 else if ((Rm & 0xFFFF0000) == 0)
4711 scount = 2;
4712 else if ((Rm & 0xFF000000) == 0)
4713 scount = 3;
4714 else
4715 scount = 4;
4716
4717 return 2 + scount;
4718 }
4719
4720 /***************************************************************************\
4721 * This function does the work of multiplying two 32bit values and adding *
4722 * a 64bit value to give a 64bit result. *
4723 \***************************************************************************/
4724
4725 static unsigned
4726 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4727 {
4728 unsigned scount;
4729 ARMword RdLo, RdHi;
4730 int nRdHi, nRdLo;
4731 int carry = 0;
4732
4733 nRdHi = BITS (16, 19);
4734 nRdLo = BITS (12, 15);
4735
4736 RdHi = state->Reg[nRdHi];
4737 RdLo = state->Reg[nRdLo];
4738
4739 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4740
4741 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4742 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4743
4744 state->Reg[nRdLo] = RdLo;
4745 state->Reg[nRdHi] = RdHi;
4746
4747 if (scc)
4748 {
4749 /* Ensure that both RdHi and RdLo are used to compute Z, but
4750 don't let RdLo's sign bit make it to N. */
4751 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4752 }
4753
4754 return scount + 1; /* extra cycle for addition */
4755 }
This page took 0.220547 seconds and 5 git commands to generate.