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