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