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