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