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