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