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