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