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