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