d8a8c6c662b9fb075eaa019bfa411b83a1f1a0cc
1 /* This file is part of SIS (SPARC instruction simulator)
3 Copyright (C) 1995-2021 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/>. */
19 /* This must come before any other includes. */
26 extern int32 sis_verbose
, sparclite
;
29 /* Load/store interlock delay */
32 /* Load delay (delete if unwanted - speeds up simulation) */
43 #define FSR_QNE 0x2000
75 #define PSR_N 0x0800000
76 #define PSR_Z 0x0400000
77 #define PSR_V 0x0200000
78 #define PSR_C 0x0100000
79 #define PSR_CC 0x0F00000
81 #define PSR_PIL 0x0f00
83 #define ICC_N (icc >> 3)
84 #define ICC_Z (icc >> 2)
85 #define ICC_V (icc >> 1)
88 #define FP_PRES (sregs->fpu_pres)
100 #define TRAP_DIV0 0x2a
102 #define FSR_TT 0x1C000
103 #define FP_IEEE 0x04000
104 #define FP_UNIMP 0x0C000
105 #define FP_SEQ_ERR 0x10000
124 #define INST_SIMM13 0x1fff
125 #define INST_RS2 0x1f
126 #define INST_I 0x2000
133 #define TADDCCTV 0x22
134 #define TSUBCCTV 0x23
214 #define SIGN_BIT 0x80000000
216 /* # of cycles overhead when a trap is taken */
219 /* Forward declarations */
221 static uint32
sub_cc (uint32 psr
, int32 operand1
, int32 operand2
,
223 static uint32
add_cc (uint32 psr
, int32 operand1
, int32 operand2
,
225 static void log_cc (int32 result
, struct pstate
*sregs
);
226 static int fpexec (uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
,
227 struct pstate
*sregs
);
228 static int chk_asi (struct pstate
*sregs
, uint32
*asi
, uint32 op3
);
231 extern struct estate ebase
;
232 extern int32 nfp
,ift
;
235 extern uint32 errtt
, errftt
;
239 sub_cc(uint32 psr
, int32 operand1
, int32 operand2
, int32 result
)
241 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
246 psr
= (psr
& ~PSR_V
) | ((((operand1
& ~operand2
& ~result
) |
247 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
248 psr
= (psr
& ~PSR_C
) | ((((~operand1
& operand2
) |
249 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
254 add_cc(uint32 psr
, int32 operand1
, int32 operand2
, int32 result
)
256 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
261 psr
= (psr
& ~PSR_V
) | ((((operand1
& operand2
& ~result
) |
262 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
263 psr
= (psr
& ~PSR_C
) | ((((operand1
& operand2
) |
264 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
269 log_cc(int32 result
, struct pstate
*sregs
)
271 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
272 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
277 /* Add two unsigned 32-bit integers, and calculate the carry out. */
280 add32 (uint32 n1
, uint32 n2
, int *carry
)
282 uint32 result
= n1
+ n2
;
284 *carry
= result
< n1
|| result
< n2
;
288 /* Multiply two 32-bit integers. */
291 mul64 (uint32 n1
, uint32 n2
, uint32
*result_hi
, uint32
*result_lo
, int msigned
)
293 uint32 lo
, mid1
, mid2
, hi
, reg_lo
, reg_hi
;
297 /* If this is a signed multiply, calculate the sign of the result
298 and make the operands positive. */
301 sign
= (n1
^ n2
) & SIGN_BIT
;
309 /* We can split the 32x32 into four 16x16 operations. This ensures
310 that we do not lose precision on 32bit only hosts: */
311 lo
= ((n1
& 0xFFFF) * (n2
& 0xFFFF));
312 mid1
= ((n1
& 0xFFFF) * ((n2
>> 16) & 0xFFFF));
313 mid2
= (((n1
>> 16) & 0xFFFF) * (n2
& 0xFFFF));
314 hi
= (((n1
>> 16) & 0xFFFF) * ((n2
>> 16) & 0xFFFF));
316 /* We now need to add all of these results together, taking care
317 to propogate the carries from the additions: */
318 reg_lo
= add32 (lo
, (mid1
<< 16), &carry
);
320 reg_lo
= add32 (reg_lo
, (mid2
<< 16), &carry
);
321 reg_hi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
323 /* Negate result if necessary. */
337 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
338 that the host compiler supports long long operations. */
341 div64 (uint32 n1_hi
, uint32 n1_low
, uint32 n2
, uint32
*result
, int msigned
)
345 n1
= ((uint64
) n1_hi
) << 32;
346 n1
|= ((uint64
) n1_low
) & 0xffffffff;
350 int64 n1_s
= (int64
) n1
;
351 int32 n2_s
= (int32
) n2
;
358 *result
= (uint32
) (n1
& 0xffffffff);
363 extract_short (uint32 data
, uint32 address
)
365 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
369 extract_short_signed (uint32 data
, uint32 address
)
371 uint32 tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
378 extract_byte (uint32 data
, uint32 address
)
380 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
384 extract_byte_signed (uint32 data
, uint32 address
)
386 uint32 tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
393 dispatch_instruction(struct pstate
*sregs
)
396 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
399 int32 operand1
, operand2
, *rdd
, result
, eicc
,
401 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
405 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
406 op
= sregs
->inst
>> 30;
408 npc
= sregs
->npc
+ 4;
409 op3
= rd
= rs1
= operand2
= eicc
= 0;
413 op3
= (sregs
->inst
>> 19) & 0x3f;
414 rs1
= (sregs
->inst
>> 14) & 0x1f;
415 rd
= (sregs
->inst
>> 25) & 0x1f;
419 /* Check if load dependecy is possible */
420 if (ebase
.simtime
<= sregs
->ildtime
)
421 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
424 if (sregs
->inst
& INST_I
) {
425 if (ldep
&& (sregs
->ildreg
== rs1
))
427 operand2
= sregs
->inst
;
428 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
430 rs2
= sregs
->inst
& INST_RS2
;
432 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
434 operand2
= sregs
->g
[rs2
];
435 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
439 if (sregs
->inst
& INST_I
) {
440 operand2
= sregs
->inst
;
441 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
443 rs2
= sregs
->inst
& INST_RS2
;
445 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
447 operand2
= sregs
->g
[rs2
];
452 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
454 rdd
= &(sregs
->g
[rd
]);
456 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
462 op2
= (sregs
->inst
>> 22) & 0x7;
465 rd
= (sregs
->inst
>> 25) & 0x1f;
467 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
469 rdd
= &(sregs
->g
[rd
]);
470 *rdd
= sregs
->inst
<< 10;
476 icc
= sregs
->psr
>> 20;
477 cond
= ((sregs
->inst
>> 25) & 0x0f);
486 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
489 eicc
= (ICC_N
^ ICC_V
);
492 eicc
= ICC_C
| ICC_Z
;
505 if (sregs
->inst
& 0x20000000)
512 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
515 eicc
= ~(ICC_N
^ ICC_V
);
518 eicc
= ~(ICC_C
| ICC_Z
);
531 operand1
= sregs
->inst
;
532 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
533 npc
= sregs
->pc
+ operand1
;
535 if (sregs
->inst
& 0x20000000)
543 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
544 sregs
->trap
= TRAP_FPDIS
;
547 if (ebase
.simtime
< sregs
->ftime
) {
548 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
550 cond
= ((sregs
->inst
>> 25) & 0x0f);
551 fcc
= (sregs
->fsr
>> 10) & 0x3;
557 eicc
= (fcc
!= FCC_E
);
560 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
563 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
566 eicc
= (fcc
== FCC_L
);
569 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
572 eicc
= (fcc
== FCC_G
);
575 eicc
= (fcc
== FCC_U
);
579 if (sregs
->inst
& 0x20000000)
583 eicc
= !(fcc
!= FCC_E
);
586 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
589 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
592 eicc
= !(fcc
== FCC_L
);
595 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
598 eicc
= !(fcc
== FCC_G
);
601 eicc
= !(fcc
== FCC_U
);
605 operand1
= sregs
->inst
;
606 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
607 npc
= sregs
->pc
+ operand1
;
609 if (sregs
->inst
& 0x20000000)
615 sregs
->trap
= TRAP_UNIMP
;
623 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
624 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
628 if ((op3
>> 1) == 0x1a) {
629 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
630 sregs
->trap
= TRAP_FPDIS
;
632 rs1
= (sregs
->inst
>> 14) & 0x1f;
633 rs2
= sregs
->inst
& 0x1f;
634 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
640 icc
= sregs
->psr
>> 20;
641 cond
= ((sregs
->inst
>> 25) & 0x0f);
650 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
653 eicc
= (ICC_N
^ ICC_V
);
656 eicc
= ICC_C
| ICC_Z
;
674 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
677 eicc
= ~(ICC_N
^ ICC_V
);
680 eicc
= ~(ICC_C
| ICC_Z
);
693 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
699 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
701 if ((sregs
->y
& 1) == 0)
703 *rdd
= operand1
+ operand2
;
704 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
705 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
710 uint32 result
, remainder
;
714 sregs
->trap
= TRAP_UNIMP
;
718 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
720 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
722 /* If true sign is positive, calculate remainder - divisor.
723 Otherwise, calculate remainder + divisor. */
725 operand2
= ~operand2
+ 1;
726 result
= remainder
+ operand2
;
728 /* The SPARClite User's Manual is not clear on how
729 the "carry out" of the above ALU operation is to
730 be calculated. From trial and error tests
731 on the the chip itself, it appears that it is
732 a normal addition carry, and not a subtraction borrow,
733 even in cases where the divisor is subtracted
734 from the remainder. FIXME: get the true story
736 c0
= result
< (uint32
) remainder
737 || result
< (uint32
) operand2
;
739 if (result
& 0x80000000)
742 sregs
->psr
&= ~PSR_N
;
744 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
746 if (result
== 0 && sign
== y31
)
749 sregs
->psr
&= ~PSR_Z
;
751 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
753 if (sign
^ (result
>> 31))
756 sregs
->psr
&= ~PSR_V
;
761 sregs
->psr
&= ~PSR_C
;
766 *rdd
= (rs1
<< 1) | !sign
;
771 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
778 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
780 if (result
& 0x80000000)
783 sregs
->psr
&= ~PSR_N
;
788 sregs
->psr
&= ~PSR_Z
;
795 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
802 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
804 if (result
& 0x80000000)
807 sregs
->psr
&= ~PSR_N
;
812 sregs
->psr
&= ~PSR_Z
;
820 sregs
->trap
= TRAP_UNIMP
;
825 sregs
->trap
= TRAP_DIV0
;
829 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
837 sregs
->trap
= TRAP_UNIMP
;
842 sregs
->trap
= TRAP_DIV0
;
846 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
848 if (result
& 0x80000000)
851 sregs
->psr
&= ~PSR_N
;
856 sregs
->psr
&= ~PSR_Z
;
858 /* FIXME: should set overflow flag correctly. */
859 sregs
->psr
&= ~(PSR_C
| PSR_V
);
867 sregs
->trap
= TRAP_UNIMP
;
872 sregs
->trap
= TRAP_DIV0
;
876 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
884 sregs
->trap
= TRAP_UNIMP
;
889 sregs
->trap
= TRAP_DIV0
;
893 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
895 if (result
& 0x80000000)
898 sregs
->psr
&= ~PSR_N
;
903 sregs
->psr
&= ~PSR_Z
;
905 /* FIXME: should set overflow flag correctly. */
906 sregs
->psr
&= ~(PSR_C
| PSR_V
);
912 *rdd
= rs1
^ ~operand2
;
915 *rdd
= rs1
^ ~operand2
;
919 *rdd
= rs1
^ operand2
;
922 *rdd
= rs1
^ operand2
;
926 *rdd
= rs1
| operand2
;
929 *rdd
= rs1
| operand2
;
933 *rdd
= rs1
| ~operand2
;
936 *rdd
= rs1
| ~operand2
;
940 *rdd
= rs1
& ~operand2
;
944 *rdd
= rs1
& ~operand2
;
947 *rdd
= rs1
& operand2
;
950 *rdd
= rs1
& operand2
;
954 *rdd
= rs1
- operand2
;
957 *rdd
= rs1
- operand2
;
958 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
961 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
964 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
965 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
968 *rdd
= rs1
+ operand2
;
971 *rdd
= rs1
+ operand2
;
972 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
975 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
978 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
979 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
982 *rdd
= rs1
+ operand2
;
983 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
984 if ((rs1
| operand2
) & 0x3)
988 *rdd
= rs1
- operand2
;
989 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
990 if ((rs1
| operand2
) & 0x3)
994 *rdd
= rs1
+ operand2
;
995 result
= add_cc(0, rs1
, operand2
, *rdd
);
996 if ((rs1
| operand2
) & 0x3)
998 if (result
& PSR_V
) {
999 sregs
->trap
= TRAP_TAG
;
1001 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1005 *rdd
= rs1
- operand2
;
1006 result
= add_cc (0, rs1
, operand2
, *rdd
);
1007 if ((rs1
| operand2
) & 0x3)
1011 sregs
->trap
= TRAP_TAG
;
1015 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1019 *rdd
= rs1
<< (operand2
& 0x1f);
1022 *rdd
= rs1
>> (operand2
& 0x1f);
1025 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1028 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1031 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1032 if (sregs
->wim
& (1 << new_cwp
)) {
1033 sregs
->trap
= TRAP_WOFL
;
1037 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1038 *rdd
= rs1
+ operand2
;
1039 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1043 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1044 if (sregs
->wim
& (1 << new_cwp
)) {
1045 sregs
->trap
= TRAP_WUFL
;
1049 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1050 *rdd
= rs1
+ operand2
;
1051 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1054 if (!(sregs
->psr
& PSR_S
)) {
1055 sregs
->trap
= TRAP_PRIVI
;
1064 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1065 if ( 0 == rs1_is_asr
)
1067 else if ( 17 == rs1_is_asr
)
1068 *rdd
= sregs
->asr17
;
1070 sregs
->trap
= TRAP_UNIMP
;
1076 if (!(sregs
->psr
& PSR_S
)) {
1077 sregs
->trap
= TRAP_PRIVI
;
1083 if (!(sregs
->psr
& PSR_S
)) {
1084 sregs
->trap
= TRAP_PRIVI
;
1090 if ((sregs
->psr
& 0x1f) > 7) {
1091 sregs
->trap
= TRAP_UNIMP
;
1094 if (!(sregs
->psr
& PSR_S
)) {
1095 sregs
->trap
= TRAP_PRIVI
;
1098 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1099 (rs1
^ operand2
) & 0x00f03fff;
1102 if (!(sregs
->psr
& PSR_S
)) {
1103 sregs
->trap
= TRAP_PRIVI
;
1106 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1109 if (!(sregs
->psr
& PSR_S
)) {
1110 sregs
->trap
= TRAP_PRIVI
;
1113 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1114 ((rs1
^ operand2
) & 0xfffff000);
1118 sregs
->y
= (rs1
^ operand2
);
1121 sregs
->y
= (rs1
^ operand2
);
1122 else if ( 17 == rd
)
1123 sregs
->asr17
= (rs1
^ operand2
);
1125 sregs
->trap
= TRAP_UNIMP
;
1135 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1137 sregs
->trap
= TRAP_UNALI
;
1141 npc
= rs1
+ operand2
;
1144 address
= rs1
+ operand2
;
1145 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1146 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1147 if (sregs
->psr
& PSR_ET
) {
1148 sregs
->trap
= TRAP_UNIMP
;
1151 if (!(sregs
->psr
& PSR_S
)) {
1152 sregs
->trap
= TRAP_PRIVI
;
1155 if (sregs
->wim
& (1 << new_cwp
)) {
1156 sregs
->trap
= TRAP_WUFL
;
1159 if (address
& 0x3) {
1160 sregs
->trap
= TRAP_UNALI
;
1163 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1165 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1171 uint32 result
, mask
;
1175 sregs
->trap
= TRAP_UNIMP
;
1178 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1179 result
= rs1
^ mask
;
1181 for (i
= 0; i
< 32; i
++) {
1182 if (result
& 0x80000000)
1187 *rdd
= i
== 32 ? 63 : i
;
1192 sregs
->trap
= TRAP_UNIMP
;
1197 case 3: /* Load/store instructions */
1199 address
= rs1
+ operand2
;
1201 if (sregs
->psr
& PSR_S
)
1207 sregs
->icnt
= T_ST
; /* Set store instruction count */
1212 sregs
->icnt
= T_LD
; /* Set load instruction count */
1218 /* Decode load/store instructions */
1222 if (!chk_asi(sregs
, &asi
, op3
)) break;
1224 if (address
& 0x7) {
1225 sregs
->trap
= TRAP_UNALI
;
1231 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1233 rdd
= &(sregs
->g
[rd
]);
1235 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1237 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1239 sregs
->icnt
= T_LDD
;
1241 sregs
->trap
= TRAP_DEXC
;
1246 sregs
->nload
++; /* Double load counts twice */
1252 if (!chk_asi(sregs
, &asi
, op3
)) break;
1254 if (address
& 0x3) {
1255 sregs
->trap
= TRAP_UNALI
;
1258 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1261 sregs
->trap
= TRAP_DEXC
;
1267 if (!chk_asi(sregs
, &asi
, op3
)) break;
1269 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1271 sregs
->icnt
= T_LDST
;
1273 sregs
->trap
= TRAP_DEXC
;
1276 data
= extract_byte (data
, address
);
1279 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1282 sregs
->trap
= TRAP_DEXC
;
1290 if (!chk_asi(sregs
, &asi
, op3
)) break;
1293 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1296 sregs
->trap
= TRAP_DEXC
;
1300 data
= extract_byte_signed (data
, address
);
1302 data
= extract_byte (data
, address
);
1307 if (!chk_asi(sregs
, &asi
, op3
)) break;
1310 if (address
& 0x1) {
1311 sregs
->trap
= TRAP_UNALI
;
1314 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1317 sregs
->trap
= TRAP_DEXC
;
1321 data
= extract_short_signed (data
, address
);
1323 data
= extract_short (data
, address
);
1327 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1328 sregs
->trap
= TRAP_FPDIS
;
1331 if (address
& 0x3) {
1332 sregs
->trap
= TRAP_UNALI
;
1335 if (ebase
.simtime
< sregs
->ftime
) {
1336 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1337 (sregs
->frs2
== rd
))
1338 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1340 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1343 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1344 sregs
->hold
+ sregs
->fhold
;
1346 sregs
->trap
= TRAP_DEXC
;
1348 sregs
->fs
[rd
] = *((float32
*) & data
);
1352 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1353 sregs
->trap
= TRAP_FPDIS
;
1356 if (address
& 0x7) {
1357 sregs
->trap
= TRAP_UNALI
;
1360 if (ebase
.simtime
< sregs
->ftime
) {
1361 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1362 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1363 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1364 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1366 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1368 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1370 sregs
->icnt
= T_LDD
;
1372 sregs
->trap
= TRAP_DEXC
;
1376 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1378 sregs
->nload
++; /* Double load counts twice */
1380 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1381 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1382 sregs
->hold
+ sregs
->fhold
;
1386 if (ebase
.simtime
< sregs
->ftime
) {
1387 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1389 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1390 sregs
->trap
= TRAP_FPDIS
;
1393 if (address
& 0x3) {
1394 sregs
->trap
= TRAP_UNALI
;
1397 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1400 sregs
->trap
= TRAP_DEXC
;
1403 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1404 set_fsr(sregs
->fsr
);
1408 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1409 sregs
->trap
= TRAP_FPDIS
;
1412 if (address
& 0x3) {
1413 sregs
->trap
= TRAP_UNALI
;
1416 if (ebase
.simtime
< sregs
->ftime
) {
1417 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1419 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1422 sregs
->trap
= TRAP_DEXC
;
1427 if (!chk_asi(sregs
, &asi
, op3
)) break;
1429 if (address
& 0x3) {
1430 sregs
->trap
= TRAP_UNALI
;
1433 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1436 sregs
->trap
= TRAP_DEXC
;
1440 if (!chk_asi(sregs
, &asi
, op3
)) break;
1442 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1445 sregs
->trap
= TRAP_DEXC
;
1449 if (!chk_asi(sregs
, &asi
, op3
)) break;
1451 if (address
& 0x7) {
1452 sregs
->trap
= TRAP_UNALI
;
1458 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1460 rdd
= &(sregs
->g
[rd
]);
1462 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1464 sregs
->icnt
= T_STD
;
1466 sregs
->nstore
++; /* Double store counts twice */
1469 sregs
->trap
= TRAP_DEXC
;
1474 if ((sregs
->psr
& 0x1f) > 7) {
1475 sregs
->trap
= TRAP_UNIMP
;
1478 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1479 sregs
->trap
= TRAP_FPDIS
;
1482 if (address
& 0x7) {
1483 sregs
->trap
= TRAP_UNALI
;
1486 if (!(sregs
->fsr
& FSR_QNE
)) {
1487 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1490 rdd
= &(sregs
->fpq
[0]);
1491 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1493 sregs
->icnt
= T_STD
;
1495 sregs
->nstore
++; /* Double store counts twice */
1498 sregs
->trap
= TRAP_DEXC
;
1501 sregs
->fsr
&= ~FSR_QNE
;
1502 sregs
->fpstate
= FP_EXE_MODE
;
1506 if (!chk_asi(sregs
, &asi
, op3
)) break;
1508 if (address
& 0x1) {
1509 sregs
->trap
= TRAP_UNALI
;
1512 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1515 sregs
->trap
= TRAP_DEXC
;
1519 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1520 sregs
->trap
= TRAP_FPDIS
;
1523 if (address
& 0x3) {
1524 sregs
->trap
= TRAP_UNALI
;
1527 if (ebase
.simtime
< sregs
->ftime
) {
1528 if (sregs
->frd
== rd
)
1529 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1531 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1534 sregs
->trap
= TRAP_DEXC
;
1538 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1539 sregs
->trap
= TRAP_FPDIS
;
1542 if (address
& 0x7) {
1543 sregs
->trap
= TRAP_UNALI
;
1547 if (ebase
.simtime
< sregs
->ftime
) {
1548 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1549 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1551 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1553 sregs
->icnt
= T_STD
;
1555 sregs
->nstore
++; /* Double store counts twice */
1558 sregs
->trap
= TRAP_DEXC
;
1562 if (!chk_asi(sregs
, &asi
, op3
)) break;
1564 if (address
& 0x3) {
1565 sregs
->trap
= TRAP_UNALI
;
1568 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1571 sregs
->trap
= TRAP_DEXC
;
1574 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1576 sregs
->icnt
= T_LDST
;
1578 sregs
->trap
= TRAP_DEXC
;
1589 sregs
->trap
= TRAP_UNIMP
;
1596 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1598 if ((op3
| 0x10) == 0x13)
1599 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1606 sregs
->trap
= TRAP_UNIMP
;
1665 fpexec(uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
, struct pstate
*sregs
)
1667 uint32 opf
, tem
, accex
;
1671 if (sregs
->fpstate
== FP_EXC_MODE
) {
1672 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1673 sregs
->fpstate
= FP_EXC_PE
;
1676 if (sregs
->fpstate
== FP_EXC_PE
) {
1677 sregs
->fpstate
= FP_EXC_MODE
;
1680 opf
= (sregs
->inst
>> 5) & 0x1ff;
1683 * Check if we already have an FPop in the pipe. If so, halt until it is
1684 * finished by incrementing fhold with the remaining execution time
1687 if (ebase
.simtime
< sregs
->ftime
) {
1688 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1692 /* Check load dependencies. */
1694 if (ebase
.simtime
< sregs
->ltime
) {
1696 /* Don't check rs1 if single operand instructions */
1698 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1701 /* Adjust for double floats */
1704 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1711 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1715 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1717 /* SPARC is big-endian - swap double floats if host is little-endian */
1718 /* This is ugly - I know ... */
1720 /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1721 but what about machines where float values are different endianness
1722 from integer values? */
1724 #ifdef HOST_LITTLE_ENDIAN
1736 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1737 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1738 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1739 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1749 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1750 sregs
->ftime
+= T_FABSs
;
1751 sregs
->frs1
= 32; /* rs1 ignored */
1754 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1755 sregs
->ftime
+= T_FADDs
;
1758 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1759 sregs
->ftime
+= T_FADDd
;
1763 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1765 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1767 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1771 sregs
->fsr
|= 0x0C00;
1772 sregs
->fsr
&= ~(fcc
<< 10);
1773 sregs
->ftime
+= T_FCMPs
;
1774 sregs
->frd
= 32; /* rd ignored */
1775 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1776 sregs
->fpstate
= FP_EXC_PE
;
1777 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1782 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1784 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1786 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1790 sregs
->fsr
|= 0x0C00;
1791 sregs
->fsr
&= ~(fcc
<< 10);
1792 sregs
->ftime
+= T_FCMPd
;
1793 sregs
->frd
= 32; /* rd ignored */
1794 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1795 sregs
->fpstate
= FP_EXC_PE
;
1796 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1800 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1801 sregs
->ftime
+= T_FDIVs
;
1804 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1805 sregs
->ftime
+= T_FDIVd
;
1808 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1809 sregs
->ftime
+= T_FMOVs
;
1810 sregs
->frs1
= 32; /* rs1 ignored */
1813 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1814 sregs
->ftime
+= T_FMULs
;
1817 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1818 sregs
->ftime
+= T_FMULd
;
1821 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1822 sregs
->ftime
+= T_FNEGs
;
1823 sregs
->frs1
= 32; /* rs1 ignored */
1826 if (sregs
->fs
[rs2
] < 0.0) {
1827 sregs
->fpstate
= FP_EXC_PE
;
1828 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1829 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1832 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1833 sregs
->ftime
+= T_FSQRTs
;
1834 sregs
->frs1
= 32; /* rs1 ignored */
1837 if (sregs
->fd
[rs2
>> 1] < 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
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1844 sregs
->ftime
+= T_FSQRTd
;
1845 sregs
->frs1
= 32; /* rs1 ignored */
1848 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1849 sregs
->ftime
+= T_FSUBs
;
1852 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1853 sregs
->ftime
+= T_FSUBd
;
1856 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1857 sregs
->ftime
+= T_FdTOi
;
1858 sregs
->frs1
= 32; /* rs1 ignored */
1861 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1862 sregs
->ftime
+= T_FdTOs
;
1863 sregs
->frs1
= 32; /* rs1 ignored */
1866 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1867 sregs
->ftime
+= T_FiTOs
;
1868 sregs
->frs1
= 32; /* rs1 ignored */
1871 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1872 sregs
->ftime
+= T_FiTOd
;
1873 sregs
->frs1
= 32; /* rs1 ignored */
1876 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1877 sregs
->ftime
+= T_FsTOi
;
1878 sregs
->frs1
= 32; /* rs1 ignored */
1881 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1882 sregs
->ftime
+= T_FsTOd
;
1883 sregs
->frs1
= 32; /* rs1 ignored */
1887 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1888 sregs
->fpstate
= FP_EXC_PE
;
1893 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1894 sregs
->fpstate
= FP_EXC_PE
;
1895 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1900 accex
= get_accex();
1902 #ifdef HOST_LITTLE_ENDIAN
1911 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1912 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1917 if (sregs
->fpstate
== FP_EXC_PE
) {
1918 sregs
->fpq
[0] = sregs
->pc
;
1919 sregs
->fpq
[1] = sregs
->inst
;
1920 sregs
->fsr
|= FSR_QNE
;
1922 tem
= (sregs
->fsr
>> 23) & 0x1f;
1924 sregs
->fpstate
= FP_EXC_PE
;
1925 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1926 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1928 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1930 if (sregs
->fpstate
== FP_EXC_PE
) {
1931 sregs
->fpq
[0] = sregs
->pc
;
1932 sregs
->fpq
[1] = sregs
->inst
;
1933 sregs
->fsr
|= FSR_QNE
;
1944 chk_asi(struct pstate
*sregs
, uint32
*asi
, uint32 op3
)
1946 if (!(sregs
->psr
& PSR_S
)) {
1947 sregs
->trap
= TRAP_PRIVI
;
1949 } else if (sregs
->inst
& INST_I
) {
1950 sregs
->trap
= TRAP_UNIMP
;
1953 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1958 execute_trap(struct pstate
*sregs
)
1962 if (sregs
->trap
== 256) {
1966 } else if (sregs
->trap
== 257) {
1970 if ((sregs
->psr
& PSR_ET
) == 0)
1973 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1975 sregs
->psr
&= ~PSR_ET
;
1976 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1978 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1979 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1980 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1981 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1982 sregs
->psr
|= PSR_S
;
1983 sregs
->pc
= sregs
->tbr
;
1984 sregs
->npc
= sregs
->tbr
+ 4;
1986 if ( 0 != (1 & sregs
->asr17
) ) {
1987 /* single vector trapping! */
1988 sregs
->pc
= sregs
->tbr
& 0xfffff000;
1989 sregs
->npc
= sregs
->pc
+ 4;
1992 /* Increase simulator time */
1993 sregs
->icnt
= TRAP_C
;
2002 extern struct irqcell irqarr
[16];
2005 check_interrupts(struct pstate
*sregs
)
2009 sregs
->trap
= errtt
;
2010 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2015 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2016 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2017 if (sregs
->trap
== 0) {
2018 sregs
->trap
= 16 + ext_irl
;
2019 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2027 init_regs(struct pstate
*sregs
)
2032 sregs
->psr
&= 0x00f03fdf;
2033 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2034 sregs
->breakpoint
= 0;
2036 sregs
->fpstate
= FP_EXE_MODE
;
2040 sregs
->err_mode
= 0;
2043 #ifdef HOST_LITTLE_ENDIAN
2044 sregs
->fdp
= (float32
*) sregs
->fd
;
2045 sregs
->fsi
= (int32
*) sregs
->fs
;
2047 sregs
->fs
= (float32
*) sregs
->fd
;
2048 sregs
->fsi
= (int32
*) sregs
->fd
;
2051 sregs
->fpu_pres
= !nfp
;
2052 set_fsr(sregs
->fsr
);
2060 sregs
->rett_err
= 0;
2061 sregs
->jmpltime
= 0;
This page took 0.102888 seconds and 3 git commands to generate.