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