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