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