fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/arm/opcodes.c *
7 * Created: 2004-11-03 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2011 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#include "arm.h"
30#include "internal.h"
31
32
33/*
34 * Count the number of 1 bits in v.
35 */
36static
37unsigned arm_bitcnt32 (unsigned long v)
38{
39 unsigned n;
40
41 n = 0;
42 while (v != 0) {
43 n += 1;
44 v &= v - 1;
45 }
46
47 return (n);
48}
49
50/*
51 * Write a new value to CPSR and adjust the register mapping and execution
52 * mode.
53 */
54int arm_write_cpsr (arm_t *c, uint32_t val, int prvchk)
55{
56 if (prvchk) {
57 if (arm_get_cpsr_m (c) == ARM_MODE_USR) {
58 return (1);
59 }
60 }
61
62 arm_set_reg_map (c, val & 0x1f);
63 arm_set_cpsr (c, val);
64
65 c->privileged = ((val & 0x1f) != ARM_MODE_USR);
66
67 arm_tbuf_flush (c);
68
69 return (0);
70}
71
72/*
73 * Set the N and Z condition codes according to a 32 bit result
74 */
75static
76void arm_set_cc_nz (arm_t *c, uint32_t val)
77{
78 uint32_t cc;
79
80 val &= 0xffffffff;
81 cc = 0;
82
83 if (val == 0) {
84 cc |= ARM_PSR_Z;
85 }
86 else if (val & 0x80000000) {
87 cc |= ARM_PSR_N;
88 }
89
90 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N);
91 c->cpsr |= cc;
92}
93
94/*
95 * Set the condition codes after an addition
96 */
97static
98void arm_set_cc_add (arm_t *c, uint32_t d, uint32_t s1, uint32_t s2)
99{
100 uint32_t cc;
101
102 cc = 0;
103
104 if (d == 0) {
105 cc |= ARM_PSR_Z;
106 }
107 else if (d & 0x80000000) {
108 cc |= ARM_PSR_N;
109 }
110
111 if ((d < s1) || ((d == s1) && (s2 != 0))) {
112 cc |= ARM_PSR_C;
113 }
114
115 if ((d ^ s1) & (d ^ s2) & 0x80000000) {
116 cc |= ARM_PSR_V;
117 }
118
119 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N | ARM_PSR_C | ARM_PSR_V);
120 c->cpsr |= cc;
121}
122
123/*
124 * Set the condition codes after a subtraction
125 */
126static
127void arm_set_cc_sub (arm_t *c, uint32_t d, uint32_t s1, uint32_t s2)
128{
129 uint32_t cc;
130
131 cc = 0;
132
133 if (d == 0) {
134 cc |= ARM_PSR_Z;
135 }
136 else if (d & 0x80000000) {
137 cc |= ARM_PSR_N;
138 }
139
140 if (!((d > s1) || ((d == s1) && (s2 != 0)))) {
141 cc |= ARM_PSR_C;
142 }
143
144 if ((d ^ s1) & (s1 ^ s2) & 0x80000000) {
145 cc |= ARM_PSR_V;
146 }
147
148 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N | ARM_PSR_C | ARM_PSR_V);
149 c->cpsr |= cc;
150}
151
152static
153uint32_t arm_set_psr_field (uint32_t psr, uint32_t val, unsigned fld)
154{
155 if (fld & 0x01) {
156 psr &= 0xffffff00;
157 psr |= val & 0x000000ff;
158 }
159
160 if (fld & 0x02) {
161 psr &= 0xffff00ff;
162 psr |= val & 0x0000ff00;
163 }
164
165 if (fld & 0x04) {
166 psr &= 0xff00ffff;
167 psr |= val & 0x00ff0000;
168 }
169
170 if (fld & 0x08) {
171 psr &= 0x00ffffff;
172 psr |= val & 0xff000000;
173 }
174
175 return (psr);
176}
177
178/*
179 * Check if condition cond is met
180 */
181int arm_check_cond (arm_t *c, unsigned cond)
182{
183 switch (cond & 0x0f) {
184 case 0x00: /* eq */
185 return (arm_get_cc_z (c));
186
187 case 0x01: /* ne */
188 return (!arm_get_cc_z (c));
189
190 case 0x02: /* cs */
191 return (arm_get_cc_c (c));
192
193 case 0x03: /* cc */
194 return (!arm_get_cc_c (c));
195
196 case 0x04: /* mi */
197 return (arm_get_cc_n (c));
198
199 case 0x05: /* pl */
200 return (!arm_get_cc_n (c));
201
202 case 0x06: /* vs */
203 return (arm_get_cc_v (c));
204
205 case 0x07: /* vc */
206 return (!arm_get_cc_v (c));
207
208 case 0x08: /* hi */
209 return (arm_get_cc_c (c) && !arm_get_cc_z (c));
210
211 case 0x09: /* ls */
212 return (!arm_get_cc_c (c) || arm_get_cc_z (c));
213
214 case 0x0a: /* ge */
215 return (arm_get_cc_n (c) == arm_get_cc_v (c));
216
217 case 0x0b: /* lt */
218 return (arm_get_cc_n (c) != arm_get_cc_v (c));
219
220 case 0x0c: /* gt */
221 return (!arm_get_cc_z (c) && (arm_get_cc_n (c) == arm_get_cc_v (c)));
222
223 case 0x0d: /* le */
224 return (arm_get_cc_z (c) || (arm_get_cc_n (c) != arm_get_cc_v (c)));
225
226 case 0x0e: /* al */
227 return (1);
228
229 case 0x0f: /* nv */
230 return (0);
231 }
232
233 return (0);
234}
235
236static
237uint32_t arm_get_sh (arm_t *c, uint32_t ir, uint32_t *cry)
238{
239 unsigned n;
240 uint32_t v, tmp;
241
242 if (cry == NULL) {
243 cry = &tmp;
244 }
245
246 if (arm_get_bit (ir, 25)) {
247 /* 32 bit immediate */
248
249 v = (ir & 0xff);
250 n = (ir >> 7) & 0x1e;
251
252 if (n == 0) {
253 *cry = arm_get_cc_c (c);
254 }
255 else {
256 v = ((v >> n) | (v << (32 - n))) & 0xffffffff;
257 *cry = ((v & 0x80000000) != 0);
258 }
259
260 return (v);
261 }
262
263 v = arm_get_rm (c, c->ir);
264
265 if (arm_get_bit (ir, 4)) {
266 /* register shifts */
267
268 if (arm_get_bit (ir, 7)) {
269 /* extension */
270 *cry = 0;
271 return (0);
272 }
273
274 n = arm_get_rs (c, c->ir) & 0xff;
275
276 switch (arm_get_bits (ir, 5, 2)) {
277 case 0x00: /* lsl */
278 if (n == 0) {
279 *cry = arm_get_cc_c (c);
280 }
281 else if (n <= 32) {
282 *cry = (v >> (32 - n)) & 0x01;
283 v = (n < 32) ? (v << n) : 0;
284 }
285 else {
286 *cry = 0;
287 v = 0;
288 }
289 return (v);
290
291 case 0x01: /* lsr */
292 if (n == 0) {
293 *cry = arm_get_cc_c (c);
294 }
295 else if (n <= 32) {
296 *cry = (v >> (n - 1)) & 0x01;
297 v = (n < 32) ? (v >> n) : 0;
298 }
299 else {
300 *cry = 0;
301 v = 0;
302 }
303 return (v);
304
305 case 0x02: /* asr */
306 if (n == 0) {
307 *cry = arm_get_cc_c (c);
308 }
309 else if (n < 32) {
310 *cry = (v >> (n - 1)) & 0x01;
311 if (v & 0x80000000) {
312 v = v >> n;
313 v |= (0xffffffff << (32 - n)) & 0xffffffff;
314 }
315 else {
316 v = v >> n;
317 }
318 }
319 else {
320 *cry = (v >> 31) & 0x01;
321 v = *cry ? 0xffffffffUL : 0x00000000UL;
322 }
323 return (v);
324
325 case 0x03: /* ror */
326 if (n == 0) {
327 *cry = arm_get_cc_c (c);
328 }
329 else if ((n & 0x1f) == 0) {
330 *cry = (v >> 31) & 0x01;
331 }
332 else {
333 n &= 0x1f;
334 *cry = (v >> (n - 1)) & 0x01;
335 v = (v >> n) | (v << (32 - n));
336 }
337 return (v);
338 }
339 }
340 else {
341 /* immediate shifts */
342
343 n = arm_get_bits (ir, 7, 5);
344
345 switch (arm_get_bits (ir, 5, 2)) {
346 case 0x00: /* lsl */
347 if (n == 0) {
348 *cry = arm_get_cc_c (c);
349 }
350 else {
351 *cry = (v >> (32 - n)) & 0x01;
352 v = (v << n) & 0xffffffff;
353 }
354 return (v);
355
356 case 0x01: /* lsr */
357 if (n == 0) {
358 *cry = (v >> 31) & 0x01;
359 v = 0;
360 }
361 else {
362 *cry = (v >> (n - 1)) & 0x01;
363 v = v >> n;
364 }
365 return (v);
366
367 case 0x02: /* asr */
368 if (n == 0) {
369 *cry = (v >> 31) & 0x01;
370 v = *cry ? 0xffffffffUL : 0x00000000UL;
371 }
372 else {
373 *cry = (v >> (n - 1)) & 0x01;
374 v = arm_asr32 (v, n);
375 }
376 return (v);
377
378 case 0x03: /* ror */
379 if (n == 0) {
380 *cry = v & 0x01;
381 v = (v >> 1) | (arm_get_cc_c (c) << 31);
382 }
383 else {
384 *cry = (v >> (n - 1)) & 0x01;
385 v = (v >> n) | (v << (32 - n));
386 }
387 return (v);
388 }
389 }
390
391 *cry = 0;
392
393 return (0);
394}
395
396
397void op_undefined (arm_t *c)
398{
399 if (c->log_undef != NULL) {
400 c->log_undef (c->log_ext, c->ir);
401 }
402
403 arm_set_clk (c, 0, 1);
404
405 arm_exception_undefined (c);
406}
407
408/* 00 09: mul[cond] rn, rm, rs */
409static
410void op00_09 (arm_t *c)
411{
412 uint32_t d, s1, s2;
413
414 s1 = arm_get_rm (c, c->ir);
415 s2 = arm_get_rs (c, c->ir);
416
417 d = (s1 * s2) & 0xffffffff;
418
419 arm_set_rn (c, c->ir, d);
420 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
421}
422
423/* 00 0b: str[cond][h|sh|sb|d] rd, addressing_mode */
424static
425void op00_0b (arm_t *c)
426{
427 int p, u, w, s, h;
428 uint32_t val, base, index;
429
430 p = arm_get_bit (c->ir, 24);
431 u = arm_get_bit (c->ir, 23);
432 w = arm_get_bit (c->ir, 21);
433 s = arm_get_bit (c->ir, 6);
434 h = arm_get_bit (c->ir, 5);
435
436 base = arm_get_rn (c, c->ir);
437
438 /* get index */
439 if (arm_get_bit (c->ir, 22)) {
440 index = arm_get_bits (c->ir, 8, 4) << 4;
441 index |= arm_get_bits (c->ir, 0, 4);
442 }
443 else {
444 index = arm_get_rm (c, c->ir);
445 }
446
447 /* pre-index */
448 if (p) {
449 base += u ? index : (~index + 1);
450 base &= 0xffffffff;
451 }
452
453 val = arm_get_rd (c, c->ir);
454
455 if (s) {
456 /* ldrd/strd */
457
458 if (arm_ir_rd (c->ir) & 1) {
459 op_undefined (c);
460 return;
461 }
462
463 base &= 0xfffffff8;
464
465 if (h) {
466 if (arm_dstore32 (c, base, val)) {
467 return;
468 }
469
470 val = arm_get_gpr (c, (arm_ir_rd (c->ir) + 1) & 0x0f);
471
472 if (arm_dstore32 (c, base + 4, val)) {
473 return;
474 }
475 }
476 else {
477 uint32_t val2;
478
479 if (arm_dload32 (c, base, &val)) {
480 return;
481 }
482
483 if (arm_dload32 (c, base + 4, &val2)) {
484 return;
485 }
486
487 arm_set_rd (c, c->ir, val);
488 arm_set_gpr (c, (arm_ir_rd (c->ir) + 1) & 0xff, val2);
489 }
490 }
491 else if (h) {
492 if (arm_dstore16 (c, base & 0xfffffffe, val)) {
493 return;
494 }
495 }
496 else {
497 if (arm_dstore8 (c, base, val)) {
498 return;
499 }
500 }
501
502 /* post-index */
503 if (p == 0) {
504 base += u ? index : (~index + 1);
505 base &= 0xffffffff;
506 }
507
508 /* base register writeback */
509 if ((p == 0) || (w == 1)) {
510 arm_set_rn (c, c->ir, base);
511 }
512
513 arm_set_clk (c, 4, 1);
514}
515
516/* 00 ext */
517static
518void op00_ext (arm_t *c)
519{
520 switch (arm_get_shext (c->ir)) {
521 case 0x09:
522 op00_09 (c);
523 break;
524
525 default:
526 op00_0b (c);
527 break;
528 }
529}
530
531/* 00: and[cond] rd, rn, shifter_operand */
532static
533void op00 (arm_t *c)
534{
535 uint32_t s1, s2, d;
536
537 if (arm_is_shext (c->ir)) {
538 op00_ext (c);
539 return;
540 }
541
542 s1 = arm_get_rn (c, c->ir);
543 s2 = arm_get_sh (c, c->ir, NULL);
544
545 d = s1 & s2;
546
547 arm_set_rd (c, c->ir, d);
548 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
549}
550
551/* 01 09: mul[cond]s rn, rm, rs */
552static
553void op01_09 (arm_t *c)
554{
555 uint32_t d, s1, s2;
556
557 s1 = arm_get_rm (c, c->ir);
558 s2 = arm_get_rs (c, c->ir);
559
560 d = (s1 * s2) & 0xffffffff;
561
562 arm_set_rn (c, c->ir, d);
563 arm_set_cc_nz (c, d);
564 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
565}
566
567/* 01 0b: ldr[cond][h|sh|sb] rd, addressing_mode */
568static
569void op01_0b (arm_t *c)
570{
571 int p, u, w, s, h;
572 uint32_t val, base, index;
573
574 p = arm_get_bit (c->ir, 24);
575 u = arm_get_bit (c->ir, 23);
576 w = arm_get_bit (c->ir, 21);
577 s = arm_get_bit (c->ir, 6);
578 h = arm_get_bit (c->ir, 5);
579
580 base = arm_get_rn (c, c->ir);
581
582 /* get index */
583 if (arm_get_bit (c->ir, 22)) {
584 index = arm_get_bits (c->ir, 8, 4) << 4;
585 index |= arm_get_bits (c->ir, 0, 4);
586 }
587 else {
588 index = arm_get_rm (c, c->ir);
589 }
590
591 /* pre-index */
592 if (p) {
593 base += u ? index : (~index + 1);
594 base &= 0xffffffff;
595 }
596
597 if (h) {
598 uint16_t tmp;
599
600 if (arm_dload16 (c, base & 0xfffffffe, &tmp)) {
601 return;
602 }
603
604 if (s) {
605 val = arm_exts (tmp, 16);
606 }
607 else {
608 val = arm_extu (tmp, 16);
609 }
610 }
611 else {
612 uint8_t tmp;
613
614 if (arm_dload8 (c, base, &tmp)) {
615 return;
616 }
617
618 if (s) {
619 val = arm_exts (tmp, 8);
620 }
621 else {
622 val = arm_extu (tmp, 8);
623 }
624 }
625
626 arm_set_rd (c, c->ir, val);
627
628 /* post-index */
629 if (p == 0) {
630 base += u ? index : (~index + 1);
631 base &= 0xffffffff;
632 }
633
634 /* base register writeback */
635 if ((p == 0) || (w == 1)) {
636 arm_set_rn (c, c->ir, base);
637 }
638
639 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
640}
641
642/* 01 ext */
643static
644void op01_ext (arm_t *c)
645{
646 switch (arm_get_shext (c->ir)) {
647 case 0x09:
648 op01_09 (c);
649 break;
650
651 default:
652 op01_0b (c);
653 break;
654 }
655}
656
657/* 01: and[cond]s rd, rn, shifter_operand */
658static
659void op01 (arm_t *c)
660{
661 uint32_t s1, s2, d, shc;
662
663 if (arm_is_shext (c->ir)) {
664 op01_ext (c);
665 return;
666 }
667
668 s1 = arm_get_rn (c, c->ir);
669 s2 = arm_get_sh (c, c->ir, &shc);
670
671 d = s1 & s2;
672
673 arm_set_rd (c, c->ir, d);
674
675 if (arm_rd_is_pc (c->ir)) {
676 arm_write_cpsr (c, arm_get_spsr (c), 1);
677 arm_set_clk (c, 0, 1);
678 }
679 else {
680 arm_set_cc_nz (c, d);
681 arm_set_cc_c (c, shc);
682 arm_set_clk (c, 4, 1);
683 }
684}
685
686/* 02 09: mla[cond] rn, rm, rs, rd */
687static
688void op02_09 (arm_t *c)
689{
690 uint32_t s1, s2, s3, d;
691
692 s1 = arm_get_rm (c, c->ir);
693 s2 = arm_get_rs (c, c->ir);
694 s3 = arm_get_rd (c, c->ir);
695
696 d = (s1 * s2 + s3) & 0xffffffff;
697
698 arm_set_rn (c, c->ir, d);
699 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
700}
701
702/* 02 ext */
703static
704void op02_ext (arm_t *c)
705{
706 switch (arm_get_shext (c->ir)) {
707 case 0x09:
708 op02_09 (c);
709 break;
710
711 default:
712 op00_0b (c);
713 break;
714 }
715}
716
717/* 02: eor[cond] rd, rn, shifter_operand */
718static
719void op02 (arm_t *c)
720{
721 uint32_t s1, s2, d;
722
723 if (arm_is_shext (c->ir)) {
724 op02_ext (c);
725 return;
726 }
727
728 s1 = arm_get_rn (c, c->ir);
729 s2 = arm_get_sh (c, c->ir, NULL);
730
731 d = s1 ^ s2;
732
733 arm_set_rd (c, c->ir, d);
734 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
735}
736
737/* 03 09: mla[cond]s rn, rm, rs, rd */
738static
739void op03_09 (arm_t *c)
740{
741 uint32_t s1, s2, s3, d;
742
743 s1 = arm_get_rm (c, c->ir);
744 s2 = arm_get_rs (c, c->ir);
745 s3 = arm_get_rd (c, c->ir);
746
747 d = (s1 * s2 + s3) & 0xffffffff;
748
749 arm_set_rn (c, c->ir, d);
750 arm_set_cc_nz (c, d);
751 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
752}
753
754/* 03 ext */
755static
756void op03_ext (arm_t *c)
757{
758 switch (arm_get_shext (c->ir)) {
759 case 0x09:
760 op03_09 (c);
761 break;
762
763 default:
764 op01_0b (c);
765 break;
766 }
767}
768
769/* 03: eor[cond]s rd, rn, shifter_operand */
770static
771void op03 (arm_t *c)
772{
773 uint32_t s1, s2, d, shc;
774
775 if (arm_is_shext (c->ir)) {
776 op03_ext (c);
777 return;
778 }
779
780 s1 = arm_get_rn (c, c->ir);
781 s2 = arm_get_sh (c, c->ir, &shc);
782
783 d = s1 ^ s2;
784
785 arm_set_rd (c, c->ir, d);
786
787 if (arm_rd_is_pc (c->ir)) {
788 arm_write_cpsr (c, arm_get_spsr (c), 1);
789 arm_set_clk (c, 0, 1);
790 }
791 else {
792 arm_set_cc_nz (c, d);
793 arm_set_cc_c (c, shc);
794 arm_set_clk (c, 4, 1);
795 }
796}
797
798/* 04 ext */
799static
800void op04_ext (arm_t *c)
801{
802 switch (arm_get_shext (c->ir)) {
803 case 0x09:
804 op_undefined (c);
805 break;
806
807 default:
808 op00_0b (c);
809 break;
810 }
811}
812
813/* 04: sub[cond] rd, rn, shifter_operand */
814static
815void op04 (arm_t *c)
816{
817 uint32_t s1, s2, d;
818
819 if (arm_is_shext (c->ir)) {
820 op04_ext (c);
821 return;
822 }
823
824 s1 = arm_get_rn (c, c->ir);
825 s2 = arm_get_sh (c, c->ir, NULL);
826
827 d = (s1 - s2) & 0xffffffff;
828
829 arm_set_rd (c, c->ir, d);
830 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
831}
832
833/* 05 ext */
834static
835void op05_ext (arm_t *c)
836{
837 switch (arm_get_shext (c->ir)) {
838 case 0x09:
839 op_undefined (c);
840 break;
841
842 default:
843 op01_0b (c);
844 break;
845 }
846}
847
848/* 05: sub[cond]s rd, rn, shifter_operand */
849static
850void op05 (arm_t *c)
851{
852 uint32_t s1, s2, d;
853
854 if (arm_is_shext (c->ir)) {
855 op05_ext (c);
856 return;
857 }
858
859 s1 = arm_get_rn (c, c->ir);
860 s2 = arm_get_sh (c, c->ir, NULL);
861
862 d = (s1 - s2) & 0xffffffff;
863
864 arm_set_rd (c, c->ir, d);
865
866 if (arm_rd_is_pc (c->ir)) {
867 arm_write_cpsr (c, arm_get_spsr (c), 1);
868 arm_set_clk (c, 0, 1);
869 }
870 else {
871 arm_set_cc_sub (c, d, s1, s2);
872 arm_set_clk (c, 4, 1);
873 }
874}
875
876/* 06 ext */
877static
878void op06_ext (arm_t *c)
879{
880 switch (arm_get_shext (c->ir)) {
881 case 0x09:
882 op_undefined (c);
883 break;
884
885 default:
886 op00_0b (c);
887 break;
888 }
889}
890
891/* 06: rsb[cond] rd, rn, shifter_operand */
892static
893void op06 (arm_t *c)
894{
895 uint32_t s1, s2, d;
896
897 if (arm_is_shext (c->ir)) {
898 op06_ext (c);
899 return;
900 }
901
902 s2 = arm_get_rn (c, c->ir);
903 s1 = arm_get_sh (c, c->ir, NULL);
904
905 d = (s1 - s2) & 0xffffffff;
906
907 arm_set_rd (c, c->ir, d);
908 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
909}
910
911/* 07 ext */
912static
913void op07_ext (arm_t *c)
914{
915 switch (arm_get_shext (c->ir)) {
916 case 0x09:
917 op_undefined (c);
918 break;
919
920 default:
921 op01_0b (c);
922 break;
923 }
924}
925
926/* 07: rsb[cond]s rd, rn, shifter_operand */
927static
928void op07 (arm_t *c)
929{
930 uint32_t s1, s2, d;
931
932 if (arm_is_shext (c->ir)) {
933 op07_ext (c);
934 return;
935 }
936
937 s2 = arm_get_rn (c, c->ir);
938 s1 = arm_get_sh (c, c->ir, NULL);
939
940 d = (s1 - s2) & 0xffffffff;
941
942 arm_set_rd (c, c->ir, d);
943
944 if (arm_rd_is_pc (c->ir)) {
945 arm_write_cpsr (c, arm_get_spsr (c), 1);
946 arm_set_clk (c, 0, 1);
947 }
948 else {
949 arm_set_cc_sub (c, d, s1, s2);
950 arm_set_clk (c, 4, 1);
951 }
952}
953
954/* 08 09: umull[cond] rdlo, rdhi, rm, rs */
955static
956void op08_09 (arm_t *c)
957{
958 uint32_t d1, d2, s1, s2;
959 uint64_t d;
960
961 s1 = arm_get_rm (c, c->ir);
962 s2 = arm_get_rs (c, c->ir);
963
964 d = (uint64_t) s1 * (uint64_t) s2;
965 d1 = d & 0xffffffff;
966 d2 = (d >> 32) & 0xffffffff;
967
968 arm_set_rn (c, c->ir, d2);
969 arm_set_rd (c, c->ir, d1);
970
971 arm_set_clk (c, 4, 1);
972}
973
974/* 08 ext */
975static
976void op08_ext (arm_t *c)
977{
978 switch (arm_get_shext (c->ir)) {
979 case 0x09:
980 op08_09 (c);
981 break;
982
983 default:
984 op00_0b (c);
985 break;
986 }
987}
988
989/* 08: add[cond] rd, rn, shifter_operand */
990static
991void op08 (arm_t *c)
992{
993 uint32_t s1, s2, d;
994
995 if (arm_is_shext (c->ir)) {
996 op08_ext (c);
997 return;
998 }
999
1000 s1 = arm_get_rn (c, c->ir);
1001 s2 = arm_get_sh (c, c->ir, NULL);
1002
1003 d = (s1 + s2) & 0xffffffffUL;
1004
1005 arm_set_rd (c, c->ir, d);
1006 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1007}
1008
1009/* 09 09: umull[cond]s rdlo, rdhi, rm, rs */
1010static
1011void op09_09 (arm_t *c)
1012{
1013 uint32_t d1, d2, s1, s2;
1014 uint64_t d;
1015
1016 s1 = arm_get_rm (c, c->ir);
1017 s2 = arm_get_rs (c, c->ir);
1018
1019 d = (uint64_t) s1 * (uint64_t) s2;
1020 d1 = d & 0xffffffff;
1021 d2 = (d >> 32) & 0xffffffff;
1022
1023 arm_set_rn (c, c->ir, d2);
1024 arm_set_rd (c, c->ir, d1);
1025 arm_set_cc_nz (c, d2);
1026
1027 arm_set_clk (c, 4, 1);
1028}
1029
1030/* 09 ext */
1031static
1032void op09_ext (arm_t *c)
1033{
1034 switch (arm_get_shext (c->ir)) {
1035 case 0x09:
1036 op09_09 (c);
1037 break;
1038
1039 default:
1040 op01_0b (c);
1041 break;
1042 }
1043}
1044
1045/* 09: add[cond]s rd, rn, shifter_operand */
1046static
1047void op09 (arm_t *c)
1048{
1049 uint32_t s1, s2, d;
1050
1051 if (arm_is_shext (c->ir)) {
1052 op09_ext (c);
1053 return;
1054 }
1055
1056 s1 = arm_get_rn (c, c->ir);
1057 s2 = arm_get_sh (c, c->ir, NULL);
1058
1059 d = (s1 + s2) & 0xffffffff;
1060
1061 arm_set_rd (c, c->ir, d);
1062
1063 if (arm_rd_is_pc (c->ir)) {
1064 arm_write_cpsr (c, arm_get_spsr (c), 1);
1065 arm_set_clk (c, 0, 1);
1066 }
1067 else {
1068 arm_set_cc_add (c, d, s1, s2);
1069 arm_set_clk (c, 4, 1);
1070 }
1071}
1072
1073/* 0A 09: umlal[cond] rdlo, rdhi, rm, rs */
1074static
1075void op0a_09 (arm_t *c)
1076{
1077 uint32_t s1, s2, d1, d2;
1078 uint64_t d;
1079
1080 s1 = arm_get_rm (c, c->ir);
1081 s2 = arm_get_rs (c, c->ir);
1082 d1 = arm_get_rd (c, c->ir);
1083 d2 = arm_get_rn (c, c->ir);
1084
1085 d = (uint64_t) s1 * (uint64_t) s2;
1086
1087 d += d1;
1088 d += (uint64_t) d2 << 32;
1089
1090 d1 = d & 0xffffffff;
1091 d2 = (d >> 32) & 0xffffffff;
1092
1093 arm_set_rd (c, c->ir, d1);
1094 arm_set_rn (c, c->ir, d2);
1095
1096 arm_set_clk (c, 4, 1);
1097}
1098
1099/* 0A ext */
1100static
1101void op0a_ext (arm_t *c)
1102{
1103 switch (arm_get_shext (c->ir)) {
1104 case 0x09:
1105 op0a_09 (c);
1106 break;
1107
1108 default:
1109 op00_0b (c);
1110 break;
1111 }
1112}
1113
1114/* 0A: adc[cond] rd, rn, shifter_operand */
1115static
1116void op0a (arm_t *c)
1117{
1118 uint32_t s1, s2, s3, d;
1119
1120 if (arm_is_shext (c->ir)) {
1121 op0a_ext (c);
1122 return;
1123 }
1124
1125 s1 = arm_get_rn (c, c->ir);
1126 s2 = arm_get_sh (c, c->ir, NULL);
1127 s3 = arm_get_cc_c (c);
1128
1129 d = (s1 + s2 + s3) & 0xffffffffUL;
1130
1131 arm_set_rd (c, c->ir, d);
1132 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1133}
1134
1135/* 0B 09: umlal[cond]s rdlo, rdhi, rm, rs */
1136static
1137void op0b_09 (arm_t *c)
1138{
1139 uint32_t s1, s2, d1, d2;
1140 uint64_t d;
1141
1142 s1 = arm_get_rm (c, c->ir);
1143 s2 = arm_get_rs (c, c->ir);
1144 d1 = arm_get_rd (c, c->ir);
1145 d2 = arm_get_rn (c, c->ir);
1146
1147 d = (uint64_t) s1 * (uint64_t) s2;
1148
1149 d += d1;
1150 d += (uint64_t) d2 << 32;
1151
1152 d1 = d & 0xffffffff;
1153 d2 = (d >> 32) & 0xffffffff;
1154
1155 arm_set_rd (c, c->ir, d1);
1156 arm_set_rn (c, c->ir, d2);
1157 arm_set_cc_nz (c, d2);
1158
1159 arm_set_clk (c, 4, 1);
1160}
1161
1162/* 0B ext */
1163static
1164void op0b_ext (arm_t *c)
1165{
1166 switch (arm_get_shext (c->ir)) {
1167 case 0x09:
1168 op0b_09 (c);
1169 break;
1170
1171 default:
1172 op01_0b (c);
1173 break;
1174 }
1175}
1176
1177/* 0B: adc[cond]s rd, rn, shifter_operand */
1178static
1179void op0b (arm_t *c)
1180{
1181 uint32_t s1, s2, s3, d;
1182
1183 if (arm_is_shext (c->ir)) {
1184 op0b_ext (c);
1185 return;
1186 }
1187
1188 s1 = arm_get_rn (c, c->ir);
1189 s2 = arm_get_sh (c, c->ir, NULL);
1190 s3 = arm_get_cc_c (c);
1191
1192 d = (s1 + s2 + s3) & 0xffffffff;
1193
1194 arm_set_rd (c, c->ir, d);
1195
1196 if (arm_rd_is_pc (c->ir)) {
1197 arm_write_cpsr (c, arm_get_spsr (c), 1);
1198 arm_set_clk (c, 0, 1);
1199 }
1200 else {
1201 arm_set_cc_add (c, d, s1, s2);
1202 arm_set_clk (c, 4, 1);
1203 }
1204}
1205
1206/* 0C 09: smull[cond] rdlo, rdhi, rm, rs */
1207static
1208void op0c_09 (arm_t *c)
1209{
1210 int sign;
1211 uint32_t d1, d2, s1, s2;
1212 uint64_t d;
1213
1214 s1 = arm_get_rm (c, c->ir);
1215 s2 = arm_get_rs (c, c->ir);
1216
1217 sign = ((s1 ^ s2) & 0x80000000) != 0;
1218
1219 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff;
1220 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff;
1221
1222 d = (uint64_t) s1 * (uint64_t) s2;
1223
1224 if (sign) {
1225 d = ~d + 1;
1226 }
1227
1228 d1 = d & 0xffffffff;
1229 d2 = (d >> 32) & 0xffffffff;
1230
1231 arm_set_rd (c, c->ir, d1);
1232 arm_set_rn (c, c->ir, d2);
1233
1234 arm_set_clk (c, 4, 1);
1235}
1236
1237/* 0C ext */
1238static
1239void op0c_ext (arm_t *c)
1240{
1241 switch (arm_get_shext (c->ir)) {
1242 case 0x09:
1243 op0c_09 (c);
1244 break;
1245
1246 default:
1247 op00_0b (c);
1248 break;
1249 }
1250}
1251
1252/* 0C: sbc[cond] rd, rn, shifter_operand */
1253static
1254void op0c (arm_t *c)
1255{
1256 uint32_t s1, s2, s3, d;
1257
1258 if (arm_is_shext (c->ir)) {
1259 op0c_ext (c);
1260 return;
1261 }
1262
1263 s1 = arm_get_rn (c, c->ir);
1264 s2 = arm_get_sh (c, c->ir, NULL);
1265 s3 = !arm_get_cc_c (c);
1266
1267 d = (s1 - s2 - s3) & 0xffffffff;
1268
1269 arm_set_rd (c, c->ir, d);
1270 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1271}
1272
1273/* 0D 09: smull[cond]s rdlo, rdhi, rm, rs */
1274static
1275void op0d_09 (arm_t *c)
1276{
1277 int sign;
1278 uint32_t d1, d2, s1, s2;
1279 uint64_t d;
1280
1281 s1 = arm_get_rm (c, c->ir);
1282 s2 = arm_get_rs (c, c->ir);
1283
1284 sign = ((s1 ^ s2) & 0x80000000) != 0;
1285
1286 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff;
1287 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff;
1288
1289 d = (uint64_t) s1 * (uint64_t) s2;
1290
1291 if (sign) {
1292 d = ~d + 1;
1293 }
1294
1295 d1 = d & 0xffffffff;
1296 d2 = (d >> 32) & 0xffffffff;
1297
1298 arm_set_rd (c, c->ir, d1);
1299 arm_set_rn (c, c->ir, d2);
1300 arm_set_cc_nz (c, d2);
1301
1302 arm_set_clk (c, 4, 1);
1303}
1304
1305/* 0D ext */
1306static
1307void op0d_ext (arm_t *c)
1308{
1309 switch (arm_get_shext (c->ir)) {
1310 case 0x09:
1311 op0d_09 (c);
1312 break;
1313
1314 default:
1315 op01_0b (c);
1316 break;
1317 }
1318}
1319
1320/* 0D: sbc[cond]s rd, rn, shifter_operand */
1321static
1322void op0d (arm_t *c)
1323{
1324 uint32_t s1, s2, s3, d;
1325
1326 if (arm_is_shext (c->ir)) {
1327 op0d_ext (c);
1328 return;
1329 }
1330
1331 s1 = arm_get_rn (c, c->ir);
1332 s2 = arm_get_sh (c, c->ir, NULL);
1333 s3 = !arm_get_cc_c (c);
1334
1335 d = (s1 - s2 - s3) & 0xffffffff;
1336
1337 arm_set_rd (c, c->ir, d);
1338
1339 if (arm_rd_is_pc (c->ir)) {
1340 arm_write_cpsr (c, arm_get_spsr (c), 1);
1341 arm_set_clk (c, 0, 1);
1342 }
1343 else {
1344 arm_set_cc_sub (c, d, s1, s2);
1345 arm_set_clk (c, 4, 1);
1346 }
1347}
1348
1349/* 0E 09: smlal[cond] rdlo, rdhi, rm, rs */
1350static
1351void op0e_09 (arm_t *c)
1352{
1353 int sign;
1354 uint32_t s1, s2, d1, d2;
1355 uint64_t d;
1356
1357 s1 = arm_get_rm (c, c->ir);
1358 s2 = arm_get_rs (c, c->ir);
1359 d1 = arm_get_rd (c, c->ir);
1360 d2 = arm_get_rn (c, c->ir);
1361
1362 sign = ((s1 ^ s2) & 0x80000000) != 0;
1363
1364 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff;
1365 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff;
1366
1367 d = (uint64_t) s1 * (uint64_t) s2;
1368
1369 if (sign) {
1370 d = ~d + 1;
1371 }
1372
1373 d += d1;
1374 d += (uint64_t) d2 << 32;
1375
1376 d1 = d & 0xffffffff;
1377 d2 = (d >> 32) & 0xffffffff;
1378
1379 arm_set_rd (c, c->ir, d1);
1380 arm_set_rn (c, c->ir, d2);
1381
1382 arm_set_clk (c, 4, 1);
1383}
1384
1385/* 0E ext */
1386static
1387void op0e_ext (arm_t *c)
1388{
1389 switch (arm_get_shext (c->ir)) {
1390 case 0x09:
1391 op0e_09 (c);
1392 break;
1393
1394 default:
1395 op00_0b (c);
1396 break;
1397 }
1398}
1399
1400/* 0E: rsc[cond] rd, rn, shifter_operand */
1401static
1402void op0e (arm_t *c)
1403{
1404 uint32_t s1, s2, s3, d;
1405
1406 if (arm_is_shext (c->ir)) {
1407 op0e_ext (c);
1408 return;
1409 }
1410
1411 s2 = arm_get_rn (c, c->ir);
1412 s1 = arm_get_sh (c, c->ir, NULL);
1413 s3 = !arm_get_cc_c (c);
1414
1415 d = (s1 - s2 - s3) & 0xffffffffUL;
1416
1417 arm_set_rd (c, c->ir, d);
1418 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1419}
1420
1421/* 0F 09: smlal[cond]s rdlo, rdhi, rm, rs */
1422static
1423void op0f_09 (arm_t *c)
1424{
1425 int sign;
1426 uint32_t s1, s2, d1, d2;
1427 uint64_t d;
1428
1429 s1 = arm_get_rm (c, c->ir);
1430 s2 = arm_get_rs (c, c->ir);
1431 d1 = arm_get_rd (c, c->ir);
1432 d2 = arm_get_rn (c, c->ir);
1433
1434 sign = ((s1 ^ s2) & 0x80000000) != 0;
1435
1436 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff;
1437 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff;
1438
1439 d = (uint64_t) s1 * (uint64_t) s2;
1440
1441 if (sign) {
1442 d = ~d + 1;
1443 }
1444
1445 d += d1;
1446 d += (uint64_t) d2 << 32;
1447
1448 d1 = d & 0xffffffff;
1449 d2 = (d >> 32) & 0xffffffff;
1450
1451 arm_set_rd (c, c->ir, d1);
1452 arm_set_rn (c, c->ir, d2);
1453 arm_set_cc_nz (c, d2);
1454
1455 arm_set_clk (c, 4, 1);
1456}
1457
1458/* 0F ext */
1459static
1460void op0f_ext (arm_t *c)
1461{
1462 switch (arm_get_shext (c->ir)) {
1463 case 0x09:
1464 op0f_09 (c);
1465 break;
1466
1467 default:
1468 op01_0b (c);
1469 break;
1470 }
1471}
1472
1473/* 0F: rsc[cond]s rd, rn, shifter_operand */
1474static
1475void op0f (arm_t *c)
1476{
1477 uint32_t s1, s2, s3, d;
1478
1479 if (arm_is_shext (c->ir)) {
1480 op0f_ext (c);
1481 return;
1482 }
1483
1484 s2 = arm_get_rn (c, c->ir);
1485 s1 = arm_get_sh (c, c->ir, NULL);
1486 s3 = !arm_get_cc_c (c);
1487
1488 d = (s1 - s2 - s3) & 0xffffffff;
1489
1490 arm_set_rd (c, c->ir, d);
1491
1492 if (arm_rd_is_pc (c->ir)) {
1493 arm_write_cpsr (c, arm_get_spsr (c), 1);
1494 arm_set_clk (c, 0, 1);
1495 }
1496 else {
1497 arm_set_cc_sub (c, d, s1, s2);
1498 arm_set_clk (c, 4, 1);
1499 }
1500}
1501
1502/* 10 00: mrs[cond] rd, cpsr */
1503static
1504void op10_00 (arm_t *c)
1505{
1506 arm_set_rd (c, c->ir, arm_get_cpsr (c));
1507 arm_set_clk (c, 4, 1);
1508}
1509
1510/* 10 09: swp[cond] rd, rm, rn */
1511static
1512void op10_09 (arm_t *c)
1513{
1514 uint32_t addr, d, s;
1515
1516 addr = arm_get_rn (c, c->ir);
1517 s = arm_get_rm (c, c->ir);
1518
1519 if (arm_dload32 (c, addr & 0xfffffffc, &d)) {
1520 return;
1521 }
1522
1523 if (addr & 0x03) {
1524 d = arm_ror32 (d, (addr & 0x03) << 3);
1525 }
1526
1527 if (arm_dstore32 (c, addr & 0xfffffffc, s)) {
1528 return;
1529 }
1530
1531 arm_set_rd (c, c->ir, d);
1532 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1533}
1534
1535/* 10 */
1536static
1537void op10 (arm_t *c)
1538{
1539 switch (arm_get_bits (c->ir, 4, 4)) {
1540 case 0x00:
1541 op10_00 (c);
1542 break;
1543
1544 case 0x09:
1545 op10_09 (c);
1546 break;
1547
1548 case 0x0b:
1549 case 0x0d:
1550 case 0x0f:
1551 op00_0b (c);
1552 break;
1553
1554 default:
1555 op_undefined (c);
1556 break;
1557 }
1558}
1559
1560/* 11 ext */
1561static
1562void op11_ext (arm_t *c)
1563{
1564 switch (arm_get_shext (c->ir)) {
1565 case 0x09:
1566 op_undefined (c);
1567 break;
1568
1569 default:
1570 op01_0b (c);
1571 break;
1572 }
1573}
1574
1575/* 11: tst[cond] rn, shifter_operand */
1576static
1577void op11 (arm_t *c)
1578{
1579 uint32_t s1, s2, d, shc;
1580
1581 if (arm_is_shext (c->ir)) {
1582 op11_ext (c);
1583 return;
1584 }
1585
1586 s1 = arm_get_rn (c, c->ir);
1587 s2 = arm_get_sh (c, c->ir, &shc);
1588
1589 d = s1 & s2;
1590
1591 arm_set_cc_nz (c, d);
1592 arm_set_cc_c (c, shc);
1593 arm_set_clk (c, 4, 1);
1594}
1595
1596/* 12 00: msr[cond] fields, rm */
1597static
1598void op12_00 (arm_t *c)
1599{
1600 unsigned fld;
1601 uint32_t val;
1602
1603 fld = arm_get_bits (c->ir, 16, 4);
1604
1605 if (arm_is_privileged (c) == 0) {
1606 fld &= 0x08;
1607 }
1608
1609 val = arm_get_rm (c, c->ir);
1610
1611 if (arm_get_bit (c->ir, 22)) {
1612 val = arm_set_psr_field (arm_get_spsr (c), val, fld);
1613 arm_set_spsr (c, val);
1614 }
1615 else {
1616 val = arm_set_psr_field (arm_get_cpsr (c), val, fld);
1617 arm_write_cpsr (c, val, 0);
1618 }
1619
1620 arm_set_clk (c, 4, 1);
1621}
1622
1623/* 12 01: bx rm */
1624static
1625void op12_01 (arm_t *c)
1626{
1627 uint32_t d;
1628
1629 d = arm_get_rm (c, c->ir);
1630
1631 if (d & 1) {
1632 /* branch to thumb instruction set */
1633 op_undefined (c);
1634 return;
1635 }
1636
1637 arm_set_pc (c, d & 0xfffffffc);
1638
1639 arm_set_clk (c, 0, 1);
1640}
1641
1642/* 12 03: blx rm */
1643static
1644void op12_03 (arm_t *c)
1645{
1646 uint32_t d;
1647
1648 d = arm_get_rm (c, c->ir);
1649
1650 if (d & 1) {
1651 /* branch to thumb instruction set */
1652 op_undefined (c);
1653 return;
1654 }
1655
1656 arm_set_lr (c, (arm_get_pc (c) + 4) & 0xffffffff);
1657 arm_set_pc (c, d & 0xfffffffc);
1658
1659 arm_set_clk (c, 0, 1);
1660}
1661
1662/* 12 07: bkpt uimm16 */
1663static
1664void op12_07 (arm_t *c)
1665{
1666 arm_set_clk (c, 0, 1);
1667 arm_exception_prefetch_abort (c);
1668}
1669
1670/* 12 */
1671static
1672void op12 (arm_t *c)
1673{
1674 switch (c->ir & 0x0ff000f0) {
1675 case 0x01200000:
1676 op12_00 (c);
1677 break;
1678
1679 case 0x01200010:
1680 op12_01 (c);
1681 break;
1682
1683 case 0x01200030:
1684 op12_03 (c);
1685 break;
1686
1687 case 0x01200070:
1688 op12_07 (c);
1689 break;
1690
1691 case 0x012000b0:
1692 case 0x012000d0:
1693 case 0x012000f0:
1694 op00_0b (c);
1695 break;
1696
1697 default:
1698 op_undefined (c);
1699 break;
1700 }
1701}
1702
1703/* 13 ext */
1704static
1705void op13_ext (arm_t *c)
1706{
1707 switch (arm_get_shext (c->ir)) {
1708 case 0x09:
1709 op_undefined (c);
1710 break;
1711
1712 default:
1713 op01_0b (c);
1714 break;
1715 }
1716}
1717
1718/* 13: teq[cond] rn, shifter_operand */
1719static
1720void op13 (arm_t *c)
1721{
1722 uint32_t s1, s2, d, shc;
1723
1724 if (arm_is_shext (c->ir)) {
1725 op13_ext (c);
1726 return;
1727 }
1728
1729 s1 = arm_get_rn (c, c->ir);
1730 s2 = arm_get_sh (c, c->ir, &shc);
1731
1732 d = s1 ^ s2;
1733
1734 arm_set_cc_nz (c, d);
1735 arm_set_cc_c (c, shc);
1736 arm_set_clk (c, 4, 1);
1737}
1738
1739/* 14 00: mrs[cond] rd, spsr */
1740static
1741void op14_00 (arm_t *c)
1742{
1743 arm_set_rd (c, c->ir, arm_get_spsr (c));
1744 arm_set_clk (c, 4, 1);
1745}
1746
1747/* 14 09: swp[cond]b rd, rm, rn */
1748static
1749void op14_09 (arm_t *c)
1750{
1751 uint32_t addr, s;
1752 uint8_t d;
1753
1754 addr = arm_get_rn (c, c->ir);
1755 s = arm_get_rm (c, c->ir);
1756
1757 if (arm_dload8 (c, addr, &d)) {
1758 return;
1759 }
1760
1761 if (arm_dstore8 (c, addr, s & 0xff)) {
1762 return;
1763 }
1764
1765 arm_set_rd (c, c->ir, d & 0xff);
1766 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1767}
1768
1769/* 14 */
1770static
1771void op14 (arm_t *c)
1772{
1773 switch (arm_get_bits (c->ir, 4, 4)) {
1774 case 0x00:
1775 op14_00 (c);
1776 break;
1777
1778 case 0x09:
1779 op14_09 (c);
1780 break;
1781
1782 case 0x0b:
1783 case 0x0d:
1784 case 0x0f:
1785 op00_0b (c);
1786 break;
1787
1788 default:
1789 op_undefined (c);
1790 break;
1791 }
1792}
1793
1794/* 15 ext */
1795static
1796void op15_ext (arm_t *c)
1797{
1798 switch (arm_get_shext (c->ir)) {
1799 case 0x09:
1800 op_undefined (c);
1801 break;
1802
1803 default:
1804 op01_0b (c);
1805 break;
1806 }
1807}
1808
1809/* 15: cmp[cond] rn, shifter_operand */
1810static
1811void op15 (arm_t *c)
1812{
1813 uint32_t s1, s2, d;
1814
1815 if (arm_is_shext (c->ir)) {
1816 op15_ext (c);
1817 return;
1818 }
1819
1820 s1 = arm_get_rn (c, c->ir);
1821 s2 = arm_get_sh (c, c->ir, NULL);
1822
1823 d = (s1 - s2) & 0xffffffff;
1824
1825 arm_set_cc_sub (c, d, s1, s2);
1826 arm_set_clk (c, 4, 1);
1827}
1828
1829/* 16 01: clz rd, rm */
1830static
1831void op16_01 (arm_t *c)
1832{
1833 if (arm_get_bits (c->ir, 4, 4) == 0x01) {
1834 uint32_t d, s;
1835
1836 s = arm_get_rm (c, c->ir);
1837
1838 if (s == 0) {
1839 d = 32;
1840 }
1841 else {
1842 d = 0;
1843 while ((s & 0x80000000) == 0) {
1844 d += 1;
1845 s <<= 1;
1846 }
1847 }
1848
1849 arm_set_rd (c, c->ir, d);
1850 arm_set_clk (c, 4, 1);
1851 }
1852 else {
1853 op_undefined (c);
1854 }
1855}
1856
1857/* 16 08: smulxy[cond] rd, rm, rs */
1858static
1859void op16_08 (arm_t *c)
1860{
1861 int sign;
1862 uint32_t d, s1, s2;
1863
1864 s1 = arm_get_rm (c, c->ir);
1865 s2 = arm_get_rs (c, c->ir);
1866
1867 if (arm_get_bit (c->ir, 5)) {
1868 s1 = s1 >> 16;
1869 }
1870
1871 if (arm_get_bit (c->ir, 6)) {
1872 s2 = s2 >> 16;
1873 }
1874
1875 sign = ((s1 ^ s2) & 0x8000) != 0;
1876
1877 s1 = ((s1 & 0x8000) ? (~s1 + 1) : s1) & 0xffff;
1878 s2 = ((s2 & 0x8000) ? (~s2 + 1) : s2) & 0xffff;
1879
1880 d = s1 * s2;
1881
1882 if (sign) {
1883 d = (~d + 1) & 0xffffffff;
1884 }
1885
1886 arm_set_rn (c, c->ir, d);
1887 arm_set_clk (c, 4, 1);
1888}
1889
1890/* 16 */
1891static
1892void op16 (arm_t *c)
1893{
1894 switch (c->ir & 0x0ff000f0) {
1895 case 0x01600000:
1896 op12_00 (c);
1897 break;
1898
1899 case 0x01600010:
1900 op16_01 (c);
1901 break;
1902
1903 case 0x01600080:
1904 case 0x016000a0:
1905 case 0x016000c0:
1906 case 0x016000e0:
1907 op16_08 (c);
1908 break;
1909
1910 case 0x016000b0:
1911 case 0x016000d0:
1912 case 0x016000f0:
1913 op00_0b (c);
1914 break;
1915
1916 default:
1917 op_undefined (c);
1918 break;
1919 }
1920}
1921
1922/* 17 ext */
1923static
1924void op17_ext (arm_t *c)
1925{
1926 switch (arm_get_shext (c->ir)) {
1927 case 0x09:
1928 op_undefined (c);
1929 break;
1930
1931 default:
1932 op01_0b (c);
1933 break;
1934 }
1935}
1936
1937/* 17: cmn[cond] rn, shifter_operand */
1938static
1939void op17 (arm_t *c)
1940{
1941 uint32_t s1, s2, d;
1942
1943 if (arm_is_shext (c->ir)) {
1944 op17_ext (c);
1945 return;
1946 }
1947
1948 s1 = arm_get_rn (c, c->ir);
1949 s2 = arm_get_sh (c, c->ir, NULL);
1950
1951 d = (s1 + s2) & 0xffffffff;
1952
1953 arm_set_cc_add (c, d, s1, s2);
1954 arm_set_clk (c, 4, 1);
1955}
1956
1957/* 18 ext */
1958static
1959void op18_ext (arm_t *c)
1960{
1961 switch (arm_get_shext (c->ir)) {
1962 case 0x09:
1963 op_undefined (c);
1964 break;
1965
1966 default:
1967 op00_0b (c);
1968 break;
1969 }
1970}
1971
1972/* 18: orr[cond] rd, rn, shifter_operand */
1973static
1974void op18 (arm_t *c)
1975{
1976 uint32_t d, s1, s2;
1977
1978 if (arm_is_shext (c->ir)) {
1979 op18_ext (c);
1980 return;
1981 }
1982
1983 s1 = arm_get_rn (c, c->ir);
1984 s2 = arm_get_sh (c, c->ir, NULL);
1985
1986 d = s1 | s2;
1987
1988 arm_set_rd (c, c->ir, d);
1989 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
1990}
1991
1992/* 19 ext */
1993static
1994void op19_ext (arm_t *c)
1995{
1996 switch (arm_get_shext (c->ir)) {
1997 case 0x09:
1998 op_undefined (c);
1999 break;
2000
2001 default:
2002 op01_0b (c);
2003 break;
2004 }
2005}
2006
2007/* 19: orr[cond]s rd, rn, shifter_operand */
2008static
2009void op19 (arm_t *c)
2010{
2011 uint32_t s1, s2, d, shc;
2012
2013 if (arm_is_shext (c->ir)) {
2014 op19_ext (c);
2015 return;
2016 }
2017
2018 s1 = arm_get_rn (c, c->ir);
2019 s2 = arm_get_sh (c, c->ir, &shc);
2020
2021 d = s1 | s2;
2022
2023 arm_set_rd (c, c->ir, d);
2024
2025 if (arm_rd_is_pc (c->ir)) {
2026 arm_write_cpsr (c, arm_get_spsr (c), 1);
2027 arm_set_clk (c, 0, 1);
2028 }
2029 else {
2030 arm_set_cc_nz (c, d);
2031 arm_set_cc_c (c, shc);
2032 arm_set_clk (c, 4, 1);
2033 }
2034}
2035
2036/* 1A ext */
2037static
2038void op1a_ext (arm_t *c)
2039{
2040 switch (arm_get_shext (c->ir)) {
2041 case 0x09:
2042 op_undefined (c);
2043 break;
2044
2045 default:
2046 op00_0b (c);
2047 break;
2048 }
2049}
2050
2051/* 1A: mov[cond] rd, shifter_operand */
2052static
2053void op1a (arm_t *c)
2054{
2055 uint32_t d;
2056
2057 if (arm_is_shext (c->ir)) {
2058 op1a_ext (c);
2059 return;
2060 }
2061
2062 d = arm_get_sh (c, c->ir, NULL);
2063
2064 arm_set_rd (c, c->ir, d);
2065 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
2066}
2067
2068/* 1B ext */
2069static
2070void op1b_ext (arm_t *c)
2071{
2072 switch (arm_get_shext (c->ir)) {
2073 case 0x09:
2074 op_undefined (c);
2075 break;
2076
2077 default:
2078 op01_0b (c);
2079 break;
2080 }
2081}
2082
2083/* 1B: mov[cond]s rd, shifter_operand */
2084static
2085void op1b (arm_t *c)
2086{
2087 uint32_t d, shc;
2088
2089 if (arm_is_shext (c->ir)) {
2090 op1b_ext (c);
2091 return;
2092 }
2093
2094 d = arm_get_sh (c, c->ir, &shc);
2095
2096 arm_set_rd (c, c->ir, d);
2097
2098 if (arm_rd_is_pc (c->ir)) {
2099 arm_write_cpsr (c, arm_get_spsr (c), 1);
2100 arm_set_clk (c, 0, 1);
2101 }
2102 else {
2103 arm_set_cc_nz (c, d);
2104 arm_set_cc_c (c, shc);
2105 arm_set_clk (c, 4, 1);
2106 }
2107}
2108
2109/* 1C ext */
2110static
2111void op1c_ext (arm_t *c)
2112{
2113 switch (arm_get_shext (c->ir)) {
2114 case 0x09:
2115 op_undefined (c);
2116 break;
2117
2118 default:
2119 op00_0b (c);
2120 break;
2121 }
2122}
2123
2124/* 1C: bic[cond] rd, rn, shifter_operand */
2125static
2126void op1c (arm_t *c)
2127{
2128 uint32_t s1, s2, d;
2129
2130 if (arm_is_shext (c->ir)) {
2131 op1c_ext (c);
2132 return;
2133 }
2134
2135 s1 = arm_get_rn (c, c->ir);
2136 s2 = arm_get_sh (c, c->ir, NULL);
2137
2138 d = s1 & ~s2;
2139
2140 arm_set_rd (c, c->ir, d);
2141 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
2142}
2143
2144/* 1D ext */
2145static
2146void op1d_ext (arm_t *c)
2147{
2148 switch (arm_get_shext (c->ir)) {
2149 case 0x09:
2150 op_undefined (c);
2151 break;
2152
2153 default:
2154 op01_0b (c);
2155 break;
2156 }
2157}
2158
2159/* 1d: bic[cond]s rd, rn, shifter_operand */
2160static
2161void op1d (arm_t *c)
2162{
2163 uint32_t s1, s2, d, shc;
2164
2165 if (arm_is_shext (c->ir)) {
2166 op1d_ext (c);
2167 return;
2168 }
2169
2170 s1 = arm_get_rn (c, c->ir);
2171 s2 = arm_get_sh (c, c->ir, &shc);
2172
2173 d = s1 & ~s2;
2174
2175 arm_set_rd (c, c->ir, d);
2176
2177 if (arm_rd_is_pc (c->ir)) {
2178 arm_write_cpsr (c, arm_get_spsr (c), 1);
2179 arm_set_clk (c, 0, 1);
2180 }
2181 else {
2182 arm_set_cc_nz (c, d);
2183 arm_set_cc_c (c, shc);
2184 arm_set_clk (c, 4, 1);
2185 }
2186}
2187
2188/* 1E ext */
2189static
2190void op1e_ext (arm_t *c)
2191{
2192 switch (arm_get_shext (c->ir)) {
2193 case 0x09:
2194 op_undefined (c);
2195 break;
2196
2197 default:
2198 op00_0b (c);
2199 break;
2200 }
2201}
2202
2203/* 1E: mvn[cond] rd, shifter_operand */
2204static
2205void op1e (arm_t *c)
2206{
2207 uint32_t d;
2208
2209 if (arm_is_shext (c->ir)) {
2210 op1e_ext (c);
2211 return;
2212 }
2213
2214 d = arm_get_sh (c, c->ir, NULL);
2215
2216 d = ~d & 0xffffffff;
2217
2218 arm_set_rd (c, c->ir, d);
2219 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
2220}
2221
2222/* 1F ext */
2223static
2224void op1f_ext (arm_t *c)
2225{
2226 switch (arm_get_shext (c->ir)) {
2227 case 0x09:
2228 op_undefined (c);
2229 break;
2230
2231 default:
2232 op01_0b (c);
2233 break;
2234 }
2235}
2236
2237/* 1F: mvn[cond]s rd, shifter_operand */
2238static
2239void op1f (arm_t *c)
2240{
2241 uint32_t d, shc;
2242
2243 if (arm_is_shext (c->ir)) {
2244 op1f_ext (c);
2245 return;
2246 }
2247
2248 d = arm_get_sh (c, c->ir, &shc);
2249
2250 d = ~d & 0xffffffff;
2251
2252 arm_set_rd (c, c->ir, d);
2253
2254 if (arm_rd_is_pc (c->ir)) {
2255 arm_write_cpsr (c, arm_get_spsr (c), 1);
2256 arm_set_clk (c, 0, 1);
2257 }
2258 else {
2259 arm_set_cc_nz (c, d);
2260 arm_set_cc_c (c, shc);
2261 arm_set_clk (c, 4, 1);
2262 }
2263}
2264
2265/* 32: msr[cond] fields, #imm */
2266static
2267void op32 (arm_t *c)
2268{
2269 unsigned fld, rot;
2270 uint32_t val;
2271
2272 fld = arm_get_bits (c->ir, 16, 4);
2273 rot = 2 * arm_get_bits (c->ir, 8, 4);
2274
2275 if (arm_is_privileged (c) == 0) {
2276 fld &= 0x08;
2277 }
2278
2279 val = arm_get_bits (c->ir, 0, 8);
2280 val = arm_ror32 (val, rot);
2281
2282 if (arm_get_bit (c->ir, 22)) {
2283 val = arm_set_psr_field (arm_get_spsr (c), val, fld);
2284 arm_set_spsr (c, val);
2285 }
2286 else {
2287 val = arm_set_psr_field (arm_get_cpsr (c), val, fld);
2288 arm_write_cpsr (c, val, 0);
2289 }
2290
2291 arm_set_clk (c, 4, 1);
2292}
2293
2294/* 40: str[cond][b][t] rd, [rn], address */
2295static
2296void op40 (arm_t *c)
2297{
2298 int p, u, b, w, t;
2299 uint32_t val, base, index;
2300
2301 p = arm_get_bit (c->ir, 24);
2302 u = arm_get_bit (c->ir, 23);
2303 b = arm_get_bit (c->ir, 22);
2304 w = arm_get_bit (c->ir, 21);
2305 t = (p == 0) && (w == 1);
2306
2307 base = arm_get_rn (c, c->ir);
2308
2309 /* get index */
2310 if (arm_get_bit (c->ir, 25)) {
2311 unsigned n;
2312
2313 index = arm_get_rm (c, c->ir);
2314 n = arm_get_bits (c->ir, 7, 5);
2315
2316 switch (arm_get_bits (c->ir, 5, 2)) {
2317 case 0x00: /* lsl */
2318 index = index << n;
2319 break;
2320
2321 case 0x01: /* lsr */
2322 index = (n == 0) ? 0 : (index >> n);
2323 break;
2324
2325 case 0x02: /* asr */
2326 if (n == 0) {
2327 if (index & 0x80000000) {
2328 index = 0xffffffff;
2329 }
2330 else {
2331 index = 0x00000000;
2332 }
2333 }
2334 else {
2335 index = arm_asr32 (index, n);
2336 }
2337 break;
2338
2339 case 0x03: /* ror / rrx */
2340 if (n == 0) {
2341 index = (index >> 1) | (arm_get_cc_c (c) << 31);
2342 }
2343 else {
2344 index = (index >> n) | (index << (32 - n));
2345 }
2346 }
2347 }
2348 else {
2349 index = arm_extu (c->ir, 12);
2350 }
2351
2352 /* pre-index */
2353 if (p) {
2354 base += u ? index : (~index + 1);
2355 base &= 0xffffffff;
2356 }
2357
2358 val = arm_get_rd (c, c->ir);
2359
2360 if (b) {
2361 if (t) {
2362 if (arm_dstore8_t (c, base, val)) {
2363 return;
2364 }
2365 }
2366 else {
2367 if (arm_dstore8 (c, base, val)) {
2368 return;
2369 }
2370 }
2371 }
2372 else {
2373 if (t) {
2374 if (arm_dstore32_t (c, base, val)) {
2375 return;
2376 }
2377 }
2378 else {
2379 if (arm_dstore32 (c, base, val)) {
2380 return;
2381 }
2382 }
2383 }
2384
2385 /* post-index */
2386 if (p == 0) {
2387 base += u ? index : (~index + 1);
2388 base &= 0xffffffff;
2389 }
2390
2391 /* base register writeback */
2392 if ((p == 0) || (w == 1)) {
2393 arm_set_rn (c, c->ir, base);
2394 }
2395
2396 arm_set_clk (c, 4, 1);
2397}
2398
2399/* 41: ldr[cond][b][t] rd, [rn], address */
2400static
2401void op41 (arm_t *c)
2402{
2403 int p, u, b, w, t;
2404 uint32_t val, base, index;
2405
2406 p = arm_get_bit (c->ir, 24);
2407 u = arm_get_bit (c->ir, 23);
2408 b = arm_get_bit (c->ir, 22);
2409 w = arm_get_bit (c->ir, 21);
2410 t = (p == 0) && (w == 1);
2411
2412 base = arm_get_rn (c, c->ir);
2413
2414 /* get index */
2415 if (arm_get_bit (c->ir, 25)) {
2416 unsigned n;
2417
2418 index = arm_get_rm (c, c->ir);
2419 n = arm_get_bits (c->ir, 7, 5);
2420
2421 switch (arm_get_bits (c->ir, 5, 2)) {
2422 case 0x00: /* lsl */
2423 index = index << n;
2424 break;
2425
2426 case 0x01: /* lsr */
2427 index = (n == 0) ? 0 : (index >> n);
2428 break;
2429
2430 case 0x02: /* asr */
2431 if (n == 0) {
2432 if (index & 0x80000000) {
2433 index = 0xffffffff;
2434 }
2435 else {
2436 index = 0x00000000;
2437 }
2438 }
2439 else {
2440 index = arm_asr32 (index, n);
2441 }
2442 break;
2443
2444 case 0x03: /* ror / rrx */
2445 if (n == 0) {
2446 index = (index >> 1) | (arm_get_cc_c (c) << 31);
2447 }
2448 else {
2449 index = (index >> n) | (index << (32 - n));
2450 }
2451 }
2452 }
2453 else {
2454 index = arm_extu (c->ir, 12);
2455 }
2456
2457 /* pre-index */
2458 if (p) {
2459 base += u ? index : (~index + 1);
2460 base &= 0xffffffff;
2461 }
2462
2463 if (b) {
2464 uint8_t tmp;
2465
2466 if (t) {
2467 if (arm_dload8_t (c, base, &tmp)) {
2468 return;
2469 }
2470 }
2471 else {
2472 if (arm_dload8 (c, base, &tmp)) {
2473 return;
2474 }
2475 }
2476
2477 val = tmp & 0xff;
2478 }
2479 else {
2480 if (t) {
2481 if (arm_dload32_t (c, base & 0xfffffffc, &val)) {
2482 return;
2483 }
2484 }
2485 else {
2486 if (arm_dload32 (c, base & 0xfffffffc, &val)) {
2487 return;
2488 }
2489 }
2490
2491 if (base & 0x03) {
2492 val = arm_ror32 (val, (base & 0x03) << 3);
2493 }
2494 }
2495
2496 arm_set_rd (c, c->ir, val);
2497
2498 /* post-index */
2499 if (p == 0) {
2500 base += u ? index : (~index + 1);
2501 base &= 0xffffffff;
2502 }
2503
2504 /* base register writeback */
2505 if ((p == 0) || (w == 1)) {
2506 arm_set_rn (c, c->ir, base);
2507 }
2508
2509 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1);
2510}
2511
2512/* 80: stm[cond][mode] rn[!], registers[^] */
2513static
2514void op80 (arm_t *c)
2515{
2516 int p, u, s, w;
2517 unsigned i;
2518 unsigned regs, regn;
2519 unsigned mode;
2520 uint32_t addr, base, writeback;
2521 uint32_t val;
2522
2523 p = arm_get_bit (c->ir, 24);
2524 u = arm_get_bit (c->ir, 23);
2525 s = arm_get_bit (c->ir, 22);
2526 w = arm_get_bit (c->ir, 21);
2527
2528 regs = arm_get_bits (c->ir, 0, 16);
2529 regn = arm_bitcnt32 (regs);
2530 mode = arm_get_cpsr_m (c);
2531 base = arm_get_rn (c, c->ir);
2532
2533 if (u) {
2534 writeback = base + 4 * regn;
2535
2536 if (p) {
2537 /* ib */
2538 addr = base + 4;
2539 }
2540 else {
2541 /* ia */
2542 addr = base;
2543 }
2544 }
2545 else {
2546 writeback = base - 4 * regn;
2547
2548 if (p) {
2549 /* db */
2550 addr = base - 4 * regn;
2551 }
2552 else {
2553 /* da */
2554 addr = base - 4 * regn + 4;
2555 }
2556 }
2557
2558 if (s) {
2559 /* access user mode registers */
2560 arm_set_reg_map (c, ARM_MODE_USR);
2561 }
2562
2563 for (i = 0; i < 16; i++) {
2564 if (regs & (1U << i)) {
2565 val = arm_get_reg_pc (c, i, 8);
2566
2567 if (arm_dstore32 (c, addr & 0xfffffffc, val)) {
2568 return;
2569 }
2570
2571 addr += 4;
2572 }
2573 }
2574
2575 if (s) {
2576 arm_set_reg_map (c, mode);
2577 }
2578
2579 if (w) {
2580 arm_set_rn (c, c->ir, writeback);
2581 }
2582
2583 arm_set_clk (c, 4, 1);
2584}
2585
2586/* 81: ldm[cond][mode] rn[!], registers[^] */
2587static
2588void op81 (arm_t *c)
2589{
2590 int p, u, s, w;
2591 unsigned i;
2592 unsigned regs, regn;
2593 unsigned mode;
2594 uint32_t addr, base, writeback;
2595 uint32_t val;
2596
2597 p = arm_get_bit (c->ir, 24);
2598 u = arm_get_bit (c->ir, 23);
2599 s = arm_get_bit (c->ir, 22);
2600 w = arm_get_bit (c->ir, 21);
2601
2602 regs = arm_get_bits (c->ir, 0, 16);
2603 regn = arm_bitcnt32 (regs);
2604 mode = arm_get_cpsr_m (c);
2605 base = arm_get_rn (c, c->ir);
2606
2607 if (u) {
2608 writeback = base + 4 * regn;
2609
2610 if (p) {
2611 /* ib */
2612 addr = base + 4;
2613 }
2614 else {
2615 /* ia */
2616 addr = base;
2617 }
2618 }
2619 else {
2620 writeback = base - 4 * regn;
2621
2622 if (p) {
2623 /* db */
2624 addr = base - 4 * regn;
2625 }
2626 else {
2627 /* da */
2628 addr = base - 4 * regn + 4;
2629 }
2630 }
2631
2632 if (s && !(regs & 0x8000)) {
2633 /* access user mode registers */
2634 arm_set_reg_map (c, ARM_MODE_USR);
2635 }
2636
2637 for (i = 0; i < 16; i++) {
2638 if (regs & (1U << i)) {
2639 if (arm_dload32 (c, addr & 0xfffffffc, &val)) {
2640 return;
2641 }
2642
2643 if (i == arm_ir_rn (c->ir)) {
2644 /* defer modification of base register */
2645 base = val;
2646 }
2647 else {
2648 arm_set_gpr (c, i, val);
2649 }
2650
2651 addr += 4;
2652 }
2653 }
2654
2655 arm_set_rn (c, c->ir, base);
2656
2657 if (s) {
2658 if (regs & 0x8000) {
2659 arm_write_cpsr (c, arm_get_spsr (c), 1);
2660 }
2661 else {
2662 arm_set_reg_map (c, mode);
2663 }
2664 }
2665
2666 if (w) {
2667 arm_set_rn (c, c->ir, writeback);
2668 }
2669
2670 arm_set_clk (c, (regs & 0x8000) ? 0 : 4, 1);
2671}
2672
2673/* A0: b[cond] target */
2674static
2675void opa0 (arm_t *c)
2676{
2677 uint32_t d;
2678
2679 d = arm_exts (c->ir, 24);
2680 d = (arm_get_pc (c) + (d << 2) + 8) & 0xffffffff;
2681
2682 arm_set_pc (c, d);
2683
2684 arm_set_clk (c, 0, 1);
2685}
2686
2687/* B0: bl[cond] target */
2688static
2689void opb0 (arm_t *c)
2690{
2691 uint32_t d;
2692
2693 d = arm_exts (c->ir, 24);
2694 d = (arm_get_pc (c) + (d << 2) + 8) & 0xffffffff;
2695
2696 arm_set_lr (c, (arm_get_pc (c) + 4) & 0xffffffff);
2697 arm_set_pc (c, d);
2698
2699 arm_set_clk (c, 0, 1);
2700}
2701
2702/* C4: mcrr[cond] coproc, opcode, rd, rn, crm */
2703static
2704void opc4 (arm_t *c)
2705{
2706 int r;
2707 unsigned cop;
2708
2709 cop = arm_get_bits (c->ir, 8, 4);
2710
2711 if (arm_copr_check (c, cop) == 0) {
2712 r = c->copr[cop]->exec (c, c->copr[cop]);
2713 }
2714 else {
2715 r = 1;
2716 }
2717
2718 if (cop == 0) {
2719 /* hack */
2720 arm_set_clk (c, 4, 1);
2721 return;
2722 }
2723
2724 if (r) {
2725 arm_set_clk (c, 0, 1);
2726 arm_exception_undefined (c);
2727 return;
2728 }
2729}
2730
2731/* C5: mrrc[cond] coproc, opcode, rd, rn, crm */
2732static
2733void opc5 (arm_t *c)
2734{
2735 int r;
2736 unsigned cop;
2737
2738 cop = arm_get_bits (c->ir, 8, 4);
2739
2740 if (arm_copr_check (c, cop) == 0) {
2741 r = c->copr[cop]->exec (c, c->copr[cop]);
2742 }
2743 else {
2744 r = 1;
2745 }
2746
2747 if (cop == 0) {
2748 /* hack */
2749 arm_set_clk (c, 4, 1);
2750 return;
2751 }
2752
2753 if (r) {
2754 arm_set_clk (c, 0, 1);
2755 arm_exception_undefined (c);
2756 return;
2757 }
2758}
2759
2760/* E0 00: cdp[cond] coproc, opcode1, crd, crn, crm, opcode2 */
2761static
2762void ope0_00 (arm_t *c)
2763{
2764 int r;
2765 unsigned cop;
2766
2767 cop = arm_get_bits (c->ir, 8, 4);
2768
2769 if (arm_copr_check (c, cop) == 0) {
2770 r = c->copr[cop]->exec (c, c->copr[cop]);
2771 }
2772 else {
2773 r = 1;
2774 }
2775
2776 if (r) {
2777 arm_set_clk (c, 0, 1);
2778 arm_exception_undefined (c);
2779 return;
2780 }
2781
2782 arm_set_clk (c, 4, 1);
2783}
2784
2785/* E0 01: mcr[cond] coproc, opcode1, rd, crn, crm, opcode2 */
2786static
2787void ope0_01 (arm_t *c)
2788{
2789 int r;
2790 unsigned cop;
2791
2792 cop = arm_get_bits (c->ir, 8, 4);
2793
2794 if (arm_copr_check (c, cop) == 0) {
2795 r = c->copr[cop]->exec (c, c->copr[cop]);
2796 }
2797 else {
2798 r = 1;
2799 }
2800
2801 if (r) {
2802 arm_set_clk (c, 0, 1);
2803 arm_exception_undefined (c);
2804 return;
2805 }
2806}
2807
2808/* E0 11: mrc[cond] coproc, opcode1, rd, crn, crm, opcode2 */
2809static
2810void ope0_11 (arm_t *c)
2811{
2812 int r;
2813 unsigned cop;
2814
2815 cop = arm_get_bits (c->ir, 8, 4);
2816
2817 if (arm_copr_check (c, cop) == 0) {
2818 r = c->copr[cop]->exec (c, c->copr[cop]);
2819 }
2820 else {
2821 r = 1;
2822 }
2823
2824 if (cop == 0) {
2825 /* hack */
2826 arm_set_clk (c, 4, 1);
2827 return;
2828 }
2829
2830 if (r) {
2831 arm_set_clk (c, 0, 1);
2832 arm_exception_undefined (c);
2833 return;
2834 }
2835}
2836
2837/* E0 */
2838static
2839void ope0 (arm_t *c)
2840{
2841 switch (c->ir & 0x00100010) {
2842 case 0x00000000:
2843 case 0x00100000:
2844 ope0_00 (c);
2845 break;
2846
2847 case 0x00000010:
2848 ope0_01 (c);
2849 break;
2850
2851 case 0x00100010:
2852 ope0_11 (c);
2853 break;
2854
2855 default:
2856 op_undefined (c);
2857 break;
2858 }
2859}
2860
2861/* F0: swi[cond] immediate */
2862static
2863void opf0 (arm_t *c)
2864{
2865 arm_set_clk (c, 0, 1);
2866
2867 arm_exception_swi (c);
2868}
2869
2870
2871static
2872arm_opcode_f arm_opcodes[256] = {
2873 op00, op01, op02, op03, op04, op05, op06, op07, /* 00 */
2874 op08, op09, op0a, op0b, op0c, op0d, op0e, op0f,
2875 op10, op11, op12, op13, op14, op15, op16, op17, /* 10 */
2876 op18, op19, op1a, op1b, op1c, op1d, op1e, op1f,
2877 op00, op01, op02, op03, op04, op05, op06, op07, /* 20 */
2878 op08, op09, op0a, op0b, op0c, op0d, op0e, op0f,
2879 NULL, op11, op32, op13, NULL, op15, NULL, op17, /* 30 */
2880 op18, op19, op1a, op1b, op1c, op1d, op1e, op1f,
2881 op40, op41, op40, op41, op40, op41, op40, op41, /* 40 */
2882 op40, op41, op40, op41, op40, op41, op40, op41,
2883 op40, op41, op40, op41, op40, op41, op40, op41, /* 50 */
2884 op40, op41, op40, op41, op40, op41, op40, op41,
2885 op40, op41, op40, op41, op40, op41, op40, op41, /* 60 */
2886 op40, op41, op40, op41, op40, op41, op40, op41,
2887 op40, op41, op40, op41, op40, op41, op40, op41, /* 70 */
2888 op40, op41, op40, op41, op40, op41, op40, op41,
2889 op80, op81, op80, op81, op80, op81, op80, op81, /* 80 */
2890 op80, op81, op80, op81, op80, op81, op80, op81,
2891 op80, op81, op80, op81, op80, op81, op80, op81, /* 90 */
2892 op80, op81, op80, op81, op80, op81, op80, op81,
2893 opa0, opa0, opa0, opa0, opa0, opa0, opa0, opa0, /* a0 */
2894 opa0, opa0, opa0, opa0, opa0, opa0, opa0, opa0,
2895 opb0, opb0, opb0, opb0, opb0, opb0, opb0, opb0, /* b0 */
2896 opb0, opb0, opb0, opb0, opb0, opb0, opb0, opb0,
2897 NULL, NULL, NULL, NULL, opc4, opc5, NULL, NULL, /* c0 */
2898 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2899 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* d0 */
2900 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2901 ope0, ope0, ope0, ope0, ope0, ope0, ope0, ope0, /* e0 */
2902 ope0, ope0, ope0, ope0, ope0, ope0, ope0, ope0,
2903 opf0, opf0, opf0, opf0, opf0, opf0, opf0, opf0, /* f0 */
2904 opf0, opf0, opf0, opf0, opf0, opf0, opf0, opf0
2905};
2906
2907
2908void arm_set_opcodes (arm_t *c)
2909{
2910 unsigned i;
2911
2912 for (i = 0; i < 256; i++) {
2913 if (arm_opcodes[i] != NULL) {
2914 c->opcodes[i] = arm_opcodes[i];
2915 }
2916 else {
2917 c->opcodes[i] = op_undefined;
2918 }
2919 }
2920}