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