Revisión | 3c29390f0cb4faa183825ee7c80b627b8b9a219b (tree) |
---|---|
Tiempo | 2015-12-17 02:41:18 |
Autor | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
RXv2 instructions support
@@ -49,7 +49,9 @@ enum sim_rx_regnum | ||
49 | 49 | sim_rx_bpc_regnum, |
50 | 50 | sim_rx_fintv_regnum, |
51 | 51 | sim_rx_fpsw_regnum, |
52 | - sim_rx_acc_regnum, | |
52 | + sim_rx_acc0_regnum, | |
53 | + sim_rx_acc1_regnum, | |
54 | + sim_rx_extb_regnum, | |
53 | 55 | sim_rx_num_regs |
54 | 56 | }; |
55 | 57 |
@@ -40,6 +40,7 @@ SIM_OBJS = \ | ||
40 | 40 | $(ENDLIST) |
41 | 41 | |
42 | 42 | LIBS = $B/bfd/libbfd.a $B/libiberty/libiberty.a |
43 | +SIM_EXTRA_LIBS = -lm | |
43 | 44 | |
44 | 45 | ## COMMON_POST_CONFIG_FRAG |
45 | 46 |
@@ -35,6 +35,12 @@ extern int rx_big_endian; | ||
35 | 35 | |
36 | 36 | typedef struct |
37 | 37 | { |
38 | + SI hi; | |
39 | + DI lo; | |
40 | +} acc_t; | |
41 | + | |
42 | +typedef struct | |
43 | +{ | |
38 | 44 | SI r[16]; |
39 | 45 | |
40 | 46 | SI r_psw; |
@@ -51,8 +57,8 @@ typedef struct | ||
51 | 57 | SI r_isp; |
52 | 58 | SI r_fintv; |
53 | 59 | SI r_intb; |
54 | - SI r__reserved_cr_13; | |
55 | - SI r__reserved_cr_14; | |
60 | + SI r_extb; | |
61 | + SI r_li; | |
56 | 62 | SI r__reserved_cr_15; |
57 | 63 | |
58 | 64 | SI r__reserved_cr_16; |
@@ -75,7 +81,7 @@ typedef struct | ||
75 | 81 | |
76 | 82 | SI r_temp; |
77 | 83 | |
78 | - DI r_acc; | |
84 | + acc_t r_acc[2]; | |
79 | 85 | |
80 | 86 | #ifdef CYCLE_ACCURATE |
81 | 87 | /* If set, RTS/RTSD take 2 fewer cycles. */ |
@@ -105,12 +111,12 @@ typedef struct | ||
105 | 111 | #define isp 26 |
106 | 112 | #define fintv 27 |
107 | 113 | #define intb 28 |
114 | +#define extb 29 | |
115 | +#define li 30 | |
108 | 116 | |
109 | 117 | #define r_temp_idx 48 |
110 | -#define acc64 49 | |
111 | -#define acchi 50 | |
112 | -#define accmi 51 | |
113 | -#define acclo 52 | |
118 | +#define acc0 49 | |
119 | +#define acc1 50 | |
114 | 120 | |
115 | 121 | extern regs_type regs; |
116 | 122 |
@@ -170,9 +176,9 @@ void init_regs (void); | ||
170 | 176 | void stack_heap_stats (void); |
171 | 177 | void set_pointer_width (int bytes); |
172 | 178 | unsigned int get_reg (int id); |
173 | -unsigned long long get_reg64 (int id); | |
179 | +void get_acc (int id, acc_t *valuel); | |
174 | 180 | void put_reg (int id, unsigned int value); |
175 | -void put_reg64 (int id, unsigned long long value); | |
181 | +void put_acc (int id, acc_t *value); | |
176 | 182 | |
177 | 183 | void set_flags (int mask, int newbits); |
178 | 184 | void set_oszc (long long value, int bytes, int c); |
@@ -790,3 +790,174 @@ rxfp_itof (long fa, int round_mode) | ||
790 | 790 | return rv; |
791 | 791 | } |
792 | 792 | |
793 | +double sqrt(double x); | |
794 | + | |
795 | +static FP_ExceptionCases ex_sqrt_tab[5][5] = { | |
796 | + /* N +0 -0 +In -In */ | |
797 | + { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */ | |
798 | + { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */ | |
799 | + { eSZ, eIn, eIn, eNZ, ePZ }, /* -0 */ | |
800 | + { eSI, ePI, eNI, eIn, eIn }, /* +Inf */ | |
801 | + { eSI, eNI, ePI, eIn, eIn }, /* -Inf */ | |
802 | +}; | |
803 | + | |
804 | +fp_t | |
805 | +rxfp_fsqrt (fp_t fa) | |
806 | +{ | |
807 | + FP_Parts a, b, c; | |
808 | + fp_t rv; | |
809 | + double da; | |
810 | + | |
811 | + fp_explode (fa, &a); | |
812 | + fp_explode (fa, &b); | |
813 | + CHECK_EXCEPTIONS (a, b, rv, ex_sqrt_tab); | |
814 | + | |
815 | + da = fp_to_double (&a); | |
816 | + tprintf("sqrt(%g) = %g\n", da, sqrt(da)); | |
817 | + | |
818 | + double_to_fp (sqrt(da), &c); | |
819 | + rv = fp_implode (&c); | |
820 | + | |
821 | + return rv; | |
822 | +} | |
823 | + | |
824 | +unsigned long | |
825 | +rxfp_ftou (fp_t fa, int round_mode) | |
826 | +{ | |
827 | + FP_Parts a; | |
828 | + fp_t rv; | |
829 | + int sign; | |
830 | + int whole_bits, frac_bits; | |
831 | + | |
832 | + fp_explode (fa, &a); | |
833 | + sign = fa & 0x80000000UL; | |
834 | + | |
835 | + switch (a.type) | |
836 | + { | |
837 | + case FP_NORMAL: | |
838 | + break; | |
839 | + case FP_PZERO: | |
840 | + case FP_NZERO: | |
841 | + return 0; | |
842 | + case FP_PINFINITY: | |
843 | + FP_RAISE (V); | |
844 | + return 0xffffffffL; | |
845 | + case FP_NINFINITY: | |
846 | + FP_RAISE (V); | |
847 | + return 0x00000000L; | |
848 | + case FP_DENORMAL: | |
849 | + FP_RAISE (E); | |
850 | + return 0; | |
851 | + case FP_QNAN: | |
852 | + case FP_SNAN: | |
853 | + FP_RAISE (V); | |
854 | + return sign ? 0x00000000 : 0xffffffff; | |
855 | + } | |
856 | + | |
857 | + if (sign) | |
858 | + return 0; | |
859 | + if (a.exp >= 32) | |
860 | + { | |
861 | + FP_RAISE (V); | |
862 | + return 0xffffffff; | |
863 | + } | |
864 | + | |
865 | + a.exp -= 23; | |
866 | + | |
867 | + if (a.exp <= -25) | |
868 | + { | |
869 | + /* Less than 0.49999 */ | |
870 | + frac_bits = a.mant; | |
871 | + whole_bits = 0; | |
872 | + } | |
873 | + else if (a.exp < 0) | |
874 | + { | |
875 | + frac_bits = a.mant << (33 + a.exp); | |
876 | + whole_bits = a.mant >> (-a.exp); | |
877 | + } | |
878 | + else | |
879 | + { | |
880 | + frac_bits = 0; | |
881 | + whole_bits = a.mant << a.exp; | |
882 | + } | |
883 | + | |
884 | + if (frac_bits) | |
885 | + { | |
886 | + switch (round_mode & 3) | |
887 | + { | |
888 | + case FPRM_NEAREST: | |
889 | + if (frac_bits & 0x80000000UL) | |
890 | + whole_bits ++; | |
891 | + break; | |
892 | + case FPRM_ZERO: | |
893 | + case FPRM_NINF: | |
894 | + break; | |
895 | + case FPRM_PINF: | |
896 | + if (!sign) | |
897 | + whole_bits ++; | |
898 | + break; | |
899 | + } | |
900 | + } | |
901 | + | |
902 | + rv = whole_bits; | |
903 | + | |
904 | + return rv; | |
905 | +} | |
906 | + | |
907 | +fp_t | |
908 | +rxfp_utof (unsigned long fa, int round_mode) | |
909 | +{ | |
910 | + fp_t rv; | |
911 | + int sign = 0; | |
912 | + unsigned int frac_bits; | |
913 | + volatile unsigned int whole_bits; | |
914 | + FP_Parts a; | |
915 | + | |
916 | + if (fa == 0) | |
917 | + return PLUS_ZERO; | |
918 | + | |
919 | + a.sign = 1; | |
920 | + | |
921 | + whole_bits = fa; | |
922 | + a.exp = 31; | |
923 | + | |
924 | + while (! (whole_bits & 0x80000000UL)) | |
925 | + { | |
926 | + a.exp --; | |
927 | + whole_bits <<= 1; | |
928 | + } | |
929 | + frac_bits = whole_bits & 0xff; | |
930 | + whole_bits = whole_bits >> 8; | |
931 | + | |
932 | + if (frac_bits) | |
933 | + { | |
934 | + /* We must round */ | |
935 | + switch (round_mode & 3) | |
936 | + { | |
937 | + case FPRM_NEAREST: | |
938 | + if (frac_bits & 0x80) | |
939 | + whole_bits ++; | |
940 | + break; | |
941 | + case FPRM_ZERO: | |
942 | + break; | |
943 | + case FPRM_PINF: | |
944 | + if (!sign) | |
945 | + whole_bits ++; | |
946 | + break; | |
947 | + case FPRM_NINF: | |
948 | + if (sign) | |
949 | + whole_bits ++; | |
950 | + break; | |
951 | + } | |
952 | + } | |
953 | + | |
954 | + a.mant = whole_bits; | |
955 | + if (whole_bits & 0xff000000UL) | |
956 | + { | |
957 | + a.mant >>= 1; | |
958 | + a.exp ++; | |
959 | + } | |
960 | + | |
961 | + rv = fp_implode (&a); | |
962 | + return rv; | |
963 | +} |
@@ -27,3 +27,6 @@ extern fp_t rxfp_div (fp_t fa, fp_t fb); | ||
27 | 27 | extern void rxfp_cmp (fp_t fa, fp_t fb); |
28 | 28 | extern long rxfp_ftoi (fp_t fa, int round_mode); |
29 | 29 | extern fp_t rxfp_itof (long fa, int round_mode); |
30 | +extern fp_t rxfp_fsqrt (fp_t fa); | |
31 | +extern unsigned long rxfp_ftou (fp_t fa, int round_mode); | |
32 | +extern fp_t rxfp_utof (unsigned long fa, int round_mode); |
@@ -387,6 +387,9 @@ reg_size (enum sim_rx_regnum regno) | ||
387 | 387 | case sim_rx_intb_regnum: |
388 | 388 | size = sizeof (regs.r_intb); |
389 | 389 | break; |
390 | + case sim_rx_extb_regnum: | |
391 | + size = sizeof (regs.r_extb); | |
392 | + break; | |
390 | 393 | case sim_rx_pc_regnum: |
391 | 394 | size = sizeof (regs.r_pc); |
392 | 395 | break; |
@@ -405,8 +408,9 @@ reg_size (enum sim_rx_regnum regno) | ||
405 | 408 | case sim_rx_fpsw_regnum: |
406 | 409 | size = sizeof (regs.r_fpsw); |
407 | 410 | break; |
408 | - case sim_rx_acc_regnum: | |
409 | - size = sizeof (regs.r_acc); | |
411 | + case sim_rx_acc0_regnum: | |
412 | + case sim_rx_acc1_regnum: | |
413 | + size = 8; | |
410 | 414 | break; |
411 | 415 | default: |
412 | 416 | size = 0; |
@@ -490,6 +494,9 @@ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) | ||
490 | 494 | case sim_rx_intb_regnum: |
491 | 495 | val = get_reg (intb); |
492 | 496 | break; |
497 | + case sim_rx_extb_regnum: | |
498 | + val = get_reg (extb); | |
499 | + break; | |
493 | 500 | case sim_rx_pc_regnum: |
494 | 501 | val = get_reg (pc); |
495 | 502 | break; |
@@ -508,9 +515,34 @@ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) | ||
508 | 515 | case sim_rx_fpsw_regnum: |
509 | 516 | val = get_reg (fpsw); |
510 | 517 | break; |
511 | - case sim_rx_acc_regnum: | |
512 | - val = ((DI) get_reg (acchi) << 32) | get_reg (acclo); | |
513 | - break; | |
518 | + case sim_rx_acc0_regnum: | |
519 | + { | |
520 | + acc_t acc; | |
521 | + get_acc(0, &acc); | |
522 | + if (rx_big_endian) | |
523 | + { | |
524 | + put_be (buf, 8, acc.lo); | |
525 | + } | |
526 | + else | |
527 | + { | |
528 | + put_le (buf, 8, acc.lo); | |
529 | + } | |
530 | + return 8; | |
531 | + } | |
532 | + case sim_rx_acc1_regnum: | |
533 | + { | |
534 | + acc_t acc; | |
535 | + get_acc(1, &acc); | |
536 | + if (rx_big_endian) | |
537 | + { | |
538 | + put_be (buf, 8, acc.lo); | |
539 | + } | |
540 | + else | |
541 | + { | |
542 | + put_le (buf, 8, acc.lo); | |
543 | + } | |
544 | + return 8; | |
545 | + } | |
514 | 546 | default: |
515 | 547 | fprintf (stderr, "rx minisim: unrecognized register number: %d\n", |
516 | 548 | regno); |
@@ -623,10 +655,38 @@ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length) | ||
623 | 655 | case sim_rx_fpsw_regnum: |
624 | 656 | put_reg (fpsw, val); |
625 | 657 | break; |
626 | - case sim_rx_acc_regnum: | |
627 | - put_reg (acclo, val & 0xffffffff); | |
628 | - put_reg (acchi, (val >> 32) & 0xffffffff); | |
629 | - break; | |
658 | + case sim_rx_acc0_regnum: | |
659 | + { | |
660 | + acc_t acc; | |
661 | + if (rx_big_endian) | |
662 | + { | |
663 | + acc.hi = get_be (buf, 8); | |
664 | + acc.lo = get_be (buf + 8, 8); | |
665 | + } | |
666 | + else | |
667 | + { | |
668 | + acc.lo = get_le (buf, 8); | |
669 | + acc.hi = get_le (buf + 8, 8); | |
670 | + } | |
671 | + put_acc (0, &acc); | |
672 | + break; | |
673 | + } | |
674 | + case sim_rx_acc1_regnum: | |
675 | + { | |
676 | + acc_t acc; | |
677 | + if (rx_big_endian) | |
678 | + { | |
679 | + acc.hi = get_be (buf, 8); | |
680 | + acc.lo = get_be (buf + 8, 8); | |
681 | + } | |
682 | + else | |
683 | + { | |
684 | + acc.lo = get_le (buf, 8); | |
685 | + acc.hi = get_le (buf + 8, 8); | |
686 | + } | |
687 | + put_acc (1, &acc); | |
688 | + break; | |
689 | + } | |
630 | 690 | default: |
631 | 691 | fprintf (stderr, "rx minisim: unrecognized register number: %d\n", |
632 | 692 | regno); |
@@ -50,10 +50,10 @@ char *reg_names[] = { | ||
50 | 50 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
51 | 51 | /* control register */ |
52 | 52 | "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES", |
53 | - "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES", | |
53 | + "bpsw", "bpc", "isp", "fintv", "intb", "extb", "li", "RES", | |
54 | 54 | "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", |
55 | 55 | "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", |
56 | - "temp", "acc", "acchi", "accmi", "acclo" | |
56 | + "temp", "acc0", "acc1", | |
57 | 57 | }; |
58 | 58 | |
59 | 59 | unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; |
@@ -69,6 +69,9 @@ init_regs (void) | ||
69 | 69 | memset (®s, 0, sizeof (regs)); |
70 | 70 | memset (&oldregs, 0, sizeof (oldregs)); |
71 | 71 | |
72 | + regs.r_extb = 0xffffff80; | |
73 | + oldregs.r_extb = 0xffffff80; | |
74 | + | |
72 | 75 | #ifdef CYCLE_ACCURATE |
73 | 76 | regs.rt = -1; |
74 | 77 | oldregs.rt = -1; |
@@ -102,16 +105,14 @@ get_reg_i (int id) | ||
102 | 105 | return regs.r_fintv; |
103 | 106 | case intb: |
104 | 107 | return regs.r_intb; |
108 | + case extb: | |
109 | + return regs.r_extb; | |
110 | + case li: | |
111 | + return regs.r_li; | |
105 | 112 | case pc: |
106 | 113 | return regs.r_pc; |
107 | 114 | case r_temp_idx: |
108 | 115 | return regs.r_temp; |
109 | - case acchi: | |
110 | - return (SI)(regs.r_acc >> 32); | |
111 | - case accmi: | |
112 | - return (SI)(regs.r_acc >> 16); | |
113 | - case acclo: | |
114 | - return (SI)regs.r_acc; | |
115 | 116 | } |
116 | 117 | abort(); |
117 | 118 | } |
@@ -125,25 +126,14 @@ get_reg (int id) | ||
125 | 126 | return rv; |
126 | 127 | } |
127 | 128 | |
128 | -static unsigned long long | |
129 | -get_reg64_i (int id) | |
130 | -{ | |
131 | - switch (id) | |
132 | - { | |
133 | - case acc64: | |
134 | - return regs.r_acc; | |
135 | - default: | |
136 | - abort (); | |
137 | - } | |
138 | -} | |
139 | - | |
140 | -unsigned long long | |
141 | -get_reg64 (int id) | |
129 | +void | |
130 | +get_acc (int id, acc_t *acc) | |
142 | 131 | { |
143 | - unsigned long long rv = get_reg64_i (id); | |
144 | - if (trace > ((id != pc && id != sp) ? 0 : 1)) | |
145 | - printf ("get_reg (%s) = %016llx\n", reg_names[id], rv); | |
146 | - return rv; | |
132 | + if (id >= 2) | |
133 | + abort (); | |
134 | + *acc = regs.r_acc[id]; | |
135 | + if (trace > 0) | |
136 | + printf ("get_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo); | |
147 | 137 | } |
148 | 138 | |
149 | 139 | static int highest_sp = 0, lowest_sp = 0xffffff; |
@@ -203,18 +193,14 @@ put_reg (int id, unsigned int v) | ||
203 | 193 | case intb: |
204 | 194 | regs.r_intb = v; |
205 | 195 | break; |
206 | - case pc: | |
207 | - regs.r_pc = v; | |
196 | + case extb: | |
197 | + regs.r_extb = v; | |
208 | 198 | break; |
209 | - | |
210 | - case acchi: | |
211 | - regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32); | |
199 | + case li: | |
200 | + regs.r_li = v; | |
212 | 201 | break; |
213 | - case accmi: | |
214 | - regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16); | |
215 | - break; | |
216 | - case acclo: | |
217 | - regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v); | |
202 | + case pc: | |
203 | + regs.r_pc = v; | |
218 | 204 | break; |
219 | 205 | |
220 | 206 | case 0: /* Stack pointer is "in" R0. */ |
@@ -261,19 +247,15 @@ put_reg (int id, unsigned int v) | ||
261 | 247 | } |
262 | 248 | |
263 | 249 | void |
264 | -put_reg64 (int id, unsigned long long v) | |
250 | +put_acc (int id, acc_t *acc) | |
265 | 251 | { |
266 | - if (trace > ((id != pc) ? 0 : 1)) | |
267 | - printf ("put_reg (%s) = %016llx\n", reg_names[id], v); | |
268 | 252 | |
269 | - switch (id) | |
270 | - { | |
271 | - case acc64: | |
272 | - regs.r_acc = v; | |
273 | - break; | |
274 | - default: | |
275 | - abort (); | |
276 | - } | |
253 | + if (id >= 2) | |
254 | + abort (); | |
255 | + if (trace > 0) | |
256 | + printf ("put_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo); | |
257 | + | |
258 | + regs.r_acc[id] = *acc; | |
277 | 259 | } |
278 | 260 | |
279 | 261 | int |
@@ -545,14 +527,19 @@ trace_register_changes (void) | ||
545 | 527 | oldregs.r_fpsw = regs.r_fpsw; |
546 | 528 | } |
547 | 529 | |
548 | - if (oldregs.r_acc != regs.r_acc) | |
530 | + for(i = 0; i < 2; i++) | |
549 | 531 | { |
550 | - if (tag) { printf (tag); tag = 0; } | |
551 | - printf(" acc %016llx:", oldregs.r_acc); | |
552 | - printf("%016llx", regs.r_acc); | |
553 | - oldregs.r_acc = regs.r_acc; | |
532 | + if (oldregs.r_acc[i].hi != regs.r_acc[i].hi || | |
533 | + oldregs.r_acc[i].lo != regs.r_acc[i].lo) | |
534 | + { | |
535 | + if (tag) { printf (tag); tag = 0; } | |
536 | + printf(" acc%d %08x%016lx:", i, oldregs.r_acc[i].hi, | |
537 | + oldregs.r_acc[i].lo); | |
538 | + printf("%08x%016lx", regs.r_acc[i].hi, | |
539 | + oldregs.r_acc[i].lo); | |
540 | + oldregs.r_acc[i] = regs.r_acc[i]; | |
541 | + } | |
554 | 542 | } |
555 | - | |
556 | 543 | if (tag == 0) |
557 | 544 | printf ("\033[0m\n"); |
558 | 545 | } |
@@ -137,6 +137,25 @@ static const char * id_names[] = { | ||
137 | 137 | "RXO_wait", |
138 | 138 | |
139 | 139 | "RXO_sccnd", /* d = cond(s) ? 1 : 0 */ |
140 | + | |
141 | + "RXO_fsqrt", | |
142 | + "RXO_ftou", | |
143 | + "RXO_utof", | |
144 | + "RXO_movco", | |
145 | + "RXO_movli", | |
146 | + "RXO_emaca", | |
147 | + "RXO_emsba", | |
148 | + "RXO_emula", | |
149 | + "RXO_maclh", | |
150 | + "RXO_msbhi", | |
151 | + "RXO_msblh", | |
152 | + "RXO_msblo", | |
153 | + "RXO_mullh", | |
154 | + "RXO_mvfacgu", | |
155 | + "RXO_mvtacgu", | |
156 | + "RXO_racl", | |
157 | + "RXO_rdacl", | |
158 | + "RXO_rdacw", | |
140 | 159 | }; |
141 | 160 | |
142 | 161 | static const char * optype_names[] = { |
@@ -806,8 +825,8 @@ fop_fsub (fp_t s1, fp_t s2, fp_t *d) | ||
806 | 825 | int do_store; \ |
807 | 826 | fp_t fa, fb, fc; \ |
808 | 827 | FPCLEAR(); \ |
809 | - fb = GS (); \ | |
810 | - fa = GD (); \ | |
828 | + fb = US2 (); \ | |
829 | + fa = US1 (); \ | |
811 | 830 | do_store = fop_##func (fa, fb, &fc); \ |
812 | 831 | tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \ |
813 | 832 | FPCHECK(); \ |
@@ -929,6 +948,66 @@ op_is_memory (const RX_Opcode_Decoded *rd, int i) | ||
929 | 948 | |
930 | 949 | #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); } |
931 | 950 | |
951 | +#define MULADD(val, s) \ | |
952 | +{ \ | |
953 | + get_acc(opcode->op[0].reg - 32, &acc); \ | |
954 | + sll = val; \ | |
955 | + sll <<= s; \ | |
956 | + if (sll > 0 && (unsigned long long)acc.lo > (unsigned long long)(acc.lo + sll)) \ | |
957 | + acc.hi++; \ | |
958 | + else if (sll < 0 && (unsigned long long)(acc.lo + sll) > (unsigned long long)acc.lo) \ | |
959 | + acc.hi--; \ | |
960 | + acc.lo += sll; \ | |
961 | + put_acc (opcode->op[0].reg - 32, &acc); \ | |
962 | + E1; \ | |
963 | + break; \ | |
964 | +} | |
965 | + | |
966 | +#define MULSUB(val, s) \ | |
967 | +{ \ | |
968 | + get_acc(opcode->op[0].reg - 32, &acc); \ | |
969 | + sll = val; \ | |
970 | + sll <<= s; \ | |
971 | + if (sll > 0 && (unsigned long long)(sll - acc.lo) > (unsigned long long)acc.lo) \ | |
972 | + acc.hi--; \ | |
973 | + else if (sll < 0 && (unsigned long long)acc.lo >(unsigned long long)(sll - acc.lo)) \ | |
974 | + acc.hi++; \ | |
975 | + acc.hi = (signed char)acc.hi; \ | |
976 | + acc.lo -= sll; \ | |
977 | + put_acc (opcode->op[0].reg - 32, &acc); \ | |
978 | + E1; \ | |
979 | + break; \ | |
980 | +} | |
981 | + | |
982 | +#define MULACC(val, s) \ | |
983 | +{ \ | |
984 | + sll = val; \ | |
985 | + sll <<= s; \ | |
986 | + acc.lo = sll; \ | |
987 | + acc.hi = (sll < 0)? -1 : 0; \ | |
988 | + put_acc (opcode->op[0].reg - 32, &acc); \ | |
989 | + E1; \ | |
990 | + break; \ | |
991 | +} | |
992 | + | |
993 | +#define RAC(add, pl, ml) \ | |
994 | +{ \ | |
995 | + get_acc(opcode->op[0].reg - 32, &acc); \ | |
996 | + ll = acc.lo << GS (); \ | |
997 | + ll += add; \ | |
998 | + if ((signed long long)ll > (signed long long)0x00007fff00000000ULL) \ | |
999 | + ll = 0x00007fff00000000ULL; \ | |
1000 | + else if ((signed long long)ll < (signed long long)0xffff800000000000ULL) \ | |
1001 | + ll = 0xffff800000000000ULL; \ | |
1002 | + else \ | |
1003 | + ll &= 0xffffffff00000000ULL; \ | |
1004 | + acc.hi = ((signed long long)ll < 0) ? -1 : 0; \ | |
1005 | + acc.lo = ll; \ | |
1006 | + put_acc (opcode->op[0].reg - 32, &acc); \ | |
1007 | + E1; \ | |
1008 | + break; \ | |
1009 | +} | |
1010 | + | |
932 | 1011 | int |
933 | 1012 | decode_opcode () |
934 | 1013 | { |
@@ -940,6 +1019,7 @@ decode_opcode () | ||
940 | 1019 | unsigned long opcode_pc; |
941 | 1020 | RX_Data rx_data; |
942 | 1021 | const RX_Opcode_Decoded *opcode; |
1022 | + acc_t acc; | |
943 | 1023 | #ifdef CYCLE_STATS |
944 | 1024 | unsigned long long prev_cycle_count; |
945 | 1025 | #endif |
@@ -1216,6 +1296,12 @@ decode_opcode () | ||
1216 | 1296 | } |
1217 | 1297 | break; |
1218 | 1298 | |
1299 | + case RXO_emaca: | |
1300 | + MULADD((long long)GS2 () * (long long)GS (), 0) | |
1301 | + | |
1302 | + case RXO_emsba: | |
1303 | + MULSUB((long long)GS2 () * (long long)GS (), 0) | |
1304 | + | |
1219 | 1305 | case RXO_emul: |
1220 | 1306 | ma = GD (); |
1221 | 1307 | mb = GS (); |
@@ -1226,6 +1312,18 @@ decode_opcode () | ||
1226 | 1312 | E2; |
1227 | 1313 | break; |
1228 | 1314 | |
1315 | + case RXO_emula: | |
1316 | + ma = GS2 (); | |
1317 | + mb = GS (); | |
1318 | + acc.lo = (long long)ma * (long long)mb; | |
1319 | + if (acc.lo < 0) | |
1320 | + acc.hi = -1; | |
1321 | + else | |
1322 | + acc.hi = 0; | |
1323 | + put_acc (opcode->op[0].reg - 32, &acc); | |
1324 | + E (3); | |
1325 | + break; | |
1326 | + | |
1229 | 1327 | case RXO_emulu: |
1230 | 1328 | uma = GD (); |
1231 | 1329 | umb = GS (); |
@@ -1264,12 +1362,24 @@ decode_opcode () | ||
1264 | 1362 | PRIVILEDGED (); |
1265 | 1363 | regs.r_psw = regs.r_bpsw; |
1266 | 1364 | regs.r_pc = regs.r_bpc; |
1365 | + regs.r_li = 0; | |
1267 | 1366 | #ifdef CYCLE_ACCURATE |
1268 | 1367 | regs.fast_return = 0; |
1269 | 1368 | cycles(3); |
1270 | 1369 | #endif |
1271 | 1370 | break; |
1272 | 1371 | |
1372 | + case RXO_fsqrt: | |
1373 | + ma = GS (); | |
1374 | + FPCLEAR (); | |
1375 | + mb = rxfp_fsqrt (ma); | |
1376 | + FPCHECK (); | |
1377 | + PD (mb); | |
1378 | + tprintf("(int) %g = %d\n", int2float(ma), mb); | |
1379 | + set_sz (mb, 4); | |
1380 | + E (16); | |
1381 | + break; | |
1382 | + | |
1273 | 1383 | case RXO_fsub: |
1274 | 1384 | FLOAT_OP (fsub); |
1275 | 1385 | E (4); |
@@ -1286,6 +1396,17 @@ decode_opcode () | ||
1286 | 1396 | E (2); |
1287 | 1397 | break; |
1288 | 1398 | |
1399 | + case RXO_ftou: | |
1400 | + ma = GS (); | |
1401 | + FPCLEAR (); | |
1402 | + mb = rxfp_ftou (ma, FPRM_ZERO); | |
1403 | + FPCHECK (); | |
1404 | + PD (mb); | |
1405 | + tprintf("(int) %g = %d\n", int2float(ma), mb); | |
1406 | + set_sz (mb, 4); | |
1407 | + E (2); | |
1408 | + break; | |
1409 | + | |
1289 | 1410 | case RXO_int: |
1290 | 1411 | v = GS (); |
1291 | 1412 | if (v == 255) |
@@ -1352,18 +1473,13 @@ decode_opcode () | ||
1352 | 1473 | break; |
1353 | 1474 | |
1354 | 1475 | case RXO_machi: |
1355 | - ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16); | |
1356 | - ll <<= 16; | |
1357 | - put_reg64 (acc64, ll + regs.r_acc); | |
1358 | - E1; | |
1359 | - break; | |
1476 | + MULADD((long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16), 16) | |
1477 | + | |
1478 | + case RXO_maclh: | |
1479 | + MULADD((long long)(signed short)(GS()) * (long long)(signed short)(GS2 () >> 16), 16) | |
1360 | 1480 | |
1361 | 1481 | case RXO_maclo: |
1362 | - ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ()); | |
1363 | - ll <<= 16; | |
1364 | - put_reg64 (acc64, ll + regs.r_acc); | |
1365 | - E1; | |
1366 | - break; | |
1482 | + MULADD((long long)(signed short)(GS()) * (long long)(signed short)(GS2 ()), 16) | |
1367 | 1483 | |
1368 | 1484 | case RXO_max: |
1369 | 1485 | mb = GS(); |
@@ -1457,6 +1573,33 @@ decode_opcode () | ||
1457 | 1573 | cycles (1); |
1458 | 1574 | break; |
1459 | 1575 | |
1576 | + case RXO_movli: | |
1577 | + PD (mem_get_si (GS ())); | |
1578 | + regs.r_li = 1; | |
1579 | + E1; | |
1580 | + break; | |
1581 | + | |
1582 | + case RXO_movco: | |
1583 | + if (regs.r_li == 1) | |
1584 | + { | |
1585 | + mem_put_si (GD (), GS ()); | |
1586 | + PS (0); | |
1587 | + } | |
1588 | + else | |
1589 | + PS (1); | |
1590 | + regs.r_li = 0; | |
1591 | + E1; | |
1592 | + break; | |
1593 | + | |
1594 | + case RXO_msbhi: | |
1595 | + MULSUB((long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16), 16) | |
1596 | + | |
1597 | + case RXO_msblh: | |
1598 | + MULSUB((long long)(signed short)(GS()) * (long long)(signed short)(GS2 () >> 16), 16) | |
1599 | + | |
1600 | + case RXO_msblo: | |
1601 | + MULSUB((long long)(signed short)(GS()) * (long long)(signed short)(GS2 ()), 16) | |
1602 | + | |
1460 | 1603 | case RXO_mul: |
1461 | 1604 | v = US2 (); |
1462 | 1605 | ll = (unsigned long long) US1() * (unsigned long long) v; |
@@ -1465,43 +1608,64 @@ decode_opcode () | ||
1465 | 1608 | break; |
1466 | 1609 | |
1467 | 1610 | case RXO_mulhi: |
1468 | - v = GS2 (); | |
1469 | - ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16); | |
1470 | - ll <<= 16; | |
1471 | - put_reg64 (acc64, ll); | |
1472 | - E1; | |
1473 | - break; | |
1611 | + MULACC((long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16), 16) | |
1612 | + case RXO_mullh: | |
1613 | + MULACC((long long)(signed short)(GS()) * (long long)(signed short)(GS2 () >> 16), 16) | |
1474 | 1614 | |
1475 | 1615 | case RXO_mullo: |
1476 | - v = GS2 (); | |
1477 | - ll = (long long)(signed short)(GS()) * (long long)(signed short)(v); | |
1478 | - ll <<= 16; | |
1479 | - put_reg64 (acc64, ll); | |
1480 | - E1; | |
1481 | - break; | |
1616 | + MULACC((long long)(signed short)(GS()) * (long long)(signed short)(GS2 ()), 16) | |
1482 | 1617 | |
1483 | 1618 | case RXO_mvfachi: |
1484 | - PD (get_reg (acchi)); | |
1619 | + get_acc (opcode->op[1].reg - 32, &acc); | |
1620 | + PD ((acc.lo << GS2 ()) >> 32); | |
1485 | 1621 | E1; |
1486 | 1622 | break; |
1487 | 1623 | |
1488 | 1624 | case RXO_mvfaclo: |
1489 | - PD (get_reg (acclo)); | |
1625 | + get_acc (opcode->op[1].reg - 32, &acc); | |
1626 | + PD (acc.lo << GS2 ()); | |
1490 | 1627 | E1; |
1491 | 1628 | break; |
1492 | 1629 | |
1493 | 1630 | case RXO_mvfacmi: |
1494 | - PD (get_reg (accmi)); | |
1631 | + get_acc (opcode->op[1].reg - 32, &acc); | |
1632 | + PD ((acc.lo << GS2 ()) >> 16); | |
1633 | + E1; | |
1634 | + break; | |
1635 | + | |
1636 | + case RXO_mvfacgu: | |
1637 | + get_acc (opcode->op[1].reg - 32, &acc); | |
1638 | + uma = (signed char)acc.hi; | |
1639 | + umb = GS2 (); | |
1640 | + if (umb) | |
1641 | + { | |
1642 | + uma <<= umb; | |
1643 | + uma |= ((acc.lo >> (64 - umb)) & 3); | |
1644 | + } | |
1645 | + PD (uma); | |
1495 | 1646 | E1; |
1496 | 1647 | break; |
1497 | 1648 | |
1498 | 1649 | case RXO_mvtachi: |
1499 | - put_reg (acchi, GS ()); | |
1650 | + get_acc (opcode->op[0].reg - 32, &acc); | |
1651 | + acc.lo &= ((1ULL << 32) - 1); | |
1652 | + acc.lo |= (unsigned long long) GS () << 32ULL; | |
1653 | + put_acc (opcode->op[0].reg - 32, &acc); | |
1500 | 1654 | E1; |
1501 | 1655 | break; |
1502 | 1656 | |
1503 | 1657 | case RXO_mvtaclo: |
1504 | - put_reg (acclo, GS ()); | |
1658 | + get_acc (opcode->op[0].reg - 32, &acc); | |
1659 | + acc.lo &= ~((1ULL << 32ULL) - 1); | |
1660 | + acc.lo |= (unsigned long) GS (); | |
1661 | + put_acc (opcode->op[0].reg - 32, &acc); | |
1662 | + E1; | |
1663 | + break; | |
1664 | + | |
1665 | + case RXO_mvtacgu: | |
1666 | + get_acc (opcode->op[0].reg - 32, &acc); | |
1667 | + acc.hi = GS (); | |
1668 | + put_acc (opcode->op[0].reg - 32, &acc); | |
1505 | 1669 | E1; |
1506 | 1670 | break; |
1507 | 1671 |
@@ -1560,22 +1724,22 @@ decode_opcode () | ||
1560 | 1724 | break; |
1561 | 1725 | |
1562 | 1726 | case RXO_racw: |
1563 | - ll = get_reg64 (acc64) << GS (); | |
1564 | - ll += 0x80000000ULL; | |
1565 | - if ((signed long long)ll > (signed long long)0x00007fff00000000ULL) | |
1566 | - ll = 0x00007fff00000000ULL; | |
1567 | - else if ((signed long long)ll < (signed long long)0xffff800000000000ULL) | |
1568 | - ll = 0xffff800000000000ULL; | |
1569 | - else | |
1570 | - ll &= 0xffffffff00000000ULL; | |
1571 | - put_reg64 (acc64, ll); | |
1572 | - E1; | |
1573 | - break; | |
1727 | + RAC(0x80000000ULL, 0x00007fff00000000ULL, 0xffff800000000000ULL) | |
1728 | + | |
1729 | + case RXO_rdacw: | |
1730 | + RAC(0, 0x00007fff00000000ULL, 0xffffffff80000000ULL) | |
1731 | + | |
1732 | + case RXO_racl: | |
1733 | + RAC(0x80000000ULL, 0x7fffffff00000000ULL, 0xffffffff80000000ULL) | |
1734 | + | |
1735 | + case RXO_rdacl: | |
1736 | + RAC(0, 0x7fffffff00000000ULL, 0xffff800000000000ULL) | |
1574 | 1737 | |
1575 | 1738 | case RXO_rte: |
1576 | 1739 | PRIVILEDGED (); |
1577 | 1740 | regs.r_pc = poppc (); |
1578 | 1741 | regs.r_psw = poppc (); |
1742 | + regs.r_li = 0; | |
1579 | 1743 | if (FLAG_PM) |
1580 | 1744 | regs.r_psw |= FLAGBIT_U; |
1581 | 1745 | #ifdef CYCLE_ACCURATE |
@@ -2130,6 +2294,21 @@ decode_opcode () | ||
2130 | 2294 | set_zc (0, ((int)uma - (int)umb) >= 0); |
2131 | 2295 | break; |
2132 | 2296 | |
2297 | + case RXO_utof: | |
2298 | + ma = GS (); | |
2299 | + FPCLEAR (); | |
2300 | + mb = rxfp_utof (ma, regs.r_fpsw); | |
2301 | + FPCHECK (); | |
2302 | + tprintf("(float) %d = %x\n", ma, mb); | |
2303 | + PD (mb); | |
2304 | + if (mb) | |
2305 | + set_flags (FLAGBIT_Z, 0); | |
2306 | + else | |
2307 | + set_flags (FLAGBIT_Z, FLAGBIT_Z); | |
2308 | + set_flags (FLAGBIT_S, 0); | |
2309 | + E (2); | |
2310 | + break; | |
2311 | + | |
2133 | 2312 | case RXO_wait: |
2134 | 2313 | PRIVILEDGED (); |
2135 | 2314 | regs.r_psw |= FLAGBIT_I; |