]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/armemu.c
Fix compile time warning messages.
[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 && BITS (17, 18) == 0)
1117 { /* MSR reg to CPSR */
1118 UNDEF_MSRPC;
1119 temp = DPRegRHS;
1120 ARMul_FixCPSR (state, instr, temp);
1121 }
1122 else
1123 {
1124 UNDEF_Test;
1125 }
1126 break;
1127
1128 case 0x13: /* TEQP reg */
1129 #ifdef MODET
1130 if ((BITS (4, 11) & 0xF9) == 0x9)
1131 {
1132 /* LDR register offset, write-back, down, pre indexed */
1133 LHPREDOWNWB ();
1134 /* continue with remaining instruction decode */
1135 }
1136 #endif
1137 if (DESTReg == 15)
1138 { /* TEQP reg */
1139 #ifdef MODE32
1140 state->Cpsr = GETSPSR (state->Bank);
1141 ARMul_CPSRAltered (state);
1142 #else
1143 rhs = DPRegRHS;
1144 temp = LHS ^ rhs;
1145 SETR15PSR (temp);
1146 #endif
1147 }
1148 else
1149 { /* TEQ Reg */
1150 rhs = DPSRegRHS;
1151 dest = LHS ^ rhs;
1152 ARMul_NegZero (state, dest);
1153 }
1154 break;
1155
1156 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1157 #ifdef MODET
1158 if (BITS (4, 7) == 0xB)
1159 {
1160 /* STRH immediate offset, no write-back, down, pre indexed */
1161 SHPREDOWN ();
1162 break;
1163 }
1164 #endif
1165 if (BITS (4, 11) == 9)
1166 { /* SWP */
1167 UNDEF_SWPPC;
1168 temp = LHS;
1169 BUSUSEDINCPCS;
1170 #ifndef MODE32
1171 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1172 {
1173 INTERNALABORT (temp);
1174 (void) ARMul_LoadByte (state, temp);
1175 (void) ARMul_LoadByte (state, temp);
1176 }
1177 else
1178 #endif
1179 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1180 if (state->abortSig || state->Aborted)
1181 {
1182 TAKEABORT;
1183 }
1184 }
1185 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1186 { /* MRS SPSR */
1187 UNDEF_MRSPC;
1188 DEST = GETSPSR (state->Bank);
1189 }
1190 else
1191 {
1192 UNDEF_Test;
1193 }
1194 break;
1195
1196 case 0x15: /* CMPP reg */
1197 #ifdef MODET
1198 if ((BITS (4, 7) & 0x9) == 0x9)
1199 {
1200 /* LDR immediate offset, no write-back, down, pre indexed */
1201 LHPREDOWN ();
1202 /* continue with remaining instruction decode */
1203 }
1204 #endif
1205 if (DESTReg == 15)
1206 { /* CMPP reg */
1207 #ifdef MODE32
1208 state->Cpsr = GETSPSR (state->Bank);
1209 ARMul_CPSRAltered (state);
1210 #else
1211 rhs = DPRegRHS;
1212 temp = LHS - rhs;
1213 SETR15PSR (temp);
1214 #endif
1215 }
1216 else
1217 { /* CMP reg */
1218 lhs = LHS;
1219 rhs = DPRegRHS;
1220 dest = lhs - rhs;
1221 ARMul_NegZero (state, dest);
1222 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1223 {
1224 ARMul_SubCarry (state, lhs, rhs, dest);
1225 ARMul_SubOverflow (state, lhs, rhs, dest);
1226 }
1227 else
1228 {
1229 CLEARC;
1230 CLEARV;
1231 }
1232 }
1233 break;
1234
1235 case 0x16: /* CMN reg and MSR reg to SPSR */
1236 #ifdef MODET
1237 if (BITS (4, 7) == 0xB)
1238 {
1239 /* STRH immediate offset, write-back, down, pre indexed */
1240 SHPREDOWNWB ();
1241 break;
1242 }
1243 #endif
1244 if (DESTReg == 15 && BITS (17, 18) == 0)
1245 { /* MSR */
1246 UNDEF_MSRPC;
1247 ARMul_FixSPSR (state, instr, DPRegRHS);
1248 }
1249 else
1250 {
1251 UNDEF_Test;
1252 }
1253 break;
1254
1255 case 0x17: /* CMNP reg */
1256 #ifdef MODET
1257 if ((BITS (4, 7) & 0x9) == 0x9)
1258 {
1259 /* LDR immediate offset, write-back, down, pre indexed */
1260 LHPREDOWNWB ();
1261 /* continue with remaining instruction decoding */
1262 }
1263 #endif
1264 if (DESTReg == 15)
1265 {
1266 #ifdef MODE32
1267 state->Cpsr = GETSPSR (state->Bank);
1268 ARMul_CPSRAltered (state);
1269 #else
1270 rhs = DPRegRHS;
1271 temp = LHS + rhs;
1272 SETR15PSR (temp);
1273 #endif
1274 break;
1275 }
1276 else
1277 { /* CMN reg */
1278 lhs = LHS;
1279 rhs = DPRegRHS;
1280 dest = lhs + rhs;
1281 ASSIGNZ (dest == 0);
1282 if ((lhs | rhs) >> 30)
1283 { /* possible C,V,N to set */
1284 ASSIGNN (NEG (dest));
1285 ARMul_AddCarry (state, lhs, rhs, dest);
1286 ARMul_AddOverflow (state, lhs, rhs, dest);
1287 }
1288 else
1289 {
1290 CLEARN;
1291 CLEARC;
1292 CLEARV;
1293 }
1294 }
1295 break;
1296
1297 case 0x18: /* ORR reg */
1298 #ifdef MODET
1299 if (BITS (4, 11) == 0xB)
1300 {
1301 /* STRH register offset, no write-back, up, pre indexed */
1302 SHPREUP ();
1303 break;
1304 }
1305 #endif
1306 rhs = DPRegRHS;
1307 dest = LHS | rhs;
1308 WRITEDEST (dest);
1309 break;
1310
1311 case 0x19: /* ORRS reg */
1312 #ifdef MODET
1313 if ((BITS (4, 11) & 0xF9) == 0x9)
1314 {
1315 /* LDR register offset, no write-back, up, pre indexed */
1316 LHPREUP ();
1317 /* continue with remaining instruction decoding */
1318 }
1319 #endif
1320 rhs = DPSRegRHS;
1321 dest = LHS | rhs;
1322 WRITESDEST (dest);
1323 break;
1324
1325 case 0x1a: /* MOV reg */
1326 #ifdef MODET
1327 if (BITS (4, 11) == 0xB)
1328 {
1329 /* STRH register offset, write-back, up, pre indexed */
1330 SHPREUPWB ();
1331 break;
1332 }
1333 #endif
1334 dest = DPRegRHS;
1335 WRITEDEST (dest);
1336 break;
1337
1338 case 0x1b: /* MOVS reg */
1339 #ifdef MODET
1340 if ((BITS (4, 11) & 0xF9) == 0x9)
1341 {
1342 /* LDR register offset, write-back, up, pre indexed */
1343 LHPREUPWB ();
1344 /* continue with remaining instruction decoding */
1345 }
1346 #endif
1347 dest = DPSRegRHS;
1348 WRITESDEST (dest);
1349 break;
1350
1351 case 0x1c: /* BIC reg */
1352 #ifdef MODET
1353 if (BITS (4, 7) == 0xB)
1354 {
1355 /* STRH immediate offset, no write-back, up, pre indexed */
1356 SHPREUP ();
1357 break;
1358 }
1359 #endif
1360 rhs = DPRegRHS;
1361 dest = LHS & ~rhs;
1362 WRITEDEST (dest);
1363 break;
1364
1365 case 0x1d: /* BICS reg */
1366 #ifdef MODET
1367 if ((BITS (4, 7) & 0x9) == 0x9)
1368 {
1369 /* LDR immediate offset, no write-back, up, pre indexed */
1370 LHPREUP ();
1371 /* continue with instruction decoding */
1372 }
1373 #endif
1374 rhs = DPSRegRHS;
1375 dest = LHS & ~rhs;
1376 WRITESDEST (dest);
1377 break;
1378
1379 case 0x1e: /* MVN reg */
1380 #ifdef MODET
1381 if (BITS (4, 7) == 0xB)
1382 {
1383 /* STRH immediate offset, write-back, up, pre indexed */
1384 SHPREUPWB ();
1385 break;
1386 }
1387 #endif
1388 dest = ~DPRegRHS;
1389 WRITEDEST (dest);
1390 break;
1391
1392 case 0x1f: /* MVNS reg */
1393 #ifdef MODET
1394 if ((BITS (4, 7) & 0x9) == 0x9)
1395 {
1396 /* LDR immediate offset, write-back, up, pre indexed */
1397 LHPREUPWB ();
1398 /* continue instruction decoding */
1399 }
1400 #endif
1401 dest = ~DPSRegRHS;
1402 WRITESDEST (dest);
1403 break;
1404
1405 /***************************************************************************\
1406 * Data Processing Immediate RHS Instructions *
1407 \***************************************************************************/
1408
1409 case 0x20: /* AND immed */
1410 dest = LHS & DPImmRHS;
1411 WRITEDEST (dest);
1412 break;
1413
1414 case 0x21: /* ANDS immed */
1415 DPSImmRHS;
1416 dest = LHS & rhs;
1417 WRITESDEST (dest);
1418 break;
1419
1420 case 0x22: /* EOR immed */
1421 dest = LHS ^ DPImmRHS;
1422 WRITEDEST (dest);
1423 break;
1424
1425 case 0x23: /* EORS immed */
1426 DPSImmRHS;
1427 dest = LHS ^ rhs;
1428 WRITESDEST (dest);
1429 break;
1430
1431 case 0x24: /* SUB immed */
1432 dest = LHS - DPImmRHS;
1433 WRITEDEST (dest);
1434 break;
1435
1436 case 0x25: /* SUBS immed */
1437 lhs = LHS;
1438 rhs = DPImmRHS;
1439 dest = lhs - rhs;
1440 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1441 {
1442 ARMul_SubCarry (state, lhs, rhs, dest);
1443 ARMul_SubOverflow (state, lhs, rhs, dest);
1444 }
1445 else
1446 {
1447 CLEARC;
1448 CLEARV;
1449 }
1450 WRITESDEST (dest);
1451 break;
1452
1453 case 0x26: /* RSB immed */
1454 dest = DPImmRHS - LHS;
1455 WRITEDEST (dest);
1456 break;
1457
1458 case 0x27: /* RSBS immed */
1459 lhs = LHS;
1460 rhs = DPImmRHS;
1461 dest = rhs - lhs;
1462 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1463 {
1464 ARMul_SubCarry (state, rhs, lhs, dest);
1465 ARMul_SubOverflow (state, rhs, lhs, dest);
1466 }
1467 else
1468 {
1469 CLEARC;
1470 CLEARV;
1471 }
1472 WRITESDEST (dest);
1473 break;
1474
1475 case 0x28: /* ADD immed */
1476 dest = LHS + DPImmRHS;
1477 WRITEDEST (dest);
1478 break;
1479
1480 case 0x29: /* ADDS immed */
1481 lhs = LHS;
1482 rhs = DPImmRHS;
1483 dest = lhs + rhs;
1484 ASSIGNZ (dest == 0);
1485 if ((lhs | rhs) >> 30)
1486 { /* possible C,V,N to set */
1487 ASSIGNN (NEG (dest));
1488 ARMul_AddCarry (state, lhs, rhs, dest);
1489 ARMul_AddOverflow (state, lhs, rhs, dest);
1490 }
1491 else
1492 {
1493 CLEARN;
1494 CLEARC;
1495 CLEARV;
1496 }
1497 WRITESDEST (dest);
1498 break;
1499
1500 case 0x2a: /* ADC immed */
1501 dest = LHS + DPImmRHS + CFLAG;
1502 WRITEDEST (dest);
1503 break;
1504
1505 case 0x2b: /* ADCS immed */
1506 lhs = LHS;
1507 rhs = DPImmRHS;
1508 dest = lhs + rhs + CFLAG;
1509 ASSIGNZ (dest == 0);
1510 if ((lhs | rhs) >> 30)
1511 { /* possible C,V,N to set */
1512 ASSIGNN (NEG (dest));
1513 ARMul_AddCarry (state, lhs, rhs, dest);
1514 ARMul_AddOverflow (state, lhs, rhs, dest);
1515 }
1516 else
1517 {
1518 CLEARN;
1519 CLEARC;
1520 CLEARV;
1521 }
1522 WRITESDEST (dest);
1523 break;
1524
1525 case 0x2c: /* SBC immed */
1526 dest = LHS - DPImmRHS - !CFLAG;
1527 WRITEDEST (dest);
1528 break;
1529
1530 case 0x2d: /* SBCS immed */
1531 lhs = LHS;
1532 rhs = DPImmRHS;
1533 dest = lhs - rhs - !CFLAG;
1534 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1535 {
1536 ARMul_SubCarry (state, lhs, rhs, dest);
1537 ARMul_SubOverflow (state, lhs, rhs, dest);
1538 }
1539 else
1540 {
1541 CLEARC;
1542 CLEARV;
1543 }
1544 WRITESDEST (dest);
1545 break;
1546
1547 case 0x2e: /* RSC immed */
1548 dest = DPImmRHS - LHS - !CFLAG;
1549 WRITEDEST (dest);
1550 break;
1551
1552 case 0x2f: /* RSCS immed */
1553 lhs = LHS;
1554 rhs = DPImmRHS;
1555 dest = rhs - lhs - !CFLAG;
1556 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1557 {
1558 ARMul_SubCarry (state, rhs, lhs, dest);
1559 ARMul_SubOverflow (state, rhs, lhs, dest);
1560 }
1561 else
1562 {
1563 CLEARC;
1564 CLEARV;
1565 }
1566 WRITESDEST (dest);
1567 break;
1568
1569 case 0x30: /* TST immed */
1570 UNDEF_Test;
1571 break;
1572
1573 case 0x31: /* TSTP immed */
1574 if (DESTReg == 15)
1575 { /* TSTP immed */
1576 #ifdef MODE32
1577 state->Cpsr = GETSPSR (state->Bank);
1578 ARMul_CPSRAltered (state);
1579 #else
1580 temp = LHS & DPImmRHS;
1581 SETR15PSR (temp);
1582 #endif
1583 }
1584 else
1585 {
1586 DPSImmRHS; /* TST immed */
1587 dest = LHS & rhs;
1588 ARMul_NegZero (state, dest);
1589 }
1590 break;
1591
1592 case 0x32: /* TEQ immed and MSR immed to CPSR */
1593 if (DESTReg == 15 && BITS (17, 18) == 0)
1594 { /* MSR immed to CPSR */
1595 ARMul_FixCPSR (state, instr, DPImmRHS);
1596 }
1597 else
1598 {
1599 UNDEF_Test;
1600 }
1601 break;
1602
1603 case 0x33: /* TEQP immed */
1604 if (DESTReg == 15)
1605 { /* TEQP immed */
1606 #ifdef MODE32
1607 state->Cpsr = GETSPSR (state->Bank);
1608 ARMul_CPSRAltered (state);
1609 #else
1610 temp = LHS ^ DPImmRHS;
1611 SETR15PSR (temp);
1612 #endif
1613 }
1614 else
1615 {
1616 DPSImmRHS; /* TEQ immed */
1617 dest = LHS ^ rhs;
1618 ARMul_NegZero (state, dest);
1619 }
1620 break;
1621
1622 case 0x34: /* CMP immed */
1623 UNDEF_Test;
1624 break;
1625
1626 case 0x35: /* CMPP immed */
1627 if (DESTReg == 15)
1628 { /* CMPP immed */
1629 #ifdef MODE32
1630 state->Cpsr = GETSPSR (state->Bank);
1631 ARMul_CPSRAltered (state);
1632 #else
1633 temp = LHS - DPImmRHS;
1634 SETR15PSR (temp);
1635 #endif
1636 break;
1637 }
1638 else
1639 {
1640 lhs = LHS; /* CMP immed */
1641 rhs = DPImmRHS;
1642 dest = lhs - rhs;
1643 ARMul_NegZero (state, dest);
1644 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1645 {
1646 ARMul_SubCarry (state, lhs, rhs, dest);
1647 ARMul_SubOverflow (state, lhs, rhs, dest);
1648 }
1649 else
1650 {
1651 CLEARC;
1652 CLEARV;
1653 }
1654 }
1655 break;
1656
1657 case 0x36: /* CMN immed and MSR immed to SPSR */
1658 if (DESTReg == 15 && BITS (17, 18) == 0) /* MSR */
1659 ARMul_FixSPSR (state, instr, DPImmRHS);
1660 else
1661 {
1662 UNDEF_Test;
1663 }
1664 break;
1665
1666 case 0x37: /* CMNP immed */
1667 if (DESTReg == 15)
1668 { /* CMNP immed */
1669 #ifdef MODE32
1670 state->Cpsr = GETSPSR (state->Bank);
1671 ARMul_CPSRAltered (state);
1672 #else
1673 temp = LHS + DPImmRHS;
1674 SETR15PSR (temp);
1675 #endif
1676 break;
1677 }
1678 else
1679 {
1680 lhs = LHS; /* CMN immed */
1681 rhs = DPImmRHS;
1682 dest = lhs + rhs;
1683 ASSIGNZ (dest == 0);
1684 if ((lhs | rhs) >> 30)
1685 { /* possible C,V,N to set */
1686 ASSIGNN (NEG (dest));
1687 ARMul_AddCarry (state, lhs, rhs, dest);
1688 ARMul_AddOverflow (state, lhs, rhs, dest);
1689 }
1690 else
1691 {
1692 CLEARN;
1693 CLEARC;
1694 CLEARV;
1695 }
1696 }
1697 break;
1698
1699 case 0x38: /* ORR immed */
1700 dest = LHS | DPImmRHS;
1701 WRITEDEST (dest);
1702 break;
1703
1704 case 0x39: /* ORRS immed */
1705 DPSImmRHS;
1706 dest = LHS | rhs;
1707 WRITESDEST (dest);
1708 break;
1709
1710 case 0x3a: /* MOV immed */
1711 dest = DPImmRHS;
1712 WRITEDEST (dest);
1713 break;
1714
1715 case 0x3b: /* MOVS immed */
1716 DPSImmRHS;
1717 WRITESDEST (rhs);
1718 break;
1719
1720 case 0x3c: /* BIC immed */
1721 dest = LHS & ~DPImmRHS;
1722 WRITEDEST (dest);
1723 break;
1724
1725 case 0x3d: /* BICS immed */
1726 DPSImmRHS;
1727 dest = LHS & ~rhs;
1728 WRITESDEST (dest);
1729 break;
1730
1731 case 0x3e: /* MVN immed */
1732 dest = ~DPImmRHS;
1733 WRITEDEST (dest);
1734 break;
1735
1736 case 0x3f: /* MVNS immed */
1737 DPSImmRHS;
1738 WRITESDEST (~rhs);
1739 break;
1740
1741 /***************************************************************************\
1742 * Single Data Transfer Immediate RHS Instructions *
1743 \***************************************************************************/
1744
1745 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
1746 lhs = LHS;
1747 if (StoreWord (state, instr, lhs))
1748 LSBase = lhs - LSImmRHS;
1749 break;
1750
1751 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
1752 lhs = LHS;
1753 if (LoadWord (state, instr, lhs))
1754 LSBase = lhs - LSImmRHS;
1755 break;
1756
1757 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
1758 UNDEF_LSRBaseEQDestWb;
1759 UNDEF_LSRPCBaseWb;
1760 lhs = LHS;
1761 temp = lhs - LSImmRHS;
1762 state->NtransSig = LOW;
1763 if (StoreWord (state, instr, lhs))
1764 LSBase = temp;
1765 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1766 break;
1767
1768 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
1769 UNDEF_LSRBaseEQDestWb;
1770 UNDEF_LSRPCBaseWb;
1771 lhs = LHS;
1772 state->NtransSig = LOW;
1773 if (LoadWord (state, instr, lhs))
1774 LSBase = lhs - LSImmRHS;
1775 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1776 break;
1777
1778 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
1779 lhs = LHS;
1780 if (StoreByte (state, instr, lhs))
1781 LSBase = lhs - LSImmRHS;
1782 break;
1783
1784 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
1785 lhs = LHS;
1786 if (LoadByte (state, instr, lhs, LUNSIGNED))
1787 LSBase = lhs - LSImmRHS;
1788 break;
1789
1790 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
1791 UNDEF_LSRBaseEQDestWb;
1792 UNDEF_LSRPCBaseWb;
1793 lhs = LHS;
1794 state->NtransSig = LOW;
1795 if (StoreByte (state, instr, lhs))
1796 LSBase = lhs - LSImmRHS;
1797 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1798 break;
1799
1800 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
1801 UNDEF_LSRBaseEQDestWb;
1802 UNDEF_LSRPCBaseWb;
1803 lhs = LHS;
1804 state->NtransSig = LOW;
1805 if (LoadByte (state, instr, lhs, LUNSIGNED))
1806 LSBase = lhs - LSImmRHS;
1807 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1808 break;
1809
1810 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
1811 lhs = LHS;
1812 if (StoreWord (state, instr, lhs))
1813 LSBase = lhs + LSImmRHS;
1814 break;
1815
1816 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
1817 lhs = LHS;
1818 if (LoadWord (state, instr, lhs))
1819 LSBase = lhs + LSImmRHS;
1820 break;
1821
1822 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
1823 UNDEF_LSRBaseEQDestWb;
1824 UNDEF_LSRPCBaseWb;
1825 lhs = LHS;
1826 state->NtransSig = LOW;
1827 if (StoreWord (state, instr, lhs))
1828 LSBase = lhs + LSImmRHS;
1829 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1830 break;
1831
1832 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
1833 UNDEF_LSRBaseEQDestWb;
1834 UNDEF_LSRPCBaseWb;
1835 lhs = LHS;
1836 state->NtransSig = LOW;
1837 if (LoadWord (state, instr, lhs))
1838 LSBase = lhs + LSImmRHS;
1839 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1840 break;
1841
1842 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
1843 lhs = LHS;
1844 if (StoreByte (state, instr, lhs))
1845 LSBase = lhs + LSImmRHS;
1846 break;
1847
1848 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
1849 lhs = LHS;
1850 if (LoadByte (state, instr, lhs, LUNSIGNED))
1851 LSBase = lhs + LSImmRHS;
1852 break;
1853
1854 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
1855 UNDEF_LSRBaseEQDestWb;
1856 UNDEF_LSRPCBaseWb;
1857 lhs = LHS;
1858 state->NtransSig = LOW;
1859 if (StoreByte (state, instr, lhs))
1860 LSBase = lhs + LSImmRHS;
1861 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1862 break;
1863
1864 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
1865 UNDEF_LSRBaseEQDestWb;
1866 UNDEF_LSRPCBaseWb;
1867 lhs = LHS;
1868 state->NtransSig = LOW;
1869 if (LoadByte (state, instr, lhs, LUNSIGNED))
1870 LSBase = lhs + LSImmRHS;
1871 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
1872 break;
1873
1874
1875 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
1876 (void) StoreWord (state, instr, LHS - LSImmRHS);
1877 break;
1878
1879 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
1880 (void) LoadWord (state, instr, LHS - LSImmRHS);
1881 break;
1882
1883 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
1884 UNDEF_LSRBaseEQDestWb;
1885 UNDEF_LSRPCBaseWb;
1886 temp = LHS - LSImmRHS;
1887 if (StoreWord (state, instr, temp))
1888 LSBase = temp;
1889 break;
1890
1891 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
1892 UNDEF_LSRBaseEQDestWb;
1893 UNDEF_LSRPCBaseWb;
1894 temp = LHS - LSImmRHS;
1895 if (LoadWord (state, instr, temp))
1896 LSBase = temp;
1897 break;
1898
1899 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
1900 (void) StoreByte (state, instr, LHS - LSImmRHS);
1901 break;
1902
1903 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
1904 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
1905 break;
1906
1907 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
1908 UNDEF_LSRBaseEQDestWb;
1909 UNDEF_LSRPCBaseWb;
1910 temp = LHS - LSImmRHS;
1911 if (StoreByte (state, instr, temp))
1912 LSBase = temp;
1913 break;
1914
1915 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
1916 UNDEF_LSRBaseEQDestWb;
1917 UNDEF_LSRPCBaseWb;
1918 temp = LHS - LSImmRHS;
1919 if (LoadByte (state, instr, temp, LUNSIGNED))
1920 LSBase = temp;
1921 break;
1922
1923 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
1924 (void) StoreWord (state, instr, LHS + LSImmRHS);
1925 break;
1926
1927 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
1928 (void) LoadWord (state, instr, LHS + LSImmRHS);
1929 break;
1930
1931 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
1932 UNDEF_LSRBaseEQDestWb;
1933 UNDEF_LSRPCBaseWb;
1934 temp = LHS + LSImmRHS;
1935 if (StoreWord (state, instr, temp))
1936 LSBase = temp;
1937 break;
1938
1939 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
1940 UNDEF_LSRBaseEQDestWb;
1941 UNDEF_LSRPCBaseWb;
1942 temp = LHS + LSImmRHS;
1943 if (LoadWord (state, instr, temp))
1944 LSBase = temp;
1945 break;
1946
1947 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
1948 (void) StoreByte (state, instr, LHS + LSImmRHS);
1949 break;
1950
1951 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
1952 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
1953 break;
1954
1955 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
1956 UNDEF_LSRBaseEQDestWb;
1957 UNDEF_LSRPCBaseWb;
1958 temp = LHS + LSImmRHS;
1959 if (StoreByte (state, instr, temp))
1960 LSBase = temp;
1961 break;
1962
1963 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
1964 UNDEF_LSRBaseEQDestWb;
1965 UNDEF_LSRPCBaseWb;
1966 temp = LHS + LSImmRHS;
1967 if (LoadByte (state, instr, temp, LUNSIGNED))
1968 LSBase = temp;
1969 break;
1970
1971 /***************************************************************************\
1972 * Single Data Transfer Register RHS Instructions *
1973 \***************************************************************************/
1974
1975 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
1976 if (BIT (4))
1977 {
1978 ARMul_UndefInstr (state, instr);
1979 break;
1980 }
1981 UNDEF_LSRBaseEQOffWb;
1982 UNDEF_LSRBaseEQDestWb;
1983 UNDEF_LSRPCBaseWb;
1984 UNDEF_LSRPCOffWb;
1985 lhs = LHS;
1986 if (StoreWord (state, instr, lhs))
1987 LSBase = lhs - LSRegRHS;
1988 break;
1989
1990 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
1991 if (BIT (4))
1992 {
1993 ARMul_UndefInstr (state, instr);
1994 break;
1995 }
1996 UNDEF_LSRBaseEQOffWb;
1997 UNDEF_LSRBaseEQDestWb;
1998 UNDEF_LSRPCBaseWb;
1999 UNDEF_LSRPCOffWb;
2000 lhs = LHS;
2001 if (LoadWord (state, instr, lhs))
2002 LSBase = lhs - LSRegRHS;
2003 break;
2004
2005 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2006 if (BIT (4))
2007 {
2008 ARMul_UndefInstr (state, instr);
2009 break;
2010 }
2011 UNDEF_LSRBaseEQOffWb;
2012 UNDEF_LSRBaseEQDestWb;
2013 UNDEF_LSRPCBaseWb;
2014 UNDEF_LSRPCOffWb;
2015 lhs = LHS;
2016 state->NtransSig = LOW;
2017 if (StoreWord (state, instr, lhs))
2018 LSBase = lhs - LSRegRHS;
2019 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2020 break;
2021
2022 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2023 if (BIT (4))
2024 {
2025 ARMul_UndefInstr (state, instr);
2026 break;
2027 }
2028 UNDEF_LSRBaseEQOffWb;
2029 UNDEF_LSRBaseEQDestWb;
2030 UNDEF_LSRPCBaseWb;
2031 UNDEF_LSRPCOffWb;
2032 lhs = LHS;
2033 state->NtransSig = LOW;
2034 if (LoadWord (state, instr, lhs))
2035 LSBase = lhs - LSRegRHS;
2036 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2037 break;
2038
2039 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2040 if (BIT (4))
2041 {
2042 ARMul_UndefInstr (state, instr);
2043 break;
2044 }
2045 UNDEF_LSRBaseEQOffWb;
2046 UNDEF_LSRBaseEQDestWb;
2047 UNDEF_LSRPCBaseWb;
2048 UNDEF_LSRPCOffWb;
2049 lhs = LHS;
2050 if (StoreByte (state, instr, lhs))
2051 LSBase = lhs - LSRegRHS;
2052 break;
2053
2054 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2055 if (BIT (4))
2056 {
2057 ARMul_UndefInstr (state, instr);
2058 break;
2059 }
2060 UNDEF_LSRBaseEQOffWb;
2061 UNDEF_LSRBaseEQDestWb;
2062 UNDEF_LSRPCBaseWb;
2063 UNDEF_LSRPCOffWb;
2064 lhs = LHS;
2065 if (LoadByte (state, instr, lhs, LUNSIGNED))
2066 LSBase = lhs - LSRegRHS;
2067 break;
2068
2069 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2070 if (BIT (4))
2071 {
2072 ARMul_UndefInstr (state, instr);
2073 break;
2074 }
2075 UNDEF_LSRBaseEQOffWb;
2076 UNDEF_LSRBaseEQDestWb;
2077 UNDEF_LSRPCBaseWb;
2078 UNDEF_LSRPCOffWb;
2079 lhs = LHS;
2080 state->NtransSig = LOW;
2081 if (StoreByte (state, instr, lhs))
2082 LSBase = lhs - LSRegRHS;
2083 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2084 break;
2085
2086 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2087 if (BIT (4))
2088 {
2089 ARMul_UndefInstr (state, instr);
2090 break;
2091 }
2092 UNDEF_LSRBaseEQOffWb;
2093 UNDEF_LSRBaseEQDestWb;
2094 UNDEF_LSRPCBaseWb;
2095 UNDEF_LSRPCOffWb;
2096 lhs = LHS;
2097 state->NtransSig = LOW;
2098 if (LoadByte (state, instr, lhs, LUNSIGNED))
2099 LSBase = lhs - LSRegRHS;
2100 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2101 break;
2102
2103 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2104 if (BIT (4))
2105 {
2106 ARMul_UndefInstr (state, instr);
2107 break;
2108 }
2109 UNDEF_LSRBaseEQOffWb;
2110 UNDEF_LSRBaseEQDestWb;
2111 UNDEF_LSRPCBaseWb;
2112 UNDEF_LSRPCOffWb;
2113 lhs = LHS;
2114 if (StoreWord (state, instr, lhs))
2115 LSBase = lhs + LSRegRHS;
2116 break;
2117
2118 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2119 if (BIT (4))
2120 {
2121 ARMul_UndefInstr (state, instr);
2122 break;
2123 }
2124 UNDEF_LSRBaseEQOffWb;
2125 UNDEF_LSRBaseEQDestWb;
2126 UNDEF_LSRPCBaseWb;
2127 UNDEF_LSRPCOffWb;
2128 lhs = LHS;
2129 if (LoadWord (state, instr, lhs))
2130 LSBase = lhs + LSRegRHS;
2131 break;
2132
2133 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2134 if (BIT (4))
2135 {
2136 ARMul_UndefInstr (state, instr);
2137 break;
2138 }
2139 UNDEF_LSRBaseEQOffWb;
2140 UNDEF_LSRBaseEQDestWb;
2141 UNDEF_LSRPCBaseWb;
2142 UNDEF_LSRPCOffWb;
2143 lhs = LHS;
2144 state->NtransSig = LOW;
2145 if (StoreWord (state, instr, lhs))
2146 LSBase = lhs + LSRegRHS;
2147 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2148 break;
2149
2150 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2151 if (BIT (4))
2152 {
2153 ARMul_UndefInstr (state, instr);
2154 break;
2155 }
2156 UNDEF_LSRBaseEQOffWb;
2157 UNDEF_LSRBaseEQDestWb;
2158 UNDEF_LSRPCBaseWb;
2159 UNDEF_LSRPCOffWb;
2160 lhs = LHS;
2161 state->NtransSig = LOW;
2162 if (LoadWord (state, instr, lhs))
2163 LSBase = lhs + LSRegRHS;
2164 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2165 break;
2166
2167 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2168 if (BIT (4))
2169 {
2170 ARMul_UndefInstr (state, instr);
2171 break;
2172 }
2173 UNDEF_LSRBaseEQOffWb;
2174 UNDEF_LSRBaseEQDestWb;
2175 UNDEF_LSRPCBaseWb;
2176 UNDEF_LSRPCOffWb;
2177 lhs = LHS;
2178 if (StoreByte (state, instr, lhs))
2179 LSBase = lhs + LSRegRHS;
2180 break;
2181
2182 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2183 if (BIT (4))
2184 {
2185 ARMul_UndefInstr (state, instr);
2186 break;
2187 }
2188 UNDEF_LSRBaseEQOffWb;
2189 UNDEF_LSRBaseEQDestWb;
2190 UNDEF_LSRPCBaseWb;
2191 UNDEF_LSRPCOffWb;
2192 lhs = LHS;
2193 if (LoadByte (state, instr, lhs, LUNSIGNED))
2194 LSBase = lhs + LSRegRHS;
2195 break;
2196
2197 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2198 if (BIT (4))
2199 {
2200 ARMul_UndefInstr (state, instr);
2201 break;
2202 }
2203 UNDEF_LSRBaseEQOffWb;
2204 UNDEF_LSRBaseEQDestWb;
2205 UNDEF_LSRPCBaseWb;
2206 UNDEF_LSRPCOffWb;
2207 lhs = LHS;
2208 state->NtransSig = LOW;
2209 if (StoreByte (state, instr, lhs))
2210 LSBase = lhs + LSRegRHS;
2211 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2212 break;
2213
2214 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2215 if (BIT (4))
2216 {
2217 ARMul_UndefInstr (state, instr);
2218 break;
2219 }
2220 UNDEF_LSRBaseEQOffWb;
2221 UNDEF_LSRBaseEQDestWb;
2222 UNDEF_LSRPCBaseWb;
2223 UNDEF_LSRPCOffWb;
2224 lhs = LHS;
2225 state->NtransSig = LOW;
2226 if (LoadByte (state, instr, lhs, LUNSIGNED))
2227 LSBase = lhs + LSRegRHS;
2228 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2229 break;
2230
2231
2232 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2233 if (BIT (4))
2234 {
2235 ARMul_UndefInstr (state, instr);
2236 break;
2237 }
2238 (void) StoreWord (state, instr, LHS - LSRegRHS);
2239 break;
2240
2241 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2242 if (BIT (4))
2243 {
2244 ARMul_UndefInstr (state, instr);
2245 break;
2246 }
2247 (void) LoadWord (state, instr, LHS - LSRegRHS);
2248 break;
2249
2250 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2251 if (BIT (4))
2252 {
2253 ARMul_UndefInstr (state, instr);
2254 break;
2255 }
2256 UNDEF_LSRBaseEQOffWb;
2257 UNDEF_LSRBaseEQDestWb;
2258 UNDEF_LSRPCBaseWb;
2259 UNDEF_LSRPCOffWb;
2260 temp = LHS - LSRegRHS;
2261 if (StoreWord (state, instr, temp))
2262 LSBase = temp;
2263 break;
2264
2265 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2266 if (BIT (4))
2267 {
2268 ARMul_UndefInstr (state, instr);
2269 break;
2270 }
2271 UNDEF_LSRBaseEQOffWb;
2272 UNDEF_LSRBaseEQDestWb;
2273 UNDEF_LSRPCBaseWb;
2274 UNDEF_LSRPCOffWb;
2275 temp = LHS - LSRegRHS;
2276 if (LoadWord (state, instr, temp))
2277 LSBase = temp;
2278 break;
2279
2280 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2281 if (BIT (4))
2282 {
2283 ARMul_UndefInstr (state, instr);
2284 break;
2285 }
2286 (void) StoreByte (state, instr, LHS - LSRegRHS);
2287 break;
2288
2289 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2290 if (BIT (4))
2291 {
2292 ARMul_UndefInstr (state, instr);
2293 break;
2294 }
2295 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2296 break;
2297
2298 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2299 if (BIT (4))
2300 {
2301 ARMul_UndefInstr (state, instr);
2302 break;
2303 }
2304 UNDEF_LSRBaseEQOffWb;
2305 UNDEF_LSRBaseEQDestWb;
2306 UNDEF_LSRPCBaseWb;
2307 UNDEF_LSRPCOffWb;
2308 temp = LHS - LSRegRHS;
2309 if (StoreByte (state, instr, temp))
2310 LSBase = temp;
2311 break;
2312
2313 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2314 if (BIT (4))
2315 {
2316 ARMul_UndefInstr (state, instr);
2317 break;
2318 }
2319 UNDEF_LSRBaseEQOffWb;
2320 UNDEF_LSRBaseEQDestWb;
2321 UNDEF_LSRPCBaseWb;
2322 UNDEF_LSRPCOffWb;
2323 temp = LHS - LSRegRHS;
2324 if (LoadByte (state, instr, temp, LUNSIGNED))
2325 LSBase = temp;
2326 break;
2327
2328 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2329 if (BIT (4))
2330 {
2331 ARMul_UndefInstr (state, instr);
2332 break;
2333 }
2334 (void) StoreWord (state, instr, LHS + LSRegRHS);
2335 break;
2336
2337 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2338 if (BIT (4))
2339 {
2340 ARMul_UndefInstr (state, instr);
2341 break;
2342 }
2343 (void) LoadWord (state, instr, LHS + LSRegRHS);
2344 break;
2345
2346 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2347 if (BIT (4))
2348 {
2349 ARMul_UndefInstr (state, instr);
2350 break;
2351 }
2352 UNDEF_LSRBaseEQOffWb;
2353 UNDEF_LSRBaseEQDestWb;
2354 UNDEF_LSRPCBaseWb;
2355 UNDEF_LSRPCOffWb;
2356 temp = LHS + LSRegRHS;
2357 if (StoreWord (state, instr, temp))
2358 LSBase = temp;
2359 break;
2360
2361 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2362 if (BIT (4))
2363 {
2364 ARMul_UndefInstr (state, instr);
2365 break;
2366 }
2367 UNDEF_LSRBaseEQOffWb;
2368 UNDEF_LSRBaseEQDestWb;
2369 UNDEF_LSRPCBaseWb;
2370 UNDEF_LSRPCOffWb;
2371 temp = LHS + LSRegRHS;
2372 if (LoadWord (state, instr, temp))
2373 LSBase = temp;
2374 break;
2375
2376 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2377 if (BIT (4))
2378 {
2379 ARMul_UndefInstr (state, instr);
2380 break;
2381 }
2382 (void) StoreByte (state, instr, LHS + LSRegRHS);
2383 break;
2384
2385 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2386 if (BIT (4))
2387 {
2388 ARMul_UndefInstr (state, instr);
2389 break;
2390 }
2391 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2392 break;
2393
2394 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2395 if (BIT (4))
2396 {
2397 ARMul_UndefInstr (state, instr);
2398 break;
2399 }
2400 UNDEF_LSRBaseEQOffWb;
2401 UNDEF_LSRBaseEQDestWb;
2402 UNDEF_LSRPCBaseWb;
2403 UNDEF_LSRPCOffWb;
2404 temp = LHS + LSRegRHS;
2405 if (StoreByte (state, instr, temp))
2406 LSBase = temp;
2407 break;
2408
2409 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2410 if (BIT (4))
2411 {
2412 /* Check for the special breakpoint opcode.
2413 This value should correspond to the value defined
2414 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2415 if (BITS (0, 19) == 0xfdefe)
2416 {
2417 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2418 ARMul_Abort (state, ARMul_SWIV);
2419 }
2420 else
2421 ARMul_UndefInstr (state, instr);
2422 break;
2423 }
2424 UNDEF_LSRBaseEQOffWb;
2425 UNDEF_LSRBaseEQDestWb;
2426 UNDEF_LSRPCBaseWb;
2427 UNDEF_LSRPCOffWb;
2428 temp = LHS + LSRegRHS;
2429 if (LoadByte (state, instr, temp, LUNSIGNED))
2430 LSBase = temp;
2431 break;
2432
2433 /***************************************************************************\
2434 * Multiple Data Transfer Instructions *
2435 \***************************************************************************/
2436
2437 case 0x80: /* Store, No WriteBack, Post Dec */
2438 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2439 break;
2440
2441 case 0x81: /* Load, No WriteBack, Post Dec */
2442 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2443 break;
2444
2445 case 0x82: /* Store, WriteBack, Post Dec */
2446 temp = LSBase - LSMNumRegs;
2447 STOREMULT (instr, temp + 4L, temp);
2448 break;
2449
2450 case 0x83: /* Load, WriteBack, Post Dec */
2451 temp = LSBase - LSMNumRegs;
2452 LOADMULT (instr, temp + 4L, temp);
2453 break;
2454
2455 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2456 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2457 break;
2458
2459 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2460 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2461 break;
2462
2463 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2464 temp = LSBase - LSMNumRegs;
2465 STORESMULT (instr, temp + 4L, temp);
2466 break;
2467
2468 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2469 temp = LSBase - LSMNumRegs;
2470 LOADSMULT (instr, temp + 4L, temp);
2471 break;
2472
2473
2474 case 0x88: /* Store, No WriteBack, Post Inc */
2475 STOREMULT (instr, LSBase, 0L);
2476 break;
2477
2478 case 0x89: /* Load, No WriteBack, Post Inc */
2479 LOADMULT (instr, LSBase, 0L);
2480 break;
2481
2482 case 0x8a: /* Store, WriteBack, Post Inc */
2483 temp = LSBase;
2484 STOREMULT (instr, temp, temp + LSMNumRegs);
2485 break;
2486
2487 case 0x8b: /* Load, WriteBack, Post Inc */
2488 temp = LSBase;
2489 LOADMULT (instr, temp, temp + LSMNumRegs);
2490 break;
2491
2492 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2493 STORESMULT (instr, LSBase, 0L);
2494 break;
2495
2496 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2497 LOADSMULT (instr, LSBase, 0L);
2498 break;
2499
2500 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2501 temp = LSBase;
2502 STORESMULT (instr, temp, temp + LSMNumRegs);
2503 break;
2504
2505 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2506 temp = LSBase;
2507 LOADSMULT (instr, temp, temp + LSMNumRegs);
2508 break;
2509
2510
2511 case 0x90: /* Store, No WriteBack, Pre Dec */
2512 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
2513 break;
2514
2515 case 0x91: /* Load, No WriteBack, Pre Dec */
2516 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
2517 break;
2518
2519 case 0x92: /* Store, WriteBack, Pre Dec */
2520 temp = LSBase - LSMNumRegs;
2521 STOREMULT (instr, temp, temp);
2522 break;
2523
2524 case 0x93: /* Load, WriteBack, Pre Dec */
2525 temp = LSBase - LSMNumRegs;
2526 LOADMULT (instr, temp, temp);
2527 break;
2528
2529 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2530 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
2531 break;
2532
2533 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2534 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
2535 break;
2536
2537 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2538 temp = LSBase - LSMNumRegs;
2539 STORESMULT (instr, temp, temp);
2540 break;
2541
2542 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2543 temp = LSBase - LSMNumRegs;
2544 LOADSMULT (instr, temp, temp);
2545 break;
2546
2547
2548 case 0x98: /* Store, No WriteBack, Pre Inc */
2549 STOREMULT (instr, LSBase + 4L, 0L);
2550 break;
2551
2552 case 0x99: /* Load, No WriteBack, Pre Inc */
2553 LOADMULT (instr, LSBase + 4L, 0L);
2554 break;
2555
2556 case 0x9a: /* Store, WriteBack, Pre Inc */
2557 temp = LSBase;
2558 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
2559 break;
2560
2561 case 0x9b: /* Load, WriteBack, Pre Inc */
2562 temp = LSBase;
2563 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
2564 break;
2565
2566 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2567 STORESMULT (instr, LSBase + 4L, 0L);
2568 break;
2569
2570 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2571 LOADSMULT (instr, LSBase + 4L, 0L);
2572 break;
2573
2574 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2575 temp = LSBase;
2576 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
2577 break;
2578
2579 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2580 temp = LSBase;
2581 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
2582 break;
2583
2584 /***************************************************************************\
2585 * Branch forward *
2586 \***************************************************************************/
2587
2588 case 0xa0:
2589 case 0xa1:
2590 case 0xa2:
2591 case 0xa3:
2592 case 0xa4:
2593 case 0xa5:
2594 case 0xa6:
2595 case 0xa7:
2596 state->Reg[15] = pc + 8 + POSBRANCH;
2597 FLUSHPIPE;
2598 break;
2599
2600 /***************************************************************************\
2601 * Branch backward *
2602 \***************************************************************************/
2603
2604 case 0xa8:
2605 case 0xa9:
2606 case 0xaa:
2607 case 0xab:
2608 case 0xac:
2609 case 0xad:
2610 case 0xae:
2611 case 0xaf:
2612 state->Reg[15] = pc + 8 + NEGBRANCH;
2613 FLUSHPIPE;
2614 break;
2615
2616 /***************************************************************************\
2617 * Branch and Link forward *
2618 \***************************************************************************/
2619
2620 case 0xb0:
2621 case 0xb1:
2622 case 0xb2:
2623 case 0xb3:
2624 case 0xb4:
2625 case 0xb5:
2626 case 0xb6:
2627 case 0xb7:
2628 #ifdef MODE32
2629 state->Reg[14] = pc + 4; /* put PC into Link */
2630 #else
2631 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
2632 #endif
2633 state->Reg[15] = pc + 8 + POSBRANCH;
2634 FLUSHPIPE;
2635 break;
2636
2637 /***************************************************************************\
2638 * Branch and Link backward *
2639 \***************************************************************************/
2640
2641 case 0xb8:
2642 case 0xb9:
2643 case 0xba:
2644 case 0xbb:
2645 case 0xbc:
2646 case 0xbd:
2647 case 0xbe:
2648 case 0xbf:
2649 #ifdef MODE32
2650 state->Reg[14] = pc + 4; /* put PC into Link */
2651 #else
2652 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */
2653 #endif
2654 state->Reg[15] = pc + 8 + NEGBRANCH;
2655 FLUSHPIPE;
2656 break;
2657
2658 /***************************************************************************\
2659 * Co-Processor Data Transfers *
2660 \***************************************************************************/
2661
2662 case 0xc4:
2663 case 0xc0: /* Store , No WriteBack , Post Dec */
2664 ARMul_STC (state, instr, LHS);
2665 break;
2666
2667 case 0xc5:
2668 case 0xc1: /* Load , No WriteBack , Post Dec */
2669 ARMul_LDC (state, instr, LHS);
2670 break;
2671
2672 case 0xc2:
2673 case 0xc6: /* Store , WriteBack , Post Dec */
2674 lhs = LHS;
2675 state->Base = lhs - LSCOff;
2676 ARMul_STC (state, instr, lhs);
2677 break;
2678
2679 case 0xc3:
2680 case 0xc7: /* Load , WriteBack , Post Dec */
2681 lhs = LHS;
2682 state->Base = lhs - LSCOff;
2683 ARMul_LDC (state, instr, lhs);
2684 break;
2685
2686 case 0xc8:
2687 case 0xcc: /* Store , No WriteBack , Post Inc */
2688 ARMul_STC (state, instr, LHS);
2689 break;
2690
2691 case 0xc9:
2692 case 0xcd: /* Load , No WriteBack , Post Inc */
2693 ARMul_LDC (state, instr, LHS);
2694 break;
2695
2696 case 0xca:
2697 case 0xce: /* Store , WriteBack , Post Inc */
2698 lhs = LHS;
2699 state->Base = lhs + LSCOff;
2700 ARMul_STC (state, instr, LHS);
2701 break;
2702
2703 case 0xcb:
2704 case 0xcf: /* Load , WriteBack , Post Inc */
2705 lhs = LHS;
2706 state->Base = lhs + LSCOff;
2707 ARMul_LDC (state, instr, LHS);
2708 break;
2709
2710
2711 case 0xd0:
2712 case 0xd4: /* Store , No WriteBack , Pre Dec */
2713 ARMul_STC (state, instr, LHS - LSCOff);
2714 break;
2715
2716 case 0xd1:
2717 case 0xd5: /* Load , No WriteBack , Pre Dec */
2718 ARMul_LDC (state, instr, LHS - LSCOff);
2719 break;
2720
2721 case 0xd2:
2722 case 0xd6: /* Store , WriteBack , Pre Dec */
2723 lhs = LHS - LSCOff;
2724 state->Base = lhs;
2725 ARMul_STC (state, instr, lhs);
2726 break;
2727
2728 case 0xd3:
2729 case 0xd7: /* Load , WriteBack , Pre Dec */
2730 lhs = LHS - LSCOff;
2731 state->Base = lhs;
2732 ARMul_LDC (state, instr, lhs);
2733 break;
2734
2735 case 0xd8:
2736 case 0xdc: /* Store , No WriteBack , Pre Inc */
2737 ARMul_STC (state, instr, LHS + LSCOff);
2738 break;
2739
2740 case 0xd9:
2741 case 0xdd: /* Load , No WriteBack , Pre Inc */
2742 ARMul_LDC (state, instr, LHS + LSCOff);
2743 break;
2744
2745 case 0xda:
2746 case 0xde: /* Store , WriteBack , Pre Inc */
2747 lhs = LHS + LSCOff;
2748 state->Base = lhs;
2749 ARMul_STC (state, instr, lhs);
2750 break;
2751
2752 case 0xdb:
2753 case 0xdf: /* Load , WriteBack , Pre Inc */
2754 lhs = LHS + LSCOff;
2755 state->Base = lhs;
2756 ARMul_LDC (state, instr, lhs);
2757 break;
2758
2759 /***************************************************************************\
2760 * Co-Processor Register Transfers (MCR) and Data Ops *
2761 \***************************************************************************/
2762
2763 case 0xe2:
2764 case 0xe0:
2765 case 0xe4:
2766 case 0xe6:
2767 case 0xe8:
2768 case 0xea:
2769 case 0xec:
2770 case 0xee:
2771 if (BIT (4))
2772 { /* MCR */
2773 if (DESTReg == 15)
2774 {
2775 UNDEF_MCRPC;
2776 #ifdef MODE32
2777 ARMul_MCR (state, instr, state->Reg[15] + isize);
2778 #else
2779 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
2780 ((state->Reg[15] + isize) & R15PCBITS));
2781 #endif
2782 }
2783 else
2784 ARMul_MCR (state, instr, DEST);
2785 }
2786 else /* CDP Part 1 */
2787 ARMul_CDP (state, instr);
2788 break;
2789
2790 /***************************************************************************\
2791 * Co-Processor Register Transfers (MRC) and Data Ops *
2792 \***************************************************************************/
2793
2794 case 0xe1:
2795 case 0xe3:
2796 case 0xe5:
2797 case 0xe7:
2798 case 0xe9:
2799 case 0xeb:
2800 case 0xed:
2801 case 0xef:
2802 if (BIT (4))
2803 { /* MRC */
2804 temp = ARMul_MRC (state, instr);
2805 if (DESTReg == 15)
2806 {
2807 ASSIGNN ((temp & NBIT) != 0);
2808 ASSIGNZ ((temp & ZBIT) != 0);
2809 ASSIGNC ((temp & CBIT) != 0);
2810 ASSIGNV ((temp & VBIT) != 0);
2811 }
2812 else
2813 DEST = temp;
2814 }
2815 else /* CDP Part 2 */
2816 ARMul_CDP (state, instr);
2817 break;
2818
2819 /***************************************************************************\
2820 * SWI instruction *
2821 \***************************************************************************/
2822
2823 case 0xf0:
2824 case 0xf1:
2825 case 0xf2:
2826 case 0xf3:
2827 case 0xf4:
2828 case 0xf5:
2829 case 0xf6:
2830 case 0xf7:
2831 case 0xf8:
2832 case 0xf9:
2833 case 0xfa:
2834 case 0xfb:
2835 case 0xfc:
2836 case 0xfd:
2837 case 0xfe:
2838 case 0xff:
2839 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
2840 { /* a prefetch abort */
2841 ARMul_Abort (state, ARMul_PrefetchAbortV);
2842 break;
2843 }
2844
2845 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
2846 {
2847 ARMul_Abort (state, ARMul_SWIV);
2848 }
2849 break;
2850 } /* 256 way main switch */
2851 } /* if temp */
2852
2853 #ifdef MODET
2854 donext:
2855 #endif
2856
2857 #ifdef NEED_UI_LOOP_HOOK
2858 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
2859 {
2860 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
2861 ui_loop_hook (0);
2862 }
2863 #endif /* NEED_UI_LOOP_HOOK */
2864
2865 if (state->Emulate == ONCE)
2866 state->Emulate = STOP;
2867 else if (state->Emulate != RUN)
2868 break;
2869 }
2870 while (!stop_simulator); /* do loop */
2871
2872 state->decoded = decoded;
2873 state->loaded = loaded;
2874 state->pc = pc;
2875 return (pc);
2876 } /* Emulate 26/32 in instruction based mode */
2877
2878
2879 /***************************************************************************\
2880 * This routine evaluates most Data Processing register RHS's with the S *
2881 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2882 * filters the common case of an unshifted register with in line code *
2883 \***************************************************************************/
2884
2885 static ARMword
2886 GetDPRegRHS (ARMul_State * state, ARMword instr)
2887 {
2888 ARMword shamt, base;
2889
2890 base = RHSReg;
2891 if (BIT (4))
2892 { /* shift amount in a register */
2893 UNDEF_Shift;
2894 INCPC;
2895 #ifndef MODE32
2896 if (base == 15)
2897 base = ECC | ER15INT | R15PC | EMODE;
2898 else
2899 #endif
2900 base = state->Reg[base];
2901 ARMul_Icycles (state, 1, 0L);
2902 shamt = state->Reg[BITS (8, 11)] & 0xff;
2903 switch ((int) BITS (5, 6))
2904 {
2905 case LSL:
2906 if (shamt == 0)
2907 return (base);
2908 else if (shamt >= 32)
2909 return (0);
2910 else
2911 return (base << shamt);
2912 case LSR:
2913 if (shamt == 0)
2914 return (base);
2915 else if (shamt >= 32)
2916 return (0);
2917 else
2918 return (base >> shamt);
2919 case ASR:
2920 if (shamt == 0)
2921 return (base);
2922 else if (shamt >= 32)
2923 return ((ARMword) ((long int) base >> 31L));
2924 else
2925 return ((ARMword) ((long int) base >> (int) shamt));
2926 case ROR:
2927 shamt &= 0x1f;
2928 if (shamt == 0)
2929 return (base);
2930 else
2931 return ((base << (32 - shamt)) | (base >> shamt));
2932 }
2933 }
2934 else
2935 { /* shift amount is a constant */
2936 #ifndef MODE32
2937 if (base == 15)
2938 base = ECC | ER15INT | R15PC | EMODE;
2939 else
2940 #endif
2941 base = state->Reg[base];
2942 shamt = BITS (7, 11);
2943 switch ((int) BITS (5, 6))
2944 {
2945 case LSL:
2946 return (base << shamt);
2947 case LSR:
2948 if (shamt == 0)
2949 return (0);
2950 else
2951 return (base >> shamt);
2952 case ASR:
2953 if (shamt == 0)
2954 return ((ARMword) ((long int) base >> 31L));
2955 else
2956 return ((ARMword) ((long int) base >> (int) shamt));
2957 case ROR:
2958 if (shamt == 0) /* its an RRX */
2959 return ((base >> 1) | (CFLAG << 31));
2960 else
2961 return ((base << (32 - shamt)) | (base >> shamt));
2962 }
2963 }
2964 return (0); /* just to shut up lint */
2965 }
2966
2967 /***************************************************************************\
2968 * This routine evaluates most Logical Data Processing register RHS's *
2969 * with the S bit set. It is intended to be called from the macro *
2970 * DPSRegRHS, which filters the common case of an unshifted register *
2971 * with in line code *
2972 \***************************************************************************/
2973
2974 static ARMword
2975 GetDPSRegRHS (ARMul_State * state, ARMword instr)
2976 {
2977 ARMword shamt, base;
2978
2979 base = RHSReg;
2980 if (BIT (4))
2981 { /* shift amount in a register */
2982 UNDEF_Shift;
2983 INCPC;
2984 #ifndef MODE32
2985 if (base == 15)
2986 base = ECC | ER15INT | R15PC | EMODE;
2987 else
2988 #endif
2989 base = state->Reg[base];
2990 ARMul_Icycles (state, 1, 0L);
2991 shamt = state->Reg[BITS (8, 11)] & 0xff;
2992 switch ((int) BITS (5, 6))
2993 {
2994 case LSL:
2995 if (shamt == 0)
2996 return (base);
2997 else if (shamt == 32)
2998 {
2999 ASSIGNC (base & 1);
3000 return (0);
3001 }
3002 else if (shamt > 32)
3003 {
3004 CLEARC;
3005 return (0);
3006 }
3007 else
3008 {
3009 ASSIGNC ((base >> (32 - shamt)) & 1);
3010 return (base << shamt);
3011 }
3012 case LSR:
3013 if (shamt == 0)
3014 return (base);
3015 else if (shamt == 32)
3016 {
3017 ASSIGNC (base >> 31);
3018 return (0);
3019 }
3020 else if (shamt > 32)
3021 {
3022 CLEARC;
3023 return (0);
3024 }
3025 else
3026 {
3027 ASSIGNC ((base >> (shamt - 1)) & 1);
3028 return (base >> shamt);
3029 }
3030 case ASR:
3031 if (shamt == 0)
3032 return (base);
3033 else if (shamt >= 32)
3034 {
3035 ASSIGNC (base >> 31L);
3036 return ((ARMword) ((long int) base >> 31L));
3037 }
3038 else
3039 {
3040 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3041 return ((ARMword) ((long int) base >> (int) shamt));
3042 }
3043 case ROR:
3044 if (shamt == 0)
3045 return (base);
3046 shamt &= 0x1f;
3047 if (shamt == 0)
3048 {
3049 ASSIGNC (base >> 31);
3050 return (base);
3051 }
3052 else
3053 {
3054 ASSIGNC ((base >> (shamt - 1)) & 1);
3055 return ((base << (32 - shamt)) | (base >> shamt));
3056 }
3057 }
3058 }
3059 else
3060 { /* shift amount is a constant */
3061 #ifndef MODE32
3062 if (base == 15)
3063 base = ECC | ER15INT | R15PC | EMODE;
3064 else
3065 #endif
3066 base = state->Reg[base];
3067 shamt = BITS (7, 11);
3068 switch ((int) BITS (5, 6))
3069 {
3070 case LSL:
3071 ASSIGNC ((base >> (32 - shamt)) & 1);
3072 return (base << shamt);
3073 case LSR:
3074 if (shamt == 0)
3075 {
3076 ASSIGNC (base >> 31);
3077 return (0);
3078 }
3079 else
3080 {
3081 ASSIGNC ((base >> (shamt - 1)) & 1);
3082 return (base >> shamt);
3083 }
3084 case ASR:
3085 if (shamt == 0)
3086 {
3087 ASSIGNC (base >> 31L);
3088 return ((ARMword) ((long int) base >> 31L));
3089 }
3090 else
3091 {
3092 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3093 return ((ARMword) ((long int) base >> (int) shamt));
3094 }
3095 case ROR:
3096 if (shamt == 0)
3097 { /* its an RRX */
3098 shamt = CFLAG;
3099 ASSIGNC (base & 1);
3100 return ((base >> 1) | (shamt << 31));
3101 }
3102 else
3103 {
3104 ASSIGNC ((base >> (shamt - 1)) & 1);
3105 return ((base << (32 - shamt)) | (base >> shamt));
3106 }
3107 }
3108 }
3109 return (0); /* just to shut up lint */
3110 }
3111
3112 /***************************************************************************\
3113 * This routine handles writes to register 15 when the S bit is not set. *
3114 \***************************************************************************/
3115
3116 static void
3117 WriteR15 (ARMul_State * state, ARMword src)
3118 {
3119 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
3120 #ifdef MODE32
3121 state->Reg[15] = src & PCBITS & ~0x1;
3122 #else
3123 state->Reg[15] = (src & R15PCBITS & ~0x1) | ECC | ER15INT | EMODE;
3124 ARMul_R15Altered (state);
3125 #endif
3126 FLUSHPIPE;
3127 }
3128
3129 /***************************************************************************\
3130 * This routine handles writes to register 15 when the S bit is set. *
3131 \***************************************************************************/
3132
3133 static void
3134 WriteSR15 (ARMul_State * state, ARMword src)
3135 {
3136 #ifdef MODE32
3137 state->Reg[15] = src & PCBITS;
3138 if (state->Bank > 0)
3139 {
3140 state->Cpsr = state->Spsr[state->Bank];
3141 ARMul_CPSRAltered (state);
3142 }
3143 #else
3144 if (state->Bank == USERBANK)
3145 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3146 else
3147 state->Reg[15] = src;
3148 ARMul_R15Altered (state);
3149 #endif
3150 FLUSHPIPE;
3151 }
3152
3153 /***************************************************************************\
3154 * This routine evaluates most Load and Store register RHS's. It is *
3155 * intended to be called from the macro LSRegRHS, which filters the *
3156 * common case of an unshifted register with in line code *
3157 \***************************************************************************/
3158
3159 static ARMword
3160 GetLSRegRHS (ARMul_State * state, ARMword instr)
3161 {
3162 ARMword shamt, base;
3163
3164 base = RHSReg;
3165 #ifndef MODE32
3166 if (base == 15)
3167 base = ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but .... */
3168 else
3169 #endif
3170 base = state->Reg[base];
3171
3172 shamt = BITS (7, 11);
3173 switch ((int) BITS (5, 6))
3174 {
3175 case LSL:
3176 return (base << shamt);
3177 case LSR:
3178 if (shamt == 0)
3179 return (0);
3180 else
3181 return (base >> shamt);
3182 case ASR:
3183 if (shamt == 0)
3184 return ((ARMword) ((long int) base >> 31L));
3185 else
3186 return ((ARMword) ((long int) base >> (int) shamt));
3187 case ROR:
3188 if (shamt == 0) /* its an RRX */
3189 return ((base >> 1) | (CFLAG << 31));
3190 else
3191 return ((base << (32 - shamt)) | (base >> shamt));
3192 }
3193 return (0); /* just to shut up lint */
3194 }
3195
3196 /***************************************************************************\
3197 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3198 \***************************************************************************/
3199
3200 static ARMword
3201 GetLS7RHS (ARMul_State * state, ARMword instr)
3202 {
3203 if (BIT (22) == 0)
3204 { /* register */
3205 #ifndef MODE32
3206 if (RHSReg == 15)
3207 return ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but ... */
3208 #endif
3209 return state->Reg[RHSReg];
3210 }
3211
3212 /* else immediate */
3213 return BITS (0, 3) | (BITS (8, 11) << 4);
3214 }
3215
3216 /***************************************************************************\
3217 * This function does the work of loading a word for a LDR instruction. *
3218 \***************************************************************************/
3219
3220 static unsigned
3221 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3222 {
3223 ARMword dest;
3224
3225 BUSUSEDINCPCS;
3226 #ifndef MODE32
3227 if (ADDREXCEPT (address))
3228 {
3229 INTERNALABORT (address);
3230 }
3231 #endif
3232 dest = ARMul_LoadWordN (state, address);
3233 if (state->Aborted)
3234 {
3235 TAKEABORT;
3236 return (state->lateabtSig);
3237 }
3238 if (address & 3)
3239 dest = ARMul_Align (state, address, dest);
3240 WRITEDEST (dest);
3241 ARMul_Icycles (state, 1, 0L);
3242
3243 return (DESTReg != LHSReg);
3244 }
3245
3246 #ifdef MODET
3247 /***************************************************************************\
3248 * This function does the work of loading a halfword. *
3249 \***************************************************************************/
3250
3251 static unsigned
3252 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3253 int signextend)
3254 {
3255 ARMword dest;
3256
3257 BUSUSEDINCPCS;
3258 #ifndef MODE32
3259 if (ADDREXCEPT (address))
3260 {
3261 INTERNALABORT (address);
3262 }
3263 #endif
3264 dest = ARMul_LoadHalfWord (state, address);
3265 if (state->Aborted)
3266 {
3267 TAKEABORT;
3268 return (state->lateabtSig);
3269 }
3270 UNDEF_LSRBPC;
3271 if (signextend)
3272 {
3273 if (dest & 1 << (16 - 1))
3274 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
3275 }
3276 WRITEDEST (dest);
3277 ARMul_Icycles (state, 1, 0L);
3278 return (DESTReg != LHSReg);
3279 }
3280
3281 #endif /* MODET */
3282
3283 /***************************************************************************\
3284 * This function does the work of loading a byte for a LDRB instruction. *
3285 \***************************************************************************/
3286
3287 static unsigned
3288 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
3289 {
3290 ARMword dest;
3291
3292 BUSUSEDINCPCS;
3293 #ifndef MODE32
3294 if (ADDREXCEPT (address))
3295 {
3296 INTERNALABORT (address);
3297 }
3298 #endif
3299 dest = ARMul_LoadByte (state, address);
3300 if (state->Aborted)
3301 {
3302 TAKEABORT;
3303 return (state->lateabtSig);
3304 }
3305 UNDEF_LSRBPC;
3306 if (signextend)
3307 {
3308 if (dest & 1 << (8 - 1))
3309 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
3310 }
3311 WRITEDEST (dest);
3312 ARMul_Icycles (state, 1, 0L);
3313 return (DESTReg != LHSReg);
3314 }
3315
3316 /***************************************************************************\
3317 * This function does the work of storing a word from a STR instruction. *
3318 \***************************************************************************/
3319
3320 static unsigned
3321 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
3322 {
3323 BUSUSEDINCPCN;
3324 #ifndef MODE32
3325 if (DESTReg == 15)
3326 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3327 #endif
3328 #ifdef MODE32
3329 ARMul_StoreWordN (state, address, DEST);
3330 #else
3331 if (VECTORACCESS (address) || ADDREXCEPT (address))
3332 {
3333 INTERNALABORT (address);
3334 (void) ARMul_LoadWordN (state, address);
3335 }
3336 else
3337 ARMul_StoreWordN (state, address, DEST);
3338 #endif
3339 if (state->Aborted)
3340 {
3341 TAKEABORT;
3342 return (state->lateabtSig);
3343 }
3344 return (TRUE);
3345 }
3346
3347 #ifdef MODET
3348 /***************************************************************************\
3349 * This function does the work of storing a byte for a STRH instruction. *
3350 \***************************************************************************/
3351
3352 static unsigned
3353 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
3354 {
3355 BUSUSEDINCPCN;
3356
3357 #ifndef MODE32
3358 if (DESTReg == 15)
3359 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3360 #endif
3361
3362 #ifdef MODE32
3363 ARMul_StoreHalfWord (state, address, DEST);
3364 #else
3365 if (VECTORACCESS (address) || ADDREXCEPT (address))
3366 {
3367 INTERNALABORT (address);
3368 (void) ARMul_LoadHalfWord (state, address);
3369 }
3370 else
3371 ARMul_StoreHalfWord (state, address, DEST);
3372 #endif
3373
3374 if (state->Aborted)
3375 {
3376 TAKEABORT;
3377 return (state->lateabtSig);
3378 }
3379
3380 return (TRUE);
3381 }
3382
3383 #endif /* MODET */
3384
3385 /***************************************************************************\
3386 * This function does the work of storing a byte for a STRB instruction. *
3387 \***************************************************************************/
3388
3389 static unsigned
3390 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
3391 {
3392 BUSUSEDINCPCN;
3393 #ifndef MODE32
3394 if (DESTReg == 15)
3395 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
3396 #endif
3397 #ifdef MODE32
3398 ARMul_StoreByte (state, address, DEST);
3399 #else
3400 if (VECTORACCESS (address) || ADDREXCEPT (address))
3401 {
3402 INTERNALABORT (address);
3403 (void) ARMul_LoadByte (state, address);
3404 }
3405 else
3406 ARMul_StoreByte (state, address, DEST);
3407 #endif
3408 if (state->Aborted)
3409 {
3410 TAKEABORT;
3411 return (state->lateabtSig);
3412 }
3413 UNDEF_LSRBPC;
3414 return (TRUE);
3415 }
3416
3417 /***************************************************************************\
3418 * This function does the work of loading the registers listed in an LDM *
3419 * instruction, when the S bit is clear. The code here is always increment *
3420 * after, it's up to the caller to get the input address correct and to *
3421 * handle base register modification. *
3422 \***************************************************************************/
3423
3424 static void
3425 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
3426 {
3427 ARMword dest, temp;
3428
3429 UNDEF_LSMNoRegs;
3430 UNDEF_LSMPCBase;
3431 UNDEF_LSMBaseInListWb;
3432 BUSUSEDINCPCS;
3433 #ifndef MODE32
3434 if (ADDREXCEPT (address))
3435 {
3436 INTERNALABORT (address);
3437 }
3438 #endif
3439 if (BIT (21) && LHSReg != 15)
3440 LSBase = WBBase;
3441
3442 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3443 dest = ARMul_LoadWordN (state, address);
3444 if (!state->abortSig && !state->Aborted)
3445 state->Reg[temp++] = dest;
3446 else if (!state->Aborted)
3447 state->Aborted = ARMul_DataAbortV;
3448
3449 for (; temp < 16; temp++) /* S cycles from here on */
3450 if (BIT (temp))
3451 { /* load this register */
3452 address += 4;
3453 dest = ARMul_LoadWordS (state, address);
3454 if (!state->abortSig && !state->Aborted)
3455 state->Reg[temp] = dest;
3456 else if (!state->Aborted)
3457 state->Aborted = ARMul_DataAbortV;
3458 }
3459
3460 if (BIT (15))
3461 { /* PC is in the reg list */
3462 #ifdef MODE32
3463 state->Reg[15] = PC;
3464 #endif
3465 FLUSHPIPE;
3466 }
3467
3468 ARMul_Icycles (state, 1, 0L); /* to write back the final register */
3469
3470 if (state->Aborted)
3471 {
3472 if (BIT (21) && LHSReg != 15)
3473 LSBase = WBBase;
3474 TAKEABORT;
3475 }
3476 }
3477
3478 /***************************************************************************\
3479 * This function does the work of loading the registers listed in an LDM *
3480 * instruction, when the S bit is set. The code here is always increment *
3481 * after, it's up to the caller to get the input address correct and to *
3482 * handle base register modification. *
3483 \***************************************************************************/
3484
3485 static void
3486 LoadSMult (ARMul_State * state, ARMword instr,
3487 ARMword address, ARMword WBBase)
3488 {
3489 ARMword dest, temp;
3490
3491 UNDEF_LSMNoRegs;
3492 UNDEF_LSMPCBase;
3493 UNDEF_LSMBaseInListWb;
3494 BUSUSEDINCPCS;
3495 #ifndef MODE32
3496 if (ADDREXCEPT (address))
3497 {
3498 INTERNALABORT (address);
3499 }
3500 #endif
3501
3502 if (!BIT (15) && state->Bank != USERBANK)
3503 {
3504 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); /* temporary reg bank switch */
3505 UNDEF_LSMUserBankWb;
3506 }
3507
3508 if (BIT (21) && LHSReg != 15)
3509 LSBase = WBBase;
3510
3511 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3512 dest = ARMul_LoadWordN (state, address);
3513 if (!state->abortSig)
3514 state->Reg[temp++] = dest;
3515 else if (!state->Aborted)
3516 state->Aborted = ARMul_DataAbortV;
3517
3518 for (; temp < 16; temp++) /* S cycles from here on */
3519 if (BIT (temp))
3520 { /* load this register */
3521 address += 4;
3522 dest = ARMul_LoadWordS (state, address);
3523 if (!state->abortSig || state->Aborted)
3524 state->Reg[temp] = dest;
3525 else if (!state->Aborted)
3526 state->Aborted = ARMul_DataAbortV;
3527 }
3528
3529 if (BIT (15))
3530 { /* PC is in the reg list */
3531 #ifdef MODE32
3532 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
3533 {
3534 state->Cpsr = GETSPSR (state->Bank);
3535 ARMul_CPSRAltered (state);
3536 }
3537 state->Reg[15] = PC;
3538 #else
3539 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
3540 { /* protect bits in user mode */
3541 ASSIGNN ((state->Reg[15] & NBIT) != 0);
3542 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
3543 ASSIGNC ((state->Reg[15] & CBIT) != 0);
3544 ASSIGNV ((state->Reg[15] & VBIT) != 0);
3545 }
3546 else
3547 ARMul_R15Altered (state);
3548 #endif
3549 FLUSHPIPE;
3550 }
3551
3552 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
3553 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); /* restore the correct bank */
3554
3555 ARMul_Icycles (state, 1, 0L); /* to write back the final register */
3556
3557 if (state->Aborted)
3558 {
3559 if (BIT (21) && LHSReg != 15)
3560 LSBase = WBBase;
3561 TAKEABORT;
3562 }
3563
3564 }
3565
3566 /***************************************************************************\
3567 * This function does the work of storing the registers listed in an STM *
3568 * instruction, when the S bit is clear. The code here is always increment *
3569 * after, it's up to the caller to get the input address correct and to *
3570 * handle base register modification. *
3571 \***************************************************************************/
3572
3573 static void
3574 StoreMult (ARMul_State * state, ARMword instr,
3575 ARMword address, ARMword WBBase)
3576 {
3577 ARMword temp;
3578
3579 UNDEF_LSMNoRegs;
3580 UNDEF_LSMPCBase;
3581 UNDEF_LSMBaseInListWb;
3582 if (!TFLAG)
3583 {
3584 BUSUSEDINCPCN; /* N-cycle, increment the PC and update the NextInstr state */
3585 }
3586
3587 #ifndef MODE32
3588 if (VECTORACCESS (address) || ADDREXCEPT (address))
3589 {
3590 INTERNALABORT (address);
3591 }
3592 if (BIT (15))
3593 PATCHR15;
3594 #endif
3595
3596 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3597 #ifdef MODE32
3598 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3599 #else
3600 if (state->Aborted)
3601 {
3602 (void) ARMul_LoadWordN (state, address);
3603 for (; temp < 16; temp++) /* Fake the Stores as Loads */
3604 if (BIT (temp))
3605 { /* save this register */
3606 address += 4;
3607 (void) ARMul_LoadWordS (state, address);
3608 }
3609 if (BIT (21) && LHSReg != 15)
3610 LSBase = WBBase;
3611 TAKEABORT;
3612 return;
3613 }
3614 else
3615 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3616 #endif
3617 if (state->abortSig && !state->Aborted)
3618 state->Aborted = ARMul_DataAbortV;
3619
3620 if (BIT (21) && LHSReg != 15)
3621 LSBase = WBBase;
3622
3623 for (; temp < 16; temp++) /* S cycles from here on */
3624 if (BIT (temp))
3625 { /* save this register */
3626 address += 4;
3627 ARMul_StoreWordS (state, address, state->Reg[temp]);
3628 if (state->abortSig && !state->Aborted)
3629 state->Aborted = ARMul_DataAbortV;
3630 }
3631 if (state->Aborted)
3632 {
3633 TAKEABORT;
3634 }
3635 }
3636
3637 /***************************************************************************\
3638 * This function does the work of storing the registers listed in an STM *
3639 * instruction when the S bit is set. The code here is always increment *
3640 * after, it's up to the caller to get the input address correct and to *
3641 * handle base register modification. *
3642 \***************************************************************************/
3643
3644 static void
3645 StoreSMult (ARMul_State * state, ARMword instr,
3646 ARMword address, ARMword WBBase)
3647 {
3648 ARMword temp;
3649
3650 UNDEF_LSMNoRegs;
3651 UNDEF_LSMPCBase;
3652 UNDEF_LSMBaseInListWb;
3653 BUSUSEDINCPCN;
3654 #ifndef MODE32
3655 if (VECTORACCESS (address) || ADDREXCEPT (address))
3656 {
3657 INTERNALABORT (address);
3658 }
3659 if (BIT (15))
3660 PATCHR15;
3661 #endif
3662
3663 if (state->Bank != USERBANK)
3664 {
3665 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); /* Force User Bank */
3666 UNDEF_LSMUserBankWb;
3667 }
3668
3669 for (temp = 0; !BIT (temp); temp++); /* N cycle first */
3670 #ifdef MODE32
3671 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3672 #else
3673 if (state->Aborted)
3674 {
3675 (void) ARMul_LoadWordN (state, address);
3676 for (; temp < 16; temp++) /* Fake the Stores as Loads */
3677 if (BIT (temp))
3678 { /* save this register */
3679 address += 4;
3680 (void) ARMul_LoadWordS (state, address);
3681 }
3682 if (BIT (21) && LHSReg != 15)
3683 LSBase = WBBase;
3684 TAKEABORT;
3685 return;
3686 }
3687 else
3688 ARMul_StoreWordN (state, address, state->Reg[temp++]);
3689 #endif
3690 if (state->abortSig && !state->Aborted)
3691 state->Aborted = ARMul_DataAbortV;
3692
3693 if (BIT (21) && LHSReg != 15)
3694 LSBase = WBBase;
3695
3696 for (; temp < 16; temp++) /* S cycles from here on */
3697 if (BIT (temp))
3698 { /* save this register */
3699 address += 4;
3700 ARMul_StoreWordS (state, address, state->Reg[temp]);
3701 if (state->abortSig && !state->Aborted)
3702 state->Aborted = ARMul_DataAbortV;
3703 }
3704
3705 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
3706 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); /* restore the correct bank */
3707
3708 if (state->Aborted)
3709 {
3710 TAKEABORT;
3711 }
3712 }
3713
3714 /***************************************************************************\
3715 * This function does the work of adding two 32bit values together, and *
3716 * calculating if a carry has occurred. *
3717 \***************************************************************************/
3718
3719 static ARMword
3720 Add32 (ARMword a1, ARMword a2, int *carry)
3721 {
3722 ARMword result = (a1 + a2);
3723 unsigned int uresult = (unsigned int) result;
3724 unsigned int ua1 = (unsigned int) a1;
3725
3726 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3727 or (result > RdLo) then we have no carry: */
3728 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
3729 *carry = 1;
3730 else
3731 *carry = 0;
3732
3733 return (result);
3734 }
3735
3736 /***************************************************************************\
3737 * This function does the work of multiplying two 32bit values to give a *
3738 * 64bit result. *
3739 \***************************************************************************/
3740
3741 static unsigned
3742 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
3743 {
3744 int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */
3745 ARMword RdHi = 0, RdLo = 0, Rm;
3746 int scount; /* cycle count */
3747
3748 nRdHi = BITS (16, 19);
3749 nRdLo = BITS (12, 15);
3750 nRs = BITS (8, 11);
3751 nRm = BITS (0, 3);
3752
3753 /* Needed to calculate the cycle count: */
3754 Rm = state->Reg[nRm];
3755
3756 /* Check for illegal operand combinations first: */
3757 if (nRdHi != 15
3758 && nRdLo != 15
3759 && nRs != 15
3760 && nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm)
3761 {
3762 ARMword lo, mid1, mid2, hi; /* intermediate results */
3763 int carry;
3764 ARMword Rs = state->Reg[nRs];
3765 int sign = 0;
3766
3767 if (msigned)
3768 {
3769 /* Compute sign of result and adjust operands if necessary. */
3770
3771 sign = (Rm ^ Rs) & 0x80000000;
3772
3773 if (((signed long) Rm) < 0)
3774 Rm = -Rm;
3775
3776 if (((signed long) Rs) < 0)
3777 Rs = -Rs;
3778 }
3779
3780 /* We can split the 32x32 into four 16x16 operations. This ensures
3781 that we do not lose precision on 32bit only hosts: */
3782 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
3783 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3784 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
3785 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3786
3787 /* We now need to add all of these results together, taking care
3788 to propogate the carries from the additions: */
3789 RdLo = Add32 (lo, (mid1 << 16), &carry);
3790 RdHi = carry;
3791 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
3792 RdHi +=
3793 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
3794
3795 if (sign)
3796 {
3797 /* Negate result if necessary. */
3798
3799 RdLo = ~RdLo;
3800 RdHi = ~RdHi;
3801 if (RdLo == 0xFFFFFFFF)
3802 {
3803 RdLo = 0;
3804 RdHi += 1;
3805 }
3806 else
3807 RdLo += 1;
3808 }
3809
3810 state->Reg[nRdLo] = RdLo;
3811 state->Reg[nRdHi] = RdHi;
3812 } /* else undefined result */
3813 else
3814 fprintf (stderr, "MULTIPLY64 - INVALID ARGUMENTS\n");
3815
3816 if (scc)
3817 {
3818 if ((RdHi == 0) && (RdLo == 0))
3819 ARMul_NegZero (state, RdHi); /* zero value */
3820 else
3821 ARMul_NegZero (state, scc); /* non-zero value */
3822 }
3823
3824 /* The cycle count depends on whether the instruction is a signed or
3825 unsigned multiply, and what bits are clear in the multiplier: */
3826 if (msigned && (Rm & ((unsigned) 1 << 31)))
3827 Rm = ~Rm; /* invert the bits to make the check against zero */
3828
3829 if ((Rm & 0xFFFFFF00) == 0)
3830 scount = 1;
3831 else if ((Rm & 0xFFFF0000) == 0)
3832 scount = 2;
3833 else if ((Rm & 0xFF000000) == 0)
3834 scount = 3;
3835 else
3836 scount = 4;
3837
3838 return 2 + scount;
3839 }
3840
3841 /***************************************************************************\
3842 * This function does the work of multiplying two 32bit values and adding *
3843 * a 64bit value to give a 64bit result. *
3844 \***************************************************************************/
3845
3846 static unsigned
3847 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
3848 {
3849 unsigned scount;
3850 ARMword RdLo, RdHi;
3851 int nRdHi, nRdLo;
3852 int carry = 0;
3853
3854 nRdHi = BITS (16, 19);
3855 nRdLo = BITS (12, 15);
3856
3857 RdHi = state->Reg[nRdHi];
3858 RdLo = state->Reg[nRdLo];
3859
3860 scount = Multiply64 (state, instr, msigned, LDEFAULT);
3861
3862 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
3863 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
3864
3865 state->Reg[nRdLo] = RdLo;
3866 state->Reg[nRdHi] = RdHi;
3867
3868 if (scc)
3869 {
3870 if ((RdHi == 0) && (RdLo == 0))
3871 ARMul_NegZero (state, RdHi); /* zero value */
3872 else
3873 ARMul_NegZero (state, scc); /* non-zero value */
3874 }
3875
3876 return scount + 1; /* extra cycle for addition */
3877 }