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