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