1 /* This file is part of SIS (SPARC instruction simulator)
3 Copyright (C) 1995-2019 Free Software Foundation, Inc.
4 Contributed by Jiri Gaisler, European Space Agency
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 extern int32 sis_verbose
, sparclite
;
27 /* Load/store interlock delay */
30 /* Load delay (delete if unwanted - speeds up simulation) */
41 #define FSR_QNE 0x2000
73 #define PSR_N 0x0800000
74 #define PSR_Z 0x0400000
75 #define PSR_V 0x0200000
76 #define PSR_C 0x0100000
77 #define PSR_CC 0x0F00000
79 #define PSR_PIL 0x0f00
81 #define ICC_N (icc >> 3)
82 #define ICC_Z (icc >> 2)
83 #define ICC_V (icc >> 1)
86 #define FP_PRES (sregs->fpu_pres)
98 #define TRAP_DIV0 0x2a
100 #define FSR_TT 0x1C000
101 #define FP_IEEE 0x04000
102 #define FP_UNIMP 0x0C000
103 #define FP_SEQ_ERR 0x10000
122 #define INST_SIMM13 0x1fff
123 #define INST_RS2 0x1f
124 #define INST_I 0x2000
131 #define TADDCCTV 0x22
132 #define TSUBCCTV 0x23
212 #define SIGN_BIT 0x80000000
214 /* # of cycles overhead when a trap is taken */
217 /* Forward declarations */
219 static uint32
sub_cc (uint32 psr
, int32 operand1
, int32 operand2
,
221 static uint32
add_cc (uint32 psr
, int32 operand1
, int32 operand2
,
223 static void log_cc (int32 result
, struct pstate
*sregs
);
224 static int fpexec (uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
,
225 struct pstate
*sregs
);
226 static int chk_asi (struct pstate
*sregs
, uint32
*asi
, uint32 op3
);
229 extern struct estate ebase
;
230 extern int32 nfp
,ift
;
233 extern uint32 errtt
, errftt
;
237 sub_cc(psr
, operand1
, operand2
, result
)
243 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
248 psr
= (psr
& ~PSR_V
) | ((((operand1
& ~operand2
& ~result
) |
249 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
250 psr
= (psr
& ~PSR_C
) | ((((~operand1
& operand2
) |
251 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
256 add_cc(psr
, operand1
, operand2
, result
)
262 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
267 psr
= (psr
& ~PSR_V
) | ((((operand1
& operand2
& ~result
) |
268 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
269 psr
= (psr
& ~PSR_C
) | ((((operand1
& operand2
) |
270 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
275 log_cc(result
, sregs
)
277 struct pstate
*sregs
;
279 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
280 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
285 /* Add two unsigned 32-bit integers, and calculate the carry out. */
288 add32 (uint32 n1
, uint32 n2
, int *carry
)
290 uint32 result
= n1
+ n2
;
292 *carry
= result
< n1
|| result
< n2
;
296 /* Multiply two 32-bit integers. */
299 mul64 (uint32 n1
, uint32 n2
, uint32
*result_hi
, uint32
*result_lo
, int msigned
)
301 uint32 lo
, mid1
, mid2
, hi
, reg_lo
, reg_hi
;
305 /* If this is a signed multiply, calculate the sign of the result
306 and make the operands positive. */
309 sign
= (n1
^ n2
) & SIGN_BIT
;
317 /* We can split the 32x32 into four 16x16 operations. This ensures
318 that we do not lose precision on 32bit only hosts: */
319 lo
= ((n1
& 0xFFFF) * (n2
& 0xFFFF));
320 mid1
= ((n1
& 0xFFFF) * ((n2
>> 16) & 0xFFFF));
321 mid2
= (((n1
>> 16) & 0xFFFF) * (n2
& 0xFFFF));
322 hi
= (((n1
>> 16) & 0xFFFF) * ((n2
>> 16) & 0xFFFF));
324 /* We now need to add all of these results together, taking care
325 to propogate the carries from the additions: */
326 reg_lo
= add32 (lo
, (mid1
<< 16), &carry
);
328 reg_lo
= add32 (reg_lo
, (mid2
<< 16), &carry
);
329 reg_hi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
331 /* Negate result if necessary. */
345 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
346 that the host compiler supports long long operations. */
349 div64 (uint32 n1_hi
, uint32 n1_low
, uint32 n2
, uint32
*result
, int msigned
)
353 n1
= ((uint64
) n1_hi
) << 32;
354 n1
|= ((uint64
) n1_low
) & 0xffffffff;
358 int64 n1_s
= (int64
) n1
;
359 int32 n2_s
= (int32
) n2
;
366 *result
= (uint32
) (n1
& 0xffffffff);
371 extract_short (uint32 data
, uint32 address
)
373 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
377 extract_short_signed (uint32 data
, uint32 address
)
379 uint32 tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
386 extract_byte (uint32 data
, uint32 address
)
388 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
392 extract_byte_signed (uint32 data
, uint32 address
)
394 uint32 tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
401 dispatch_instruction(sregs
)
402 struct pstate
*sregs
;
405 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
408 int32 operand1
, operand2
, *rdd
, result
, eicc
,
410 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
414 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
415 op
= sregs
->inst
>> 30;
417 npc
= sregs
->npc
+ 4;
418 op3
= rd
= rs1
= operand2
= eicc
= 0;
422 op3
= (sregs
->inst
>> 19) & 0x3f;
423 rs1
= (sregs
->inst
>> 14) & 0x1f;
424 rd
= (sregs
->inst
>> 25) & 0x1f;
428 /* Check if load dependecy is possible */
429 if (ebase
.simtime
<= sregs
->ildtime
)
430 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
433 if (sregs
->inst
& INST_I
) {
434 if (ldep
&& (sregs
->ildreg
== rs1
))
436 operand2
= sregs
->inst
;
437 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
439 rs2
= sregs
->inst
& INST_RS2
;
441 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
443 operand2
= sregs
->g
[rs2
];
444 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
448 if (sregs
->inst
& INST_I
) {
449 operand2
= sregs
->inst
;
450 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
452 rs2
= sregs
->inst
& INST_RS2
;
454 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
456 operand2
= sregs
->g
[rs2
];
461 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
463 rdd
= &(sregs
->g
[rd
]);
465 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
471 op2
= (sregs
->inst
>> 22) & 0x7;
474 rd
= (sregs
->inst
>> 25) & 0x1f;
476 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
478 rdd
= &(sregs
->g
[rd
]);
479 *rdd
= sregs
->inst
<< 10;
485 icc
= sregs
->psr
>> 20;
486 cond
= ((sregs
->inst
>> 25) & 0x0f);
495 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
498 eicc
= (ICC_N
^ ICC_V
);
501 eicc
= ICC_C
| ICC_Z
;
514 if (sregs
->inst
& 0x20000000)
521 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
524 eicc
= ~(ICC_N
^ ICC_V
);
527 eicc
= ~(ICC_C
| ICC_Z
);
540 operand1
= sregs
->inst
;
541 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
542 npc
= sregs
->pc
+ operand1
;
544 if (sregs
->inst
& 0x20000000)
552 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
553 sregs
->trap
= TRAP_FPDIS
;
556 if (ebase
.simtime
< sregs
->ftime
) {
557 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
559 cond
= ((sregs
->inst
>> 25) & 0x0f);
560 fcc
= (sregs
->fsr
>> 10) & 0x3;
566 eicc
= (fcc
!= FCC_E
);
569 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
572 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
575 eicc
= (fcc
== FCC_L
);
578 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
581 eicc
= (fcc
== FCC_G
);
584 eicc
= (fcc
== FCC_U
);
588 if (sregs
->inst
& 0x20000000)
592 eicc
= !(fcc
!= FCC_E
);
595 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
598 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
601 eicc
= !(fcc
== FCC_L
);
604 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
607 eicc
= !(fcc
== FCC_G
);
610 eicc
= !(fcc
== FCC_U
);
614 operand1
= sregs
->inst
;
615 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
616 npc
= sregs
->pc
+ operand1
;
618 if (sregs
->inst
& 0x20000000)
624 sregs
->trap
= TRAP_UNIMP
;
632 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
633 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
637 if ((op3
>> 1) == 0x1a) {
638 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
639 sregs
->trap
= TRAP_FPDIS
;
641 rs1
= (sregs
->inst
>> 14) & 0x1f;
642 rs2
= sregs
->inst
& 0x1f;
643 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
649 icc
= sregs
->psr
>> 20;
650 cond
= ((sregs
->inst
>> 25) & 0x0f);
659 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
662 eicc
= (ICC_N
^ ICC_V
);
665 eicc
= ICC_C
| ICC_Z
;
683 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
686 eicc
= ~(ICC_N
^ ICC_V
);
689 eicc
= ~(ICC_C
| ICC_Z
);
702 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
708 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
710 if ((sregs
->y
& 1) == 0)
712 *rdd
= operand1
+ operand2
;
713 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
714 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
719 uint32 result
, remainder
;
723 sregs
->trap
= TRAP_UNIMP
;
727 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
729 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
731 /* If true sign is positive, calculate remainder - divisor.
732 Otherwise, calculate remainder + divisor. */
734 operand2
= ~operand2
+ 1;
735 result
= remainder
+ operand2
;
737 /* The SPARClite User's Manual is not clear on how
738 the "carry out" of the above ALU operation is to
739 be calculated. From trial and error tests
740 on the the chip itself, it appears that it is
741 a normal addition carry, and not a subtraction borrow,
742 even in cases where the divisor is subtracted
743 from the remainder. FIXME: get the true story
745 c0
= result
< (uint32
) remainder
746 || result
< (uint32
) operand2
;
748 if (result
& 0x80000000)
751 sregs
->psr
&= ~PSR_N
;
753 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
755 if (result
== 0 && sign
== y31
)
758 sregs
->psr
&= ~PSR_Z
;
760 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
762 if (sign
^ (result
>> 31))
765 sregs
->psr
&= ~PSR_V
;
770 sregs
->psr
&= ~PSR_C
;
775 *rdd
= (rs1
<< 1) | !sign
;
780 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
787 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
789 if (result
& 0x80000000)
792 sregs
->psr
&= ~PSR_N
;
797 sregs
->psr
&= ~PSR_Z
;
804 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
811 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
813 if (result
& 0x80000000)
816 sregs
->psr
&= ~PSR_N
;
821 sregs
->psr
&= ~PSR_Z
;
829 sregs
->trap
= TRAP_UNIMP
;
834 sregs
->trap
= TRAP_DIV0
;
838 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
846 sregs
->trap
= TRAP_UNIMP
;
851 sregs
->trap
= TRAP_DIV0
;
855 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
857 if (result
& 0x80000000)
860 sregs
->psr
&= ~PSR_N
;
865 sregs
->psr
&= ~PSR_Z
;
867 /* FIXME: should set overflow flag correctly. */
868 sregs
->psr
&= ~(PSR_C
| PSR_V
);
876 sregs
->trap
= TRAP_UNIMP
;
881 sregs
->trap
= TRAP_DIV0
;
885 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
893 sregs
->trap
= TRAP_UNIMP
;
898 sregs
->trap
= TRAP_DIV0
;
902 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
904 if (result
& 0x80000000)
907 sregs
->psr
&= ~PSR_N
;
912 sregs
->psr
&= ~PSR_Z
;
914 /* FIXME: should set overflow flag correctly. */
915 sregs
->psr
&= ~(PSR_C
| PSR_V
);
921 *rdd
= rs1
^ ~operand2
;
924 *rdd
= rs1
^ ~operand2
;
928 *rdd
= rs1
^ operand2
;
931 *rdd
= rs1
^ operand2
;
935 *rdd
= rs1
| operand2
;
938 *rdd
= rs1
| operand2
;
942 *rdd
= rs1
| ~operand2
;
945 *rdd
= rs1
| ~operand2
;
949 *rdd
= rs1
& ~operand2
;
953 *rdd
= rs1
& ~operand2
;
956 *rdd
= rs1
& operand2
;
959 *rdd
= rs1
& operand2
;
963 *rdd
= rs1
- operand2
;
966 *rdd
= rs1
- operand2
;
967 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
970 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
973 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
974 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
977 *rdd
= rs1
+ operand2
;
980 *rdd
= rs1
+ operand2
;
981 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
984 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
987 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
988 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
991 *rdd
= rs1
+ operand2
;
992 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
993 if ((rs1
| operand2
) & 0x3)
997 *rdd
= rs1
- operand2
;
998 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
999 if ((rs1
| operand2
) & 0x3)
1000 sregs
->psr
|= PSR_V
;
1003 *rdd
= rs1
+ operand2
;
1004 result
= add_cc(0, rs1
, operand2
, *rdd
);
1005 if ((rs1
| operand2
) & 0x3)
1007 if (result
& PSR_V
) {
1008 sregs
->trap
= TRAP_TAG
;
1010 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1014 *rdd
= rs1
- operand2
;
1015 result
= add_cc (0, rs1
, operand2
, *rdd
);
1016 if ((rs1
| operand2
) & 0x3)
1020 sregs
->trap
= TRAP_TAG
;
1024 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1028 *rdd
= rs1
<< (operand2
& 0x1f);
1031 *rdd
= rs1
>> (operand2
& 0x1f);
1034 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1037 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1040 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1041 if (sregs
->wim
& (1 << new_cwp
)) {
1042 sregs
->trap
= TRAP_WOFL
;
1046 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1047 *rdd
= rs1
+ operand2
;
1048 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1052 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1053 if (sregs
->wim
& (1 << new_cwp
)) {
1054 sregs
->trap
= TRAP_WUFL
;
1058 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1059 *rdd
= rs1
+ operand2
;
1060 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1063 if (!(sregs
->psr
& PSR_S
)) {
1064 sregs
->trap
= TRAP_PRIVI
;
1073 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1074 if ( 0 == rs1_is_asr
)
1076 else if ( 17 == rs1_is_asr
)
1077 *rdd
= sregs
->asr17
;
1079 sregs
->trap
= TRAP_UNIMP
;
1085 if (!(sregs
->psr
& PSR_S
)) {
1086 sregs
->trap
= TRAP_PRIVI
;
1092 if (!(sregs
->psr
& PSR_S
)) {
1093 sregs
->trap
= TRAP_PRIVI
;
1099 if ((sregs
->psr
& 0x1f) > 7) {
1100 sregs
->trap
= TRAP_UNIMP
;
1103 if (!(sregs
->psr
& PSR_S
)) {
1104 sregs
->trap
= TRAP_PRIVI
;
1107 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1108 (rs1
^ operand2
) & 0x00f03fff;
1111 if (!(sregs
->psr
& PSR_S
)) {
1112 sregs
->trap
= TRAP_PRIVI
;
1115 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1118 if (!(sregs
->psr
& PSR_S
)) {
1119 sregs
->trap
= TRAP_PRIVI
;
1122 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1123 ((rs1
^ operand2
) & 0xfffff000);
1127 sregs
->y
= (rs1
^ operand2
);
1130 sregs
->y
= (rs1
^ operand2
);
1131 else if ( 17 == rd
)
1132 sregs
->asr17
= (rs1
^ operand2
);
1134 sregs
->trap
= TRAP_UNIMP
;
1144 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1146 sregs
->trap
= TRAP_UNALI
;
1150 npc
= rs1
+ operand2
;
1153 address
= rs1
+ operand2
;
1154 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1155 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1156 if (sregs
->psr
& PSR_ET
) {
1157 sregs
->trap
= TRAP_UNIMP
;
1160 if (!(sregs
->psr
& PSR_S
)) {
1161 sregs
->trap
= TRAP_PRIVI
;
1164 if (sregs
->wim
& (1 << new_cwp
)) {
1165 sregs
->trap
= TRAP_WUFL
;
1168 if (address
& 0x3) {
1169 sregs
->trap
= TRAP_UNALI
;
1172 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1174 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1180 uint32 result
, mask
;
1184 sregs
->trap
= TRAP_UNIMP
;
1187 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1188 result
= rs1
^ mask
;
1190 for (i
= 0; i
< 32; i
++) {
1191 if (result
& 0x80000000)
1196 *rdd
= i
== 32 ? 63 : i
;
1201 sregs
->trap
= TRAP_UNIMP
;
1206 case 3: /* Load/store instructions */
1208 address
= rs1
+ operand2
;
1210 if (sregs
->psr
& PSR_S
)
1216 sregs
->icnt
= T_ST
; /* Set store instruction count */
1221 sregs
->icnt
= T_LD
; /* Set load instruction count */
1227 /* Decode load/store instructions */
1231 if (!chk_asi(sregs
, &asi
, op3
)) break;
1233 if (address
& 0x7) {
1234 sregs
->trap
= TRAP_UNALI
;
1240 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1242 rdd
= &(sregs
->g
[rd
]);
1244 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1246 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1248 sregs
->icnt
= T_LDD
;
1250 sregs
->trap
= TRAP_DEXC
;
1255 sregs
->nload
++; /* Double load counts twice */
1261 if (!chk_asi(sregs
, &asi
, op3
)) break;
1263 if (address
& 0x3) {
1264 sregs
->trap
= TRAP_UNALI
;
1267 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1270 sregs
->trap
= TRAP_DEXC
;
1276 if (!chk_asi(sregs
, &asi
, op3
)) break;
1278 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1280 sregs
->icnt
= T_LDST
;
1282 sregs
->trap
= TRAP_DEXC
;
1285 data
= extract_byte (data
, address
);
1288 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1291 sregs
->trap
= TRAP_DEXC
;
1299 if (!chk_asi(sregs
, &asi
, op3
)) break;
1302 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1305 sregs
->trap
= TRAP_DEXC
;
1309 data
= extract_byte_signed (data
, address
);
1311 data
= extract_byte (data
, address
);
1316 if (!chk_asi(sregs
, &asi
, op3
)) break;
1319 if (address
& 0x1) {
1320 sregs
->trap
= TRAP_UNALI
;
1323 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1326 sregs
->trap
= TRAP_DEXC
;
1330 data
= extract_short_signed (data
, address
);
1332 data
= extract_short (data
, address
);
1336 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1337 sregs
->trap
= TRAP_FPDIS
;
1340 if (address
& 0x3) {
1341 sregs
->trap
= TRAP_UNALI
;
1344 if (ebase
.simtime
< sregs
->ftime
) {
1345 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1346 (sregs
->frs2
== rd
))
1347 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1349 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1352 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1353 sregs
->hold
+ sregs
->fhold
;
1355 sregs
->trap
= TRAP_DEXC
;
1357 sregs
->fs
[rd
] = *((float32
*) & data
);
1361 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1362 sregs
->trap
= TRAP_FPDIS
;
1365 if (address
& 0x7) {
1366 sregs
->trap
= TRAP_UNALI
;
1369 if (ebase
.simtime
< sregs
->ftime
) {
1370 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1371 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1372 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1373 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1375 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1377 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1379 sregs
->icnt
= T_LDD
;
1381 sregs
->trap
= TRAP_DEXC
;
1385 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1387 sregs
->nload
++; /* Double load counts twice */
1389 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1390 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1391 sregs
->hold
+ sregs
->fhold
;
1395 if (ebase
.simtime
< sregs
->ftime
) {
1396 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1398 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1399 sregs
->trap
= TRAP_FPDIS
;
1402 if (address
& 0x3) {
1403 sregs
->trap
= TRAP_UNALI
;
1406 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1409 sregs
->trap
= TRAP_DEXC
;
1412 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1413 set_fsr(sregs
->fsr
);
1417 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1418 sregs
->trap
= TRAP_FPDIS
;
1421 if (address
& 0x3) {
1422 sregs
->trap
= TRAP_UNALI
;
1425 if (ebase
.simtime
< sregs
->ftime
) {
1426 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1428 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1431 sregs
->trap
= TRAP_DEXC
;
1436 if (!chk_asi(sregs
, &asi
, op3
)) break;
1438 if (address
& 0x3) {
1439 sregs
->trap
= TRAP_UNALI
;
1442 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1445 sregs
->trap
= TRAP_DEXC
;
1449 if (!chk_asi(sregs
, &asi
, op3
)) break;
1451 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1454 sregs
->trap
= TRAP_DEXC
;
1458 if (!chk_asi(sregs
, &asi
, op3
)) break;
1460 if (address
& 0x7) {
1461 sregs
->trap
= TRAP_UNALI
;
1467 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1469 rdd
= &(sregs
->g
[rd
]);
1471 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1473 sregs
->icnt
= T_STD
;
1475 sregs
->nstore
++; /* Double store counts twice */
1478 sregs
->trap
= TRAP_DEXC
;
1483 if ((sregs
->psr
& 0x1f) > 7) {
1484 sregs
->trap
= TRAP_UNIMP
;
1487 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1488 sregs
->trap
= TRAP_FPDIS
;
1491 if (address
& 0x7) {
1492 sregs
->trap
= TRAP_UNALI
;
1495 if (!(sregs
->fsr
& FSR_QNE
)) {
1496 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1499 rdd
= &(sregs
->fpq
[0]);
1500 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1502 sregs
->icnt
= T_STD
;
1504 sregs
->nstore
++; /* Double store counts twice */
1507 sregs
->trap
= TRAP_DEXC
;
1510 sregs
->fsr
&= ~FSR_QNE
;
1511 sregs
->fpstate
= FP_EXE_MODE
;
1515 if (!chk_asi(sregs
, &asi
, op3
)) break;
1517 if (address
& 0x1) {
1518 sregs
->trap
= TRAP_UNALI
;
1521 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1524 sregs
->trap
= TRAP_DEXC
;
1528 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1529 sregs
->trap
= TRAP_FPDIS
;
1532 if (address
& 0x3) {
1533 sregs
->trap
= TRAP_UNALI
;
1536 if (ebase
.simtime
< sregs
->ftime
) {
1537 if (sregs
->frd
== rd
)
1538 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1540 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1543 sregs
->trap
= TRAP_DEXC
;
1547 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1548 sregs
->trap
= TRAP_FPDIS
;
1551 if (address
& 0x7) {
1552 sregs
->trap
= TRAP_UNALI
;
1556 if (ebase
.simtime
< sregs
->ftime
) {
1557 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1558 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1560 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1562 sregs
->icnt
= T_STD
;
1564 sregs
->nstore
++; /* Double store counts twice */
1567 sregs
->trap
= TRAP_DEXC
;
1571 if (!chk_asi(sregs
, &asi
, op3
)) break;
1573 if (address
& 0x3) {
1574 sregs
->trap
= TRAP_UNALI
;
1577 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1580 sregs
->trap
= TRAP_DEXC
;
1583 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1585 sregs
->icnt
= T_LDST
;
1587 sregs
->trap
= TRAP_DEXC
;
1598 sregs
->trap
= TRAP_UNIMP
;
1605 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1607 if ((op3
| 0x10) == 0x13)
1608 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1615 sregs
->trap
= TRAP_UNIMP
;
1674 fpexec(op3
, rd
, rs1
, rs2
, sregs
)
1675 uint32 op3
, rd
, rs1
, rs2
;
1676 struct pstate
*sregs
;
1678 uint32 opf
, tem
, accex
;
1682 if (sregs
->fpstate
== FP_EXC_MODE
) {
1683 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1684 sregs
->fpstate
= FP_EXC_PE
;
1687 if (sregs
->fpstate
== FP_EXC_PE
) {
1688 sregs
->fpstate
= FP_EXC_MODE
;
1691 opf
= (sregs
->inst
>> 5) & 0x1ff;
1694 * Check if we already have an FPop in the pipe. If so, halt until it is
1695 * finished by incrementing fhold with the remaining execution time
1698 if (ebase
.simtime
< sregs
->ftime
) {
1699 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1703 /* Check load dependencies. */
1705 if (ebase
.simtime
< sregs
->ltime
) {
1707 /* Don't check rs1 if single operand instructions */
1709 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1712 /* Adjust for double floats */
1715 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1722 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1726 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1728 /* SPARC is big-endian - swap double floats if host is little-endian */
1729 /* This is ugly - I know ... */
1731 /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1732 but what about machines where float values are different endianness
1733 from integer values? */
1735 #ifdef HOST_LITTLE_ENDIAN
1747 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1748 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1749 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1750 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1760 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1761 sregs
->ftime
+= T_FABSs
;
1762 sregs
->frs1
= 32; /* rs1 ignored */
1765 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1766 sregs
->ftime
+= T_FADDs
;
1769 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1770 sregs
->ftime
+= T_FADDd
;
1774 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1776 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1778 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1782 sregs
->fsr
|= 0x0C00;
1783 sregs
->fsr
&= ~(fcc
<< 10);
1784 sregs
->ftime
+= T_FCMPs
;
1785 sregs
->frd
= 32; /* rd ignored */
1786 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1787 sregs
->fpstate
= FP_EXC_PE
;
1788 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1793 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1795 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1797 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1801 sregs
->fsr
|= 0x0C00;
1802 sregs
->fsr
&= ~(fcc
<< 10);
1803 sregs
->ftime
+= T_FCMPd
;
1804 sregs
->frd
= 32; /* rd ignored */
1805 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1806 sregs
->fpstate
= FP_EXC_PE
;
1807 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1811 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1812 sregs
->ftime
+= T_FDIVs
;
1815 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1816 sregs
->ftime
+= T_FDIVd
;
1819 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1820 sregs
->ftime
+= T_FMOVs
;
1821 sregs
->frs1
= 32; /* rs1 ignored */
1824 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1825 sregs
->ftime
+= T_FMULs
;
1828 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1829 sregs
->ftime
+= T_FMULd
;
1832 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1833 sregs
->ftime
+= T_FNEGs
;
1834 sregs
->frs1
= 32; /* rs1 ignored */
1837 if (sregs
->fs
[rs2
] < 0.0) {
1838 sregs
->fpstate
= FP_EXC_PE
;
1839 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1840 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1843 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1844 sregs
->ftime
+= T_FSQRTs
;
1845 sregs
->frs1
= 32; /* rs1 ignored */
1848 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1849 sregs
->fpstate
= FP_EXC_PE
;
1850 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1851 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1854 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1855 sregs
->ftime
+= T_FSQRTd
;
1856 sregs
->frs1
= 32; /* rs1 ignored */
1859 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1860 sregs
->ftime
+= T_FSUBs
;
1863 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1864 sregs
->ftime
+= T_FSUBd
;
1867 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1868 sregs
->ftime
+= T_FdTOi
;
1869 sregs
->frs1
= 32; /* rs1 ignored */
1872 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1873 sregs
->ftime
+= T_FdTOs
;
1874 sregs
->frs1
= 32; /* rs1 ignored */
1877 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1878 sregs
->ftime
+= T_FiTOs
;
1879 sregs
->frs1
= 32; /* rs1 ignored */
1882 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1883 sregs
->ftime
+= T_FiTOd
;
1884 sregs
->frs1
= 32; /* rs1 ignored */
1887 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1888 sregs
->ftime
+= T_FsTOi
;
1889 sregs
->frs1
= 32; /* rs1 ignored */
1892 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1893 sregs
->ftime
+= T_FsTOd
;
1894 sregs
->frs1
= 32; /* rs1 ignored */
1898 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1899 sregs
->fpstate
= FP_EXC_PE
;
1904 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1905 sregs
->fpstate
= FP_EXC_PE
;
1906 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1911 accex
= get_accex();
1913 #ifdef HOST_LITTLE_ENDIAN
1922 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1923 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1928 if (sregs
->fpstate
== FP_EXC_PE
) {
1929 sregs
->fpq
[0] = sregs
->pc
;
1930 sregs
->fpq
[1] = sregs
->inst
;
1931 sregs
->fsr
|= FSR_QNE
;
1933 tem
= (sregs
->fsr
>> 23) & 0x1f;
1935 sregs
->fpstate
= FP_EXC_PE
;
1936 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1937 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1939 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1941 if (sregs
->fpstate
== FP_EXC_PE
) {
1942 sregs
->fpq
[0] = sregs
->pc
;
1943 sregs
->fpq
[1] = sregs
->inst
;
1944 sregs
->fsr
|= FSR_QNE
;
1955 chk_asi(sregs
, asi
, op3
)
1956 struct pstate
*sregs
;
1960 if (!(sregs
->psr
& PSR_S
)) {
1961 sregs
->trap
= TRAP_PRIVI
;
1963 } else if (sregs
->inst
& INST_I
) {
1964 sregs
->trap
= TRAP_UNIMP
;
1967 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1973 struct pstate
*sregs
;
1977 if (sregs
->trap
== 256) {
1981 } else if (sregs
->trap
== 257) {
1985 if ((sregs
->psr
& PSR_ET
) == 0)
1988 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1990 sregs
->psr
&= ~PSR_ET
;
1991 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1993 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1994 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1995 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1996 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1997 sregs
->psr
|= PSR_S
;
1998 sregs
->pc
= sregs
->tbr
;
1999 sregs
->npc
= sregs
->tbr
+ 4;
2001 if ( 0 != (1 & sregs
->asr17
) ) {
2002 /* single vector trapping! */
2003 sregs
->pc
= sregs
->tbr
& 0xfffff000;
2004 sregs
->npc
= sregs
->pc
+ 4;
2007 /* Increase simulator time */
2008 sregs
->icnt
= TRAP_C
;
2017 extern struct irqcell irqarr
[16];
2020 check_interrupts(sregs
)
2021 struct pstate
*sregs
;
2025 sregs
->trap
= errtt
;
2026 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2031 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2032 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2033 if (sregs
->trap
== 0) {
2034 sregs
->trap
= 16 + ext_irl
;
2035 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2044 struct pstate
*sregs
;
2049 sregs
->psr
&= 0x00f03fdf;
2050 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2051 sregs
->breakpoint
= 0;
2053 sregs
->fpstate
= FP_EXE_MODE
;
2057 sregs
->err_mode
= 0;
2060 #ifdef HOST_LITTLE_ENDIAN
2061 sregs
->fdp
= (float32
*) sregs
->fd
;
2062 sregs
->fsi
= (int32
*) sregs
->fs
;
2064 sregs
->fs
= (float32
*) sregs
->fd
;
2065 sregs
->fsi
= (int32
*) sregs
->fd
;
2068 sregs
->fpu_pres
= !nfp
;
2069 set_fsr(sregs
->fsr
);
2077 sregs
->rett_err
= 0;
2078 sregs
->jmpltime
= 0;