PR ld/15323
[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
2318 case 0x30: /* TST immed */
2319 UNDEF_Test;
2320 break;
2321
2322 case 0x31: /* TSTP immed */
2323 if (DESTReg == 15)
57165fb4
NC
2324 {
2325 /* TSTP immed. */
c906108c 2326#ifdef MODE32
dfcd3bfb
JM
2327 state->Cpsr = GETSPSR (state->Bank);
2328 ARMul_CPSRAltered (state);
c906108c 2329#else
dfcd3bfb
JM
2330 temp = LHS & DPImmRHS;
2331 SETR15PSR (temp);
2332#endif
2333 }
2334 else
2335 {
57165fb4
NC
2336 /* TST immed. */
2337 DPSImmRHS;
dfcd3bfb
JM
2338 dest = LHS & rhs;
2339 ARMul_NegZero (state, dest);
2340 }
2341 break;
2342
2343 case 0x32: /* TEQ immed and MSR immed to CPSR */
4ef2594f 2344 if (DESTReg == 15)
57165fb4
NC
2345 /* MSR immed to CPSR. */
2346 ARMul_FixCPSR (state, instr, DPImmRHS);
dfcd3bfb 2347 else
57165fb4 2348 UNDEF_Test;
dfcd3bfb
JM
2349 break;
2350
2351 case 0x33: /* TEQP immed */
2352 if (DESTReg == 15)
57165fb4
NC
2353 {
2354 /* TEQP immed. */
c906108c 2355#ifdef MODE32
dfcd3bfb
JM
2356 state->Cpsr = GETSPSR (state->Bank);
2357 ARMul_CPSRAltered (state);
c906108c 2358#else
dfcd3bfb
JM
2359 temp = LHS ^ DPImmRHS;
2360 SETR15PSR (temp);
2361#endif
2362 }
2363 else
2364 {
2365 DPSImmRHS; /* TEQ immed */
2366 dest = LHS ^ rhs;
2367 ARMul_NegZero (state, dest);
2368 }
2369 break;
2370
2371 case 0x34: /* CMP immed */
2372 UNDEF_Test;
2373 break;
2374
2375 case 0x35: /* CMPP immed */
2376 if (DESTReg == 15)
57165fb4
NC
2377 {
2378 /* CMPP immed. */
c906108c 2379#ifdef MODE32
dfcd3bfb
JM
2380 state->Cpsr = GETSPSR (state->Bank);
2381 ARMul_CPSRAltered (state);
c906108c 2382#else
dfcd3bfb
JM
2383 temp = LHS - DPImmRHS;
2384 SETR15PSR (temp);
2385#endif
2386 break;
2387 }
2388 else
2389 {
57165fb4
NC
2390 /* CMP immed. */
2391 lhs = LHS;
dfcd3bfb
JM
2392 rhs = DPImmRHS;
2393 dest = lhs - rhs;
2394 ARMul_NegZero (state, dest);
57165fb4 2395
dfcd3bfb
JM
2396 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2397 {
2398 ARMul_SubCarry (state, lhs, rhs, dest);
2399 ARMul_SubOverflow (state, lhs, rhs, dest);
2400 }
2401 else
2402 {
2403 CLEARC;
2404 CLEARV;
2405 }
2406 }
2407 break;
2408
2409 case 0x36: /* CMN immed and MSR immed to SPSR */
57165fb4 2410 if (DESTReg == 15)
dfcd3bfb
JM
2411 ARMul_FixSPSR (state, instr, DPImmRHS);
2412 else
57165fb4 2413 UNDEF_Test;
dfcd3bfb
JM
2414 break;
2415
57165fb4 2416 case 0x37: /* CMNP immed. */
dfcd3bfb 2417 if (DESTReg == 15)
57165fb4
NC
2418 {
2419 /* CMNP immed. */
c906108c 2420#ifdef MODE32
dfcd3bfb
JM
2421 state->Cpsr = GETSPSR (state->Bank);
2422 ARMul_CPSRAltered (state);
c906108c 2423#else
dfcd3bfb
JM
2424 temp = LHS + DPImmRHS;
2425 SETR15PSR (temp);
2426#endif
2427 break;
2428 }
2429 else
2430 {
57165fb4
NC
2431 /* CMN immed. */
2432 lhs = LHS;
dfcd3bfb
JM
2433 rhs = DPImmRHS;
2434 dest = lhs + rhs;
2435 ASSIGNZ (dest == 0);
2436 if ((lhs | rhs) >> 30)
57165fb4
NC
2437 {
2438 /* Possible C,V,N to set. */
dfcd3bfb
JM
2439 ASSIGNN (NEG (dest));
2440 ARMul_AddCarry (state, lhs, rhs, dest);
2441 ARMul_AddOverflow (state, lhs, rhs, dest);
2442 }
2443 else
2444 {
2445 CLEARN;
2446 CLEARC;
2447 CLEARV;
2448 }
2449 }
2450 break;
2451
57165fb4 2452 case 0x38: /* ORR immed. */
dfcd3bfb
JM
2453 dest = LHS | DPImmRHS;
2454 WRITEDEST (dest);
2455 break;
2456
57165fb4 2457 case 0x39: /* ORRS immed. */
dfcd3bfb
JM
2458 DPSImmRHS;
2459 dest = LHS | rhs;
2460 WRITESDEST (dest);
2461 break;
2462
57165fb4 2463 case 0x3a: /* MOV immed. */
dfcd3bfb
JM
2464 dest = DPImmRHS;
2465 WRITEDEST (dest);
2466 break;
2467
57165fb4 2468 case 0x3b: /* MOVS immed. */
dfcd3bfb
JM
2469 DPSImmRHS;
2470 WRITESDEST (rhs);
2471 break;
2472
57165fb4 2473 case 0x3c: /* BIC immed. */
dfcd3bfb
JM
2474 dest = LHS & ~DPImmRHS;
2475 WRITEDEST (dest);
2476 break;
2477
57165fb4 2478 case 0x3d: /* BICS immed. */
dfcd3bfb
JM
2479 DPSImmRHS;
2480 dest = LHS & ~rhs;
2481 WRITESDEST (dest);
2482 break;
2483
57165fb4 2484 case 0x3e: /* MVN immed. */
dfcd3bfb
JM
2485 dest = ~DPImmRHS;
2486 WRITEDEST (dest);
2487 break;
2488
57165fb4 2489 case 0x3f: /* MVNS immed. */
dfcd3bfb
JM
2490 DPSImmRHS;
2491 WRITESDEST (~rhs);
2492 break;
c906108c 2493
57165fb4 2494
ff44f8e3 2495 /* Single Data Transfer Immediate RHS Instructions. */
c906108c 2496
57165fb4 2497 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2498 lhs = LHS;
2499 if (StoreWord (state, instr, lhs))
2500 LSBase = lhs - LSImmRHS;
2501 break;
2502
57165fb4 2503 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2504 lhs = LHS;
2505 if (LoadWord (state, instr, lhs))
2506 LSBase = lhs - LSImmRHS;
2507 break;
2508
57165fb4 2509 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2510 UNDEF_LSRBaseEQDestWb;
2511 UNDEF_LSRPCBaseWb;
2512 lhs = LHS;
2513 temp = lhs - LSImmRHS;
2514 state->NtransSig = LOW;
2515 if (StoreWord (state, instr, lhs))
2516 LSBase = temp;
2517 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2518 break;
2519
57165fb4 2520 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2521 UNDEF_LSRBaseEQDestWb;
2522 UNDEF_LSRPCBaseWb;
2523 lhs = LHS;
2524 state->NtransSig = LOW;
2525 if (LoadWord (state, instr, lhs))
2526 LSBase = lhs - LSImmRHS;
2527 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2528 break;
2529
57165fb4 2530 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2531 lhs = LHS;
2532 if (StoreByte (state, instr, lhs))
2533 LSBase = lhs - LSImmRHS;
2534 break;
2535
57165fb4 2536 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2537 lhs = LHS;
2538 if (LoadByte (state, instr, lhs, LUNSIGNED))
2539 LSBase = lhs - LSImmRHS;
2540 break;
2541
57165fb4 2542 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2543 UNDEF_LSRBaseEQDestWb;
2544 UNDEF_LSRPCBaseWb;
2545 lhs = LHS;
2546 state->NtransSig = LOW;
2547 if (StoreByte (state, instr, lhs))
2548 LSBase = lhs - LSImmRHS;
2549 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2550 break;
2551
57165fb4 2552 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
dfcd3bfb
JM
2553 UNDEF_LSRBaseEQDestWb;
2554 UNDEF_LSRPCBaseWb;
2555 lhs = LHS;
2556 state->NtransSig = LOW;
2557 if (LoadByte (state, instr, lhs, LUNSIGNED))
2558 LSBase = lhs - LSImmRHS;
2559 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2560 break;
2561
57165fb4 2562 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2563 lhs = LHS;
2564 if (StoreWord (state, instr, lhs))
2565 LSBase = lhs + LSImmRHS;
2566 break;
2567
57165fb4 2568 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2569 lhs = LHS;
2570 if (LoadWord (state, instr, lhs))
2571 LSBase = lhs + LSImmRHS;
2572 break;
2573
57165fb4 2574 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2575 UNDEF_LSRBaseEQDestWb;
2576 UNDEF_LSRPCBaseWb;
2577 lhs = LHS;
2578 state->NtransSig = LOW;
2579 if (StoreWord (state, instr, lhs))
2580 LSBase = lhs + LSImmRHS;
2581 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2582 break;
2583
57165fb4 2584 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2585 UNDEF_LSRBaseEQDestWb;
2586 UNDEF_LSRPCBaseWb;
2587 lhs = LHS;
2588 state->NtransSig = LOW;
2589 if (LoadWord (state, instr, lhs))
2590 LSBase = lhs + LSImmRHS;
2591 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2592 break;
2593
57165fb4 2594 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2595 lhs = LHS;
2596 if (StoreByte (state, instr, lhs))
2597 LSBase = lhs + LSImmRHS;
2598 break;
2599
57165fb4 2600 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2601 lhs = LHS;
2602 if (LoadByte (state, instr, lhs, LUNSIGNED))
2603 LSBase = lhs + LSImmRHS;
2604 break;
2605
57165fb4 2606 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2607 UNDEF_LSRBaseEQDestWb;
2608 UNDEF_LSRPCBaseWb;
2609 lhs = LHS;
2610 state->NtransSig = LOW;
2611 if (StoreByte (state, instr, lhs))
2612 LSBase = lhs + LSImmRHS;
2613 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2614 break;
2615
57165fb4 2616 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
dfcd3bfb
JM
2617 UNDEF_LSRBaseEQDestWb;
2618 UNDEF_LSRPCBaseWb;
2619 lhs = LHS;
2620 state->NtransSig = LOW;
2621 if (LoadByte (state, instr, lhs, LUNSIGNED))
2622 LSBase = lhs + LSImmRHS;
2623 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2624 break;
2625
2626
57165fb4 2627 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2628 (void) StoreWord (state, instr, LHS - LSImmRHS);
2629 break;
2630
57165fb4 2631 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2632 (void) LoadWord (state, instr, LHS - LSImmRHS);
2633 break;
2634
57165fb4 2635 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2636 UNDEF_LSRBaseEQDestWb;
2637 UNDEF_LSRPCBaseWb;
2638 temp = LHS - LSImmRHS;
2639 if (StoreWord (state, instr, temp))
2640 LSBase = temp;
2641 break;
2642
57165fb4 2643 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2644 UNDEF_LSRBaseEQDestWb;
2645 UNDEF_LSRPCBaseWb;
2646 temp = LHS - LSImmRHS;
2647 if (LoadWord (state, instr, temp))
2648 LSBase = temp;
2649 break;
2650
57165fb4 2651 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2652 (void) StoreByte (state, instr, LHS - LSImmRHS);
2653 break;
2654
57165fb4 2655 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2656 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2657 break;
2658
57165fb4 2659 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2660 UNDEF_LSRBaseEQDestWb;
2661 UNDEF_LSRPCBaseWb;
2662 temp = LHS - LSImmRHS;
2663 if (StoreByte (state, instr, temp))
2664 LSBase = temp;
2665 break;
2666
57165fb4 2667 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
dfcd3bfb
JM
2668 UNDEF_LSRBaseEQDestWb;
2669 UNDEF_LSRPCBaseWb;
2670 temp = LHS - LSImmRHS;
2671 if (LoadByte (state, instr, temp, LUNSIGNED))
2672 LSBase = temp;
2673 break;
2674
57165fb4 2675 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2676 (void) StoreWord (state, instr, LHS + LSImmRHS);
2677 break;
2678
57165fb4 2679 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2680 (void) LoadWord (state, instr, LHS + LSImmRHS);
2681 break;
2682
57165fb4 2683 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2684 UNDEF_LSRBaseEQDestWb;
2685 UNDEF_LSRPCBaseWb;
2686 temp = LHS + LSImmRHS;
2687 if (StoreWord (state, instr, temp))
2688 LSBase = temp;
2689 break;
2690
57165fb4 2691 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2692 UNDEF_LSRBaseEQDestWb;
2693 UNDEF_LSRPCBaseWb;
2694 temp = LHS + LSImmRHS;
2695 if (LoadWord (state, instr, temp))
2696 LSBase = temp;
2697 break;
2698
57165fb4 2699 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2700 (void) StoreByte (state, instr, LHS + LSImmRHS);
2701 break;
2702
57165fb4 2703 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2704 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2705 break;
2706
57165fb4 2707 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2708 UNDEF_LSRBaseEQDestWb;
2709 UNDEF_LSRPCBaseWb;
2710 temp = LHS + LSImmRHS;
2711 if (StoreByte (state, instr, temp))
2712 LSBase = temp;
2713 break;
2714
57165fb4 2715 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
dfcd3bfb
JM
2716 UNDEF_LSRBaseEQDestWb;
2717 UNDEF_LSRPCBaseWb;
2718 temp = LHS + LSImmRHS;
2719 if (LoadByte (state, instr, temp, LUNSIGNED))
2720 LSBase = temp;
2721 break;
c906108c 2722
ff44f8e3
NC
2723
2724 /* Single Data Transfer Register RHS Instructions. */
c906108c 2725
57165fb4 2726 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2727 if (BIT (4))
2728 {
2729 ARMul_UndefInstr (state, instr);
2730 break;
2731 }
2732 UNDEF_LSRBaseEQOffWb;
2733 UNDEF_LSRBaseEQDestWb;
2734 UNDEF_LSRPCBaseWb;
2735 UNDEF_LSRPCOffWb;
2736 lhs = LHS;
2737 if (StoreWord (state, instr, lhs))
2738 LSBase = lhs - LSRegRHS;
2739 break;
2740
57165fb4 2741 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2742 if (BIT (4))
2743 {
8207e0f2
NC
2744#ifdef MODE32
2745 if (state->is_v6
2746 && handle_v6_insn (state, instr))
2747 break;
2748#endif
dfcd3bfb
JM
2749 ARMul_UndefInstr (state, instr);
2750 break;
2751 }
2752 UNDEF_LSRBaseEQOffWb;
2753 UNDEF_LSRBaseEQDestWb;
2754 UNDEF_LSRPCBaseWb;
2755 UNDEF_LSRPCOffWb;
2756 lhs = LHS;
e62263b8 2757 temp = lhs - LSRegRHS;
dfcd3bfb 2758 if (LoadWord (state, instr, lhs))
e62263b8 2759 LSBase = temp;
dfcd3bfb
JM
2760 break;
2761
57165fb4 2762 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2763 if (BIT (4))
2764 {
8207e0f2
NC
2765#ifdef MODE32
2766 if (state->is_v6
2767 && handle_v6_insn (state, instr))
2768 break;
2769#endif
dfcd3bfb
JM
2770 ARMul_UndefInstr (state, instr);
2771 break;
2772 }
2773 UNDEF_LSRBaseEQOffWb;
2774 UNDEF_LSRBaseEQDestWb;
2775 UNDEF_LSRPCBaseWb;
2776 UNDEF_LSRPCOffWb;
2777 lhs = LHS;
2778 state->NtransSig = LOW;
2779 if (StoreWord (state, instr, lhs))
2780 LSBase = lhs - LSRegRHS;
2781 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2782 break;
2783
57165fb4 2784 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2785 if (BIT (4))
2786 {
8207e0f2
NC
2787#ifdef MODE32
2788 if (state->is_v6
2789 && handle_v6_insn (state, instr))
2790 break;
2791#endif
dfcd3bfb
JM
2792 ARMul_UndefInstr (state, instr);
2793 break;
2794 }
2795 UNDEF_LSRBaseEQOffWb;
2796 UNDEF_LSRBaseEQDestWb;
2797 UNDEF_LSRPCBaseWb;
2798 UNDEF_LSRPCOffWb;
2799 lhs = LHS;
e62263b8 2800 temp = lhs - LSRegRHS;
dfcd3bfb
JM
2801 state->NtransSig = LOW;
2802 if (LoadWord (state, instr, lhs))
e62263b8 2803 LSBase = temp;
dfcd3bfb
JM
2804 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2805 break;
2806
57165fb4 2807 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2808 if (BIT (4))
2809 {
2810 ARMul_UndefInstr (state, instr);
2811 break;
2812 }
2813 UNDEF_LSRBaseEQOffWb;
2814 UNDEF_LSRBaseEQDestWb;
2815 UNDEF_LSRPCBaseWb;
2816 UNDEF_LSRPCOffWb;
2817 lhs = LHS;
2818 if (StoreByte (state, instr, lhs))
2819 LSBase = lhs - LSRegRHS;
2820 break;
2821
57165fb4 2822 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2823 if (BIT (4))
2824 {
8207e0f2
NC
2825#ifdef MODE32
2826 if (state->is_v6
2827 && handle_v6_insn (state, instr))
2828 break;
2829#endif
dfcd3bfb
JM
2830 ARMul_UndefInstr (state, instr);
2831 break;
2832 }
2833 UNDEF_LSRBaseEQOffWb;
2834 UNDEF_LSRBaseEQDestWb;
2835 UNDEF_LSRPCBaseWb;
2836 UNDEF_LSRPCOffWb;
2837 lhs = LHS;
e62263b8 2838 temp = lhs - LSRegRHS;
dfcd3bfb 2839 if (LoadByte (state, instr, lhs, LUNSIGNED))
e62263b8 2840 LSBase = temp;
dfcd3bfb
JM
2841 break;
2842
57165fb4 2843 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2844 if (BIT (4))
2845 {
8207e0f2
NC
2846#ifdef MODE32
2847 if (state->is_v6
2848 && handle_v6_insn (state, instr))
2849 break;
2850#endif
dfcd3bfb
JM
2851 ARMul_UndefInstr (state, instr);
2852 break;
2853 }
2854 UNDEF_LSRBaseEQOffWb;
2855 UNDEF_LSRBaseEQDestWb;
2856 UNDEF_LSRPCBaseWb;
2857 UNDEF_LSRPCOffWb;
2858 lhs = LHS;
2859 state->NtransSig = LOW;
2860 if (StoreByte (state, instr, lhs))
2861 LSBase = lhs - LSRegRHS;
2862 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2863 break;
2864
57165fb4 2865 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
dfcd3bfb
JM
2866 if (BIT (4))
2867 {
8207e0f2
NC
2868#ifdef MODE32
2869 if (state->is_v6
2870 && handle_v6_insn (state, instr))
2871 break;
2872#endif
dfcd3bfb
JM
2873 ARMul_UndefInstr (state, instr);
2874 break;
2875 }
2876 UNDEF_LSRBaseEQOffWb;
2877 UNDEF_LSRBaseEQDestWb;
2878 UNDEF_LSRPCBaseWb;
2879 UNDEF_LSRPCOffWb;
2880 lhs = LHS;
e62263b8 2881 temp = lhs - LSRegRHS;
dfcd3bfb
JM
2882 state->NtransSig = LOW;
2883 if (LoadByte (state, instr, lhs, LUNSIGNED))
e62263b8 2884 LSBase = temp;
dfcd3bfb
JM
2885 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2886 break;
2887
57165fb4 2888 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2889 if (BIT (4))
2890 {
8207e0f2
NC
2891#ifdef MODE32
2892 if (state->is_v6
2893 && handle_v6_insn (state, instr))
2894 break;
2895#endif
dfcd3bfb
JM
2896 ARMul_UndefInstr (state, instr);
2897 break;
2898 }
2899 UNDEF_LSRBaseEQOffWb;
2900 UNDEF_LSRBaseEQDestWb;
2901 UNDEF_LSRPCBaseWb;
2902 UNDEF_LSRPCOffWb;
2903 lhs = LHS;
2904 if (StoreWord (state, instr, lhs))
2905 LSBase = lhs + LSRegRHS;
2906 break;
2907
57165fb4 2908 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2909 if (BIT (4))
2910 {
2911 ARMul_UndefInstr (state, instr);
2912 break;
2913 }
2914 UNDEF_LSRBaseEQOffWb;
2915 UNDEF_LSRBaseEQDestWb;
2916 UNDEF_LSRPCBaseWb;
2917 UNDEF_LSRPCOffWb;
2918 lhs = LHS;
e62263b8 2919 temp = lhs + LSRegRHS;
dfcd3bfb 2920 if (LoadWord (state, instr, lhs))
e62263b8 2921 LSBase = temp;
dfcd3bfb
JM
2922 break;
2923
57165fb4 2924 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2925 if (BIT (4))
2926 {
8207e0f2
NC
2927#ifdef MODE32
2928 if (state->is_v6
2929 && handle_v6_insn (state, instr))
2930 break;
2931#endif
dfcd3bfb
JM
2932 ARMul_UndefInstr (state, instr);
2933 break;
2934 }
2935 UNDEF_LSRBaseEQOffWb;
2936 UNDEF_LSRBaseEQDestWb;
2937 UNDEF_LSRPCBaseWb;
2938 UNDEF_LSRPCOffWb;
2939 lhs = LHS;
2940 state->NtransSig = LOW;
2941 if (StoreWord (state, instr, lhs))
2942 LSBase = lhs + LSRegRHS;
2943 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2944 break;
2945
57165fb4 2946 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2947 if (BIT (4))
2948 {
8207e0f2
NC
2949#ifdef MODE32
2950 if (state->is_v6
2951 && handle_v6_insn (state, instr))
2952 break;
2953#endif
dfcd3bfb
JM
2954 ARMul_UndefInstr (state, instr);
2955 break;
2956 }
2957 UNDEF_LSRBaseEQOffWb;
2958 UNDEF_LSRBaseEQDestWb;
2959 UNDEF_LSRPCBaseWb;
2960 UNDEF_LSRPCOffWb;
2961 lhs = LHS;
e62263b8 2962 temp = lhs + LSRegRHS;
dfcd3bfb
JM
2963 state->NtransSig = LOW;
2964 if (LoadWord (state, instr, lhs))
e62263b8 2965 LSBase = temp;
dfcd3bfb
JM
2966 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2967 break;
2968
57165fb4 2969 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2970 if (BIT (4))
2971 {
8207e0f2
NC
2972#ifdef MODE32
2973 if (state->is_v6
2974 && handle_v6_insn (state, instr))
2975 break;
2976#endif
dfcd3bfb
JM
2977 ARMul_UndefInstr (state, instr);
2978 break;
2979 }
2980 UNDEF_LSRBaseEQOffWb;
2981 UNDEF_LSRBaseEQDestWb;
2982 UNDEF_LSRPCBaseWb;
2983 UNDEF_LSRPCOffWb;
2984 lhs = LHS;
2985 if (StoreByte (state, instr, lhs))
2986 LSBase = lhs + LSRegRHS;
2987 break;
2988
57165fb4 2989 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
2990 if (BIT (4))
2991 {
2992 ARMul_UndefInstr (state, instr);
2993 break;
2994 }
2995 UNDEF_LSRBaseEQOffWb;
2996 UNDEF_LSRBaseEQDestWb;
2997 UNDEF_LSRPCBaseWb;
2998 UNDEF_LSRPCOffWb;
2999 lhs = LHS;
e62263b8 3000 temp = lhs + LSRegRHS;
dfcd3bfb 3001 if (LoadByte (state, instr, lhs, LUNSIGNED))
e62263b8 3002 LSBase = temp;
dfcd3bfb
JM
3003 break;
3004
57165fb4 3005 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
3006 if (BIT (4))
3007 {
8207e0f2
NC
3008#ifdef MODE32
3009 if (state->is_v6
3010 && handle_v6_insn (state, instr))
3011 break;
3012#endif
dfcd3bfb
JM
3013 ARMul_UndefInstr (state, instr);
3014 break;
3015 }
3016 UNDEF_LSRBaseEQOffWb;
3017 UNDEF_LSRBaseEQDestWb;
3018 UNDEF_LSRPCBaseWb;
3019 UNDEF_LSRPCOffWb;
3020 lhs = LHS;
3021 state->NtransSig = LOW;
3022 if (StoreByte (state, instr, lhs))
3023 LSBase = lhs + LSRegRHS;
3024 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3025 break;
3026
57165fb4 3027 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
dfcd3bfb
JM
3028 if (BIT (4))
3029 {
8207e0f2
NC
3030#ifdef MODE32
3031 if (state->is_v6
3032 && handle_v6_insn (state, instr))
3033 break;
3034#endif
dfcd3bfb
JM
3035 ARMul_UndefInstr (state, instr);
3036 break;
3037 }
3038 UNDEF_LSRBaseEQOffWb;
3039 UNDEF_LSRBaseEQDestWb;
3040 UNDEF_LSRPCBaseWb;
3041 UNDEF_LSRPCOffWb;
3042 lhs = LHS;
e62263b8 3043 temp = lhs + LSRegRHS;
dfcd3bfb
JM
3044 state->NtransSig = LOW;
3045 if (LoadByte (state, instr, lhs, LUNSIGNED))
e62263b8 3046 LSBase = temp;
dfcd3bfb
JM
3047 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3048 break;
3049
3050
57165fb4 3051 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3052 if (BIT (4))
3053 {
8207e0f2
NC
3054#ifdef MODE32
3055 if (state->is_v6
3056 && handle_v6_insn (state, instr))
3057 break;
3058#endif
dfcd3bfb
JM
3059 ARMul_UndefInstr (state, instr);
3060 break;
3061 }
3062 (void) StoreWord (state, instr, LHS - LSRegRHS);
3063 break;
3064
57165fb4 3065 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3066 if (BIT (4))
3067 {
3068 ARMul_UndefInstr (state, instr);
3069 break;
3070 }
3071 (void) LoadWord (state, instr, LHS - LSRegRHS);
3072 break;
3073
57165fb4 3074 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3075 if (BIT (4))
3076 {
3077 ARMul_UndefInstr (state, instr);
3078 break;
3079 }
3080 UNDEF_LSRBaseEQOffWb;
3081 UNDEF_LSRBaseEQDestWb;
3082 UNDEF_LSRPCBaseWb;
3083 UNDEF_LSRPCOffWb;
3084 temp = LHS - LSRegRHS;
3085 if (StoreWord (state, instr, temp))
3086 LSBase = temp;
3087 break;
3088
57165fb4 3089 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3090 if (BIT (4))
3091 {
3092 ARMul_UndefInstr (state, instr);
3093 break;
3094 }
3095 UNDEF_LSRBaseEQOffWb;
3096 UNDEF_LSRBaseEQDestWb;
3097 UNDEF_LSRPCBaseWb;
3098 UNDEF_LSRPCOffWb;
3099 temp = LHS - LSRegRHS;
3100 if (LoadWord (state, instr, temp))
3101 LSBase = temp;
3102 break;
3103
57165fb4 3104 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3105 if (BIT (4))
3106 {
8207e0f2
NC
3107#ifdef MODE32
3108 if (state->is_v6
3109 && handle_v6_insn (state, instr))
3110 break;
3111#endif
dfcd3bfb
JM
3112 ARMul_UndefInstr (state, instr);
3113 break;
3114 }
3115 (void) StoreByte (state, instr, LHS - LSRegRHS);
3116 break;
3117
57165fb4 3118 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3119 if (BIT (4))
3120 {
8207e0f2
NC
3121#ifdef MODE32
3122 if (state->is_v6
3123 && handle_v6_insn (state, instr))
3124 break;
3125#endif
dfcd3bfb
JM
3126 ARMul_UndefInstr (state, instr);
3127 break;
3128 }
3129 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
3130 break;
3131
57165fb4 3132 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3133 if (BIT (4))
3134 {
3135 ARMul_UndefInstr (state, instr);
3136 break;
3137 }
3138 UNDEF_LSRBaseEQOffWb;
3139 UNDEF_LSRBaseEQDestWb;
3140 UNDEF_LSRPCBaseWb;
3141 UNDEF_LSRPCOffWb;
3142 temp = LHS - LSRegRHS;
3143 if (StoreByte (state, instr, temp))
3144 LSBase = temp;
3145 break;
3146
57165fb4 3147 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
dfcd3bfb
JM
3148 if (BIT (4))
3149 {
3150 ARMul_UndefInstr (state, instr);
3151 break;
3152 }
3153 UNDEF_LSRBaseEQOffWb;
3154 UNDEF_LSRBaseEQDestWb;
3155 UNDEF_LSRPCBaseWb;
3156 UNDEF_LSRPCOffWb;
3157 temp = LHS - LSRegRHS;
3158 if (LoadByte (state, instr, temp, LUNSIGNED))
3159 LSBase = temp;
3160 break;
3161
57165fb4 3162 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3163 if (BIT (4))
3164 {
8207e0f2
NC
3165#ifdef MODE32
3166 if (state->is_v6
3167 && handle_v6_insn (state, instr))
3168 break;
3169#endif
dfcd3bfb
JM
3170 ARMul_UndefInstr (state, instr);
3171 break;
3172 }
3173 (void) StoreWord (state, instr, LHS + LSRegRHS);
3174 break;
3175
57165fb4 3176 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3177 if (BIT (4))
3178 {
3179 ARMul_UndefInstr (state, instr);
3180 break;
3181 }
3182 (void) LoadWord (state, instr, LHS + LSRegRHS);
3183 break;
3184
57165fb4 3185 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3186 if (BIT (4))
3187 {
8207e0f2
NC
3188#ifdef MODE32
3189 if (state->is_v6
3190 && handle_v6_insn (state, instr))
3191 break;
3192#endif
dfcd3bfb
JM
3193 ARMul_UndefInstr (state, instr);
3194 break;
3195 }
3196 UNDEF_LSRBaseEQOffWb;
3197 UNDEF_LSRBaseEQDestWb;
3198 UNDEF_LSRPCBaseWb;
3199 UNDEF_LSRPCOffWb;
3200 temp = LHS + LSRegRHS;
3201 if (StoreWord (state, instr, temp))
3202 LSBase = temp;
3203 break;
3204
57165fb4 3205 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3206 if (BIT (4))
3207 {
3208 ARMul_UndefInstr (state, instr);
3209 break;
3210 }
3211 UNDEF_LSRBaseEQOffWb;
3212 UNDEF_LSRBaseEQDestWb;
3213 UNDEF_LSRPCBaseWb;
3214 UNDEF_LSRPCOffWb;
3215 temp = LHS + LSRegRHS;
3216 if (LoadWord (state, instr, temp))
3217 LSBase = temp;
3218 break;
3219
57165fb4 3220 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3221 if (BIT (4))
3222 {
8207e0f2
NC
3223#ifdef MODE32
3224 if (state->is_v6
3225 && handle_v6_insn (state, instr))
3226 break;
3227#endif
dfcd3bfb
JM
3228 ARMul_UndefInstr (state, instr);
3229 break;
3230 }
3231 (void) StoreByte (state, instr, LHS + LSRegRHS);
3232 break;
3233
57165fb4 3234 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3235 if (BIT (4))
3236 {
3237 ARMul_UndefInstr (state, instr);
3238 break;
3239 }
3240 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
3241 break;
3242
57165fb4 3243 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3244 if (BIT (4))
3245 {
3246 ARMul_UndefInstr (state, instr);
3247 break;
3248 }
3249 UNDEF_LSRBaseEQOffWb;
3250 UNDEF_LSRBaseEQDestWb;
3251 UNDEF_LSRPCBaseWb;
3252 UNDEF_LSRPCOffWb;
3253 temp = LHS + LSRegRHS;
3254 if (StoreByte (state, instr, temp))
3255 LSBase = temp;
3256 break;
3257
57165fb4 3258 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
dfcd3bfb
JM
3259 if (BIT (4))
3260 {
3261 /* Check for the special breakpoint opcode.
3262 This value should correspond to the value defined
f1129fb8 3263 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
dfcd3bfb
JM
3264 if (BITS (0, 19) == 0xfdefe)
3265 {
3266 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
3267 ARMul_Abort (state, ARMul_SWIV);
3268 }
3269 else
3270 ARMul_UndefInstr (state, instr);
3271 break;
3272 }
3273 UNDEF_LSRBaseEQOffWb;
3274 UNDEF_LSRBaseEQDestWb;
3275 UNDEF_LSRPCBaseWb;
3276 UNDEF_LSRPCOffWb;
3277 temp = LHS + LSRegRHS;
3278 if (LoadByte (state, instr, temp, LUNSIGNED))
3279 LSBase = temp;
3280 break;
c906108c 3281
ff44f8e3
NC
3282
3283 /* Multiple Data Transfer Instructions. */
c906108c 3284
57165fb4 3285 case 0x80: /* Store, No WriteBack, Post Dec. */
dfcd3bfb
JM
3286 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3287 break;
3288
57165fb4 3289 case 0x81: /* Load, No WriteBack, Post Dec. */
dfcd3bfb
JM
3290 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3291 break;
3292
57165fb4 3293 case 0x82: /* Store, WriteBack, Post Dec. */
dfcd3bfb
JM
3294 temp = LSBase - LSMNumRegs;
3295 STOREMULT (instr, temp + 4L, temp);
3296 break;
c906108c 3297
57165fb4 3298 case 0x83: /* Load, WriteBack, Post Dec. */
dfcd3bfb
JM
3299 temp = LSBase - LSMNumRegs;
3300 LOADMULT (instr, temp + 4L, temp);
3301 break;
c906108c 3302
57165fb4 3303 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
dfcd3bfb
JM
3304 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3305 break;
c906108c 3306
57165fb4 3307 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
dfcd3bfb
JM
3308 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3309 break;
3310
57165fb4 3311 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
dfcd3bfb
JM
3312 temp = LSBase - LSMNumRegs;
3313 STORESMULT (instr, temp + 4L, temp);
3314 break;
3315
57165fb4 3316 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
dfcd3bfb
JM
3317 temp = LSBase - LSMNumRegs;
3318 LOADSMULT (instr, temp + 4L, temp);
3319 break;
c906108c 3320
57165fb4 3321 case 0x88: /* Store, No WriteBack, Post Inc. */
dfcd3bfb
JM
3322 STOREMULT (instr, LSBase, 0L);
3323 break;
3324
57165fb4 3325 case 0x89: /* Load, No WriteBack, Post Inc. */
dfcd3bfb
JM
3326 LOADMULT (instr, LSBase, 0L);
3327 break;
3328
57165fb4 3329 case 0x8a: /* Store, WriteBack, Post Inc. */
dfcd3bfb
JM
3330 temp = LSBase;
3331 STOREMULT (instr, temp, temp + LSMNumRegs);
3332 break;
3333
57165fb4 3334 case 0x8b: /* Load, WriteBack, Post Inc. */
dfcd3bfb
JM
3335 temp = LSBase;
3336 LOADMULT (instr, temp, temp + LSMNumRegs);
3337 break;
3338
57165fb4 3339 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
dfcd3bfb
JM
3340 STORESMULT (instr, LSBase, 0L);
3341 break;
3342
57165fb4 3343 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
dfcd3bfb
JM
3344 LOADSMULT (instr, LSBase, 0L);
3345 break;
3346
57165fb4 3347 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
dfcd3bfb
JM
3348 temp = LSBase;
3349 STORESMULT (instr, temp, temp + LSMNumRegs);
3350 break;
3351
57165fb4 3352 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
dfcd3bfb
JM
3353 temp = LSBase;
3354 LOADSMULT (instr, temp, temp + LSMNumRegs);
3355 break;
3356
57165fb4 3357 case 0x90: /* Store, No WriteBack, Pre Dec. */
dfcd3bfb
JM
3358 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3359 break;
3360
57165fb4 3361 case 0x91: /* Load, No WriteBack, Pre Dec. */
dfcd3bfb
JM
3362 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3363 break;
3364
57165fb4 3365 case 0x92: /* Store, WriteBack, Pre Dec. */
dfcd3bfb
JM
3366 temp = LSBase - LSMNumRegs;
3367 STOREMULT (instr, temp, temp);
3368 break;
3369
57165fb4 3370 case 0x93: /* Load, WriteBack, Pre Dec. */
dfcd3bfb
JM
3371 temp = LSBase - LSMNumRegs;
3372 LOADMULT (instr, temp, temp);
3373 break;
3374
57165fb4 3375 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
dfcd3bfb
JM
3376 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3377 break;
3378
57165fb4 3379 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
dfcd3bfb
JM
3380 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3381 break;
3382
57165fb4 3383 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
dfcd3bfb
JM
3384 temp = LSBase - LSMNumRegs;
3385 STORESMULT (instr, temp, temp);
3386 break;
3387
57165fb4 3388 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
dfcd3bfb
JM
3389 temp = LSBase - LSMNumRegs;
3390 LOADSMULT (instr, temp, temp);
3391 break;
3392
57165fb4 3393 case 0x98: /* Store, No WriteBack, Pre Inc. */
dfcd3bfb
JM
3394 STOREMULT (instr, LSBase + 4L, 0L);
3395 break;
3396
57165fb4 3397 case 0x99: /* Load, No WriteBack, Pre Inc. */
dfcd3bfb
JM
3398 LOADMULT (instr, LSBase + 4L, 0L);
3399 break;
3400
57165fb4 3401 case 0x9a: /* Store, WriteBack, Pre Inc. */
dfcd3bfb
JM
3402 temp = LSBase;
3403 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3404 break;
3405
57165fb4 3406 case 0x9b: /* Load, WriteBack, Pre Inc. */
dfcd3bfb
JM
3407 temp = LSBase;
3408 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3409 break;
c906108c 3410
57165fb4 3411 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
dfcd3bfb
JM
3412 STORESMULT (instr, LSBase + 4L, 0L);
3413 break;
c906108c 3414
57165fb4 3415 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
dfcd3bfb
JM
3416 LOADSMULT (instr, LSBase + 4L, 0L);
3417 break;
c906108c 3418
57165fb4 3419 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
dfcd3bfb
JM
3420 temp = LSBase;
3421 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3422 break;
3423
57165fb4 3424 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
dfcd3bfb
JM
3425 temp = LSBase;
3426 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3427 break;
c906108c 3428
c906108c 3429
ff44f8e3 3430 /* Branch forward. */
dfcd3bfb
JM
3431 case 0xa0:
3432 case 0xa1:
3433 case 0xa2:
3434 case 0xa3:
3435 case 0xa4:
3436 case 0xa5:
3437 case 0xa6:
3438 case 0xa7:
3439 state->Reg[15] = pc + 8 + POSBRANCH;
3440 FLUSHPIPE;
3441 break;
c906108c 3442
c906108c 3443
ff44f8e3 3444 /* Branch backward. */
dfcd3bfb
JM
3445 case 0xa8:
3446 case 0xa9:
3447 case 0xaa:
3448 case 0xab:
3449 case 0xac:
3450 case 0xad:
3451 case 0xae:
3452 case 0xaf:
3453 state->Reg[15] = pc + 8 + NEGBRANCH;
3454 FLUSHPIPE;
3455 break;
c906108c 3456
c906108c 3457
ff44f8e3 3458 /* Branch and Link forward. */
dfcd3bfb
JM
3459 case 0xb0:
3460 case 0xb1:
3461 case 0xb2:
3462 case 0xb3:
3463 case 0xb4:
3464 case 0xb5:
3465 case 0xb6:
3466 case 0xb7:
ff44f8e3 3467 /* Put PC into Link. */
c906108c 3468#ifdef MODE32
ff44f8e3 3469 state->Reg[14] = pc + 4;
c906108c 3470#else
ff44f8e3 3471 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
c906108c 3472#endif
dfcd3bfb
JM
3473 state->Reg[15] = pc + 8 + POSBRANCH;
3474 FLUSHPIPE;
3475 break;
c906108c 3476
c906108c 3477
ff44f8e3 3478 /* Branch and Link backward. */
dfcd3bfb
JM
3479 case 0xb8:
3480 case 0xb9:
3481 case 0xba:
3482 case 0xbb:
3483 case 0xbc:
3484 case 0xbd:
3485 case 0xbe:
3486 case 0xbf:
ff44f8e3 3487 /* Put PC into Link. */
c906108c 3488#ifdef MODE32
ff44f8e3 3489 state->Reg[14] = pc + 4;
c906108c 3490#else
ff44f8e3 3491 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
c906108c 3492#endif
dfcd3bfb
JM
3493 state->Reg[15] = pc + 8 + NEGBRANCH;
3494 FLUSHPIPE;
3495 break;
c906108c 3496
57165fb4 3497
ff44f8e3 3498 /* Co-Processor Data Transfers. */
dfcd3bfb 3499 case 0xc4:
ff44f8e3 3500 if (state->is_v5)
f1129fb8 3501 {
ff44f8e3
NC
3502 /* Reading from R15 is UNPREDICTABLE. */
3503 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
f1129fb8 3504 ARMul_UndefInstr (state, instr);
ff44f8e3
NC
3505 /* Is access to coprocessor 0 allowed ? */
3506 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3507 ARMul_UndefInstr (state, instr);
3508 /* Special treatment for XScale coprocessors. */
3509 else if (state->is_XScale)
f1129fb8 3510 {
ff44f8e3
NC
3511 /* Only opcode 0 is supported. */
3512 if (BITS (4, 7) != 0x00)
3513 ARMul_UndefInstr (state, instr);
3514 /* Only coporcessor 0 is supported. */
3515 else if (CPNum != 0x00)
3516 ARMul_UndefInstr (state, instr);
3517 /* Only accumulator 0 is supported. */
3518 else if (BITS (0, 3) != 0x00)
3519 ARMul_UndefInstr (state, instr);
3520 else
3521 {
10b57fcb 3522 /* XScale MAR insn. Move two registers into accumulator. */
ff44f8e3
NC
3523 state->Accumulator = state->Reg[BITS (12, 15)];
3524 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3525 }
f1129fb8 3526 }
ff44f8e3
NC
3527 else
3528 /* FIXME: Not sure what to do for other v5 processors. */
3529 ARMul_UndefInstr (state, instr);
f1129fb8
NC
3530 break;
3531 }
3532 /* Drop through. */
3533
57165fb4 3534 case 0xc0: /* Store , No WriteBack , Post Dec. */
dfcd3bfb
JM
3535 ARMul_STC (state, instr, LHS);
3536 break;
3537
3538 case 0xc5:
ff44f8e3 3539 if (state->is_v5)
f1129fb8 3540 {
ff44f8e3
NC
3541 /* Writes to R15 are UNPREDICATABLE. */
3542 if (DESTReg == 15 || LHSReg == 15)
f1129fb8 3543 ARMul_UndefInstr (state, instr);
ff44f8e3
NC
3544 /* Is access to the coprocessor allowed ? */
3545 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3546 ARMul_UndefInstr (state, instr);
3547 /* Special handling for XScale coprcoessors. */
3548 else if (state->is_XScale)
f1129fb8 3549 {
ff44f8e3
NC
3550 /* Only opcode 0 is supported. */
3551 if (BITS (4, 7) != 0x00)
3552 ARMul_UndefInstr (state, instr);
3553 /* Only coprocessor 0 is supported. */
3554 else if (CPNum != 0x00)
3555 ARMul_UndefInstr (state, instr);
3556 /* Only accumulator 0 is supported. */
3557 else if (BITS (0, 3) != 0x00)
3558 ARMul_UndefInstr (state, instr);
3559 else
3560 {
3561 /* XScale MRA insn. Move accumulator into two registers. */
3562 ARMword t1 = (state->Accumulator >> 32) & 255;
f1129fb8 3563
ff44f8e3
NC
3564 if (t1 & 128)
3565 t1 -= 256;
f1129fb8 3566
ff44f8e3
NC
3567 state->Reg[BITS (12, 15)] = state->Accumulator;
3568 state->Reg[BITS (16, 19)] = t1;
3569 break;
3570 }
f1129fb8 3571 }
ff44f8e3
NC
3572 else
3573 /* FIXME: Not sure what to do for other v5 processors. */
3574 ARMul_UndefInstr (state, instr);
f1129fb8
NC
3575 break;
3576 }
3577 /* Drop through. */
3578
57165fb4 3579 case 0xc1: /* Load , No WriteBack , Post Dec. */
dfcd3bfb
JM
3580 ARMul_LDC (state, instr, LHS);
3581 break;
3582
3583 case 0xc2:
57165fb4 3584 case 0xc6: /* Store , WriteBack , Post Dec. */
dfcd3bfb
JM
3585 lhs = LHS;
3586 state->Base = lhs - LSCOff;
3587 ARMul_STC (state, instr, lhs);
3588 break;
3589
3590 case 0xc3:
57165fb4 3591 case 0xc7: /* Load , WriteBack , Post Dec. */
dfcd3bfb
JM
3592 lhs = LHS;
3593 state->Base = lhs - LSCOff;
3594 ARMul_LDC (state, instr, lhs);
3595 break;
3596
3597 case 0xc8:
57165fb4 3598 case 0xcc: /* Store , No WriteBack , Post Inc. */
dfcd3bfb
JM
3599 ARMul_STC (state, instr, LHS);
3600 break;
3601
3602 case 0xc9:
57165fb4 3603 case 0xcd: /* Load , No WriteBack , Post Inc. */
dfcd3bfb
JM
3604 ARMul_LDC (state, instr, LHS);
3605 break;
3606
3607 case 0xca:
57165fb4 3608 case 0xce: /* Store , WriteBack , Post Inc. */
dfcd3bfb
JM
3609 lhs = LHS;
3610 state->Base = lhs + LSCOff;
3611 ARMul_STC (state, instr, LHS);
3612 break;
3613
3614 case 0xcb:
57165fb4 3615 case 0xcf: /* Load , WriteBack , Post Inc. */
dfcd3bfb
JM
3616 lhs = LHS;
3617 state->Base = lhs + LSCOff;
3618 ARMul_LDC (state, instr, LHS);
3619 break;
3620
dfcd3bfb 3621 case 0xd0:
57165fb4 3622 case 0xd4: /* Store , No WriteBack , Pre Dec. */
dfcd3bfb
JM
3623 ARMul_STC (state, instr, LHS - LSCOff);
3624 break;
3625
3626 case 0xd1:
57165fb4 3627 case 0xd5: /* Load , No WriteBack , Pre Dec. */
dfcd3bfb
JM
3628 ARMul_LDC (state, instr, LHS - LSCOff);
3629 break;
3630
3631 case 0xd2:
57165fb4 3632 case 0xd6: /* Store , WriteBack , Pre Dec. */
dfcd3bfb
JM
3633 lhs = LHS - LSCOff;
3634 state->Base = lhs;
3635 ARMul_STC (state, instr, lhs);
3636 break;
3637
3638 case 0xd3:
57165fb4 3639 case 0xd7: /* Load , WriteBack , Pre Dec. */
dfcd3bfb
JM
3640 lhs = LHS - LSCOff;
3641 state->Base = lhs;
3642 ARMul_LDC (state, instr, lhs);
3643 break;
3644
3645 case 0xd8:
57165fb4 3646 case 0xdc: /* Store , No WriteBack , Pre Inc. */
dfcd3bfb
JM
3647 ARMul_STC (state, instr, LHS + LSCOff);
3648 break;
3649
3650 case 0xd9:
57165fb4 3651 case 0xdd: /* Load , No WriteBack , Pre Inc. */
dfcd3bfb
JM
3652 ARMul_LDC (state, instr, LHS + LSCOff);
3653 break;
3654
3655 case 0xda:
57165fb4 3656 case 0xde: /* Store , WriteBack , Pre Inc. */
dfcd3bfb
JM
3657 lhs = LHS + LSCOff;
3658 state->Base = lhs;
3659 ARMul_STC (state, instr, lhs);
3660 break;
3661
3662 case 0xdb:
57165fb4 3663 case 0xdf: /* Load , WriteBack , Pre Inc. */
dfcd3bfb
JM
3664 lhs = LHS + LSCOff;
3665 state->Base = lhs;
3666 ARMul_LDC (state, instr, lhs);
3667 break;
c906108c 3668
c906108c 3669
ff44f8e3 3670 /* Co-Processor Register Transfers (MCR) and Data Ops. */
57165fb4 3671
dfcd3bfb 3672 case 0xe2:
ff44f8e3
NC
3673 if (! CP_ACCESS_ALLOWED (state, CPNum))
3674 {
3675 ARMul_UndefInstr (state, instr);
3676 break;
3677 }
f1129fb8
NC
3678 if (state->is_XScale)
3679 switch (BITS (18, 19))
3680 {
3681 case 0x0:
630ace25
NC
3682 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3683 {
3684 /* XScale MIA instruction. Signed multiplication of
3685 two 32 bit values and addition to 40 bit accumulator. */
c4793bac
PB
3686 ARMsdword Rm = state->Reg[MULLHSReg];
3687 ARMsdword Rs = state->Reg[MULACCReg];
630ace25
NC
3688
3689 if (Rm & (1 << 31))
3690 Rm -= 1ULL << 32;
3691 if (Rs & (1 << 31))
3692 Rs -= 1ULL << 32;
3693 state->Accumulator += Rm * Rs;
3694 goto donext;
3695 }
3696 break;
f1129fb8
NC
3697
3698 case 0x2:
630ace25
NC
3699 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3700 {
3701 /* XScale MIAPH instruction. */
3702 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3703 ARMword t2 = state->Reg[MULACCReg] >> 16;
3704 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3705 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
c4793bac 3706 ARMsdword t5;
630ace25
NC
3707
3708 if (t1 & (1 << 15))
3709 t1 -= 1 << 16;
3710 if (t2 & (1 << 15))
3711 t2 -= 1 << 16;
3712 if (t3 & (1 << 15))
3713 t3 -= 1 << 16;
3714 if (t4 & (1 << 15))
3715 t4 -= 1 << 16;
3716 t1 *= t2;
3717 t5 = t1;
3718 if (t5 & (1 << 31))
3719 t5 -= 1ULL << 32;
3720 state->Accumulator += t5;
3721 t3 *= t4;
3722 t5 = t3;
3723 if (t5 & (1 << 31))
3724 t5 -= 1ULL << 32;
3725 state->Accumulator += t5;
3726 goto donext;
3727 }
3728 break;
f1129fb8
NC
3729
3730 case 0x3:
630ace25
NC
3731 if (BITS (4, 11) == 1)
3732 {
3733 /* XScale MIAxy instruction. */
3734 ARMword t1;
3735 ARMword t2;
c4793bac 3736 ARMsdword t5;
630ace25
NC
3737
3738 if (BIT (17))
3739 t1 = state->Reg[MULLHSReg] >> 16;
3740 else
3741 t1 = state->Reg[MULLHSReg] & 0xffff;
3742
3743 if (BIT (16))
3744 t2 = state->Reg[MULACCReg] >> 16;
3745 else
3746 t2 = state->Reg[MULACCReg] & 0xffff;
3747
3748 if (t1 & (1 << 15))
3749 t1 -= 1 << 16;
3750 if (t2 & (1 << 15))
3751 t2 -= 1 << 16;
3752 t1 *= t2;
3753 t5 = t1;
3754 if (t5 & (1 << 31))
3755 t5 -= 1ULL << 32;
3756 state->Accumulator += t5;
3757 goto donext;
3758 }
3759 break;
f1129fb8
NC
3760
3761 default:
3762 break;
3763 }
3764 /* Drop through. */
3765
dfcd3bfb
JM
3766 case 0xe0:
3767 case 0xe4:
3768 case 0xe6:
3769 case 0xe8:
3770 case 0xea:
3771 case 0xec:
3772 case 0xee:
3773 if (BIT (4))
57165fb4
NC
3774 {
3775 /* MCR. */
dfcd3bfb
JM
3776 if (DESTReg == 15)
3777 {
3778 UNDEF_MCRPC;
c906108c 3779#ifdef MODE32
dfcd3bfb 3780 ARMul_MCR (state, instr, state->Reg[15] + isize);
c906108c 3781#else
dfcd3bfb
JM
3782 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3783 ((state->Reg[15] + isize) & R15PCBITS));
c906108c 3784#endif
dfcd3bfb
JM
3785 }
3786 else
3787 ARMul_MCR (state, instr, DEST);
3788 }
57165fb4
NC
3789 else
3790 /* CDP Part 1. */
dfcd3bfb
JM
3791 ARMul_CDP (state, instr);
3792 break;
c906108c 3793
c906108c 3794
ff44f8e3 3795 /* Co-Processor Register Transfers (MRC) and Data Ops. */
dfcd3bfb
JM
3796 case 0xe1:
3797 case 0xe3:
3798 case 0xe5:
3799 case 0xe7:
3800 case 0xe9:
3801 case 0xeb:
3802 case 0xed:
3803 case 0xef:
3804 if (BIT (4))
57165fb4
NC
3805 {
3806 /* MRC */
dfcd3bfb
JM
3807 temp = ARMul_MRC (state, instr);
3808 if (DESTReg == 15)
3809 {
3810 ASSIGNN ((temp & NBIT) != 0);
3811 ASSIGNZ ((temp & ZBIT) != 0);
3812 ASSIGNC ((temp & CBIT) != 0);
3813 ASSIGNV ((temp & VBIT) != 0);
3814 }
3815 else
3816 DEST = temp;
3817 }
57165fb4
NC
3818 else
3819 /* CDP Part 2. */
dfcd3bfb
JM
3820 ARMul_CDP (state, instr);
3821 break;
c906108c 3822
c906108c 3823
57165fb4 3824 /* SWI instruction. */
dfcd3bfb
JM
3825 case 0xf0:
3826 case 0xf1:
3827 case 0xf2:
3828 case 0xf3:
3829 case 0xf4:
3830 case 0xf5:
3831 case 0xf6:
3832 case 0xf7:
3833 case 0xf8:
3834 case 0xf9:
3835 case 0xfa:
3836 case 0xfb:
3837 case 0xfc:
3838 case 0xfd:
3839 case 0xfe:
3840 case 0xff:
3841 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
fae0bf59
NC
3842 {
3843 /* A prefetch abort. */
c3ae2f98 3844 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
dfcd3bfb
JM
3845 ARMul_Abort (state, ARMul_PrefetchAbortV);
3846 break;
3847 }
3848
3849 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
ff44f8e3
NC
3850 ARMul_Abort (state, ARMul_SWIV);
3851
dfcd3bfb 3852 break;
ff44f8e3
NC
3853 }
3854 }
c906108c
SS
3855
3856#ifdef MODET
dfcd3bfb 3857 donext:
c906108c
SS
3858#endif
3859
7a292a7a 3860#ifdef NEED_UI_LOOP_HOOK
0aaa4a81 3861 if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
dfcd3bfb
JM
3862 {
3863 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
0aaa4a81 3864 deprecated_ui_loop_hook (0);
dfcd3bfb 3865 }
7a292a7a
SS
3866#endif /* NEED_UI_LOOP_HOOK */
3867
dfcd3bfb
JM
3868 if (state->Emulate == ONCE)
3869 state->Emulate = STOP;
c1a72ffd
NC
3870 /* If we have changed mode, allow the PC to advance before stopping. */
3871 else if (state->Emulate == CHANGEMODE)
3872 continue;
dfcd3bfb
JM
3873 else if (state->Emulate != RUN)
3874 break;
3875 }
ff44f8e3 3876 while (!stop_simulator);
c906108c 3877
dfcd3bfb
JM
3878 state->decoded = decoded;
3879 state->loaded = loaded;
3880 state->pc = pc;
c1a72ffd
NC
3881
3882 return pc;
ff44f8e3 3883}
c906108c 3884
ff44f8e3
NC
3885/* This routine evaluates most Data Processing register RHS's with the S
3886 bit clear. It is intended to be called from the macro DPRegRHS, which
3887 filters the common case of an unshifted register with in line code. */
c906108c 3888
dfcd3bfb
JM
3889static ARMword
3890GetDPRegRHS (ARMul_State * state, ARMword instr)
3891{
3892 ARMword shamt, base;
c906108c 3893
dfcd3bfb
JM
3894 base = RHSReg;
3895 if (BIT (4))
ff44f8e3
NC
3896 {
3897 /* Shift amount in a register. */
dfcd3bfb
JM
3898 UNDEF_Shift;
3899 INCPC;
c906108c 3900#ifndef MODE32
dfcd3bfb
JM
3901 if (base == 15)
3902 base = ECC | ER15INT | R15PC | EMODE;
3903 else
3904#endif
3905 base = state->Reg[base];
3906 ARMul_Icycles (state, 1, 0L);
3907 shamt = state->Reg[BITS (8, 11)] & 0xff;
3908 switch ((int) BITS (5, 6))
3909 {
3910 case LSL:
3911 if (shamt == 0)
3912 return (base);
3913 else if (shamt >= 32)
3914 return (0);
3915 else
3916 return (base << shamt);
3917 case LSR:
3918 if (shamt == 0)
3919 return (base);
3920 else if (shamt >= 32)
3921 return (0);
3922 else
3923 return (base >> shamt);
3924 case ASR:
3925 if (shamt == 0)
3926 return (base);
3927 else if (shamt >= 32)
c4793bac 3928 return ((ARMword) ((ARMsword) base >> 31L));
dfcd3bfb 3929 else
c4793bac 3930 return ((ARMword) ((ARMsword) base >> (int) shamt));
dfcd3bfb
JM
3931 case ROR:
3932 shamt &= 0x1f;
3933 if (shamt == 0)
3934 return (base);
3935 else
3936 return ((base << (32 - shamt)) | (base >> shamt));
3937 }
c906108c 3938 }
dfcd3bfb 3939 else
ff44f8e3
NC
3940 {
3941 /* Shift amount is a constant. */
c906108c 3942#ifndef MODE32
dfcd3bfb
JM
3943 if (base == 15)
3944 base = ECC | ER15INT | R15PC | EMODE;
3945 else
3946#endif
3947 base = state->Reg[base];
3948 shamt = BITS (7, 11);
3949 switch ((int) BITS (5, 6))
3950 {
3951 case LSL:
3952 return (base << shamt);
3953 case LSR:
3954 if (shamt == 0)
3955 return (0);
3956 else
3957 return (base >> shamt);
3958 case ASR:
3959 if (shamt == 0)
c4793bac 3960 return ((ARMword) ((ARMsword) base >> 31L));
dfcd3bfb 3961 else
c4793bac 3962 return ((ARMword) ((ARMsword) base >> (int) shamt));
dfcd3bfb 3963 case ROR:
57165fb4
NC
3964 if (shamt == 0)
3965 /* It's an RRX. */
dfcd3bfb
JM
3966 return ((base >> 1) | (CFLAG << 31));
3967 else
3968 return ((base << (32 - shamt)) | (base >> shamt));
3969 }
c906108c 3970 }
57165fb4 3971
ff44f8e3 3972 return 0;
dfcd3bfb
JM
3973}
3974
ff44f8e3
NC
3975/* This routine evaluates most Logical Data Processing register RHS's
3976 with the S bit set. It is intended to be called from the macro
3977 DPSRegRHS, which filters the common case of an unshifted register
3978 with in line code. */
c906108c 3979
dfcd3bfb
JM
3980static ARMword
3981GetDPSRegRHS (ARMul_State * state, ARMword instr)
3982{
3983 ARMword shamt, base;
c906108c 3984
dfcd3bfb
JM
3985 base = RHSReg;
3986 if (BIT (4))
ff44f8e3
NC
3987 {
3988 /* Shift amount in a register. */
dfcd3bfb
JM
3989 UNDEF_Shift;
3990 INCPC;
c906108c 3991#ifndef MODE32
dfcd3bfb
JM
3992 if (base == 15)
3993 base = ECC | ER15INT | R15PC | EMODE;
3994 else
3995#endif
3996 base = state->Reg[base];
3997 ARMul_Icycles (state, 1, 0L);
3998 shamt = state->Reg[BITS (8, 11)] & 0xff;
3999 switch ((int) BITS (5, 6))
4000 {
4001 case LSL:
4002 if (shamt == 0)
4003 return (base);
4004 else if (shamt == 32)
4005 {
4006 ASSIGNC (base & 1);
4007 return (0);
4008 }
4009 else if (shamt > 32)
4010 {
4011 CLEARC;
4012 return (0);
4013 }
4014 else
4015 {
4016 ASSIGNC ((base >> (32 - shamt)) & 1);
4017 return (base << shamt);
4018 }
4019 case LSR:
4020 if (shamt == 0)
4021 return (base);
4022 else if (shamt == 32)
4023 {
4024 ASSIGNC (base >> 31);
4025 return (0);
4026 }
4027 else if (shamt > 32)
4028 {
4029 CLEARC;
4030 return (0);
4031 }
4032 else
4033 {
4034 ASSIGNC ((base >> (shamt - 1)) & 1);
4035 return (base >> shamt);
4036 }
4037 case ASR:
4038 if (shamt == 0)
4039 return (base);
4040 else if (shamt >= 32)
4041 {
4042 ASSIGNC (base >> 31L);
c4793bac 4043 return ((ARMword) ((ARMsword) base >> 31L));
dfcd3bfb
JM
4044 }
4045 else
4046 {
c4793bac
PB
4047 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4048 return ((ARMword) ((ARMsword) base >> (int) shamt));
dfcd3bfb
JM
4049 }
4050 case ROR:
4051 if (shamt == 0)
4052 return (base);
4053 shamt &= 0x1f;
4054 if (shamt == 0)
4055 {
4056 ASSIGNC (base >> 31);
4057 return (base);
4058 }
4059 else
4060 {
4061 ASSIGNC ((base >> (shamt - 1)) & 1);
4062 return ((base << (32 - shamt)) | (base >> shamt));
4063 }
4064 }
c906108c 4065 }
dfcd3bfb 4066 else
ff44f8e3
NC
4067 {
4068 /* Shift amount is a constant. */
c906108c 4069#ifndef MODE32
dfcd3bfb
JM
4070 if (base == 15)
4071 base = ECC | ER15INT | R15PC | EMODE;
4072 else
4073#endif
4074 base = state->Reg[base];
4075 shamt = BITS (7, 11);
57165fb4 4076
dfcd3bfb
JM
4077 switch ((int) BITS (5, 6))
4078 {
4079 case LSL:
4080 ASSIGNC ((base >> (32 - shamt)) & 1);
4081 return (base << shamt);
4082 case LSR:
4083 if (shamt == 0)
4084 {
4085 ASSIGNC (base >> 31);
4086 return (0);
4087 }
4088 else
4089 {
4090 ASSIGNC ((base >> (shamt - 1)) & 1);
4091 return (base >> shamt);
4092 }
4093 case ASR:
4094 if (shamt == 0)
4095 {
4096 ASSIGNC (base >> 31L);
c4793bac 4097 return ((ARMword) ((ARMsword) base >> 31L));
dfcd3bfb
JM
4098 }
4099 else
4100 {
c4793bac
PB
4101 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4102 return ((ARMword) ((ARMsword) base >> (int) shamt));
dfcd3bfb
JM
4103 }
4104 case ROR:
4105 if (shamt == 0)
57165fb4
NC
4106 {
4107 /* It's an RRX. */
dfcd3bfb
JM
4108 shamt = CFLAG;
4109 ASSIGNC (base & 1);
4110 return ((base >> 1) | (shamt << 31));
4111 }
4112 else
4113 {
4114 ASSIGNC ((base >> (shamt - 1)) & 1);
4115 return ((base << (32 - shamt)) | (base >> shamt));
4116 }
4117 }
c906108c 4118 }
ff44f8e3
NC
4119
4120 return 0;
dfcd3bfb 4121}
c906108c 4122
ff44f8e3 4123/* This routine handles writes to register 15 when the S bit is not set. */
c906108c 4124
dfcd3bfb
JM
4125static void
4126WriteR15 (ARMul_State * state, ARMword src)
c906108c 4127{
892c6b9d
AO
4128 /* The ARM documentation states that the two least significant bits
4129 are discarded when setting PC, except in the cases handled by
e063aa3b
AO
4130 WriteR15Branch() below. It's probably an oversight: in THUMB
4131 mode, the second least significant bit should probably not be
4132 discarded. */
4133#ifdef MODET
4134 if (TFLAG)
4135 src &= 0xfffffffe;
4136 else
4137#endif
4138 src &= 0xfffffffc;
57165fb4 4139
c906108c 4140#ifdef MODE32
892c6b9d 4141 state->Reg[15] = src & PCBITS;
c906108c 4142#else
892c6b9d 4143 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
dfcd3bfb 4144 ARMul_R15Altered (state);
c906108c 4145#endif
57165fb4 4146
dfcd3bfb
JM
4147 FLUSHPIPE;
4148}
c906108c 4149
ff44f8e3 4150/* This routine handles writes to register 15 when the S bit is set. */
c906108c 4151
dfcd3bfb
JM
4152static void
4153WriteSR15 (ARMul_State * state, ARMword src)
c906108c
SS
4154{
4155#ifdef MODE32
dfcd3bfb
JM
4156 if (state->Bank > 0)
4157 {
4158 state->Cpsr = state->Spsr[state->Bank];
4159 ARMul_CPSRAltered (state);
c906108c 4160 }
e063aa3b
AO
4161#ifdef MODET
4162 if (TFLAG)
4163 src &= 0xfffffffe;
4164 else
4165#endif
4166 src &= 0xfffffffc;
4167 state->Reg[15] = src & PCBITS;
c906108c 4168#else
e063aa3b
AO
4169#ifdef MODET
4170 if (TFLAG)
57165fb4
NC
4171 /* ARMul_R15Altered would have to support it. */
4172 abort ();
e063aa3b
AO
4173 else
4174#endif
4175 src &= 0xfffffffc;
57165fb4 4176
dfcd3bfb
JM
4177 if (state->Bank == USERBANK)
4178 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
4179 else
4180 state->Reg[15] = src;
57165fb4 4181
dfcd3bfb 4182 ARMul_R15Altered (state);
c906108c 4183#endif
dfcd3bfb
JM
4184 FLUSHPIPE;
4185}
c906108c 4186
892c6b9d 4187/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
ff44f8e3 4188 will switch to Thumb mode if the least significant bit is set. */
892c6b9d
AO
4189
4190static void
4191WriteR15Branch (ARMul_State * state, ARMword src)
4192{
4193#ifdef MODET
4194 if (src & 1)
ff44f8e3
NC
4195 {
4196 /* Thumb bit. */
892c6b9d
AO
4197 SETT;
4198 state->Reg[15] = src & 0xfffffffe;
4199 }
4200 else
4201 {
4202 CLEART;
4203 state->Reg[15] = src & 0xfffffffc;
4204 }
4205 FLUSHPIPE;
4206#else
4207 WriteR15 (state, src);
4208#endif
4209}
4210
ff44f8e3
NC
4211/* This routine evaluates most Load and Store register RHS's. It is
4212 intended to be called from the macro LSRegRHS, which filters the
4213 common case of an unshifted register with in line code. */
c906108c 4214
dfcd3bfb
JM
4215static ARMword
4216GetLSRegRHS (ARMul_State * state, ARMword instr)
4217{
4218 ARMword shamt, base;
c906108c 4219
dfcd3bfb 4220 base = RHSReg;
c906108c 4221#ifndef MODE32
dfcd3bfb 4222 if (base == 15)
57165fb4
NC
4223 /* Now forbidden, but ... */
4224 base = ECC | ER15INT | R15PC | EMODE;
dfcd3bfb
JM
4225 else
4226#endif
4227 base = state->Reg[base];
4228
4229 shamt = BITS (7, 11);
4230 switch ((int) BITS (5, 6))
4231 {
4232 case LSL:
4233 return (base << shamt);
4234 case LSR:
4235 if (shamt == 0)
4236 return (0);
4237 else
4238 return (base >> shamt);
4239 case ASR:
4240 if (shamt == 0)
c4793bac 4241 return ((ARMword) ((ARMsword) base >> 31L));
dfcd3bfb 4242 else
c4793bac 4243 return ((ARMword) ((ARMsword) base >> (int) shamt));
dfcd3bfb 4244 case ROR:
57165fb4
NC
4245 if (shamt == 0)
4246 /* It's an RRX. */
dfcd3bfb
JM
4247 return ((base >> 1) | (CFLAG << 31));
4248 else
4249 return ((base << (32 - shamt)) | (base >> shamt));
ff44f8e3
NC
4250 default:
4251 break;
c906108c 4252 }
ff44f8e3 4253 return 0;
dfcd3bfb 4254}
c906108c 4255
ff44f8e3 4256/* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
c906108c 4257
dfcd3bfb
JM
4258static ARMword
4259GetLS7RHS (ARMul_State * state, ARMword instr)
c906108c 4260{
dfcd3bfb 4261 if (BIT (22) == 0)
ff44f8e3
NC
4262 {
4263 /* Register. */
c906108c 4264#ifndef MODE32
dfcd3bfb 4265 if (RHSReg == 15)
57165fb4
NC
4266 /* Now forbidden, but ... */
4267 return ECC | ER15INT | R15PC | EMODE;
c906108c 4268#endif
dfcd3bfb 4269 return state->Reg[RHSReg];
c906108c
SS
4270 }
4271
57165fb4 4272 /* Immediate. */
dfcd3bfb
JM
4273 return BITS (0, 3) | (BITS (8, 11) << 4);
4274}
c906108c 4275
ff44f8e3 4276/* This function does the work of loading a word for a LDR instruction. */
c906108c 4277
dfcd3bfb
JM
4278static unsigned
4279LoadWord (ARMul_State * state, ARMword instr, ARMword address)
c906108c 4280{
dfcd3bfb 4281 ARMword dest;
c906108c 4282
dfcd3bfb 4283 BUSUSEDINCPCS;
c906108c 4284#ifndef MODE32
dfcd3bfb 4285 if (ADDREXCEPT (address))
ff44f8e3 4286 INTERNALABORT (address);
c906108c 4287#endif
ff44f8e3 4288
dfcd3bfb 4289 dest = ARMul_LoadWordN (state, address);
ff44f8e3 4290
dfcd3bfb
JM
4291 if (state->Aborted)
4292 {
4293 TAKEABORT;
57165fb4 4294 return state->lateabtSig;
c906108c 4295 }
dfcd3bfb
JM
4296 if (address & 3)
4297 dest = ARMul_Align (state, address, dest);
892c6b9d 4298 WRITEDESTB (dest);
dfcd3bfb 4299 ARMul_Icycles (state, 1, 0L);
c906108c 4300
dfcd3bfb 4301 return (DESTReg != LHSReg);
c906108c
SS
4302}
4303
4304#ifdef MODET
ff44f8e3 4305/* This function does the work of loading a halfword. */
c906108c 4306
dfcd3bfb
JM
4307static unsigned
4308LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
4309 int signextend)
c906108c 4310{
dfcd3bfb 4311 ARMword dest;
c906108c 4312
dfcd3bfb 4313 BUSUSEDINCPCS;
c906108c 4314#ifndef MODE32
dfcd3bfb 4315 if (ADDREXCEPT (address))
57165fb4 4316 INTERNALABORT (address);
c906108c 4317#endif
dfcd3bfb
JM
4318 dest = ARMul_LoadHalfWord (state, address);
4319 if (state->Aborted)
4320 {
4321 TAKEABORT;
57165fb4 4322 return state->lateabtSig;
c906108c 4323 }
dfcd3bfb
JM
4324 UNDEF_LSRBPC;
4325 if (signextend)
57165fb4
NC
4326 if (dest & 1 << (16 - 1))
4327 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4328
dfcd3bfb
JM
4329 WRITEDEST (dest);
4330 ARMul_Icycles (state, 1, 0L);
4331 return (DESTReg != LHSReg);
c906108c 4332}
dfcd3bfb 4333
c906108c
SS
4334#endif /* MODET */
4335
ff44f8e3 4336/* This function does the work of loading a byte for a LDRB instruction. */
c906108c 4337
dfcd3bfb
JM
4338static unsigned
4339LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
c906108c 4340{
dfcd3bfb 4341 ARMword dest;
c906108c 4342
dfcd3bfb 4343 BUSUSEDINCPCS;
c906108c 4344#ifndef MODE32
dfcd3bfb 4345 if (ADDREXCEPT (address))
57165fb4 4346 INTERNALABORT (address);
c906108c 4347#endif
dfcd3bfb
JM
4348 dest = ARMul_LoadByte (state, address);
4349 if (state->Aborted)
4350 {
4351 TAKEABORT;
57165fb4 4352 return state->lateabtSig;
dfcd3bfb
JM
4353 }
4354 UNDEF_LSRBPC;
4355 if (signextend)
57165fb4
NC
4356 if (dest & 1 << (8 - 1))
4357 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4358
dfcd3bfb
JM
4359 WRITEDEST (dest);
4360 ARMul_Icycles (state, 1, 0L);
57165fb4 4361
dfcd3bfb 4362 return (DESTReg != LHSReg);
c906108c
SS
4363}
4364
ff44f8e3 4365/* This function does the work of loading two words for a LDRD instruction. */
760a7bbe
NC
4366
4367static void
4368Handle_Load_Double (ARMul_State * state, ARMword instr)
4369{
4370 ARMword dest_reg;
4371 ARMword addr_reg;
4372 ARMword write_back = BIT (21);
4373 ARMword immediate = BIT (22);
4374 ARMword add_to_base = BIT (23);
4375 ARMword pre_indexed = BIT (24);
4376 ARMword offset;
4377 ARMword addr;
4378 ARMword sum;
4379 ARMword base;
4380 ARMword value1;
4381 ARMword value2;
4382
4383 BUSUSEDINCPCS;
4384
4385 /* If the writeback bit is set, the pre-index bit must be clear. */
4386 if (write_back && ! pre_indexed)
4387 {
4388 ARMul_UndefInstr (state, instr);
4389 return;
4390 }
4391
4392 /* Extract the base address register. */
4393 addr_reg = LHSReg;
4394
4395 /* Extract the destination register and check it. */
4396 dest_reg = DESTReg;
4397
4398 /* Destination register must be even. */
4399 if ((dest_reg & 1)
4400 /* Destination register cannot be LR. */
4401 || (dest_reg == 14))
4402 {
4403 ARMul_UndefInstr (state, instr);
4404 return;
4405 }
4406
4407 /* Compute the base address. */
4408 base = state->Reg[addr_reg];
4409
4410 /* Compute the offset. */
4411 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4412
4413 /* Compute the sum of the two. */
4414 if (add_to_base)
4415 sum = base + offset;
4416 else
4417 sum = base - offset;
4418
4419 /* If this is a pre-indexed mode use the sum. */
4420 if (pre_indexed)
4421 addr = sum;
4422 else
4423 addr = base;
4424
4425 /* The address must be aligned on a 8 byte boundary. */
4426 if (addr & 0x7)
4427 {
4428#ifdef ABORTS
4429 ARMul_DATAABORT (addr);
4430#else
4431 ARMul_UndefInstr (state, instr);
4432#endif
4433 return;
4434 }
4435
4436 /* For pre indexed or post indexed addressing modes,
4437 check that the destination registers do not overlap
4438 the address registers. */
4439 if ((! pre_indexed || write_back)
4440 && ( addr_reg == dest_reg
4441 || addr_reg == dest_reg + 1))
4442 {
4443 ARMul_UndefInstr (state, instr);
4444 return;
4445 }
4446
4447 /* Load the words. */
4448 value1 = ARMul_LoadWordN (state, addr);
4449 value2 = ARMul_LoadWordN (state, addr + 4);
4450
4451 /* Check for data aborts. */
4452 if (state->Aborted)
4453 {
4454 TAKEABORT;
4455 return;
4456 }
4457
4458 ARMul_Icycles (state, 2, 0L);
4459
4460 /* Store the values. */
4461 state->Reg[dest_reg] = value1;
4462 state->Reg[dest_reg + 1] = value2;
4463
4464 /* Do the post addressing and writeback. */
4465 if (! pre_indexed)
4466 addr = sum;
4467
4468 if (! pre_indexed || write_back)
4469 state->Reg[addr_reg] = addr;
4470}
4471
ff44f8e3 4472/* This function does the work of storing two words for a STRD instruction. */
760a7bbe
NC
4473
4474static void
4475Handle_Store_Double (ARMul_State * state, ARMword instr)
4476{
4477 ARMword src_reg;
4478 ARMword addr_reg;
4479 ARMword write_back = BIT (21);
4480 ARMword immediate = BIT (22);
4481 ARMword add_to_base = BIT (23);
4482 ARMword pre_indexed = BIT (24);
4483 ARMword offset;
4484 ARMword addr;
4485 ARMword sum;
4486 ARMword base;
4487
4488 BUSUSEDINCPCS;
4489
4490 /* If the writeback bit is set, the pre-index bit must be clear. */
4491 if (write_back && ! pre_indexed)
4492 {
4493 ARMul_UndefInstr (state, instr);
4494 return;
4495 }
4496
4497 /* Extract the base address register. */
4498 addr_reg = LHSReg;
4499
4500 /* Base register cannot be PC. */
4501 if (addr_reg == 15)
4502 {
4503 ARMul_UndefInstr (state, instr);
4504 return;
4505 }
4506
4507 /* Extract the source register. */
4508 src_reg = DESTReg;
4509
4510 /* Source register must be even. */
4511 if (src_reg & 1)
4512 {
4513 ARMul_UndefInstr (state, instr);
4514 return;
4515 }
4516
4517 /* Compute the base address. */
4518 base = state->Reg[addr_reg];
4519
4520 /* Compute the offset. */
4521 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4522
4523 /* Compute the sum of the two. */
4524 if (add_to_base)
4525 sum = base + offset;
4526 else
4527 sum = base - offset;
4528
4529 /* If this is a pre-indexed mode use the sum. */
4530 if (pre_indexed)
4531 addr = sum;
4532 else
4533 addr = base;
4534
4535 /* The address must be aligned on a 8 byte boundary. */
4536 if (addr & 0x7)
4537 {
4538#ifdef ABORTS
4539 ARMul_DATAABORT (addr);
4540#else
4541 ARMul_UndefInstr (state, instr);
4542#endif
4543 return;
4544 }
4545
4546 /* For pre indexed or post indexed addressing modes,
4547 check that the destination registers do not overlap
4548 the address registers. */
4549 if ((! pre_indexed || write_back)
4550 && ( addr_reg == src_reg
4551 || addr_reg == src_reg + 1))
4552 {
4553 ARMul_UndefInstr (state, instr);
4554 return;
4555 }
4556
4557 /* Load the words. */
4558 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4559 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4560
4561 if (state->Aborted)
4562 {
4563 TAKEABORT;
4564 return;
4565 }
4566
4567 /* Do the post addressing and writeback. */
4568 if (! pre_indexed)
4569 addr = sum;
4570
4571 if (! pre_indexed || write_back)
4572 state->Reg[addr_reg] = addr;
4573}
4574
ff44f8e3 4575/* This function does the work of storing a word from a STR instruction. */
c906108c 4576
dfcd3bfb
JM
4577static unsigned
4578StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4579{
4580 BUSUSEDINCPCN;
c906108c 4581#ifndef MODE32
dfcd3bfb
JM
4582 if (DESTReg == 15)
4583 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
c906108c
SS
4584#endif
4585#ifdef MODE32
dfcd3bfb 4586 ARMul_StoreWordN (state, address, DEST);
c906108c 4587#else
dfcd3bfb
JM
4588 if (VECTORACCESS (address) || ADDREXCEPT (address))
4589 {
4590 INTERNALABORT (address);
4591 (void) ARMul_LoadWordN (state, address);
c906108c 4592 }
dfcd3bfb
JM
4593 else
4594 ARMul_StoreWordN (state, address, DEST);
c906108c 4595#endif
dfcd3bfb
JM
4596 if (state->Aborted)
4597 {
4598 TAKEABORT;
ff44f8e3 4599 return state->lateabtSig;
c906108c 4600 }
ff44f8e3 4601 return TRUE;
c906108c
SS
4602}
4603
4604#ifdef MODET
ff44f8e3 4605/* This function does the work of storing a byte for a STRH instruction. */
c906108c 4606
dfcd3bfb
JM
4607static unsigned
4608StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4609{
4610 BUSUSEDINCPCN;
c906108c
SS
4611
4612#ifndef MODE32
dfcd3bfb
JM
4613 if (DESTReg == 15)
4614 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
c906108c
SS
4615#endif
4616
4617#ifdef MODE32
dfcd3bfb 4618 ARMul_StoreHalfWord (state, address, DEST);
c906108c 4619#else
dfcd3bfb
JM
4620 if (VECTORACCESS (address) || ADDREXCEPT (address))
4621 {
4622 INTERNALABORT (address);
4623 (void) ARMul_LoadHalfWord (state, address);
c906108c 4624 }
dfcd3bfb
JM
4625 else
4626 ARMul_StoreHalfWord (state, address, DEST);
c906108c
SS
4627#endif
4628
dfcd3bfb
JM
4629 if (state->Aborted)
4630 {
4631 TAKEABORT;
ff44f8e3 4632 return state->lateabtSig;
c906108c 4633 }
ff44f8e3 4634 return TRUE;
c906108c 4635}
dfcd3bfb 4636
c906108c
SS
4637#endif /* MODET */
4638
ff44f8e3 4639/* This function does the work of storing a byte for a STRB instruction. */
c906108c 4640
dfcd3bfb
JM
4641static unsigned
4642StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4643{
4644 BUSUSEDINCPCN;
c906108c 4645#ifndef MODE32
dfcd3bfb
JM
4646 if (DESTReg == 15)
4647 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
c906108c
SS
4648#endif
4649#ifdef MODE32
dfcd3bfb 4650 ARMul_StoreByte (state, address, DEST);
c906108c 4651#else
dfcd3bfb
JM
4652 if (VECTORACCESS (address) || ADDREXCEPT (address))
4653 {
4654 INTERNALABORT (address);
4655 (void) ARMul_LoadByte (state, address);
c906108c 4656 }
dfcd3bfb
JM
4657 else
4658 ARMul_StoreByte (state, address, DEST);
c906108c 4659#endif
dfcd3bfb
JM
4660 if (state->Aborted)
4661 {
4662 TAKEABORT;
57165fb4 4663 return state->lateabtSig;
c906108c 4664 }
dfcd3bfb 4665 UNDEF_LSRBPC;
ff44f8e3 4666 return TRUE;
c906108c
SS
4667}
4668
ff44f8e3
NC
4669/* This function does the work of loading the registers listed in an LDM
4670 instruction, when the S bit is clear. The code here is always increment
4671 after, it's up to the caller to get the input address correct and to
57165fb4 4672 handle base register modification. */
c906108c 4673
dfcd3bfb
JM
4674static void
4675LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4676{
4677 ARMword dest, temp;
c906108c 4678
dfcd3bfb
JM
4679 UNDEF_LSMNoRegs;
4680 UNDEF_LSMPCBase;
4681 UNDEF_LSMBaseInListWb;
4682 BUSUSEDINCPCS;
c906108c 4683#ifndef MODE32
dfcd3bfb 4684 if (ADDREXCEPT (address))
ff44f8e3 4685 INTERNALABORT (address);
c906108c 4686#endif
dfcd3bfb
JM
4687 if (BIT (21) && LHSReg != 15)
4688 LSBase = WBBase;
4689
57165fb4 4690 /* N cycle first. */
ff44f8e3 4691 for (temp = 0; !BIT (temp); temp++)
57165fb4 4692 ;
ff44f8e3 4693
dfcd3bfb 4694 dest = ARMul_LoadWordN (state, address);
ff44f8e3 4695
dfcd3bfb
JM
4696 if (!state->abortSig && !state->Aborted)
4697 state->Reg[temp++] = dest;
4698 else if (!state->Aborted)
fae0bf59 4699 {
ff44f8e3 4700 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4701 state->Aborted = ARMul_DataAbortV;
4702 }
dfcd3bfb 4703
57165fb4
NC
4704 /* S cycles from here on. */
4705 for (; temp < 16; temp ++)
dfcd3bfb 4706 if (BIT (temp))
57165fb4
NC
4707 {
4708 /* Load this register. */
dfcd3bfb
JM
4709 address += 4;
4710 dest = ARMul_LoadWordS (state, address);
ff44f8e3 4711
dfcd3bfb
JM
4712 if (!state->abortSig && !state->Aborted)
4713 state->Reg[temp] = dest;
4714 else if (!state->Aborted)
fae0bf59 4715 {
ff44f8e3 4716 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4717 state->Aborted = ARMul_DataAbortV;
4718 }
dfcd3bfb
JM
4719 }
4720
5d0d395e 4721 if (BIT (15) && !state->Aborted)
ff44f8e3
NC
4722 /* PC is in the reg list. */
4723 WriteR15Branch (state, PC);
c906108c 4724
ff44f8e3
NC
4725 /* To write back the final register. */
4726 ARMul_Icycles (state, 1, 0L);
c906108c 4727
dfcd3bfb
JM
4728 if (state->Aborted)
4729 {
4730 if (BIT (21) && LHSReg != 15)
4731 LSBase = WBBase;
4732 TAKEABORT;
c906108c 4733 }
dfcd3bfb 4734}
c906108c 4735
ff44f8e3
NC
4736/* This function does the work of loading the registers listed in an LDM
4737 instruction, when the S bit is set. The code here is always increment
4738 after, it's up to the caller to get the input address correct and to
4739 handle base register modification. */
c906108c 4740
dfcd3bfb 4741static void
fae0bf59
NC
4742LoadSMult (ARMul_State * state,
4743 ARMword instr,
4744 ARMword address,
4745 ARMword WBBase)
dfcd3bfb
JM
4746{
4747 ARMword dest, temp;
c906108c 4748
dfcd3bfb
JM
4749 UNDEF_LSMNoRegs;
4750 UNDEF_LSMPCBase;
4751 UNDEF_LSMBaseInListWb;
dda308f5 4752
dfcd3bfb 4753 BUSUSEDINCPCS;
dda308f5 4754
c906108c 4755#ifndef MODE32
dfcd3bfb 4756 if (ADDREXCEPT (address))
ff44f8e3 4757 INTERNALABORT (address);
c906108c
SS
4758#endif
4759
dda308f5
NC
4760 if (BIT (21) && LHSReg != 15)
4761 LSBase = WBBase;
4762
dfcd3bfb
JM
4763 if (!BIT (15) && state->Bank != USERBANK)
4764 {
dda308f5
NC
4765 /* Temporary reg bank switch. */
4766 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
dfcd3bfb 4767 UNDEF_LSMUserBankWb;
c906108c
SS
4768 }
4769
57165fb4 4770 /* N cycle first. */
dda308f5 4771 for (temp = 0; !BIT (temp); temp ++)
57165fb4 4772 ;
dfcd3bfb 4773
dfcd3bfb 4774 dest = ARMul_LoadWordN (state, address);
dda308f5 4775
dfcd3bfb
JM
4776 if (!state->abortSig)
4777 state->Reg[temp++] = dest;
4778 else if (!state->Aborted)
fae0bf59 4779 {
57165fb4 4780 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4781 state->Aborted = ARMul_DataAbortV;
4782 }
dfcd3bfb 4783
57165fb4 4784 /* S cycles from here on. */
dda308f5 4785 for (; temp < 16; temp++)
dfcd3bfb 4786 if (BIT (temp))
dda308f5
NC
4787 {
4788 /* Load this register. */
dfcd3bfb
JM
4789 address += 4;
4790 dest = ARMul_LoadWordS (state, address);
dda308f5 4791
5d0d395e 4792 if (!state->abortSig && !state->Aborted)
dfcd3bfb
JM
4793 state->Reg[temp] = dest;
4794 else if (!state->Aborted)
fae0bf59 4795 {
57165fb4 4796 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4797 state->Aborted = ARMul_DataAbortV;
4798 }
dfcd3bfb
JM
4799 }
4800
5d0d395e 4801 if (BIT (15) && !state->Aborted)
dda308f5
NC
4802 {
4803 /* PC is in the reg list. */
c906108c 4804#ifdef MODE32
dfcd3bfb
JM
4805 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4806 {
4807 state->Cpsr = GETSPSR (state->Bank);
4808 ARMul_CPSRAltered (state);
4809 }
dda308f5 4810
13b6dd6f 4811 WriteR15 (state, PC);
c906108c 4812#else
dfcd3bfb 4813 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
dda308f5
NC
4814 {
4815 /* Protect bits in user mode. */
dfcd3bfb
JM
4816 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4817 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4818 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4819 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4820 }
4821 else
4822 ARMul_R15Altered (state);
fae0bf59 4823
dfcd3bfb 4824 FLUSHPIPE;
13b6dd6f 4825#endif
c906108c
SS
4826 }
4827
dfcd3bfb 4828 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
dda308f5
NC
4829 /* Restore the correct bank. */
4830 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
c906108c 4831
dda308f5
NC
4832 /* To write back the final register. */
4833 ARMul_Icycles (state, 1, 0L);
c906108c 4834
dfcd3bfb
JM
4835 if (state->Aborted)
4836 {
4837 if (BIT (21) && LHSReg != 15)
4838 LSBase = WBBase;
fae0bf59 4839
dfcd3bfb 4840 TAKEABORT;
c906108c 4841 }
c906108c
SS
4842}
4843
ff44f8e3
NC
4844/* This function does the work of storing the registers listed in an STM
4845 instruction, when the S bit is clear. The code here is always increment
4846 after, it's up to the caller to get the input address correct and to
4847 handle base register modification. */
c906108c 4848
dfcd3bfb 4849static void
57165fb4
NC
4850StoreMult (ARMul_State * state,
4851 ARMword instr,
4852 ARMword address,
4853 ARMword WBBase)
dfcd3bfb
JM
4854{
4855 ARMword temp;
c906108c 4856
dfcd3bfb
JM
4857 UNDEF_LSMNoRegs;
4858 UNDEF_LSMPCBase;
4859 UNDEF_LSMBaseInListWb;
ff44f8e3 4860
dfcd3bfb 4861 if (!TFLAG)
ff44f8e3
NC
4862 /* N-cycle, increment the PC and update the NextInstr state. */
4863 BUSUSEDINCPCN;
c906108c
SS
4864
4865#ifndef MODE32
dfcd3bfb 4866 if (VECTORACCESS (address) || ADDREXCEPT (address))
ff44f8e3
NC
4867 INTERNALABORT (address);
4868
dfcd3bfb
JM
4869 if (BIT (15))
4870 PATCHR15;
c906108c
SS
4871#endif
4872
57165fb4
NC
4873 /* N cycle first. */
4874 for (temp = 0; !BIT (temp); temp ++)
4875 ;
ff44f8e3 4876
c906108c 4877#ifdef MODE32
dfcd3bfb 4878 ARMul_StoreWordN (state, address, state->Reg[temp++]);
c906108c 4879#else
dfcd3bfb
JM
4880 if (state->Aborted)
4881 {
4882 (void) ARMul_LoadWordN (state, address);
ff44f8e3
NC
4883
4884 /* Fake the Stores as Loads. */
4885 for (; temp < 16; temp++)
dfcd3bfb 4886 if (BIT (temp))
ff44f8e3
NC
4887 {
4888 /* Save this register. */
dfcd3bfb
JM
4889 address += 4;
4890 (void) ARMul_LoadWordS (state, address);
4891 }
57165fb4 4892
dfcd3bfb
JM
4893 if (BIT (21) && LHSReg != 15)
4894 LSBase = WBBase;
4895 TAKEABORT;
4896 return;
4897 }
4898 else
4899 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4900#endif
fae0bf59 4901
dfcd3bfb 4902 if (state->abortSig && !state->Aborted)
fae0bf59 4903 {
57165fb4 4904 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4905 state->Aborted = ARMul_DataAbortV;
4906 }
dfcd3bfb
JM
4907
4908 if (BIT (21) && LHSReg != 15)
4909 LSBase = WBBase;
4910
57165fb4
NC
4911 /* S cycles from here on. */
4912 for (; temp < 16; temp ++)
dfcd3bfb 4913 if (BIT (temp))
ff44f8e3
NC
4914 {
4915 /* Save this register. */
dfcd3bfb 4916 address += 4;
fae0bf59 4917
dfcd3bfb 4918 ARMul_StoreWordS (state, address, state->Reg[temp]);
fae0bf59 4919
dfcd3bfb 4920 if (state->abortSig && !state->Aborted)
fae0bf59 4921 {
57165fb4 4922 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4923 state->Aborted = ARMul_DataAbortV;
4924 }
dfcd3bfb 4925 }
fae0bf59 4926
dfcd3bfb 4927 if (state->Aborted)
ff44f8e3 4928 TAKEABORT;
dfcd3bfb 4929}
c906108c 4930
ff44f8e3
NC
4931/* This function does the work of storing the registers listed in an STM
4932 instruction when the S bit is set. The code here is always increment
4933 after, it's up to the caller to get the input address correct and to
4934 handle base register modification. */
c906108c 4935
dfcd3bfb 4936static void
fae0bf59 4937StoreSMult (ARMul_State * state,
dda308f5
NC
4938 ARMword instr,
4939 ARMword address,
4940 ARMword WBBase)
dfcd3bfb
JM
4941{
4942 ARMword temp;
c906108c 4943
dfcd3bfb
JM
4944 UNDEF_LSMNoRegs;
4945 UNDEF_LSMPCBase;
4946 UNDEF_LSMBaseInListWb;
dda308f5 4947
dfcd3bfb 4948 BUSUSEDINCPCN;
dda308f5 4949
c906108c 4950#ifndef MODE32
dfcd3bfb 4951 if (VECTORACCESS (address) || ADDREXCEPT (address))
ff44f8e3 4952 INTERNALABORT (address);
dda308f5 4953
dfcd3bfb
JM
4954 if (BIT (15))
4955 PATCHR15;
c906108c
SS
4956#endif
4957
dfcd3bfb
JM
4958 if (state->Bank != USERBANK)
4959 {
dda308f5
NC
4960 /* Force User Bank. */
4961 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
dfcd3bfb 4962 UNDEF_LSMUserBankWb;
c906108c
SS
4963 }
4964
dda308f5
NC
4965 for (temp = 0; !BIT (temp); temp++)
4966 ; /* N cycle first. */
4967
c906108c 4968#ifdef MODE32
dfcd3bfb 4969 ARMul_StoreWordN (state, address, state->Reg[temp++]);
c906108c 4970#else
dfcd3bfb
JM
4971 if (state->Aborted)
4972 {
4973 (void) ARMul_LoadWordN (state, address);
dda308f5
NC
4974
4975 for (; temp < 16; temp++)
4976 /* Fake the Stores as Loads. */
dfcd3bfb 4977 if (BIT (temp))
dda308f5
NC
4978 {
4979 /* Save this register. */
dfcd3bfb 4980 address += 4;
fae0bf59 4981
dfcd3bfb
JM
4982 (void) ARMul_LoadWordS (state, address);
4983 }
fae0bf59 4984
dfcd3bfb
JM
4985 if (BIT (21) && LHSReg != 15)
4986 LSBase = WBBase;
dda308f5 4987
dfcd3bfb
JM
4988 TAKEABORT;
4989 return;
c906108c 4990 }
dfcd3bfb
JM
4991 else
4992 ARMul_StoreWordN (state, address, state->Reg[temp++]);
c906108c 4993#endif
dda308f5 4994
dfcd3bfb 4995 if (state->abortSig && !state->Aborted)
fae0bf59 4996 {
57165fb4 4997 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
4998 state->Aborted = ARMul_DataAbortV;
4999 }
c906108c 5000
57165fb4 5001 /* S cycles from here on. */
dda308f5 5002 for (; temp < 16; temp++)
dfcd3bfb 5003 if (BIT (temp))
dda308f5
NC
5004 {
5005 /* Save this register. */
dfcd3bfb 5006 address += 4;
dda308f5 5007
dfcd3bfb 5008 ARMul_StoreWordS (state, address, state->Reg[temp]);
dda308f5 5009
dfcd3bfb 5010 if (state->abortSig && !state->Aborted)
fae0bf59 5011 {
57165fb4 5012 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
fae0bf59
NC
5013 state->Aborted = ARMul_DataAbortV;
5014 }
dfcd3bfb 5015 }
c906108c 5016
dfcd3bfb 5017 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
dda308f5
NC
5018 /* Restore the correct bank. */
5019 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5020
5021 if (BIT (21) && LHSReg != 15)
5022 LSBase = WBBase;
c906108c 5023
dfcd3bfb 5024 if (state->Aborted)
ff44f8e3 5025 TAKEABORT;
c906108c
SS
5026}
5027
ff44f8e3
NC
5028/* This function does the work of adding two 32bit values
5029 together, and calculating if a carry has occurred. */
c906108c 5030
dfcd3bfb
JM
5031static ARMword
5032Add32 (ARMword a1, ARMword a2, int *carry)
c906108c
SS
5033{
5034 ARMword result = (a1 + a2);
dfcd3bfb
JM
5035 unsigned int uresult = (unsigned int) result;
5036 unsigned int ua1 = (unsigned int) a1;
c906108c
SS
5037
5038 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
57165fb4 5039 or (result > RdLo) then we have no carry. */
c906108c 5040 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
dfcd3bfb 5041 *carry = 1;
c906108c 5042 else
dfcd3bfb 5043 *carry = 0;
c906108c 5044
57165fb4 5045 return result;
c906108c
SS
5046}
5047
ff44f8e3
NC
5048/* This function does the work of multiplying
5049 two 32bit values to give a 64bit result. */
c906108c 5050
dfcd3bfb
JM
5051static unsigned
5052Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
c906108c 5053{
ff44f8e3
NC
5054 /* Operand register numbers. */
5055 int nRdHi, nRdLo, nRs, nRm;
6d358e86 5056 ARMword RdHi = 0, RdLo = 0, Rm;
ff44f8e3
NC
5057 /* Cycle count. */
5058 int scount;
c906108c 5059
dfcd3bfb
JM
5060 nRdHi = BITS (16, 19);
5061 nRdLo = BITS (12, 15);
5062 nRs = BITS (8, 11);
5063 nRm = BITS (0, 3);
c906108c 5064
ff44f8e3 5065 /* Needed to calculate the cycle count. */
c906108c
SS
5066 Rm = state->Reg[nRm];
5067
ff44f8e3
NC
5068 /* Check for illegal operand combinations first. */
5069 if ( nRdHi != 15
c906108c 5070 && nRdLo != 15
ff44f8e3
NC
5071 && nRs != 15
5072 && nRm != 15
5073 && nRdHi != nRdLo
5074 && nRdHi != nRm
5075 && nRdLo != nRm)
c906108c 5076 {
ff44f8e3
NC
5077 /* Intermediate results. */
5078 ARMword lo, mid1, mid2, hi;
c906108c 5079 int carry;
dfcd3bfb 5080 ARMword Rs = state->Reg[nRs];
c906108c
SS
5081 int sign = 0;
5082
5083 if (msigned)
5084 {
5085 /* Compute sign of result and adjust operands if necessary. */
c906108c 5086 sign = (Rm ^ Rs) & 0x80000000;
dfcd3bfb 5087
c4793bac 5088 if (((ARMsword) Rm) < 0)
c906108c 5089 Rm = -Rm;
dfcd3bfb 5090
c4793bac 5091 if (((ARMsword) Rs) < 0)
c906108c
SS
5092 Rs = -Rs;
5093 }
dfcd3bfb 5094
ff44f8e3
NC
5095 /* We can split the 32x32 into four 16x16 operations. This
5096 ensures that we do not lose precision on 32bit only hosts. */
dfcd3bfb 5097 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
c906108c
SS
5098 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5099 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
dfcd3bfb
JM
5100 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5101
ff44f8e3
NC
5102 /* We now need to add all of these results together, taking
5103 care to propogate the carries from the additions. */
dfcd3bfb 5104 RdLo = Add32 (lo, (mid1 << 16), &carry);
c906108c 5105 RdHi = carry;
dfcd3bfb
JM
5106 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
5107 RdHi +=
5108 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
c906108c
SS
5109
5110 if (sign)
5111 {
5112 /* Negate result if necessary. */
dfcd3bfb
JM
5113 RdLo = ~RdLo;
5114 RdHi = ~RdHi;
c906108c
SS
5115 if (RdLo == 0xFFFFFFFF)
5116 {
5117 RdLo = 0;
5118 RdHi += 1;
5119 }
5120 else
5121 RdLo += 1;
5122 }
dfcd3bfb 5123
c906108c
SS
5124 state->Reg[nRdLo] = RdLo;
5125 state->Reg[nRdHi] = RdHi;
ff44f8e3 5126 }
dfcd3bfb 5127 else
760a7bbe 5128 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
dfcd3bfb 5129
c906108c 5130 if (scc)
57165fb4
NC
5131 /* Ensure that both RdHi and RdLo are used to compute Z,
5132 but don't let RdLo's sign bit make it to N. */
5133 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
dfcd3bfb 5134
c906108c 5135 /* The cycle count depends on whether the instruction is a signed or
ff44f8e3 5136 unsigned multiply, and what bits are clear in the multiplier. */
dfcd3bfb 5137 if (msigned && (Rm & ((unsigned) 1 << 31)))
ff44f8e3
NC
5138 /* Invert the bits to make the check against zero. */
5139 Rm = ~Rm;
dfcd3bfb 5140
c906108c 5141 if ((Rm & 0xFFFFFF00) == 0)
dfcd3bfb 5142 scount = 1;
c906108c 5143 else if ((Rm & 0xFFFF0000) == 0)
dfcd3bfb 5144 scount = 2;
c906108c 5145 else if ((Rm & 0xFF000000) == 0)
dfcd3bfb 5146 scount = 3;
c906108c 5147 else
dfcd3bfb
JM
5148 scount = 4;
5149
5150 return 2 + scount;
c906108c
SS
5151}
5152
ff44f8e3
NC
5153/* This function does the work of multiplying two 32bit
5154 values and adding a 64bit value to give a 64bit result. */
c906108c 5155
dfcd3bfb
JM
5156static unsigned
5157MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
c906108c
SS
5158{
5159 unsigned scount;
5160 ARMword RdLo, RdHi;
5161 int nRdHi, nRdLo;
5162 int carry = 0;
5163
dfcd3bfb
JM
5164 nRdHi = BITS (16, 19);
5165 nRdLo = BITS (12, 15);
c906108c 5166
dfcd3bfb
JM
5167 RdHi = state->Reg[nRdHi];
5168 RdLo = state->Reg[nRdLo];
c906108c 5169
dfcd3bfb 5170 scount = Multiply64 (state, instr, msigned, LDEFAULT);
c906108c 5171
dfcd3bfb 5172 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
c906108c
SS
5173 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
5174
5175 state->Reg[nRdLo] = RdLo;
5176 state->Reg[nRdHi] = RdHi;
5177
dfcd3bfb 5178 if (scc)
ff44f8e3
NC
5179 /* Ensure that both RdHi and RdLo are used to compute Z,
5180 but don't let RdLo's sign bit make it to N. */
5181 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
c906108c 5182
ff44f8e3
NC
5183 /* Extra cycle for addition. */
5184 return scount + 1;
c906108c 5185}
This page took 0.856202 seconds and 4 git commands to generate.