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