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