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