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