]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/armemu.c
* armemu.h (PSR_FBITS, PSR_SBITS, PSR_XBITS, PSR_CBITS): New.
[thirdparty/binutils-gdb.git] / sim / arm / armemu.c
1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #include "armdefs.h"
20 #include "armemu.h"
21 #include "armos.h"
22
23 static ARMword GetDPRegRHS (ARMul_State * state, ARMword instr);
24 static ARMword GetDPSRegRHS (ARMul_State * state, ARMword instr);
25 static void WriteR15 (ARMul_State * state, ARMword src);
26 static void WriteSR15 (ARMul_State * state, ARMword src);
27 static 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)
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)
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)
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) /* 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 temp = lhs - LSRegRHS;
2002 if (LoadWord (state, instr, lhs))
2003 LSBase = temp;
2004 break;
2005
2006 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2007 if (BIT (4))
2008 {
2009 ARMul_UndefInstr (state, instr);
2010 break;
2011 }
2012 UNDEF_LSRBaseEQOffWb;
2013 UNDEF_LSRBaseEQDestWb;
2014 UNDEF_LSRPCBaseWb;
2015 UNDEF_LSRPCOffWb;
2016 lhs = LHS;
2017 state->NtransSig = LOW;
2018 if (StoreWord (state, instr, lhs))
2019 LSBase = lhs - LSRegRHS;
2020 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2021 break;
2022
2023 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2024 if (BIT (4))
2025 {
2026 ARMul_UndefInstr (state, instr);
2027 break;
2028 }
2029 UNDEF_LSRBaseEQOffWb;
2030 UNDEF_LSRBaseEQDestWb;
2031 UNDEF_LSRPCBaseWb;
2032 UNDEF_LSRPCOffWb;
2033 lhs = LHS;
2034 temp = lhs - LSRegRHS;
2035 state->NtransSig = LOW;
2036 if (LoadWord (state, instr, lhs))
2037 LSBase = temp;
2038 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2039 break;
2040
2041 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2042 if (BIT (4))
2043 {
2044 ARMul_UndefInstr (state, instr);
2045 break;
2046 }
2047 UNDEF_LSRBaseEQOffWb;
2048 UNDEF_LSRBaseEQDestWb;
2049 UNDEF_LSRPCBaseWb;
2050 UNDEF_LSRPCOffWb;
2051 lhs = LHS;
2052 if (StoreByte (state, instr, lhs))
2053 LSBase = lhs - LSRegRHS;
2054 break;
2055
2056 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2057 if (BIT (4))
2058 {
2059 ARMul_UndefInstr (state, instr);
2060 break;
2061 }
2062 UNDEF_LSRBaseEQOffWb;
2063 UNDEF_LSRBaseEQDestWb;
2064 UNDEF_LSRPCBaseWb;
2065 UNDEF_LSRPCOffWb;
2066 lhs = LHS;
2067 temp = lhs - LSRegRHS;
2068 if (LoadByte (state, instr, lhs, LUNSIGNED))
2069 LSBase = temp;
2070 break;
2071
2072 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2073 if (BIT (4))
2074 {
2075 ARMul_UndefInstr (state, instr);
2076 break;
2077 }
2078 UNDEF_LSRBaseEQOffWb;
2079 UNDEF_LSRBaseEQDestWb;
2080 UNDEF_LSRPCBaseWb;
2081 UNDEF_LSRPCOffWb;
2082 lhs = LHS;
2083 state->NtransSig = LOW;
2084 if (StoreByte (state, instr, lhs))
2085 LSBase = lhs - LSRegRHS;
2086 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2087 break;
2088
2089 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2090 if (BIT (4))
2091 {
2092 ARMul_UndefInstr (state, instr);
2093 break;
2094 }
2095 UNDEF_LSRBaseEQOffWb;
2096 UNDEF_LSRBaseEQDestWb;
2097 UNDEF_LSRPCBaseWb;
2098 UNDEF_LSRPCOffWb;
2099 lhs = LHS;
2100 temp = lhs - LSRegRHS;
2101 state->NtransSig = LOW;
2102 if (LoadByte (state, instr, lhs, LUNSIGNED))
2103 LSBase = temp;
2104 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2105 break;
2106
2107 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2108 if (BIT (4))
2109 {
2110 ARMul_UndefInstr (state, instr);
2111 break;
2112 }
2113 UNDEF_LSRBaseEQOffWb;
2114 UNDEF_LSRBaseEQDestWb;
2115 UNDEF_LSRPCBaseWb;
2116 UNDEF_LSRPCOffWb;
2117 lhs = LHS;
2118 if (StoreWord (state, instr, lhs))
2119 LSBase = lhs + LSRegRHS;
2120 break;
2121
2122 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2123 if (BIT (4))
2124 {
2125 ARMul_UndefInstr (state, instr);
2126 break;
2127 }
2128 UNDEF_LSRBaseEQOffWb;
2129 UNDEF_LSRBaseEQDestWb;
2130 UNDEF_LSRPCBaseWb;
2131 UNDEF_LSRPCOffWb;
2132 lhs = LHS;
2133 temp = lhs + LSRegRHS;
2134 if (LoadWord (state, instr, lhs))
2135 LSBase = temp;
2136 break;
2137
2138 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2139 if (BIT (4))
2140 {
2141 ARMul_UndefInstr (state, instr);
2142 break;
2143 }
2144 UNDEF_LSRBaseEQOffWb;
2145 UNDEF_LSRBaseEQDestWb;
2146 UNDEF_LSRPCBaseWb;
2147 UNDEF_LSRPCOffWb;
2148 lhs = LHS;
2149 state->NtransSig = LOW;
2150 if (StoreWord (state, instr, lhs))
2151 LSBase = lhs + LSRegRHS;
2152 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2153 break;
2154
2155 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2156 if (BIT (4))
2157 {
2158 ARMul_UndefInstr (state, instr);
2159 break;
2160 }
2161 UNDEF_LSRBaseEQOffWb;
2162 UNDEF_LSRBaseEQDestWb;
2163 UNDEF_LSRPCBaseWb;
2164 UNDEF_LSRPCOffWb;
2165 lhs = LHS;
2166 temp = lhs + LSRegRHS;
2167 state->NtransSig = LOW;
2168 if (LoadWord (state, instr, lhs))
2169 LSBase = temp;
2170 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2171 break;
2172
2173 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2174 if (BIT (4))
2175 {
2176 ARMul_UndefInstr (state, instr);
2177 break;
2178 }
2179 UNDEF_LSRBaseEQOffWb;
2180 UNDEF_LSRBaseEQDestWb;
2181 UNDEF_LSRPCBaseWb;
2182 UNDEF_LSRPCOffWb;
2183 lhs = LHS;
2184 if (StoreByte (state, instr, lhs))
2185 LSBase = lhs + LSRegRHS;
2186 break;
2187
2188 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2189 if (BIT (4))
2190 {
2191 ARMul_UndefInstr (state, instr);
2192 break;
2193 }
2194 UNDEF_LSRBaseEQOffWb;
2195 UNDEF_LSRBaseEQDestWb;
2196 UNDEF_LSRPCBaseWb;
2197 UNDEF_LSRPCOffWb;
2198 lhs = LHS;
2199 temp = lhs + LSRegRHS;
2200 if (LoadByte (state, instr, lhs, LUNSIGNED))
2201 LSBase = temp;
2202 break;
2203
2204 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2205 if (BIT (4))
2206 {
2207 ARMul_UndefInstr (state, instr);
2208 break;
2209 }
2210 UNDEF_LSRBaseEQOffWb;
2211 UNDEF_LSRBaseEQDestWb;
2212 UNDEF_LSRPCBaseWb;
2213 UNDEF_LSRPCOffWb;
2214 lhs = LHS;
2215 state->NtransSig = LOW;
2216 if (StoreByte (state, instr, lhs))
2217 LSBase = lhs + LSRegRHS;
2218 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2219 break;
2220
2221 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2222 if (BIT (4))
2223 {
2224 ARMul_UndefInstr (state, instr);
2225 break;
2226 }
2227 UNDEF_LSRBaseEQOffWb;
2228 UNDEF_LSRBaseEQDestWb;
2229 UNDEF_LSRPCBaseWb;
2230 UNDEF_LSRPCOffWb;
2231 lhs = LHS;
2232 temp = lhs + LSRegRHS;
2233 state->NtransSig = LOW;
2234 if (LoadByte (state, instr, lhs, LUNSIGNED))
2235 LSBase = temp;
2236 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2237 break;
2238
2239
2240 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2241 if (BIT (4))
2242 {
2243 ARMul_UndefInstr (state, instr);
2244 break;
2245 }
2246 (void) StoreWord (state, instr, LHS - LSRegRHS);
2247 break;
2248
2249 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2250 if (BIT (4))
2251 {
2252 ARMul_UndefInstr (state, instr);
2253 break;
2254 }
2255 (void) LoadWord (state, instr, LHS - LSRegRHS);
2256 break;
2257
2258 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2259 if (BIT (4))
2260 {
2261 ARMul_UndefInstr (state, instr);
2262 break;
2263 }
2264 UNDEF_LSRBaseEQOffWb;
2265 UNDEF_LSRBaseEQDestWb;
2266 UNDEF_LSRPCBaseWb;
2267 UNDEF_LSRPCOffWb;
2268 temp = LHS - LSRegRHS;
2269 if (StoreWord (state, instr, temp))
2270 LSBase = temp;
2271 break;
2272
2273 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2274 if (BIT (4))
2275 {
2276 ARMul_UndefInstr (state, instr);
2277 break;
2278 }
2279 UNDEF_LSRBaseEQOffWb;
2280 UNDEF_LSRBaseEQDestWb;
2281 UNDEF_LSRPCBaseWb;
2282 UNDEF_LSRPCOffWb;
2283 temp = LHS - LSRegRHS;
2284 if (LoadWord (state, instr, temp))
2285 LSBase = temp;
2286 break;
2287
2288 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2289 if (BIT (4))
2290 {
2291 ARMul_UndefInstr (state, instr);
2292 break;
2293 }
2294 (void) StoreByte (state, instr, LHS - LSRegRHS);
2295 break;
2296
2297 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2298 if (BIT (4))
2299 {
2300 ARMul_UndefInstr (state, instr);
2301 break;
2302 }
2303 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2304 break;
2305
2306 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2307 if (BIT (4))
2308 {
2309 ARMul_UndefInstr (state, instr);
2310 break;
2311 }
2312 UNDEF_LSRBaseEQOffWb;
2313 UNDEF_LSRBaseEQDestWb;
2314 UNDEF_LSRPCBaseWb;
2315 UNDEF_LSRPCOffWb;
2316 temp = LHS - LSRegRHS;
2317 if (StoreByte (state, instr, temp))
2318 LSBase = temp;
2319 break;
2320
2321 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2322 if (BIT (4))
2323 {
2324 ARMul_UndefInstr (state, instr);
2325 break;
2326 }
2327 UNDEF_LSRBaseEQOffWb;
2328 UNDEF_LSRBaseEQDestWb;
2329 UNDEF_LSRPCBaseWb;
2330 UNDEF_LSRPCOffWb;
2331 temp = LHS - LSRegRHS;
2332 if (LoadByte (state, instr, temp, LUNSIGNED))
2333 LSBase = temp;
2334 break;
2335
2336 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2337 if (BIT (4))
2338 {
2339 ARMul_UndefInstr (state, instr);
2340 break;
2341 }
2342 (void) StoreWord (state, instr, LHS + LSRegRHS);
2343 break;
2344
2345 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2346 if (BIT (4))
2347 {
2348 ARMul_UndefInstr (state, instr);
2349 break;
2350 }
2351 (void) LoadWord (state, instr, LHS + LSRegRHS);
2352 break;
2353
2354 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2355 if (BIT (4))
2356 {
2357 ARMul_UndefInstr (state, instr);
2358 break;
2359 }
2360 UNDEF_LSRBaseEQOffWb;
2361 UNDEF_LSRBaseEQDestWb;
2362 UNDEF_LSRPCBaseWb;
2363 UNDEF_LSRPCOffWb;
2364 temp = LHS + LSRegRHS;
2365 if (StoreWord (state, instr, temp))
2366 LSBase = temp;
2367 break;
2368
2369 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2370 if (BIT (4))
2371 {
2372 ARMul_UndefInstr (state, instr);
2373 break;
2374 }
2375 UNDEF_LSRBaseEQOffWb;
2376 UNDEF_LSRBaseEQDestWb;
2377 UNDEF_LSRPCBaseWb;
2378 UNDEF_LSRPCOffWb;
2379 temp = LHS + LSRegRHS;
2380 if (LoadWord (state, instr, temp))
2381 LSBase = temp;
2382 break;
2383
2384 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2385 if (BIT (4))
2386 {
2387 ARMul_UndefInstr (state, instr);
2388 break;
2389 }
2390 (void) StoreByte (state, instr, LHS + LSRegRHS);
2391 break;
2392
2393 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2394 if (BIT (4))
2395 {
2396 ARMul_UndefInstr (state, instr);
2397 break;
2398 }
2399 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2400 break;
2401
2402 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2403 if (BIT (4))
2404 {
2405 ARMul_UndefInstr (state, instr);
2406 break;
2407 }
2408 UNDEF_LSRBaseEQOffWb;
2409 UNDEF_LSRBaseEQDestWb;
2410 UNDEF_LSRPCBaseWb;
2411 UNDEF_LSRPCOffWb;
2412 temp = LHS + LSRegRHS;
2413 if (StoreByte (state, instr, temp))
2414 LSBase = temp;
2415 break;
2416
2417 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2418 if (BIT (4))
2419 {
2420 /* Check for the special breakpoint opcode.
2421 This value should correspond to the value defined
2422 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2423 if (BITS (0, 19) == 0xfdefe)
2424 {
2425 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2426 ARMul_Abort (state, ARMul_SWIV);
2427 }
2428 else
2429 ARMul_UndefInstr (state, instr);
2430 break;
2431 }
2432 UNDEF_LSRBaseEQOffWb;
2433 UNDEF_LSRBaseEQDestWb;
2434 UNDEF_LSRPCBaseWb;
2435 UNDEF_LSRPCOffWb;
2436 temp = LHS + LSRegRHS;
2437 if (LoadByte (state, instr, temp, LUNSIGNED))
2438 LSBase = temp;
2439 break;
2440
2441 /***************************************************************************\
2442 * Multiple Data Transfer Instructions *
2443 \***************************************************************************/
2444
2445 case 0x80: /* Store, No WriteBack, Post Dec */
2446 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2447 break;
2448
2449 case 0x81: /* Load, No WriteBack, Post Dec */
2450 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2451 break;
2452
2453 case 0x82: /* Store, WriteBack, Post Dec */
2454 temp = LSBase - LSMNumRegs;
2455 STOREMULT (instr, temp + 4L, temp);
2456 break;
2457
2458 case 0x83: /* Load, WriteBack, Post Dec */
2459 temp = LSBase - LSMNumRegs;
2460 LOADMULT (instr, temp + 4L, temp);
2461 break;
2462
2463 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2464 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2465 break;
2466
2467 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2468 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2469 break;
2470
2471 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2472 temp = LSBase - LSMNumRegs;
2473 STORESMULT (instr, temp + 4L, temp);
2474 break;
2475
2476 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2477 temp = LSBase - LSMNumRegs;
2478 LOADSMULT (instr, temp + 4L, temp);
2479 break;
2480
2481
2482 case 0x88: /* Store, No WriteBack, Post Inc */
2483 STOREMULT (instr, LSBase, 0L);
2484 break;
2485
2486 case 0x89: /* Load, No WriteBack, Post Inc */
2487 LOADMULT (instr, LSBase, 0L);
2488 break;
2489
2490 case 0x8a: /* Store, WriteBack, Post Inc */
2491 temp = LSBase;
2492 STOREMULT (instr, temp, temp + LSMNumRegs);
2493 break;
2494
2495 case 0x8b: /* Load, WriteBack, Post Inc */
2496 temp = LSBase;
2497 LOADMULT (instr, temp, temp + LSMNumRegs);
2498 break;
2499
2500 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2501 STORESMULT (instr, LSBase, 0L);
2502 break;
2503
2504 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2505 LOADSMULT (instr, LSBase, 0L);
2506 break;
2507
2508 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2509 temp = LSBase;
2510 STORESMULT (instr, temp, temp + LSMNumRegs);
2511 break;
2512
2513 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2514 temp = LSBase;
2515 LOADSMULT (instr, temp, temp + LSMNumRegs);
2516 break;
2517
2518
2519 case 0x90: /* Store, No WriteBack, Pre Dec */
2520 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
2521 break;
2522
2523 case 0x91: /* Load, No WriteBack, Pre Dec */
2524 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
2525 break;
2526
2527 case 0x92: /* Store, WriteBack, Pre Dec */
2528 temp = LSBase - LSMNumRegs;
2529 STOREMULT (instr, temp, temp);
2530 break;
2531
2532 case 0x93: /* Load, WriteBack, Pre Dec */
2533 temp = LSBase - LSMNumRegs;
2534 LOADMULT (instr, temp, temp);
2535 break;
2536
2537 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2538 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
2539 break;
2540
2541 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2542 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
2543 break;
2544
2545 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2546 temp = LSBase - LSMNumRegs;
2547 STORESMULT (instr, temp, temp);
2548 break;
2549
2550 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2551 temp = LSBase - LSMNumRegs;
2552 LOADSMULT (instr, temp, temp);
2553 break;
2554
2555
2556 case 0x98: /* Store, No WriteBack, Pre Inc */
2557 STOREMULT (instr, LSBase + 4L, 0L);
2558 break;
2559
2560 case 0x99: /* Load, No WriteBack, Pre Inc */
2561 LOADMULT (instr, LSBase + 4L, 0L);
2562 break;
2563
2564 case 0x9a: /* Store, WriteBack, Pre Inc */
2565 temp = LSBase;
2566 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
2567 break;
2568
2569 case 0x9b: /* Load, WriteBack, Pre Inc */
2570 temp = LSBase;
2571 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
2572 break;
2573
2574 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2575 STORESMULT (instr, LSBase + 4L, 0L);
2576 break;
2577
2578 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2579 LOADSMULT (instr, LSBase + 4L, 0L);
2580 break;
2581
2582 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2583 temp = LSBase;
2584 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
2585 break;
2586
2587 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2588 temp = LSBase;
2589 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
2590 break;
2591
2592 /***************************************************************************\
2593 * Branch forward *
2594 \***************************************************************************/
2595
2596 case 0xa0:
2597 case 0xa1:
2598 case 0xa2:
2599 case 0xa3:
2600 case 0xa4:
2601 case 0xa5:
2602 case 0xa6:
2603 case 0xa7:
2604 state->Reg[15] = pc + 8 + POSBRANCH;
2605 FLUSHPIPE;
2606 break;
2607
2608 /***************************************************************************\
2609 * Branch backward *
2610 \***************************************************************************/
2611
2612 case 0xa8:
2613 case 0xa9:
2614 case 0xaa:
2615 case 0xab:
2616 case 0xac:
2617 case 0xad:
2618 case 0xae:
2619 case 0xaf:
2620 state->Reg[15] = pc + 8 + NEGBRANCH;
2621 FLUSHPIPE;
2622 break;
2623
2624 /***************************************************************************\
2625 * Branch and Link forward *
2626 \***************************************************************************/
2627
2628 case 0xb0:
2629 case 0xb1:
2630 case 0xb2:
2631 case 0xb3:
2632 case 0xb4:
2633 case 0xb5:
2634 case 0xb6:
2635 case 0xb7:
2636 #ifdef MODE32
2637 state->Reg[14] = pc + 4; /* put PC into Link */
2638 #else
2639 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
2640 #endif
2641 state->Reg[15] = pc + 8 + POSBRANCH;
2642 FLUSHPIPE;
2643 break;
2644
2645 /***************************************************************************\
2646 * Branch and Link backward *
2647 \***************************************************************************/
2648
2649 case 0xb8:
2650 case 0xb9:
2651 case 0xba:
2652 case 0xbb:
2653 case 0xbc:
2654 case 0xbd:
2655 case 0xbe:
2656 case 0xbf:
2657 #ifdef MODE32
2658 state->Reg[14] = pc + 4; /* put PC into Link */
2659 #else
2660 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
2661 #endif
2662 state->Reg[15] = pc + 8 + NEGBRANCH;
2663 FLUSHPIPE;
2664 break;
2665
2666 /***************************************************************************\
2667 * Co-Processor Data Transfers *
2668 \***************************************************************************/
2669
2670 case 0xc4:
2671 case 0xc0: /* Store , No WriteBack , Post Dec */
2672 ARMul_STC (state, instr, LHS);
2673 break;
2674
2675 case 0xc5:
2676 case 0xc1: /* Load , No WriteBack , Post Dec */
2677 ARMul_LDC (state, instr, LHS);
2678 break;
2679
2680 case 0xc2:
2681 case 0xc6: /* Store , WriteBack , Post Dec */
2682 lhs = LHS;
2683 state->Base = lhs - LSCOff;
2684 ARMul_STC (state, instr, lhs);
2685 break;
2686
2687 case 0xc3:
2688 case 0xc7: /* Load , WriteBack , Post Dec */
2689 lhs = LHS;
2690 state->Base = lhs - LSCOff;
2691 ARMul_LDC (state, instr, lhs);
2692 break;
2693
2694 case 0xc8:
2695 case 0xcc: /* Store , No WriteBack , Post Inc */
2696 ARMul_STC (state, instr, LHS);
2697 break;
2698
2699 case 0xc9:
2700 case 0xcd: /* Load , No WriteBack , Post Inc */
2701 ARMul_LDC (state, instr, LHS);
2702 break;
2703
2704 case 0xca:
2705 case 0xce: /* Store , WriteBack , Post Inc */
2706 lhs = LHS;
2707 state->Base = lhs + LSCOff;
2708 ARMul_STC (state, instr, LHS);
2709 break;
2710
2711 case 0xcb:
2712 case 0xcf: /* Load , WriteBack , Post Inc */
2713 lhs = LHS;
2714 state->Base = lhs + LSCOff;
2715 ARMul_LDC (state, instr, LHS);
2716 break;
2717
2718
2719 case 0xd0:
2720 case 0xd4: /* Store , No WriteBack , Pre Dec */
2721 ARMul_STC (state, instr, LHS - LSCOff);
2722 break;
2723
2724 case 0xd1:
2725 case 0xd5: /* Load , No WriteBack , Pre Dec */
2726 ARMul_LDC (state, instr, LHS - LSCOff);
2727 break;
2728
2729 case 0xd2:
2730 case 0xd6: /* Store , WriteBack , Pre Dec */
2731 lhs = LHS - LSCOff;
2732 state->Base = lhs;
2733 ARMul_STC (state, instr, lhs);
2734 break;
2735
2736 case 0xd3:
2737 case 0xd7: /* Load , WriteBack , Pre Dec */
2738 lhs = LHS - LSCOff;
2739 state->Base = lhs;
2740 ARMul_LDC (state, instr, lhs);
2741 break;
2742
2743 case 0xd8:
2744 case 0xdc: /* Store , No WriteBack , Pre Inc */
2745 ARMul_STC (state, instr, LHS + LSCOff);
2746 break;
2747
2748 case 0xd9:
2749 case 0xdd: /* Load , No WriteBack , Pre Inc */
2750 ARMul_LDC (state, instr, LHS + LSCOff);
2751 break;
2752
2753 case 0xda:
2754 case 0xde: /* Store , WriteBack , Pre Inc */
2755 lhs = LHS + LSCOff;
2756 state->Base = lhs;
2757 ARMul_STC (state, instr, lhs);
2758 break;
2759
2760 case 0xdb:
2761 case 0xdf: /* Load , WriteBack , Pre Inc */
2762 lhs = LHS + LSCOff;
2763 state->Base = lhs;
2764 ARMul_LDC (state, instr, lhs);
2765 break;
2766
2767 /***************************************************************************\
2768 * Co-Processor Register Transfers (MCR) and Data Ops *
2769 \***************************************************************************/
2770
2771 case 0xe2:
2772 case 0xe0:
2773 case 0xe4:
2774 case 0xe6:
2775 case 0xe8:
2776 case 0xea:
2777 case 0xec:
2778 case 0xee:
2779 if (BIT (4))
2780 { /* MCR */
2781 if (DESTReg == 15)
2782 {
2783 UNDEF_MCRPC;
2784 #ifdef MODE32
2785 ARMul_MCR (state, instr, state->Reg[15] + isize);
2786 #else
2787 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
2788 ((state->Reg[15] + isize) & R15PCBITS));
2789 #endif
2790 }
2791 else
2792 ARMul_MCR (state, instr, DEST);
2793 }
2794 else /* CDP Part 1 */
2795 ARMul_CDP (state, instr);
2796 break;
2797
2798 /***************************************************************************\
2799 * Co-Processor Register Transfers (MRC) and Data Ops *
2800 \***************************************************************************/
2801
2802 case 0xe1:
2803 case 0xe3:
2804 case 0xe5:
2805 case 0xe7:
2806 case 0xe9:
2807 case 0xeb:
2808 case 0xed:
2809 case 0xef:
2810 if (BIT (4))
2811 { /* MRC */
2812 temp = ARMul_MRC (state, instr);
2813 if (DESTReg == 15)
2814 {
2815 ASSIGNN ((temp & NBIT) != 0);
2816 ASSIGNZ ((temp & ZBIT) != 0);
2817 ASSIGNC ((temp & CBIT) != 0);
2818 ASSIGNV ((temp & VBIT) != 0);
2819 }
2820 else
2821 DEST = temp;
2822 }
2823 else /* CDP Part 2 */
2824 ARMul_CDP (state, instr);
2825 break;
2826
2827 /***************************************************************************\
2828 * SWI instruction *
2829 \***************************************************************************/
2830
2831 case 0xf0:
2832 case 0xf1:
2833 case 0xf2:
2834 case 0xf3:
2835 case 0xf4:
2836 case 0xf5:
2837 case 0xf6:
2838 case 0xf7:
2839 case 0xf8:
2840 case 0xf9:
2841 case 0xfa:
2842 case 0xfb:
2843 case 0xfc:
2844 case 0xfd:
2845 case 0xfe:
2846 case 0xff:
2847 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
2848 { /* a prefetch abort */
2849 ARMul_Abort (state, ARMul_PrefetchAbortV);
2850 break;
2851 }
2852
2853 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
2854 {
2855 ARMul_Abort (state, ARMul_SWIV);
2856 }
2857 break;
2858 } /* 256 way main switch */
2859 } /* if temp */
2860
2861 #ifdef MODET
2862 donext:
2863 #endif
2864
2865 #ifdef NEED_UI_LOOP_HOOK
2866 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
2867 {
2868 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
2869 ui_loop_hook (0);
2870 }
2871 #endif /* NEED_UI_LOOP_HOOK */
2872
2873 if (state->Emulate == ONCE)
2874 state->Emulate = STOP;
2875 /* If we have changed mode, allow the PC to advance before stopping. */
2876 else if (state->Emulate == CHANGEMODE)
2877 continue;
2878 else if (state->Emulate != RUN)
2879 break;
2880 }
2881 while (!stop_simulator); /* do loop */
2882
2883 state->decoded = decoded;
2884 state->loaded = loaded;
2885 state->pc = pc;
2886
2887 return pc;
2888 } /* Emulate 26/32 in instruction based mode */
2889
2890
2891 /***************************************************************************\
2892 * This routine evaluates most Data Processing register RHS's with the S *
2893 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2894 * filters the common case of an unshifted register with in line code *
2895 \***************************************************************************/
2896
2897 static ARMword
2898 GetDPRegRHS (ARMul_State * state, ARMword instr)
2899 {
2900 ARMword shamt, base;
2901
2902 base = RHSReg;
2903 if (BIT (4))
2904 { /* shift amount in a register */
2905 UNDEF_Shift;
2906 INCPC;
2907 #ifndef MODE32
2908 if (base == 15)
2909 base = ECC | ER15INT | R15PC | EMODE;
2910 else
2911 #endif
2912 base = state->Reg[base];
2913 ARMul_Icycles (state, 1, 0L);
2914 shamt = state->Reg[BITS (8, 11)] & 0xff;
2915 switch ((int) BITS (5, 6))
2916 {
2917 case LSL:
2918 if (shamt == 0)
2919 return (base);
2920 else if (shamt >= 32)
2921 return (0);
2922 else
2923 return (base << shamt);
2924 case LSR:
2925 if (shamt == 0)
2926 return (base);
2927 else if (shamt >= 32)
2928 return (0);
2929 else
2930 return (base >> shamt);
2931 case ASR:
2932 if (shamt == 0)
2933 return (base);
2934 else if (shamt >= 32)
2935 return ((ARMword) ((long int) base >> 31L));
2936 else
2937 return ((ARMword) ((long int) base >> (int) shamt));
2938 case ROR:
2939 shamt &= 0x1f;
2940 if (shamt == 0)
2941 return (base);
2942 else
2943 return ((base << (32 - shamt)) | (base >> shamt));
2944 }
2945 }
2946 else
2947 { /* shift amount is a constant */
2948 #ifndef MODE32
2949 if (base == 15)
2950 base = ECC | ER15INT | R15PC | EMODE;
2951 else
2952 #endif
2953 base = state->Reg[base];
2954 shamt = BITS (7, 11);
2955 switch ((int) BITS (5, 6))
2956 {
2957 case LSL:
2958 return (base << shamt);
2959 case LSR:
2960 if (shamt == 0)
2961 return (0);
2962 else
2963 return (base >> shamt);
2964 case ASR:
2965 if (shamt == 0)
2966 return ((ARMword) ((long int) base >> 31L));
2967 else
2968 return ((ARMword) ((long int) base >> (int) shamt));
2969 case ROR:
2970 if (shamt == 0) /* its an RRX */
2971 return ((base >> 1) | (CFLAG << 31));
2972 else
2973 return ((base << (32 - shamt)) | (base >> shamt));
2974 }
2975 }
2976 return (0); /* just to shut up lint */
2977 }
2978
2979 /***************************************************************************\
2980 * This routine evaluates most Logical Data Processing register RHS's *
2981 * with the S bit set. It is intended to be called from the macro *
2982 * DPSRegRHS, which filters the common case of an unshifted register *
2983 * with in line code *
2984 \***************************************************************************/
2985
2986 static ARMword
2987 GetDPSRegRHS (ARMul_State * state, ARMword instr)
2988 {
2989 ARMword shamt, base;
2990
2991 base = RHSReg;
2992 if (BIT (4))
2993 { /* shift amount in a register */
2994 UNDEF_Shift;
2995 INCPC;
2996 #ifndef MODE32
2997 if (base == 15)
2998 base = ECC | ER15INT | R15PC | EMODE;
2999 else
3000 #endif
3001 base = state->Reg[base];
3002 ARMul_Icycles (state, 1, 0L);
3003 shamt = state->Reg[BITS (8, 11)] & 0xff;
3004 switch ((int) BITS (5, 6))
3005 {
3006 case LSL:
3007 if (shamt == 0)
3008 return (base);
3009 else if (shamt == 32)
3010 {
3011 ASSIGNC (base & 1);
3012 return (0);
3013 }
3014 else if (shamt > 32)
3015 {
3016 CLEARC;
3017 return (0);
3018 }
3019 else
3020 {
3021 ASSIGNC ((base >> (32 - shamt)) & 1);
3022 return (base << shamt);
3023 }
3024 case LSR:
3025 if (shamt == 0)
3026 return (base);
3027 else if (shamt == 32)
3028 {
3029 ASSIGNC (base >> 31);
3030 return (0);
3031 }
3032 else if (shamt > 32)
3033 {
3034 CLEARC;
3035 return (0);
3036 }
3037 else
3038 {
3039 ASSIGNC ((base >> (shamt - 1)) & 1);
3040 return (base >> shamt);
3041 }
3042 case ASR:
3043 if (shamt == 0)
3044 return (base);
3045 else if (shamt >= 32)
3046 {
3047 ASSIGNC (base >> 31L);
3048 return ((ARMword) ((long int) base >> 31L));
3049 }
3050 else
3051 {
3052 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3053 return ((ARMword) ((long int) base >> (int) shamt));
3054 }
3055 case ROR:
3056 if (shamt == 0)
3057 return (base);
3058 shamt &= 0x1f;
3059 if (shamt == 0)
3060 {
3061 ASSIGNC (base >> 31);
3062 return (base);
3063 }
3064 else
3065 {
3066 ASSIGNC ((base >> (shamt - 1)) & 1);
3067 return ((base << (32 - shamt)) | (base >> shamt));
3068 }
3069 }
3070 }
3071 else
3072 { /* shift amount is a constant */
3073 #ifndef MODE32
3074 if (base == 15)
3075 base = ECC | ER15INT | R15PC | EMODE;
3076 else
3077 #endif
3078 base = state->Reg[base];
3079 shamt = BITS (7, 11);
3080 switch ((int) BITS (5, 6))
3081 {
3082 case LSL:
3083 ASSIGNC ((base >> (32 - shamt)) & 1);
3084 return (base << shamt);
3085 case LSR:
3086 if (shamt == 0)
3087 {
3088 ASSIGNC (base >> 31);
3089 return (0);
3090 }
3091 else
3092 {
3093 ASSIGNC ((base >> (shamt - 1)) & 1);
3094 return (base >> shamt);
3095 }
3096 case ASR:
3097 if (shamt == 0)
3098 {
3099 ASSIGNC (base >> 31L);
3100 return ((ARMword) ((long int) base >> 31L));
3101 }
3102 else
3103 {
3104 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3105 return ((ARMword) ((long int) base >> (int) shamt));
3106 }
3107 case ROR:
3108 if (shamt == 0)
3109 { /* its an RRX */
3110 shamt = CFLAG;
3111 ASSIGNC (base & 1);
3112 return ((base >> 1) | (shamt << 31));
3113 }
3114 else
3115 {
3116 ASSIGNC ((base >> (shamt - 1)) & 1);
3117 return ((base << (32 - shamt)) | (base >> shamt));
3118 }
3119 }
3120 }
3121 return (0); /* just to shut up lint */
3122 }
3123
3124 /***************************************************************************\
3125 * This routine handles writes to register 15 when the S bit is not set. *
3126 \***************************************************************************/
3127
3128 static void
3129 WriteR15 (ARMul_State * state, ARMword src)
3130 {
3131 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
3132 #ifdef MODE32
3133 state->Reg[15] = src & PCBITS & ~0x1;
3134 #else
3135 state->Reg[15] = (src & R15PCBITS & ~0x1) | ECC | ER15INT | EMODE;
3136 ARMul_R15Altered (state);
3137 #endif
3138 FLUSHPIPE;
3139 }
3140
3141 /***************************************************************************\
3142 * This routine handles writes to register 15 when the S bit is set. *
3143 \***************************************************************************/
3144
3145 static void
3146 WriteSR15 (ARMul_State * state, ARMword src)
3147 {
3148 #ifdef MODE32
3149 state->Reg[15] = src & PCBITS;
3150 if (state->Bank > 0)
3151 {
3152 state->Cpsr = state->Spsr[state->Bank];
3153 ARMul_CPSRAltered (state);
3154 }
3155 #else
3156 if (state->Bank == USERBANK)
3157 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3158 else
3159 state->Reg[15] = src;
3160 ARMul_R15Altered (state);
3161 #endif
3162 FLUSHPIPE;
3163 }
3164
3165 /***************************************************************************\
3166 * This routine evaluates most Load and Store register RHS's. It is *
3167 * intended to be called from the macro LSRegRHS, which filters the *
3168 * common case of an unshifted register with in line code *
3169 \***************************************************************************/
3170
3171 static ARMword
3172 GetLSRegRHS (ARMul_State * state, ARMword instr)
3173 {
3174 ARMword shamt, base;
3175
3176 base = RHSReg;
3177 #ifndef MODE32
3178 if (base == 15)
3179 base = ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but .... */
3180 else
3181 #endif
3182 base = state->Reg[base];
3183
3184 shamt = BITS (7, 11);
3185 switch ((int) BITS (5, 6))
3186 {
3187 case LSL:
3188 return (base << shamt);
3189 case LSR:
3190 if (shamt == 0)
3191 return (0);
3192 else
3193 return (base >> shamt);
3194 case ASR:
3195 if (shamt == 0)
3196 return ((ARMword) ((long int) base >> 31L));
3197 else
3198 return ((ARMword) ((long int) base >> (int) shamt));
3199 case ROR:
3200 if (shamt == 0) /* its an RRX */
3201 return ((base >> 1) | (CFLAG << 31));
3202 else
3203 return ((base << (32 - shamt)) | (base >> shamt));
3204 }
3205 return (0); /* just to shut up lint */
3206 }
3207
3208 /***************************************************************************\
3209 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3210 \***************************************************************************/
3211
3212 static ARMword
3213 GetLS7RHS (ARMul_State * state, ARMword instr)
3214 {
3215 if (BIT (22) == 0)
3216 { /* register */
3217 #ifndef MODE32
3218 if (RHSReg == 15)
3219 return ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but ... */
3220 #endif
3221 return state->Reg[RHSReg];
3222 }
3223
3224 /* else immediate */
3225 return BITS (0, 3) | (BITS (8, 11) << 4);
3226 }
3227
3228 /***************************************************************************\
3229 * This function does the work of loading a word for a LDR instruction. *
3230 \***************************************************************************/
3231
3232 static unsigned
3233 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3234 {
3235 ARMword dest;
3236
3237 BUSUSEDINCPCS;
3238 #ifndef MODE32
3239 if (ADDREXCEPT (address))
3240 {
3241 INTERNALABORT (address);
3242 }
3243 #endif
3244 dest = ARMul_LoadWordN (state, address);
3245 if (state->Aborted)
3246 {
3247 TAKEABORT;
3248 return (state->lateabtSig);
3249 }
3250 if (address & 3)
3251 dest = ARMul_Align (state, address, dest);
3252 WRITEDEST (dest);
3253 ARMul_Icycles (state, 1, 0L);
3254
3255 return (DESTReg != LHSReg);
3256 }
3257
3258 #ifdef MODET
3259 /***************************************************************************\
3260 * This function does the work of loading a halfword. *
3261 \***************************************************************************/
3262
3263 static unsigned
3264 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3265 int signextend)
3266 {
3267 ARMword dest;
3268
3269 BUSUSEDINCPCS;
3270 #ifndef MODE32
3271 if (ADDREXCEPT (address))
3272 {
3273 INTERNALABORT (address);
3274 }
3275 #endif
3276 dest = ARMul_LoadHalfWord (state, address);
3277 if (state->Aborted)
3278 {
3279 TAKEABORT;
3280 return (state->lateabtSig);
3281 }
3282 UNDEF_LSRBPC;
3283 if (signextend)
3284 {
3285 if (dest & 1 << (16 - 1))
3286 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
3287 }
3288 WRITEDEST (dest);
3289 ARMul_Icycles (state, 1, 0L);
3290 return (DESTReg != LHSReg);
3291 }
3292
3293 #endif /* MODET */
3294
3295 /***************************************************************************\
3296 * This function does the work of loading a byte for a LDRB instruction. *
3297 \***************************************************************************/
3298
3299 static unsigned
3300 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
3301 {
3302 ARMword dest;
3303
3304 BUSUSEDINCPCS;
3305 #ifndef MODE32
3306 if (ADDREXCEPT (address))
3307 {
3308 INTERNALABORT (address);
3309 }
3310 #endif
3311 dest = ARMul_LoadByte (state, address);
3312 if (state->Aborted)
3313 {
3314 TAKEABORT;
3315 return (state->lateabtSig);
3316 }
3317 UNDEF_LSRBPC;
3318 if (signextend)
3319 {
3320 if (dest & 1 << (8 - 1))
3321 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
3322 }
3323 WRITEDEST (dest);
3324 ARMul_Icycles (state, 1, 0L);
3325 return (DESTReg != LHSReg);
3326 }
3327
3328 /***************************************************************************\
3329 * This function does the work of storing a word from a STR instruction. *
3330 \***************************************************************************/
3331
3332 static unsigned
3333 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
3334 {
3335 BUSUSEDINCPCN;
3336 #ifndef MODE32
3337 if (DESTReg == 15)
3338 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3339 #endif
3340 #ifdef MODE32
3341 ARMul_StoreWordN (state, address, DEST);
3342 #else
3343 if (VECTORACCESS (address) || ADDREXCEPT (address))
3344 {
3345 INTERNALABORT (address);
3346 (void) ARMul_LoadWordN (state, address);
3347 }
3348 else
3349 ARMul_StoreWordN (state, address, DEST);
3350 #endif
3351 if (state->Aborted)
3352 {
3353 TAKEABORT;
3354 return (state->lateabtSig);
3355 }
3356 return (TRUE);
3357 }
3358
3359 #ifdef MODET
3360 /***************************************************************************\
3361 * This function does the work of storing a byte for a STRH instruction. *
3362 \***************************************************************************/
3363
3364 static unsigned
3365 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
3366 {
3367 BUSUSEDINCPCN;
3368
3369 #ifndef MODE32
3370 if (DESTReg == 15)
3371 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3372 #endif
3373
3374 #ifdef MODE32
3375 ARMul_StoreHalfWord (state, address, DEST);
3376 #else
3377 if (VECTORACCESS (address) || ADDREXCEPT (address))
3378 {
3379 INTERNALABORT (address);
3380 (void) ARMul_LoadHalfWord (state, address);
3381 }
3382 else
3383 ARMul_StoreHalfWord (state, address, DEST);
3384 #endif
3385
3386 if (state->Aborted)
3387 {
3388 TAKEABORT;
3389 return (state->lateabtSig);
3390 }
3391
3392 return (TRUE);
3393 }
3394
3395 #endif /* MODET */
3396
3397 /***************************************************************************\
3398 * This function does the work of storing a byte for a STRB instruction. *
3399 \***************************************************************************/
3400
3401 static unsigned
3402 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
3403 {
3404 BUSUSEDINCPCN;
3405 #ifndef MODE32
3406 if (DESTReg == 15)
3407 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3408 #endif
3409 #ifdef MODE32
3410 ARMul_StoreByte (state, address, DEST);
3411 #else
3412 if (VECTORACCESS (address) || ADDREXCEPT (address))
3413 {
3414 INTERNALABORT (address);
3415 (void) ARMul_LoadByte (state, address);
3416 }
3417 else
3418 ARMul_StoreByte (state, address, DEST);
3419 #endif
3420 if (state->Aborted)
3421 {
3422 TAKEABORT;
3423 return (state->lateabtSig);
3424 }
3425 UNDEF_LSRBPC;
3426 return (TRUE);
3427 }
3428
3429 /***************************************************************************\
3430 * This function does the work of loading the registers listed in an LDM *
3431 * instruction, when the S bit is clear. The code here is always increment *
3432 * after, it's up to the caller to get the input address correct and to *
3433 * handle base register modification. *
3434 \***************************************************************************/
3435
3436 static void
3437 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
3438 {
3439 ARMword dest, temp;
3440
3441 UNDEF_LSMNoRegs;
3442 UNDEF_LSMPCBase;
3443 UNDEF_LSMBaseInListWb;
3444 BUSUSEDINCPCS;
3445 #ifndef MODE32
3446 if (ADDREXCEPT (address))
3447 {
3448 INTERNALABORT (address);
3449 }
3450 #endif
3451 if (BIT (21) && LHSReg != 15)
3452 LSBase = WBBase;
3453
3454 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3455 dest = ARMul_LoadWordN (state, address);
3456 if (!state->abortSig && !state->Aborted)
3457 state->Reg[temp++] = dest;
3458 else if (!state->Aborted)
3459 state->Aborted = ARMul_DataAbortV;
3460
3461 for (; temp < 16; temp++) /* S cycles from here on */
3462 if (BIT (temp))
3463 { /* load this register */
3464 address += 4;
3465 dest = ARMul_LoadWordS (state, address);
3466 if (!state->abortSig && !state->Aborted)
3467 state->Reg[temp] = dest;
3468 else if (!state->Aborted)
3469 state->Aborted = ARMul_DataAbortV;
3470 }
3471
3472 if (BIT (15) && !state->Aborted)
3473 { /* PC is in the reg list */
3474 #ifdef MODE32
3475 state->Reg[15] = PC;
3476 #endif
3477 FLUSHPIPE;
3478 }
3479
3480 ARMul_Icycles (state, 1, 0L); /* to write back the final register */
3481
3482 if (state->Aborted)
3483 {
3484 if (BIT (21) && LHSReg != 15)
3485 LSBase = WBBase;
3486 TAKEABORT;
3487 }
3488 }
3489
3490 /***************************************************************************\
3491 * This function does the work of loading the registers listed in an LDM *
3492 * instruction, when the S bit is set. The code here is always increment *
3493 * after, it's up to the caller to get the input address correct and to *
3494 * handle base register modification. *
3495 \***************************************************************************/
3496
3497 static void
3498 LoadSMult (ARMul_State * state, ARMword instr,
3499 ARMword address, ARMword WBBase)
3500 {
3501 ARMword dest, temp;
3502
3503 UNDEF_LSMNoRegs;
3504 UNDEF_LSMPCBase;
3505 UNDEF_LSMBaseInListWb;
3506 BUSUSEDINCPCS;
3507 #ifndef MODE32
3508 if (ADDREXCEPT (address))
3509 {
3510 INTERNALABORT (address);
3511 }
3512 #endif
3513
3514 if (!BIT (15) && state->Bank != USERBANK)
3515 {
3516 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); /* temporary reg bank switch */
3517 UNDEF_LSMUserBankWb;
3518 }
3519
3520 if (BIT (21) && LHSReg != 15)
3521 LSBase = WBBase;
3522
3523 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3524 dest = ARMul_LoadWordN (state, address);
3525 if (!state->abortSig)
3526 state->Reg[temp++] = dest;
3527 else if (!state->Aborted)
3528 state->Aborted = ARMul_DataAbortV;
3529
3530 for (; temp < 16; temp++) /* S cycles from here on */
3531 if (BIT (temp))
3532 { /* load this register */
3533 address += 4;
3534 dest = ARMul_LoadWordS (state, address);
3535 if (!state->abortSig && !state->Aborted)
3536 state->Reg[temp] = dest;
3537 else if (!state->Aborted)
3538 state->Aborted = ARMul_DataAbortV;
3539 }
3540
3541 if (BIT (15) && !state->Aborted)
3542 { /* PC is in the reg list */
3543 #ifdef MODE32
3544 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
3545 {
3546 state->Cpsr = GETSPSR (state->Bank);
3547 ARMul_CPSRAltered (state);
3548 }
3549 state->Reg[15] = PC;
3550 #else
3551 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
3552 { /* protect bits in user mode */
3553 ASSIGNN ((state->Reg[15] & NBIT) != 0);
3554 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
3555 ASSIGNC ((state->Reg[15] & CBIT) != 0);
3556 ASSIGNV ((state->Reg[15] & VBIT) != 0);
3557 }
3558 else
3559 ARMul_R15Altered (state);
3560 #endif
3561 FLUSHPIPE;
3562 }
3563
3564 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
3565 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); /* restore the correct bank */
3566
3567 ARMul_Icycles (state, 1, 0L); /* to write back the final register */
3568
3569 if (state->Aborted)
3570 {
3571 if (BIT (21) && LHSReg != 15)
3572 LSBase = WBBase;
3573 TAKEABORT;
3574 }
3575
3576 }
3577
3578 /***************************************************************************\
3579 * This function does the work of storing the registers listed in an STM *
3580 * instruction, when the S bit is clear. The code here is always increment *
3581 * after, it's up to the caller to get the input address correct and to *
3582 * handle base register modification. *
3583 \***************************************************************************/
3584
3585 static void
3586 StoreMult (ARMul_State * state, ARMword instr,
3587 ARMword address, ARMword WBBase)
3588 {
3589 ARMword temp;
3590
3591 UNDEF_LSMNoRegs;
3592 UNDEF_LSMPCBase;
3593 UNDEF_LSMBaseInListWb;
3594 if (!TFLAG)
3595 {
3596 BUSUSEDINCPCN; /* N-cycle, increment the PC and update the NextInstr state */
3597 }
3598
3599 #ifndef MODE32
3600 if (VECTORACCESS (address) || ADDREXCEPT (address))
3601 {
3602 INTERNALABORT (address);
3603 }
3604 if (BIT (15))
3605 PATCHR15;
3606 #endif
3607
3608 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3609 #ifdef MODE32
3610 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3611 #else
3612 if (state->Aborted)
3613 {
3614 (void) ARMul_LoadWordN (state, address);
3615 for (; temp < 16; temp++) /* Fake the Stores as Loads */
3616 if (BIT (temp))
3617 { /* save this register */
3618 address += 4;
3619 (void) ARMul_LoadWordS (state, address);
3620 }
3621 if (BIT (21) && LHSReg != 15)
3622 LSBase = WBBase;
3623 TAKEABORT;
3624 return;
3625 }
3626 else
3627 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3628 #endif
3629 if (state->abortSig && !state->Aborted)
3630 state->Aborted = ARMul_DataAbortV;
3631
3632 if (BIT (21) && LHSReg != 15)
3633 LSBase = WBBase;
3634
3635 for (; temp < 16; temp++) /* S cycles from here on */
3636 if (BIT (temp))
3637 { /* save this register */
3638 address += 4;
3639 ARMul_StoreWordS (state, address, state->Reg[temp]);
3640 if (state->abortSig && !state->Aborted)
3641 state->Aborted = ARMul_DataAbortV;
3642 }
3643 if (state->Aborted)
3644 {
3645 TAKEABORT;
3646 }
3647 }
3648
3649 /***************************************************************************\
3650 * This function does the work of storing the registers listed in an STM *
3651 * instruction when the S bit is set. The code here is always increment *
3652 * after, it's up to the caller to get the input address correct and to *
3653 * handle base register modification. *
3654 \***************************************************************************/
3655
3656 static void
3657 StoreSMult (ARMul_State * state, ARMword instr,
3658 ARMword address, ARMword WBBase)
3659 {
3660 ARMword temp;
3661
3662 UNDEF_LSMNoRegs;
3663 UNDEF_LSMPCBase;
3664 UNDEF_LSMBaseInListWb;
3665 BUSUSEDINCPCN;
3666 #ifndef MODE32
3667 if (VECTORACCESS (address) || ADDREXCEPT (address))
3668 {
3669 INTERNALABORT (address);
3670 }
3671 if (BIT (15))
3672 PATCHR15;
3673 #endif
3674
3675 if (state->Bank != USERBANK)
3676 {
3677 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); /* Force User Bank */
3678 UNDEF_LSMUserBankWb;
3679 }
3680
3681 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3682 #ifdef MODE32
3683 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3684 #else
3685 if (state->Aborted)
3686 {
3687 (void) ARMul_LoadWordN (state, address);
3688 for (; temp < 16; temp++) /* Fake the Stores as Loads */
3689 if (BIT (temp))
3690 { /* save this register */
3691 address += 4;
3692 (void) ARMul_LoadWordS (state, address);
3693 }
3694 if (BIT (21) && LHSReg != 15)
3695 LSBase = WBBase;
3696 TAKEABORT;
3697 return;
3698 }
3699 else
3700 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3701 #endif
3702 if (state->abortSig && !state->Aborted)
3703 state->Aborted = ARMul_DataAbortV;
3704
3705 if (BIT (21) && LHSReg != 15)
3706 LSBase = WBBase;
3707
3708 for (; temp < 16; temp++) /* S cycles from here on */
3709 if (BIT (temp))
3710 { /* save this register */
3711 address += 4;
3712 ARMul_StoreWordS (state, address, state->Reg[temp]);
3713 if (state->abortSig && !state->Aborted)
3714 state->Aborted = ARMul_DataAbortV;
3715 }
3716
3717 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
3718 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); /* restore the correct bank */
3719
3720 if (state->Aborted)
3721 {
3722 TAKEABORT;
3723 }
3724 }
3725
3726 /***************************************************************************\
3727 * This function does the work of adding two 32bit values together, and *
3728 * calculating if a carry has occurred. *
3729 \***************************************************************************/
3730
3731 static ARMword
3732 Add32 (ARMword a1, ARMword a2, int *carry)
3733 {
3734 ARMword result = (a1 + a2);
3735 unsigned int uresult = (unsigned int) result;
3736 unsigned int ua1 = (unsigned int) a1;
3737
3738 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3739 or (result > RdLo) then we have no carry: */
3740 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
3741 *carry = 1;
3742 else
3743 *carry = 0;
3744
3745 return (result);
3746 }
3747
3748 /***************************************************************************\
3749 * This function does the work of multiplying two 32bit values to give a *
3750 * 64bit result. *
3751 \***************************************************************************/
3752
3753 static unsigned
3754 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
3755 {
3756 int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */
3757 ARMword RdHi = 0, RdLo = 0, Rm;
3758 int scount; /* cycle count */
3759
3760 nRdHi = BITS (16, 19);
3761 nRdLo = BITS (12, 15);
3762 nRs = BITS (8, 11);
3763 nRm = BITS (0, 3);
3764
3765 /* Needed to calculate the cycle count: */
3766 Rm = state->Reg[nRm];
3767
3768 /* Check for illegal operand combinations first: */
3769 if (nRdHi != 15
3770 && nRdLo != 15
3771 && nRs != 15
3772 && nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm)
3773 {
3774 ARMword lo, mid1, mid2, hi; /* intermediate results */
3775 int carry;
3776 ARMword Rs = state->Reg[nRs];
3777 int sign = 0;
3778
3779 if (msigned)
3780 {
3781 /* Compute sign of result and adjust operands if necessary. */
3782
3783 sign = (Rm ^ Rs) & 0x80000000;
3784
3785 if (((signed long) Rm) < 0)
3786 Rm = -Rm;
3787
3788 if (((signed long) Rs) < 0)
3789 Rs = -Rs;
3790 }
3791
3792 /* We can split the 32x32 into four 16x16 operations. This ensures
3793 that we do not lose precision on 32bit only hosts: */
3794 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
3795 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3796 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
3797 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3798
3799 /* We now need to add all of these results together, taking care
3800 to propogate the carries from the additions: */
3801 RdLo = Add32 (lo, (mid1 << 16), &carry);
3802 RdHi = carry;
3803 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
3804 RdHi +=
3805 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
3806
3807 if (sign)
3808 {
3809 /* Negate result if necessary. */
3810
3811 RdLo = ~RdLo;
3812 RdHi = ~RdHi;
3813 if (RdLo == 0xFFFFFFFF)
3814 {
3815 RdLo = 0;
3816 RdHi += 1;
3817 }
3818 else
3819 RdLo += 1;
3820 }
3821
3822 state->Reg[nRdLo] = RdLo;
3823 state->Reg[nRdHi] = RdHi;
3824 } /* else undefined result */
3825 else
3826 fprintf (stderr, "MULTIPLY64 - INVALID ARGUMENTS\n");
3827
3828 if (scc)
3829 {
3830 /* Ensure that both RdHi and RdLo are used to compute Z, but
3831 don't let RdLo's sign bit make it to N. */
3832 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
3833 }
3834
3835 /* The cycle count depends on whether the instruction is a signed or
3836 unsigned multiply, and what bits are clear in the multiplier: */
3837 if (msigned && (Rm & ((unsigned) 1 << 31)))
3838 Rm = ~Rm; /* invert the bits to make the check against zero */
3839
3840 if ((Rm & 0xFFFFFF00) == 0)
3841 scount = 1;
3842 else if ((Rm & 0xFFFF0000) == 0)
3843 scount = 2;
3844 else if ((Rm & 0xFF000000) == 0)
3845 scount = 3;
3846 else
3847 scount = 4;
3848
3849 return 2 + scount;
3850 }
3851
3852 /***************************************************************************\
3853 * This function does the work of multiplying two 32bit values and adding *
3854 * a 64bit value to give a 64bit result. *
3855 \***************************************************************************/
3856
3857 static unsigned
3858 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
3859 {
3860 unsigned scount;
3861 ARMword RdLo, RdHi;
3862 int nRdHi, nRdLo;
3863 int carry = 0;
3864
3865 nRdHi = BITS (16, 19);
3866 nRdLo = BITS (12, 15);
3867
3868 RdHi = state->Reg[nRdHi];
3869 RdLo = state->Reg[nRdLo];
3870
3871 scount = Multiply64 (state, instr, msigned, LDEFAULT);
3872
3873 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
3874 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
3875
3876 state->Reg[nRdLo] = RdLo;
3877 state->Reg[nRdHi] = RdHi;
3878
3879 if (scc)
3880 {
3881 /* Ensure that both RdHi and RdLo are used to compute Z, but
3882 don't let RdLo's sign bit make it to N. */
3883 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
3884 }
3885
3886 return scount + 1; /* extra cycle for addition */
3887 }