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