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