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