import gdb-1999-12-06 snapshot
[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 #ifdef MODET
882 if (BITS(4,11) == 0xB) {
883 /* STRH register offset, no write-back, down, pre indexed */
884 SHPREDOWN() ;
885 break ;
886 }
887 #endif
888 if (BITS(4,11) == 9) { /* SWP */
889 UNDEF_SWPPC ;
890 temp = LHS ;
891 BUSUSEDINCPCS ;
892 #ifndef MODE32
893 if (VECTORACCESS(temp) || ADDREXCEPT(temp)) {
894 INTERNALABORT(temp) ;
895 (void)ARMul_LoadWordN(state,temp) ;
896 (void)ARMul_LoadWordN(state,temp) ;
897 }
898 else
899 #endif
900 dest = ARMul_SwapWord(state,temp,state->Reg[RHSReg]) ;
901 if (temp & 3)
902 DEST = ARMul_Align(state,temp,dest) ;
903 else
904 DEST = dest ;
905 if (state->abortSig || state->Aborted) {
906 TAKEABORT ;
907 }
908 }
909 else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS CPSR */
910 UNDEF_MRSPC ;
911 DEST = ECC | EINT | EMODE ;
912 }
913 else {
914 UNDEF_Test ;
915 }
916 break ;
917
918 case 0x11 : /* TSTP reg */
919 #ifdef MODET
920 if ((BITS(4,11) & 0xF9) == 0x9) {
921 /* LDR register offset, no write-back, down, pre indexed */
922 LHPREDOWN() ;
923 /* continue with remaining instruction decode */
924 }
925 #endif
926 if (DESTReg == 15) { /* TSTP reg */
927 #ifdef MODE32
928 state->Cpsr = GETSPSR(state->Bank) ;
929 ARMul_CPSRAltered(state) ;
930 #else
931 rhs = DPRegRHS ;
932 temp = LHS & rhs ;
933 SETR15PSR(temp) ;
934 #endif
935 }
936 else { /* TST reg */
937 rhs = DPSRegRHS ;
938 dest = LHS & rhs ;
939 ARMul_NegZero(state,dest) ;
940 }
941 break ;
942
943 case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */
944 #ifdef MODET
945 if (BITS(4,11) == 0xB) {
946 /* STRH register offset, write-back, down, pre indexed */
947 SHPREDOWNWB() ;
948 break ;
949 }
950 #endif
951 #ifdef MODET
952 if (BITS(4,27)==0x12FFF1) { /* BX */
953 /* Branch to the address in RHSReg. If bit0 of
954 destination address is 1 then switch to Thumb mode: */
955 ARMword addr = state->Reg[RHSReg];
956
957 /* If we read the PC then the bottom bit is clear */
958 if (RHSReg == 15) addr &= ~1;
959
960 /* Enable this for a helpful bit of debugging when
961 GDB is not yet fully working...
962 fprintf (stderr, "BX at %x to %x (go %s)\n",
963 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
964
965 if (addr & (1 << 0)) { /* Thumb bit */
966 SETT;
967 state->Reg[15] = addr & 0xfffffffe;
968 /* NOTE: The other CPSR flag setting blocks do not
969 seem to update the state->Cpsr state, but just do
970 the explicit flag. The copy from the seperate
971 flags to the register must happen later. */
972 FLUSHPIPE;
973 } else {
974 CLEART;
975 state->Reg[15] = addr & 0xfffffffc;
976 FLUSHPIPE;
977 }
978 }
979 #endif
980 if (DESTReg==15 && BITS(17,18)==0) { /* MSR reg to CPSR */
981 UNDEF_MSRPC ;
982 temp = DPRegRHS ;
983 ARMul_FixCPSR(state,instr,temp) ;
984 }
985 else {
986 UNDEF_Test ;
987 }
988 break ;
989
990 case 0x13 : /* TEQP reg */
991 #ifdef MODET
992 if ((BITS(4,11) & 0xF9) == 0x9) {
993 /* LDR register offset, write-back, down, pre indexed */
994 LHPREDOWNWB() ;
995 /* continue with remaining instruction decode */
996 }
997 #endif
998 if (DESTReg == 15) { /* TEQP reg */
999 #ifdef MODE32
1000 state->Cpsr = GETSPSR(state->Bank) ;
1001 ARMul_CPSRAltered(state) ;
1002 #else
1003 rhs = DPRegRHS ;
1004 temp = LHS ^ rhs ;
1005 SETR15PSR(temp) ;
1006 #endif
1007 }
1008 else { /* TEQ Reg */
1009 rhs = DPSRegRHS ;
1010 dest = LHS ^ rhs ;
1011 ARMul_NegZero(state,dest) ;
1012 }
1013 break ;
1014
1015 case 0x14 : /* CMP reg and MRS SPSR and SWP byte */
1016 #ifdef MODET
1017 if (BITS(4,7) == 0xB) {
1018 /* STRH immediate offset, no write-back, down, pre indexed */
1019 SHPREDOWN() ;
1020 break ;
1021 }
1022 #endif
1023 if (BITS(4,11) == 9) { /* SWP */
1024 UNDEF_SWPPC ;
1025 temp = LHS ;
1026 BUSUSEDINCPCS ;
1027 #ifndef MODE32
1028 if (VECTORACCESS(temp) || ADDREXCEPT(temp)) {
1029 INTERNALABORT(temp) ;
1030 (void)ARMul_LoadByte(state,temp) ;
1031 (void)ARMul_LoadByte(state,temp) ;
1032 }
1033 else
1034 #endif
1035 DEST = ARMul_SwapByte(state,temp,state->Reg[RHSReg]) ;
1036 if (state->abortSig || state->Aborted) {
1037 TAKEABORT ;
1038 }
1039 }
1040 else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS SPSR */
1041 UNDEF_MRSPC ;
1042 DEST = GETSPSR(state->Bank) ;
1043 }
1044 else {
1045 UNDEF_Test ;
1046 }
1047 break ;
1048
1049 case 0x15 : /* CMPP reg */
1050 #ifdef MODET
1051 if ((BITS(4,7) & 0x9) == 0x9) {
1052 /* LDR immediate offset, no write-back, down, pre indexed */
1053 LHPREDOWN() ;
1054 /* continue with remaining instruction decode */
1055 }
1056 #endif
1057 if (DESTReg == 15) { /* CMPP reg */
1058 #ifdef MODE32
1059 state->Cpsr = GETSPSR(state->Bank) ;
1060 ARMul_CPSRAltered(state) ;
1061 #else
1062 rhs = DPRegRHS ;
1063 temp = LHS - rhs ;
1064 SETR15PSR(temp) ;
1065 #endif
1066 }
1067 else { /* CMP reg */
1068 lhs = LHS ;
1069 rhs = DPRegRHS ;
1070 dest = lhs - rhs ;
1071 ARMul_NegZero(state,dest) ;
1072 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1073 ARMul_SubCarry(state,lhs,rhs,dest) ;
1074 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1075 }
1076 else {
1077 CLEARC ;
1078 CLEARV ;
1079 }
1080 }
1081 break ;
1082
1083 case 0x16 : /* CMN reg and MSR reg to SPSR */
1084 #ifdef MODET
1085 if (BITS(4,7) == 0xB) {
1086 /* STRH immediate offset, write-back, down, pre indexed */
1087 SHPREDOWNWB() ;
1088 break ;
1089 }
1090 #endif
1091 if (DESTReg==15 && BITS(17,18)==0) { /* MSR */
1092 UNDEF_MSRPC ;
1093 ARMul_FixSPSR(state,instr,DPRegRHS);
1094 }
1095 else {
1096 UNDEF_Test ;
1097 }
1098 break ;
1099
1100 case 0x17 : /* CMNP reg */
1101 #ifdef MODET
1102 if ((BITS(4,7) & 0x9) == 0x9) {
1103 /* LDR immediate offset, write-back, down, pre indexed */
1104 LHPREDOWNWB() ;
1105 /* continue with remaining instruction decoding */
1106 }
1107 #endif
1108 if (DESTReg == 15) {
1109 #ifdef MODE32
1110 state->Cpsr = GETSPSR(state->Bank) ;
1111 ARMul_CPSRAltered(state) ;
1112 #else
1113 rhs = DPRegRHS ;
1114 temp = LHS + rhs ;
1115 SETR15PSR(temp) ;
1116 #endif
1117 break ;
1118 }
1119 else { /* CMN reg */
1120 lhs = LHS ;
1121 rhs = DPRegRHS ;
1122 dest = lhs + rhs ;
1123 ASSIGNZ(dest==0) ;
1124 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1125 ASSIGNN(NEG(dest)) ;
1126 ARMul_AddCarry(state,lhs,rhs,dest) ;
1127 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1128 }
1129 else {
1130 CLEARN ;
1131 CLEARC ;
1132 CLEARV ;
1133 }
1134 }
1135 break ;
1136
1137 case 0x18 : /* ORR reg */
1138 #ifdef MODET
1139 if (BITS(4,11) == 0xB) {
1140 /* STRH register offset, no write-back, up, pre indexed */
1141 SHPREUP() ;
1142 break ;
1143 }
1144 #endif
1145 rhs = DPRegRHS ;
1146 dest = LHS | rhs ;
1147 WRITEDEST(dest) ;
1148 break ;
1149
1150 case 0x19 : /* ORRS reg */
1151 #ifdef MODET
1152 if ((BITS(4,11) & 0xF9) == 0x9) {
1153 /* LDR register offset, no write-back, up, pre indexed */
1154 LHPREUP() ;
1155 /* continue with remaining instruction decoding */
1156 }
1157 #endif
1158 rhs = DPSRegRHS ;
1159 dest = LHS | rhs ;
1160 WRITESDEST(dest) ;
1161 break ;
1162
1163 case 0x1a : /* MOV reg */
1164 #ifdef MODET
1165 if (BITS(4,11) == 0xB) {
1166 /* STRH register offset, write-back, up, pre indexed */
1167 SHPREUPWB() ;
1168 break ;
1169 }
1170 #endif
1171 dest = DPRegRHS ;
1172 WRITEDEST(dest) ;
1173 break ;
1174
1175 case 0x1b : /* MOVS reg */
1176 #ifdef MODET
1177 if ((BITS(4,11) & 0xF9) == 0x9) {
1178 /* LDR register offset, write-back, up, pre indexed */
1179 LHPREUPWB() ;
1180 /* continue with remaining instruction decoding */
1181 }
1182 #endif
1183 dest = DPSRegRHS ;
1184 WRITESDEST(dest) ;
1185 break ;
1186
1187 case 0x1c : /* BIC reg */
1188 #ifdef MODET
1189 if (BITS(4,7) == 0xB) {
1190 /* STRH immediate offset, no write-back, up, pre indexed */
1191 SHPREUP() ;
1192 break ;
1193 }
1194 #endif
1195 rhs = DPRegRHS ;
1196 dest = LHS & ~rhs ;
1197 WRITEDEST(dest) ;
1198 break ;
1199
1200 case 0x1d : /* BICS reg */
1201 #ifdef MODET
1202 if ((BITS(4,7) & 0x9) == 0x9) {
1203 /* LDR immediate offset, no write-back, up, pre indexed */
1204 LHPREUP() ;
1205 /* continue with instruction decoding */
1206 }
1207 #endif
1208 rhs = DPSRegRHS ;
1209 dest = LHS & ~rhs ;
1210 WRITESDEST(dest) ;
1211 break ;
1212
1213 case 0x1e : /* MVN reg */
1214 #ifdef MODET
1215 if (BITS(4,7) == 0xB) {
1216 /* STRH immediate offset, write-back, up, pre indexed */
1217 SHPREUPWB() ;
1218 break ;
1219 }
1220 #endif
1221 dest = ~DPRegRHS ;
1222 WRITEDEST(dest) ;
1223 break ;
1224
1225 case 0x1f : /* MVNS reg */
1226 #ifdef MODET
1227 if ((BITS(4,7) & 0x9) == 0x9) {
1228 /* LDR immediate offset, write-back, up, pre indexed */
1229 LHPREUPWB() ;
1230 /* continue instruction decoding */
1231 }
1232 #endif
1233 dest = ~DPSRegRHS ;
1234 WRITESDEST(dest) ;
1235 break ;
1236
1237 /***************************************************************************\
1238 * Data Processing Immediate RHS Instructions *
1239 \***************************************************************************/
1240
1241 case 0x20 : /* AND immed */
1242 dest = LHS & DPImmRHS ;
1243 WRITEDEST(dest) ;
1244 break ;
1245
1246 case 0x21 : /* ANDS immed */
1247 DPSImmRHS ;
1248 dest = LHS & rhs ;
1249 WRITESDEST(dest) ;
1250 break ;
1251
1252 case 0x22 : /* EOR immed */
1253 dest = LHS ^ DPImmRHS ;
1254 WRITEDEST(dest) ;
1255 break ;
1256
1257 case 0x23 : /* EORS immed */
1258 DPSImmRHS ;
1259 dest = LHS ^ rhs ;
1260 WRITESDEST(dest) ;
1261 break ;
1262
1263 case 0x24 : /* SUB immed */
1264 dest = LHS - DPImmRHS ;
1265 WRITEDEST(dest) ;
1266 break ;
1267
1268 case 0x25 : /* SUBS immed */
1269 lhs = LHS ;
1270 rhs = DPImmRHS ;
1271 dest = lhs - rhs ;
1272 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1273 ARMul_SubCarry(state,lhs,rhs,dest) ;
1274 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1275 }
1276 else {
1277 CLEARC ;
1278 CLEARV ;
1279 }
1280 WRITESDEST(dest) ;
1281 break ;
1282
1283 case 0x26 : /* RSB immed */
1284 dest = DPImmRHS - LHS ;
1285 WRITEDEST(dest) ;
1286 break ;
1287
1288 case 0x27 : /* RSBS immed */
1289 lhs = LHS ;
1290 rhs = DPImmRHS ;
1291 dest = rhs - lhs ;
1292 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1293 ARMul_SubCarry(state,rhs,lhs,dest) ;
1294 ARMul_SubOverflow(state,rhs,lhs,dest) ;
1295 }
1296 else {
1297 CLEARC ;
1298 CLEARV ;
1299 }
1300 WRITESDEST(dest) ;
1301 break ;
1302
1303 case 0x28 : /* ADD immed */
1304 dest = LHS + DPImmRHS ;
1305 WRITEDEST(dest) ;
1306 break ;
1307
1308 case 0x29 : /* ADDS immed */
1309 lhs = LHS ;
1310 rhs = DPImmRHS ;
1311 dest = lhs + rhs ;
1312 ASSIGNZ(dest==0) ;
1313 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1314 ASSIGNN(NEG(dest)) ;
1315 ARMul_AddCarry(state,lhs,rhs,dest) ;
1316 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1317 }
1318 else {
1319 CLEARN ;
1320 CLEARC ;
1321 CLEARV ;
1322 }
1323 WRITESDEST(dest) ;
1324 break ;
1325
1326 case 0x2a : /* ADC immed */
1327 dest = LHS + DPImmRHS + CFLAG ;
1328 WRITEDEST(dest) ;
1329 break ;
1330
1331 case 0x2b : /* ADCS immed */
1332 lhs = LHS ;
1333 rhs = DPImmRHS ;
1334 dest = lhs + rhs + CFLAG ;
1335 ASSIGNZ(dest==0) ;
1336 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1337 ASSIGNN(NEG(dest)) ;
1338 ARMul_AddCarry(state,lhs,rhs,dest) ;
1339 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1340 }
1341 else {
1342 CLEARN ;
1343 CLEARC ;
1344 CLEARV ;
1345 }
1346 WRITESDEST(dest) ;
1347 break ;
1348
1349 case 0x2c : /* SBC immed */
1350 dest = LHS - DPImmRHS - !CFLAG ;
1351 WRITEDEST(dest) ;
1352 break ;
1353
1354 case 0x2d : /* SBCS immed */
1355 lhs = LHS ;
1356 rhs = DPImmRHS ;
1357 dest = lhs - rhs - !CFLAG ;
1358 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1359 ARMul_SubCarry(state,lhs,rhs,dest) ;
1360 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1361 }
1362 else {
1363 CLEARC ;
1364 CLEARV ;
1365 }
1366 WRITESDEST(dest) ;
1367 break ;
1368
1369 case 0x2e : /* RSC immed */
1370 dest = DPImmRHS - LHS - !CFLAG ;
1371 WRITEDEST(dest) ;
1372 break ;
1373
1374 case 0x2f : /* RSCS immed */
1375 lhs = LHS ;
1376 rhs = DPImmRHS ;
1377 dest = rhs - lhs - !CFLAG ;
1378 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1379 ARMul_SubCarry(state,rhs,lhs,dest) ;
1380 ARMul_SubOverflow(state,rhs,lhs,dest) ;
1381 }
1382 else {
1383 CLEARC ;
1384 CLEARV ;
1385 }
1386 WRITESDEST(dest) ;
1387 break ;
1388
1389 case 0x30 : /* TST immed */
1390 UNDEF_Test ;
1391 break ;
1392
1393 case 0x31 : /* TSTP immed */
1394 if (DESTReg == 15) { /* TSTP immed */
1395 #ifdef MODE32
1396 state->Cpsr = GETSPSR(state->Bank) ;
1397 ARMul_CPSRAltered(state) ;
1398 #else
1399 temp = LHS & DPImmRHS ;
1400 SETR15PSR(temp) ;
1401 #endif
1402 }
1403 else {
1404 DPSImmRHS ; /* TST immed */
1405 dest = LHS & rhs ;
1406 ARMul_NegZero(state,dest) ;
1407 }
1408 break ;
1409
1410 case 0x32 : /* TEQ immed and MSR immed to CPSR */
1411 if (DESTReg==15 && BITS(17,18)==0) { /* MSR immed to CPSR */
1412 ARMul_FixCPSR(state,instr,DPImmRHS) ;
1413 }
1414 else {
1415 UNDEF_Test ;
1416 }
1417 break ;
1418
1419 case 0x33 : /* TEQP immed */
1420 if (DESTReg == 15) { /* TEQP immed */
1421 #ifdef MODE32
1422 state->Cpsr = GETSPSR(state->Bank) ;
1423 ARMul_CPSRAltered(state) ;
1424 #else
1425 temp = LHS ^ DPImmRHS ;
1426 SETR15PSR(temp) ;
1427 #endif
1428 }
1429 else {
1430 DPSImmRHS ; /* TEQ immed */
1431 dest = LHS ^ rhs ;
1432 ARMul_NegZero(state,dest) ;
1433 }
1434 break ;
1435
1436 case 0x34 : /* CMP immed */
1437 UNDEF_Test ;
1438 break ;
1439
1440 case 0x35 : /* CMPP immed */
1441 if (DESTReg == 15) { /* CMPP immed */
1442 #ifdef MODE32
1443 state->Cpsr = GETSPSR(state->Bank) ;
1444 ARMul_CPSRAltered(state) ;
1445 #else
1446 temp = LHS - DPImmRHS ;
1447 SETR15PSR(temp) ;
1448 #endif
1449 break ;
1450 }
1451 else {
1452 lhs = LHS ; /* CMP immed */
1453 rhs = DPImmRHS ;
1454 dest = lhs - rhs ;
1455 ARMul_NegZero(state,dest) ;
1456 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1457 ARMul_SubCarry(state,lhs,rhs,dest) ;
1458 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1459 }
1460 else {
1461 CLEARC ;
1462 CLEARV ;
1463 }
1464 }
1465 break ;
1466
1467 case 0x36 : /* CMN immed and MSR immed to SPSR */
1468 if (DESTReg==15 && BITS(17,18)==0) /* MSR */
1469 ARMul_FixSPSR(state, instr, DPImmRHS) ;
1470 else {
1471 UNDEF_Test ;
1472 }
1473 break ;
1474
1475 case 0x37 : /* CMNP immed */
1476 if (DESTReg == 15) { /* CMNP immed */
1477 #ifdef MODE32
1478 state->Cpsr = GETSPSR(state->Bank) ;
1479 ARMul_CPSRAltered(state) ;
1480 #else
1481 temp = LHS + DPImmRHS ;
1482 SETR15PSR(temp) ;
1483 #endif
1484 break ;
1485 }
1486 else {
1487 lhs = LHS ; /* CMN immed */
1488 rhs = DPImmRHS ;
1489 dest = lhs + rhs ;
1490 ASSIGNZ(dest==0) ;
1491 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1492 ASSIGNN(NEG(dest)) ;
1493 ARMul_AddCarry(state,lhs,rhs,dest) ;
1494 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1495 }
1496 else {
1497 CLEARN ;
1498 CLEARC ;
1499 CLEARV ;
1500 }
1501 }
1502 break ;
1503
1504 case 0x38 : /* ORR immed */
1505 dest = LHS | DPImmRHS ;
1506 WRITEDEST(dest) ;
1507 break ;
1508
1509 case 0x39 : /* ORRS immed */
1510 DPSImmRHS ;
1511 dest = LHS | rhs ;
1512 WRITESDEST(dest) ;
1513 break ;
1514
1515 case 0x3a : /* MOV immed */
1516 dest = DPImmRHS ;
1517 WRITEDEST(dest) ;
1518 break ;
1519
1520 case 0x3b : /* MOVS immed */
1521 DPSImmRHS ;
1522 WRITESDEST(rhs) ;
1523 break ;
1524
1525 case 0x3c : /* BIC immed */
1526 dest = LHS & ~DPImmRHS ;
1527 WRITEDEST(dest) ;
1528 break ;
1529
1530 case 0x3d : /* BICS immed */
1531 DPSImmRHS ;
1532 dest = LHS & ~rhs ;
1533 WRITESDEST(dest) ;
1534 break ;
1535
1536 case 0x3e : /* MVN immed */
1537 dest = ~DPImmRHS ;
1538 WRITEDEST(dest) ;
1539 break ;
1540
1541 case 0x3f : /* MVNS immed */
1542 DPSImmRHS ;
1543 WRITESDEST(~rhs) ;
1544 break ;
1545
1546 /***************************************************************************\
1547 * Single Data Transfer Immediate RHS Instructions *
1548 \***************************************************************************/
1549
1550 case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */
1551 lhs = LHS ;
1552 if (StoreWord(state,instr,lhs))
1553 LSBase = lhs - LSImmRHS ;
1554 break ;
1555
1556 case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */
1557 lhs = LHS ;
1558 if (LoadWord(state,instr,lhs))
1559 LSBase = lhs - LSImmRHS ;
1560 break ;
1561
1562 case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */
1563 UNDEF_LSRBaseEQDestWb ;
1564 UNDEF_LSRPCBaseWb ;
1565 lhs = LHS ;
1566 temp = lhs - LSImmRHS ;
1567 state->NtransSig = LOW ;
1568 if (StoreWord(state,instr,lhs))
1569 LSBase = temp ;
1570 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1571 break ;
1572
1573 case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */
1574 UNDEF_LSRBaseEQDestWb ;
1575 UNDEF_LSRPCBaseWb ;
1576 lhs = LHS ;
1577 state->NtransSig = LOW ;
1578 if (LoadWord(state,instr,lhs))
1579 LSBase = lhs - LSImmRHS ;
1580 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1581 break ;
1582
1583 case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */
1584 lhs = LHS ;
1585 if (StoreByte(state,instr,lhs))
1586 LSBase = lhs - LSImmRHS ;
1587 break ;
1588
1589 case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */
1590 lhs = LHS ;
1591 if (LoadByte(state,instr,lhs,LUNSIGNED))
1592 LSBase = lhs - LSImmRHS ;
1593 break ;
1594
1595 case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */
1596 UNDEF_LSRBaseEQDestWb ;
1597 UNDEF_LSRPCBaseWb ;
1598 lhs = LHS ;
1599 state->NtransSig = LOW ;
1600 if (StoreByte(state,instr,lhs))
1601 LSBase = lhs - LSImmRHS ;
1602 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1603 break ;
1604
1605 case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */
1606 UNDEF_LSRBaseEQDestWb ;
1607 UNDEF_LSRPCBaseWb ;
1608 lhs = LHS ;
1609 state->NtransSig = LOW ;
1610 if (LoadByte(state,instr,lhs,LUNSIGNED))
1611 LSBase = lhs - LSImmRHS ;
1612 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1613 break ;
1614
1615 case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */
1616 lhs = LHS ;
1617 if (StoreWord(state,instr,lhs))
1618 LSBase = lhs + LSImmRHS ;
1619 break ;
1620
1621 case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */
1622 lhs = LHS ;
1623 if (LoadWord(state,instr,lhs))
1624 LSBase = lhs + LSImmRHS ;
1625 break ;
1626
1627 case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */
1628 UNDEF_LSRBaseEQDestWb ;
1629 UNDEF_LSRPCBaseWb ;
1630 lhs = LHS ;
1631 state->NtransSig = LOW ;
1632 if (StoreWord(state,instr,lhs))
1633 LSBase = lhs + LSImmRHS ;
1634 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1635 break ;
1636
1637 case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */
1638 UNDEF_LSRBaseEQDestWb ;
1639 UNDEF_LSRPCBaseWb ;
1640 lhs = LHS ;
1641 state->NtransSig = LOW ;
1642 if (LoadWord(state,instr,lhs))
1643 LSBase = lhs + LSImmRHS ;
1644 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1645 break ;
1646
1647 case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */
1648 lhs = LHS ;
1649 if (StoreByte(state,instr,lhs))
1650 LSBase = lhs + LSImmRHS ;
1651 break ;
1652
1653 case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */
1654 lhs = LHS ;
1655 if (LoadByte(state,instr,lhs,LUNSIGNED))
1656 LSBase = lhs + LSImmRHS ;
1657 break ;
1658
1659 case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */
1660 UNDEF_LSRBaseEQDestWb ;
1661 UNDEF_LSRPCBaseWb ;
1662 lhs = LHS ;
1663 state->NtransSig = LOW ;
1664 if (StoreByte(state,instr,lhs))
1665 LSBase = lhs + LSImmRHS ;
1666 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1667 break ;
1668
1669 case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */
1670 UNDEF_LSRBaseEQDestWb ;
1671 UNDEF_LSRPCBaseWb ;
1672 lhs = LHS ;
1673 state->NtransSig = LOW ;
1674 if (LoadByte(state,instr,lhs,LUNSIGNED))
1675 LSBase = lhs + LSImmRHS ;
1676 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1677 break ;
1678
1679
1680 case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */
1681 (void)StoreWord(state,instr,LHS - LSImmRHS) ;
1682 break ;
1683
1684 case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */
1685 (void)LoadWord(state,instr,LHS - LSImmRHS) ;
1686 break ;
1687
1688 case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */
1689 UNDEF_LSRBaseEQDestWb ;
1690 UNDEF_LSRPCBaseWb ;
1691 temp = LHS - LSImmRHS ;
1692 if (StoreWord(state,instr,temp))
1693 LSBase = temp ;
1694 break ;
1695
1696 case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */
1697 UNDEF_LSRBaseEQDestWb ;
1698 UNDEF_LSRPCBaseWb ;
1699 temp = LHS - LSImmRHS ;
1700 if (LoadWord(state,instr,temp))
1701 LSBase = temp ;
1702 break ;
1703
1704 case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */
1705 (void)StoreByte(state,instr,LHS - LSImmRHS) ;
1706 break ;
1707
1708 case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */
1709 (void)LoadByte(state,instr,LHS - LSImmRHS,LUNSIGNED) ;
1710 break ;
1711
1712 case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */
1713 UNDEF_LSRBaseEQDestWb ;
1714 UNDEF_LSRPCBaseWb ;
1715 temp = LHS - LSImmRHS ;
1716 if (StoreByte(state,instr,temp))
1717 LSBase = temp ;
1718 break ;
1719
1720 case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */
1721 UNDEF_LSRBaseEQDestWb ;
1722 UNDEF_LSRPCBaseWb ;
1723 temp = LHS - LSImmRHS ;
1724 if (LoadByte(state,instr,temp,LUNSIGNED))
1725 LSBase = temp ;
1726 break ;
1727
1728 case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */
1729 (void)StoreWord(state,instr,LHS + LSImmRHS) ;
1730 break ;
1731
1732 case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */
1733 (void)LoadWord(state,instr,LHS + LSImmRHS) ;
1734 break ;
1735
1736 case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */
1737 UNDEF_LSRBaseEQDestWb ;
1738 UNDEF_LSRPCBaseWb ;
1739 temp = LHS + LSImmRHS ;
1740 if (StoreWord(state,instr,temp))
1741 LSBase = temp ;
1742 break ;
1743
1744 case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */
1745 UNDEF_LSRBaseEQDestWb ;
1746 UNDEF_LSRPCBaseWb ;
1747 temp = LHS + LSImmRHS ;
1748 if (LoadWord(state,instr,temp))
1749 LSBase = temp ;
1750 break ;
1751
1752 case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */
1753 (void)StoreByte(state,instr,LHS + LSImmRHS) ;
1754 break ;
1755
1756 case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */
1757 (void)LoadByte(state,instr,LHS + LSImmRHS,LUNSIGNED) ;
1758 break ;
1759
1760 case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */
1761 UNDEF_LSRBaseEQDestWb ;
1762 UNDEF_LSRPCBaseWb ;
1763 temp = LHS + LSImmRHS ;
1764 if (StoreByte(state,instr,temp))
1765 LSBase = temp ;
1766 break ;
1767
1768 case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */
1769 UNDEF_LSRBaseEQDestWb ;
1770 UNDEF_LSRPCBaseWb ;
1771 temp = LHS + LSImmRHS ;
1772 if (LoadByte(state,instr,temp,LUNSIGNED))
1773 LSBase = temp ;
1774 break ;
1775
1776 /***************************************************************************\
1777 * Single Data Transfer Register RHS Instructions *
1778 \***************************************************************************/
1779
1780 case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */
1781 if (BIT(4)) {
1782 ARMul_UndefInstr(state,instr) ;
1783 break ;
1784 }
1785 UNDEF_LSRBaseEQOffWb ;
1786 UNDEF_LSRBaseEQDestWb ;
1787 UNDEF_LSRPCBaseWb ;
1788 UNDEF_LSRPCOffWb ;
1789 lhs = LHS ;
1790 if (StoreWord(state,instr,lhs))
1791 LSBase = lhs - LSRegRHS ;
1792 break ;
1793
1794 case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */
1795 if (BIT(4)) {
1796 ARMul_UndefInstr(state,instr) ;
1797 break ;
1798 }
1799 UNDEF_LSRBaseEQOffWb ;
1800 UNDEF_LSRBaseEQDestWb ;
1801 UNDEF_LSRPCBaseWb ;
1802 UNDEF_LSRPCOffWb ;
1803 lhs = LHS ;
1804 if (LoadWord(state,instr,lhs))
1805 LSBase = lhs - LSRegRHS ;
1806 break ;
1807
1808 case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */
1809 if (BIT(4)) {
1810 ARMul_UndefInstr(state,instr) ;
1811 break ;
1812 }
1813 UNDEF_LSRBaseEQOffWb ;
1814 UNDEF_LSRBaseEQDestWb ;
1815 UNDEF_LSRPCBaseWb ;
1816 UNDEF_LSRPCOffWb ;
1817 lhs = LHS ;
1818 state->NtransSig = LOW ;
1819 if (StoreWord(state,instr,lhs))
1820 LSBase = lhs - LSRegRHS ;
1821 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1822 break ;
1823
1824 case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */
1825 if (BIT(4)) {
1826 ARMul_UndefInstr(state,instr) ;
1827 break ;
1828 }
1829 UNDEF_LSRBaseEQOffWb ;
1830 UNDEF_LSRBaseEQDestWb ;
1831 UNDEF_LSRPCBaseWb ;
1832 UNDEF_LSRPCOffWb ;
1833 lhs = LHS ;
1834 state->NtransSig = LOW ;
1835 if (LoadWord(state,instr,lhs))
1836 LSBase = lhs - LSRegRHS ;
1837 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1838 break ;
1839
1840 case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */
1841 if (BIT(4)) {
1842 ARMul_UndefInstr(state,instr) ;
1843 break ;
1844 }
1845 UNDEF_LSRBaseEQOffWb ;
1846 UNDEF_LSRBaseEQDestWb ;
1847 UNDEF_LSRPCBaseWb ;
1848 UNDEF_LSRPCOffWb ;
1849 lhs = LHS ;
1850 if (StoreByte(state,instr,lhs))
1851 LSBase = lhs - LSRegRHS ;
1852 break ;
1853
1854 case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */
1855 if (BIT(4)) {
1856 ARMul_UndefInstr(state,instr) ;
1857 break ;
1858 }
1859 UNDEF_LSRBaseEQOffWb ;
1860 UNDEF_LSRBaseEQDestWb ;
1861 UNDEF_LSRPCBaseWb ;
1862 UNDEF_LSRPCOffWb ;
1863 lhs = LHS ;
1864 if (LoadByte(state,instr,lhs,LUNSIGNED))
1865 LSBase = lhs - LSRegRHS ;
1866 break ;
1867
1868 case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */
1869 if (BIT(4)) {
1870 ARMul_UndefInstr(state,instr) ;
1871 break ;
1872 }
1873 UNDEF_LSRBaseEQOffWb ;
1874 UNDEF_LSRBaseEQDestWb ;
1875 UNDEF_LSRPCBaseWb ;
1876 UNDEF_LSRPCOffWb ;
1877 lhs = LHS ;
1878 state->NtransSig = LOW ;
1879 if (StoreByte(state,instr,lhs))
1880 LSBase = lhs - LSRegRHS ;
1881 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1882 break ;
1883
1884 case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */
1885 if (BIT(4)) {
1886 ARMul_UndefInstr(state,instr) ;
1887 break ;
1888 }
1889 UNDEF_LSRBaseEQOffWb ;
1890 UNDEF_LSRBaseEQDestWb ;
1891 UNDEF_LSRPCBaseWb ;
1892 UNDEF_LSRPCOffWb ;
1893 lhs = LHS ;
1894 state->NtransSig = LOW ;
1895 if (LoadByte(state,instr,lhs,LUNSIGNED))
1896 LSBase = lhs - LSRegRHS ;
1897 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1898 break ;
1899
1900 case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */
1901 if (BIT(4)) {
1902 ARMul_UndefInstr(state,instr) ;
1903 break ;
1904 }
1905 UNDEF_LSRBaseEQOffWb ;
1906 UNDEF_LSRBaseEQDestWb ;
1907 UNDEF_LSRPCBaseWb ;
1908 UNDEF_LSRPCOffWb ;
1909 lhs = LHS ;
1910 if (StoreWord(state,instr,lhs))
1911 LSBase = lhs + LSRegRHS ;
1912 break ;
1913
1914 case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */
1915 if (BIT(4)) {
1916 ARMul_UndefInstr(state,instr) ;
1917 break ;
1918 }
1919 UNDEF_LSRBaseEQOffWb ;
1920 UNDEF_LSRBaseEQDestWb ;
1921 UNDEF_LSRPCBaseWb ;
1922 UNDEF_LSRPCOffWb ;
1923 lhs = LHS ;
1924 if (LoadWord(state,instr,lhs))
1925 LSBase = lhs + LSRegRHS ;
1926 break ;
1927
1928 case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */
1929 if (BIT(4)) {
1930 ARMul_UndefInstr(state,instr) ;
1931 break ;
1932 }
1933 UNDEF_LSRBaseEQOffWb ;
1934 UNDEF_LSRBaseEQDestWb ;
1935 UNDEF_LSRPCBaseWb ;
1936 UNDEF_LSRPCOffWb ;
1937 lhs = LHS ;
1938 state->NtransSig = LOW ;
1939 if (StoreWord(state,instr,lhs))
1940 LSBase = lhs + LSRegRHS ;
1941 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1942 break ;
1943
1944 case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */
1945 if (BIT(4)) {
1946 ARMul_UndefInstr(state,instr) ;
1947 break ;
1948 }
1949 UNDEF_LSRBaseEQOffWb ;
1950 UNDEF_LSRBaseEQDestWb ;
1951 UNDEF_LSRPCBaseWb ;
1952 UNDEF_LSRPCOffWb ;
1953 lhs = LHS ;
1954 state->NtransSig = LOW ;
1955 if (LoadWord(state,instr,lhs))
1956 LSBase = lhs + LSRegRHS ;
1957 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1958 break ;
1959
1960 case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */
1961 if (BIT(4)) {
1962 ARMul_UndefInstr(state,instr) ;
1963 break ;
1964 }
1965 UNDEF_LSRBaseEQOffWb ;
1966 UNDEF_LSRBaseEQDestWb ;
1967 UNDEF_LSRPCBaseWb ;
1968 UNDEF_LSRPCOffWb ;
1969 lhs = LHS ;
1970 if (StoreByte(state,instr,lhs))
1971 LSBase = lhs + LSRegRHS ;
1972 break ;
1973
1974 case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */
1975 if (BIT(4)) {
1976 ARMul_UndefInstr(state,instr) ;
1977 break ;
1978 }
1979 UNDEF_LSRBaseEQOffWb ;
1980 UNDEF_LSRBaseEQDestWb ;
1981 UNDEF_LSRPCBaseWb ;
1982 UNDEF_LSRPCOffWb ;
1983 lhs = LHS ;
1984 if (LoadByte(state,instr,lhs,LUNSIGNED))
1985 LSBase = lhs + LSRegRHS ;
1986 break ;
1987
1988 case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */
1989 if (BIT(4)) {
1990 ARMul_UndefInstr(state,instr) ;
1991 break ;
1992 }
1993 UNDEF_LSRBaseEQOffWb ;
1994 UNDEF_LSRBaseEQDestWb ;
1995 UNDEF_LSRPCBaseWb ;
1996 UNDEF_LSRPCOffWb ;
1997 lhs = LHS ;
1998 state->NtransSig = LOW ;
1999 if (StoreByte(state,instr,lhs))
2000 LSBase = lhs + LSRegRHS ;
2001 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
2002 break ;
2003
2004 case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */
2005 if (BIT(4)) {
2006 ARMul_UndefInstr(state,instr) ;
2007 break ;
2008 }
2009 UNDEF_LSRBaseEQOffWb ;
2010 UNDEF_LSRBaseEQDestWb ;
2011 UNDEF_LSRPCBaseWb ;
2012 UNDEF_LSRPCOffWb ;
2013 lhs = LHS ;
2014 state->NtransSig = LOW ;
2015 if (LoadByte(state,instr,lhs,LUNSIGNED))
2016 LSBase = lhs + LSRegRHS ;
2017 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
2018 break ;
2019
2020
2021 case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */
2022 if (BIT(4)) {
2023 ARMul_UndefInstr(state,instr) ;
2024 break ;
2025 }
2026 (void)StoreWord(state,instr,LHS - LSRegRHS) ;
2027 break ;
2028
2029 case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */
2030 if (BIT(4)) {
2031 ARMul_UndefInstr(state,instr) ;
2032 break ;
2033 }
2034 (void)LoadWord(state,instr,LHS - LSRegRHS) ;
2035 break ;
2036
2037 case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */
2038 if (BIT(4)) {
2039 ARMul_UndefInstr(state,instr) ;
2040 break ;
2041 }
2042 UNDEF_LSRBaseEQOffWb ;
2043 UNDEF_LSRBaseEQDestWb ;
2044 UNDEF_LSRPCBaseWb ;
2045 UNDEF_LSRPCOffWb ;
2046 temp = LHS - LSRegRHS ;
2047 if (StoreWord(state,instr,temp))
2048 LSBase = temp ;
2049 break ;
2050
2051 case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */
2052 if (BIT(4)) {
2053 ARMul_UndefInstr(state,instr) ;
2054 break ;
2055 }
2056 UNDEF_LSRBaseEQOffWb ;
2057 UNDEF_LSRBaseEQDestWb ;
2058 UNDEF_LSRPCBaseWb ;
2059 UNDEF_LSRPCOffWb ;
2060 temp = LHS - LSRegRHS ;
2061 if (LoadWord(state,instr,temp))
2062 LSBase = temp ;
2063 break ;
2064
2065 case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */
2066 if (BIT(4)) {
2067 ARMul_UndefInstr(state,instr) ;
2068 break ;
2069 }
2070 (void)StoreByte(state,instr,LHS - LSRegRHS) ;
2071 break ;
2072
2073 case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */
2074 if (BIT(4)) {
2075 ARMul_UndefInstr(state,instr) ;
2076 break ;
2077 }
2078 (void)LoadByte(state,instr,LHS - LSRegRHS,LUNSIGNED) ;
2079 break ;
2080
2081 case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */
2082 if (BIT(4)) {
2083 ARMul_UndefInstr(state,instr) ;
2084 break ;
2085 }
2086 UNDEF_LSRBaseEQOffWb ;
2087 UNDEF_LSRBaseEQDestWb ;
2088 UNDEF_LSRPCBaseWb ;
2089 UNDEF_LSRPCOffWb ;
2090 temp = LHS - LSRegRHS ;
2091 if (StoreByte(state,instr,temp))
2092 LSBase = temp ;
2093 break ;
2094
2095 case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */
2096 if (BIT(4)) {
2097 ARMul_UndefInstr(state,instr) ;
2098 break ;
2099 }
2100 UNDEF_LSRBaseEQOffWb ;
2101 UNDEF_LSRBaseEQDestWb ;
2102 UNDEF_LSRPCBaseWb ;
2103 UNDEF_LSRPCOffWb ;
2104 temp = LHS - LSRegRHS ;
2105 if (LoadByte(state,instr,temp,LUNSIGNED))
2106 LSBase = temp ;
2107 break ;
2108
2109 case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */
2110 if (BIT(4)) {
2111 ARMul_UndefInstr(state,instr) ;
2112 break ;
2113 }
2114 (void)StoreWord(state,instr,LHS + LSRegRHS) ;
2115 break ;
2116
2117 case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */
2118 if (BIT(4)) {
2119 ARMul_UndefInstr(state,instr) ;
2120 break ;
2121 }
2122 (void)LoadWord(state,instr,LHS + LSRegRHS) ;
2123 break ;
2124
2125 case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */
2126 if (BIT(4)) {
2127 ARMul_UndefInstr(state,instr) ;
2128 break ;
2129 }
2130 UNDEF_LSRBaseEQOffWb ;
2131 UNDEF_LSRBaseEQDestWb ;
2132 UNDEF_LSRPCBaseWb ;
2133 UNDEF_LSRPCOffWb ;
2134 temp = LHS + LSRegRHS ;
2135 if (StoreWord(state,instr,temp))
2136 LSBase = temp ;
2137 break ;
2138
2139 case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */
2140 if (BIT(4)) {
2141 ARMul_UndefInstr(state,instr) ;
2142 break ;
2143 }
2144 UNDEF_LSRBaseEQOffWb ;
2145 UNDEF_LSRBaseEQDestWb ;
2146 UNDEF_LSRPCBaseWb ;
2147 UNDEF_LSRPCOffWb ;
2148 temp = LHS + LSRegRHS ;
2149 if (LoadWord(state,instr,temp))
2150 LSBase = temp ;
2151 break ;
2152
2153 case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */
2154 if (BIT(4)) {
2155 ARMul_UndefInstr(state,instr) ;
2156 break ;
2157 }
2158 (void)StoreByte(state,instr,LHS + LSRegRHS) ;
2159 break ;
2160
2161 case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */
2162 if (BIT(4)) {
2163 ARMul_UndefInstr(state,instr) ;
2164 break ;
2165 }
2166 (void)LoadByte(state,instr,LHS + LSRegRHS,LUNSIGNED) ;
2167 break ;
2168
2169 case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */
2170 if (BIT(4)) {
2171 ARMul_UndefInstr(state,instr) ;
2172 break ;
2173 }
2174 UNDEF_LSRBaseEQOffWb ;
2175 UNDEF_LSRBaseEQDestWb ;
2176 UNDEF_LSRPCBaseWb ;
2177 UNDEF_LSRPCOffWb ;
2178 temp = LHS + LSRegRHS ;
2179 if (StoreByte(state,instr,temp))
2180 LSBase = temp ;
2181 break ;
2182
2183 case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */
2184 if (BIT(4))
2185 {
2186 /* Check for the special breakpoint opcode.
2187 This value should correspond to the value defined
2188 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2189 if (BITS (0,19) == 0xfdefe)
2190 {
2191 if (! ARMul_OSHandleSWI (state, SWI_Breakpoint))
2192 ARMul_Abort (state, ARMul_SWIV);
2193 }
2194 else
2195 ARMul_UndefInstr(state,instr) ;
2196 break ;
2197 }
2198 UNDEF_LSRBaseEQOffWb ;
2199 UNDEF_LSRBaseEQDestWb ;
2200 UNDEF_LSRPCBaseWb ;
2201 UNDEF_LSRPCOffWb ;
2202 temp = LHS + LSRegRHS ;
2203 if (LoadByte(state,instr,temp,LUNSIGNED))
2204 LSBase = temp ;
2205 break ;
2206
2207 /***************************************************************************\
2208 * Multiple Data Transfer Instructions *
2209 \***************************************************************************/
2210
2211 case 0x80 : /* Store, No WriteBack, Post Dec */
2212 STOREMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2213 break ;
2214
2215 case 0x81 : /* Load, No WriteBack, Post Dec */
2216 LOADMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2217 break ;
2218
2219 case 0x82 : /* Store, WriteBack, Post Dec */
2220 temp = LSBase - LSMNumRegs ;
2221 STOREMULT(instr,temp + 4L,temp) ;
2222 break ;
2223
2224 case 0x83 : /* Load, WriteBack, Post Dec */
2225 temp = LSBase - LSMNumRegs ;
2226 LOADMULT(instr,temp + 4L,temp) ;
2227 break ;
2228
2229 case 0x84 : /* Store, Flags, No WriteBack, Post Dec */
2230 STORESMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2231 break ;
2232
2233 case 0x85 : /* Load, Flags, No WriteBack, Post Dec */
2234 LOADSMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2235 break ;
2236
2237 case 0x86 : /* Store, Flags, WriteBack, Post Dec */
2238 temp = LSBase - LSMNumRegs ;
2239 STORESMULT(instr,temp + 4L,temp) ;
2240 break ;
2241
2242 case 0x87 : /* Load, Flags, WriteBack, Post Dec */
2243 temp = LSBase - LSMNumRegs ;
2244 LOADSMULT(instr,temp + 4L,temp) ;
2245 break ;
2246
2247
2248 case 0x88 : /* Store, No WriteBack, Post Inc */
2249 STOREMULT(instr,LSBase,0L) ;
2250 break ;
2251
2252 case 0x89 : /* Load, No WriteBack, Post Inc */
2253 LOADMULT(instr,LSBase,0L) ;
2254 break ;
2255
2256 case 0x8a : /* Store, WriteBack, Post Inc */
2257 temp = LSBase ;
2258 STOREMULT(instr,temp,temp + LSMNumRegs) ;
2259 break ;
2260
2261 case 0x8b : /* Load, WriteBack, Post Inc */
2262 temp = LSBase ;
2263 LOADMULT(instr,temp,temp + LSMNumRegs) ;
2264 break ;
2265
2266 case 0x8c : /* Store, Flags, No WriteBack, Post Inc */
2267 STORESMULT(instr,LSBase,0L) ;
2268 break ;
2269
2270 case 0x8d : /* Load, Flags, No WriteBack, Post Inc */
2271 LOADSMULT(instr,LSBase,0L) ;
2272 break ;
2273
2274 case 0x8e : /* Store, Flags, WriteBack, Post Inc */
2275 temp = LSBase ;
2276 STORESMULT(instr,temp,temp + LSMNumRegs) ;
2277 break ;
2278
2279 case 0x8f : /* Load, Flags, WriteBack, Post Inc */
2280 temp = LSBase ;
2281 LOADSMULT(instr,temp,temp + LSMNumRegs) ;
2282 break ;
2283
2284
2285 case 0x90 : /* Store, No WriteBack, Pre Dec */
2286 STOREMULT(instr,LSBase - LSMNumRegs,0L) ;
2287 break ;
2288
2289 case 0x91 : /* Load, No WriteBack, Pre Dec */
2290 LOADMULT(instr,LSBase - LSMNumRegs,0L) ;
2291 break ;
2292
2293 case 0x92 : /* Store, WriteBack, Pre Dec */
2294 temp = LSBase - LSMNumRegs ;
2295 STOREMULT(instr,temp,temp) ;
2296 break ;
2297
2298 case 0x93 : /* Load, WriteBack, Pre Dec */
2299 temp = LSBase - LSMNumRegs ;
2300 LOADMULT(instr,temp,temp) ;
2301 break ;
2302
2303 case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */
2304 STORESMULT(instr,LSBase - LSMNumRegs,0L) ;
2305 break ;
2306
2307 case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */
2308 LOADSMULT(instr,LSBase - LSMNumRegs,0L) ;
2309 break ;
2310
2311 case 0x96 : /* Store, Flags, WriteBack, Pre Dec */
2312 temp = LSBase - LSMNumRegs ;
2313 STORESMULT(instr,temp,temp) ;
2314 break ;
2315
2316 case 0x97 : /* Load, Flags, WriteBack, Pre Dec */
2317 temp = LSBase - LSMNumRegs ;
2318 LOADSMULT(instr,temp,temp) ;
2319 break ;
2320
2321
2322 case 0x98 : /* Store, No WriteBack, Pre Inc */
2323 STOREMULT(instr,LSBase + 4L,0L) ;
2324 break ;
2325
2326 case 0x99 : /* Load, No WriteBack, Pre Inc */
2327 LOADMULT(instr,LSBase + 4L,0L) ;
2328 break ;
2329
2330 case 0x9a : /* Store, WriteBack, Pre Inc */
2331 temp = LSBase ;
2332 STOREMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2333 break ;
2334
2335 case 0x9b : /* Load, WriteBack, Pre Inc */
2336 temp = LSBase ;
2337 LOADMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2338 break ;
2339
2340 case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */
2341 STORESMULT(instr,LSBase + 4L,0L) ;
2342 break ;
2343
2344 case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */
2345 LOADSMULT(instr,LSBase + 4L,0L) ;
2346 break ;
2347
2348 case 0x9e : /* Store, Flags, WriteBack, Pre Inc */
2349 temp = LSBase ;
2350 STORESMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2351 break ;
2352
2353 case 0x9f : /* Load, Flags, WriteBack, Pre Inc */
2354 temp = LSBase ;
2355 LOADSMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2356 break ;
2357
2358 /***************************************************************************\
2359 * Branch forward *
2360 \***************************************************************************/
2361
2362 case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 :
2363 case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 :
2364 state->Reg[15] = pc + 8 + POSBRANCH ;
2365 FLUSHPIPE ;
2366 break ;
2367
2368 /***************************************************************************\
2369 * Branch backward *
2370 \***************************************************************************/
2371
2372 case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
2373 case 0xac : case 0xad : case 0xae : case 0xaf :
2374 state->Reg[15] = pc + 8 + NEGBRANCH ;
2375 FLUSHPIPE ;
2376 break ;
2377
2378 /***************************************************************************\
2379 * Branch and Link forward *
2380 \***************************************************************************/
2381
2382 case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 :
2383 case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 :
2384 #ifdef MODE32
2385 state->Reg[14] = pc + 4 ; /* put PC into Link */
2386 #else
2387 state->Reg[14] = pc + 4 | ECC | ER15INT | EMODE ; /* put PC into Link */
2388 #endif
2389 state->Reg[15] = pc + 8 + POSBRANCH ;
2390 FLUSHPIPE ;
2391 break ;
2392
2393 /***************************************************************************\
2394 * Branch and Link backward *
2395 \***************************************************************************/
2396
2397 case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
2398 case 0xbc : case 0xbd : case 0xbe : case 0xbf :
2399 #ifdef MODE32
2400 state->Reg[14] = pc + 4 ; /* put PC into Link */
2401 #else
2402 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE ; /* put PC into Link */
2403 #endif
2404 state->Reg[15] = pc + 8 + NEGBRANCH ;
2405 FLUSHPIPE ;
2406 break ;
2407
2408 /***************************************************************************\
2409 * Co-Processor Data Transfers *
2410 \***************************************************************************/
2411
2412 case 0xc4 :
2413 case 0xc0 : /* Store , No WriteBack , Post Dec */
2414 ARMul_STC(state,instr,LHS) ;
2415 break ;
2416
2417 case 0xc5 :
2418 case 0xc1 : /* Load , No WriteBack , Post Dec */
2419 ARMul_LDC(state,instr,LHS) ;
2420 break ;
2421
2422 case 0xc2 :
2423 case 0xc6 : /* Store , WriteBack , Post Dec */
2424 lhs = LHS ;
2425 state->Base = lhs - LSCOff ;
2426 ARMul_STC(state,instr,lhs) ;
2427 break ;
2428
2429 case 0xc3 :
2430 case 0xc7 : /* Load , WriteBack , Post Dec */
2431 lhs = LHS ;
2432 state->Base = lhs - LSCOff ;
2433 ARMul_LDC(state,instr,lhs) ;
2434 break ;
2435
2436 case 0xc8 :
2437 case 0xcc : /* Store , No WriteBack , Post Inc */
2438 ARMul_STC(state,instr,LHS) ;
2439 break ;
2440
2441 case 0xc9 :
2442 case 0xcd : /* Load , No WriteBack , Post Inc */
2443 ARMul_LDC(state,instr,LHS) ;
2444 break ;
2445
2446 case 0xca :
2447 case 0xce : /* Store , WriteBack , Post Inc */
2448 lhs = LHS ;
2449 state->Base = lhs + LSCOff ;
2450 ARMul_STC(state,instr,LHS) ;
2451 break ;
2452
2453 case 0xcb :
2454 case 0xcf : /* Load , WriteBack , Post Inc */
2455 lhs = LHS ;
2456 state->Base = lhs + LSCOff ;
2457 ARMul_LDC(state,instr,LHS) ;
2458 break ;
2459
2460
2461 case 0xd0 :
2462 case 0xd4 : /* Store , No WriteBack , Pre Dec */
2463 ARMul_STC(state,instr,LHS - LSCOff) ;
2464 break ;
2465
2466 case 0xd1 :
2467 case 0xd5 : /* Load , No WriteBack , Pre Dec */
2468 ARMul_LDC(state,instr,LHS - LSCOff) ;
2469 break ;
2470
2471 case 0xd2 :
2472 case 0xd6 : /* Store , WriteBack , Pre Dec */
2473 lhs = LHS - LSCOff ;
2474 state->Base = lhs ;
2475 ARMul_STC(state,instr,lhs) ;
2476 break ;
2477
2478 case 0xd3 :
2479 case 0xd7 : /* Load , WriteBack , Pre Dec */
2480 lhs = LHS - LSCOff ;
2481 state->Base = lhs ;
2482 ARMul_LDC(state,instr,lhs) ;
2483 break ;
2484
2485 case 0xd8 :
2486 case 0xdc : /* Store , No WriteBack , Pre Inc */
2487 ARMul_STC(state,instr,LHS + LSCOff) ;
2488 break ;
2489
2490 case 0xd9 :
2491 case 0xdd : /* Load , No WriteBack , Pre Inc */
2492 ARMul_LDC(state,instr,LHS + LSCOff) ;
2493 break ;
2494
2495 case 0xda :
2496 case 0xde : /* Store , WriteBack , Pre Inc */
2497 lhs = LHS + LSCOff ;
2498 state->Base = lhs ;
2499 ARMul_STC(state,instr,lhs) ;
2500 break ;
2501
2502 case 0xdb :
2503 case 0xdf : /* Load , WriteBack , Pre Inc */
2504 lhs = LHS + LSCOff ;
2505 state->Base = lhs ;
2506 ARMul_LDC(state,instr,lhs) ;
2507 break ;
2508
2509 /***************************************************************************\
2510 * Co-Processor Register Transfers (MCR) and Data Ops *
2511 \***************************************************************************/
2512
2513 case 0xe2 :
2514 case 0xe0 : 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.13758 seconds and 4 git commands to generate.