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