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