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