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