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