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