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