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