1 /* This file is part of SIS (SPARC instruction simulator)
3 Copyright (C) 1995-2024 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_t 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_t sub_cc (uint32_t psr
, int32_t operand1
, int32_t operand2
,
223 static uint32_t add_cc (uint32_t psr
, int32_t operand1
, int32_t operand2
,
225 static void log_cc (int32_t result
, struct pstate
*sregs
);
226 static int fpexec (uint32_t op3
, uint32_t rd
, uint32_t rs1
, uint32_t rs2
,
227 struct pstate
*sregs
);
228 static int chk_asi (struct pstate
*sregs
, uint32_t *asi
, uint32_t op3
);
231 extern struct estate ebase
;
232 extern int32_t nfp
,ift
;
235 extern uint32_t errtt
, errftt
;
239 sub_cc(uint32_t psr
, int32_t operand1
, int32_t operand2
, int32_t 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_t psr
, int32_t operand1
, int32_t operand2
, int32_t 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_t 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_t n1
, uint32_t n2
, int *carry
)
282 uint32_t result
= n1
+ n2
;
284 *carry
= result
< n1
|| result
< n2
;
288 /* Multiply two 32-bit integers. */
291 mul64 (uint32_t n1
, uint32_t n2
, uint32_t *result_hi
, uint32_t *result_lo
, int msigned
)
293 uint32_t 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_t n1_hi
, uint32_t n1_low
, uint32_t n2
, uint32_t *result
, int msigned
)
345 n1
= ((uint64_t) n1_hi
) << 32;
346 n1
|= ((uint64_t) n1_low
) & 0xffffffff;
350 int64_t n1_s
= (int64_t) n1
;
351 int32_t n2_s
= (int32_t) n2
;
353 n1
= (uint64_t) n1_s
;
358 *result
= (uint32_t) (n1
& 0xffffffff);
363 extract_short (uint32_t data
, uint32_t address
)
365 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
369 extract_short_signed (uint32_t data
, uint32_t address
)
371 uint32_t tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
378 extract_byte (uint32_t data
, uint32_t address
)
380 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
384 extract_byte_signed (uint32_t data
, uint32_t address
)
386 uint32_t tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
393 dispatch_instruction(struct pstate
*sregs
)
396 uint32_t cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
398 uint32_t ldep
, icc
, data
, *rdd
;
399 int32_t operand1
, operand2
, result
, eicc
,
401 int32_t pc
, npc
, 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_t uresult
, 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 uresult
= 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
= uresult
< remainder
|| uresult
< (uint32_t) operand2
;
738 if (uresult
& 0x80000000)
741 sregs
->psr
&= ~PSR_N
;
743 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
745 if (uresult
== 0 && sign
== y31
)
748 sregs
->psr
&= ~PSR_Z
;
750 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
752 if (sign
^ (uresult
>> 31))
755 sregs
->psr
&= ~PSR_V
;
760 sregs
->psr
&= ~PSR_C
;
765 *rdd
= (rs1
<< 1) | !sign
;
770 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
777 mul64 (rs1
, operand2
, &sregs
->y
, &uresult
, 1);
779 if (uresult
& 0x80000000)
782 sregs
->psr
&= ~PSR_N
;
787 sregs
->psr
&= ~PSR_Z
;
794 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
801 mul64 (rs1
, operand2
, &sregs
->y
, &uresult
, 0);
803 if (uresult
& 0x80000000)
806 sregs
->psr
&= ~PSR_N
;
811 sregs
->psr
&= ~PSR_Z
;
819 sregs
->trap
= TRAP_UNIMP
;
824 sregs
->trap
= TRAP_DIV0
;
828 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
836 sregs
->trap
= TRAP_UNIMP
;
841 sregs
->trap
= TRAP_DIV0
;
845 div64 (sregs
->y
, rs1
, operand2
, &uresult
, 1);
847 if (uresult
& 0x80000000)
850 sregs
->psr
&= ~PSR_N
;
855 sregs
->psr
&= ~PSR_Z
;
857 /* FIXME: should set overflow flag correctly. */
858 sregs
->psr
&= ~(PSR_C
| PSR_V
);
866 sregs
->trap
= TRAP_UNIMP
;
871 sregs
->trap
= TRAP_DIV0
;
875 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
883 sregs
->trap
= TRAP_UNIMP
;
888 sregs
->trap
= TRAP_DIV0
;
892 div64 (sregs
->y
, rs1
, operand2
, &uresult
, 0);
894 if (uresult
& 0x80000000)
897 sregs
->psr
&= ~PSR_N
;
902 sregs
->psr
&= ~PSR_Z
;
904 /* FIXME: should set overflow flag correctly. */
905 sregs
->psr
&= ~(PSR_C
| PSR_V
);
911 *rdd
= rs1
^ ~operand2
;
914 *rdd
= rs1
^ ~operand2
;
918 *rdd
= rs1
^ operand2
;
921 *rdd
= rs1
^ operand2
;
925 *rdd
= rs1
| operand2
;
928 *rdd
= rs1
| operand2
;
932 *rdd
= rs1
| ~operand2
;
935 *rdd
= rs1
| ~operand2
;
939 *rdd
= rs1
& ~operand2
;
943 *rdd
= rs1
& ~operand2
;
946 *rdd
= rs1
& operand2
;
949 *rdd
= rs1
& operand2
;
953 *rdd
= rs1
- operand2
;
956 *rdd
= rs1
- operand2
;
957 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
960 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
963 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
964 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
967 *rdd
= rs1
+ operand2
;
970 *rdd
= rs1
+ operand2
;
971 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
974 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
977 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
978 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
981 *rdd
= rs1
+ operand2
;
982 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
983 if ((rs1
| operand2
) & 0x3)
987 *rdd
= rs1
- operand2
;
988 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
989 if ((rs1
| operand2
) & 0x3)
993 *rdd
= rs1
+ operand2
;
994 result
= add_cc(0, rs1
, operand2
, *rdd
);
995 if ((rs1
| operand2
) & 0x3)
997 if (result
& PSR_V
) {
998 sregs
->trap
= TRAP_TAG
;
1000 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1004 *rdd
= rs1
- operand2
;
1005 result
= add_cc (0, rs1
, operand2
, *rdd
);
1006 if ((rs1
| operand2
) & 0x3)
1010 sregs
->trap
= TRAP_TAG
;
1014 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1018 *rdd
= rs1
<< (operand2
& 0x1f);
1021 *rdd
= rs1
>> (operand2
& 0x1f);
1024 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1027 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1030 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1031 if (sregs
->wim
& (1 << new_cwp
)) {
1032 sregs
->trap
= TRAP_WOFL
;
1036 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1037 *rdd
= rs1
+ operand2
;
1038 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1042 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1043 if (sregs
->wim
& (1 << new_cwp
)) {
1044 sregs
->trap
= TRAP_WUFL
;
1048 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1049 *rdd
= rs1
+ operand2
;
1050 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1053 if (!(sregs
->psr
& PSR_S
)) {
1054 sregs
->trap
= TRAP_PRIVI
;
1063 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1064 if ( 0 == rs1_is_asr
)
1066 else if ( 17 == rs1_is_asr
)
1067 *rdd
= sregs
->asr17
;
1069 sregs
->trap
= TRAP_UNIMP
;
1075 if (!(sregs
->psr
& PSR_S
)) {
1076 sregs
->trap
= TRAP_PRIVI
;
1082 if (!(sregs
->psr
& PSR_S
)) {
1083 sregs
->trap
= TRAP_PRIVI
;
1089 if ((sregs
->psr
& 0x1f) > 7) {
1090 sregs
->trap
= TRAP_UNIMP
;
1093 if (!(sregs
->psr
& PSR_S
)) {
1094 sregs
->trap
= TRAP_PRIVI
;
1097 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1098 ((rs1
^ operand2
) & 0x00f03fff);
1101 if (!(sregs
->psr
& PSR_S
)) {
1102 sregs
->trap
= TRAP_PRIVI
;
1105 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1108 if (!(sregs
->psr
& PSR_S
)) {
1109 sregs
->trap
= TRAP_PRIVI
;
1112 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1113 ((rs1
^ operand2
) & 0xfffff000);
1117 sregs
->y
= (rs1
^ operand2
);
1120 sregs
->y
= (rs1
^ operand2
);
1121 else if ( 17 == rd
)
1122 sregs
->asr17
= (rs1
^ operand2
);
1124 sregs
->trap
= TRAP_UNIMP
;
1134 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1136 sregs
->trap
= TRAP_UNALI
;
1140 npc
= rs1
+ operand2
;
1143 address
= rs1
+ operand2
;
1144 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1145 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1146 if (sregs
->psr
& PSR_ET
) {
1147 sregs
->trap
= TRAP_UNIMP
;
1150 if (!(sregs
->psr
& PSR_S
)) {
1151 sregs
->trap
= TRAP_PRIVI
;
1154 if (sregs
->wim
& (1 << new_cwp
)) {
1155 sregs
->trap
= TRAP_WUFL
;
1158 if (address
& 0x3) {
1159 sregs
->trap
= TRAP_UNALI
;
1162 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1164 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1170 uint32_t uresult
, mask
;
1174 sregs
->trap
= TRAP_UNIMP
;
1177 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1178 uresult
= rs1
^ mask
;
1180 for (i
= 0; i
< 32; i
++) {
1181 if (uresult
& 0x80000000)
1186 *rdd
= i
== 32 ? 63 : i
;
1191 sregs
->trap
= TRAP_UNIMP
;
1196 case 3: /* Load/store instructions */
1198 address
= rs1
+ operand2
;
1200 if (sregs
->psr
& PSR_S
)
1206 sregs
->icnt
= T_ST
; /* Set store instruction count */
1211 sregs
->icnt
= T_LD
; /* Set load instruction count */
1217 /* Decode load/store instructions */
1221 if (!chk_asi(sregs
, &asi
, op3
)) break;
1222 ATTRIBUTE_FALLTHROUGH
;
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;
1253 ATTRIBUTE_FALLTHROUGH
;
1255 if (address
& 0x3) {
1256 sregs
->trap
= TRAP_UNALI
;
1259 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1262 sregs
->trap
= TRAP_DEXC
;
1268 if (!chk_asi(sregs
, &asi
, op3
)) break;
1269 ATTRIBUTE_FALLTHROUGH
;
1271 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1273 sregs
->icnt
= T_LDST
;
1275 sregs
->trap
= TRAP_DEXC
;
1278 data
= extract_byte (data
, address
);
1281 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1284 sregs
->trap
= TRAP_DEXC
;
1292 if (!chk_asi(sregs
, &asi
, op3
)) break;
1293 ATTRIBUTE_FALLTHROUGH
;
1296 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1299 sregs
->trap
= TRAP_DEXC
;
1303 data
= extract_byte_signed (data
, address
);
1305 data
= extract_byte (data
, address
);
1310 if (!chk_asi(sregs
, &asi
, op3
)) break;
1311 ATTRIBUTE_FALLTHROUGH
;
1314 if (address
& 0x1) {
1315 sregs
->trap
= TRAP_UNALI
;
1318 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1321 sregs
->trap
= TRAP_DEXC
;
1325 data
= extract_short_signed (data
, address
);
1327 data
= extract_short (data
, address
);
1331 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1332 sregs
->trap
= TRAP_FPDIS
;
1335 if (address
& 0x3) {
1336 sregs
->trap
= TRAP_UNALI
;
1339 if (ebase
.simtime
< sregs
->ftime
) {
1340 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1341 (sregs
->frs2
== rd
))
1342 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1344 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1347 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1348 sregs
->hold
+ sregs
->fhold
;
1350 sregs
->trap
= TRAP_DEXC
;
1352 memcpy (&sregs
->fs
[rd
], &data
, sizeof (sregs
->fs
[rd
]));
1356 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1357 sregs
->trap
= TRAP_FPDIS
;
1360 if (address
& 0x7) {
1361 sregs
->trap
= TRAP_UNALI
;
1364 if (ebase
.simtime
< sregs
->ftime
) {
1365 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1366 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1367 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1368 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1370 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1372 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1374 sregs
->icnt
= T_LDD
;
1376 sregs
->trap
= TRAP_DEXC
;
1380 memcpy (&sregs
->fs
[rd
], &ddata
[0], sizeof (sregs
->fs
[rd
]));
1382 sregs
->nload
++; /* Double load counts twice */
1384 memcpy (&sregs
->fs
[rd
+ 1], &ddata
[1],
1385 sizeof (sregs
->fs
[rd
+ 1]));
1386 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1387 sregs
->hold
+ sregs
->fhold
;
1391 if (ebase
.simtime
< sregs
->ftime
) {
1392 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1394 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1395 sregs
->trap
= TRAP_FPDIS
;
1398 if (address
& 0x3) {
1399 sregs
->trap
= TRAP_UNALI
;
1402 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1405 sregs
->trap
= TRAP_DEXC
;
1408 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1409 set_fsr(sregs
->fsr
);
1413 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1414 sregs
->trap
= TRAP_FPDIS
;
1417 if (address
& 0x3) {
1418 sregs
->trap
= TRAP_UNALI
;
1421 if (ebase
.simtime
< sregs
->ftime
) {
1422 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1424 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1427 sregs
->trap
= TRAP_DEXC
;
1432 if (!chk_asi(sregs
, &asi
, op3
)) break;
1433 ATTRIBUTE_FALLTHROUGH
;
1435 if (address
& 0x3) {
1436 sregs
->trap
= TRAP_UNALI
;
1439 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1442 sregs
->trap
= TRAP_DEXC
;
1446 if (!chk_asi(sregs
, &asi
, op3
)) break;
1447 ATTRIBUTE_FALLTHROUGH
;
1449 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1452 sregs
->trap
= TRAP_DEXC
;
1456 if (!chk_asi(sregs
, &asi
, op3
)) break;
1457 ATTRIBUTE_FALLTHROUGH
;
1459 if (address
& 0x7) {
1460 sregs
->trap
= TRAP_UNALI
;
1466 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1468 rdd
= &(sregs
->g
[rd
]);
1470 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1472 sregs
->icnt
= T_STD
;
1474 sregs
->nstore
++; /* Double store counts twice */
1477 sregs
->trap
= TRAP_DEXC
;
1482 if ((sregs
->psr
& 0x1f) > 7) {
1483 sregs
->trap
= TRAP_UNIMP
;
1486 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1487 sregs
->trap
= TRAP_FPDIS
;
1490 if (address
& 0x7) {
1491 sregs
->trap
= TRAP_UNALI
;
1494 if (!(sregs
->fsr
& FSR_QNE
)) {
1495 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1498 rdd
= &(sregs
->fpq
[0]);
1499 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1501 sregs
->icnt
= T_STD
;
1503 sregs
->nstore
++; /* Double store counts twice */
1506 sregs
->trap
= TRAP_DEXC
;
1509 sregs
->fsr
&= ~FSR_QNE
;
1510 sregs
->fpstate
= FP_EXE_MODE
;
1514 if (!chk_asi(sregs
, &asi
, op3
)) break;
1515 ATTRIBUTE_FALLTHROUGH
;
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
, (uint32_t *)&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
, (uint32_t *)&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;
1572 ATTRIBUTE_FALLTHROUGH
;
1574 if (address
& 0x3) {
1575 sregs
->trap
= TRAP_UNALI
;
1578 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1581 sregs
->trap
= TRAP_DEXC
;
1584 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1586 sregs
->icnt
= T_LDST
;
1588 sregs
->trap
= TRAP_DEXC
;
1599 sregs
->trap
= TRAP_UNIMP
;
1606 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1608 if ((op3
| 0x10) == 0x13)
1609 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1616 sregs
->trap
= TRAP_UNIMP
;
1675 fpexec(uint32_t op3
, uint32_t rd
, uint32_t rs1
, uint32_t rs2
, struct pstate
*sregs
)
1677 uint32_t opf
, tem
, accex
;
1681 if (sregs
->fpstate
== FP_EXC_MODE
) {
1682 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1683 sregs
->fpstate
= FP_EXC_PE
;
1686 if (sregs
->fpstate
== FP_EXC_PE
) {
1687 sregs
->fpstate
= FP_EXC_MODE
;
1690 opf
= (sregs
->inst
>> 5) & 0x1ff;
1693 * Check if we already have an FPop in the pipe. If so, halt until it is
1694 * finished by incrementing fhold with the remaining execution time
1697 if (ebase
.simtime
< sregs
->ftime
) {
1698 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1702 /* Check load dependencies. */
1704 if (ebase
.simtime
< sregs
->ltime
) {
1706 /* Don't check rs1 if single operand instructions */
1708 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1711 /* Adjust for double floats */
1714 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1721 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1725 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1727 /* SPARC is big-endian - swap double floats if host is little-endian */
1728 /* This is ugly - I know ... */
1730 /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1731 but what about machines where float values are different endianness
1732 from integer values? */
1734 #ifdef HOST_LITTLE_ENDIAN
1746 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1747 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1748 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1749 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1759 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1760 sregs
->ftime
+= T_FABSs
;
1761 sregs
->frs1
= 32; /* rs1 ignored */
1764 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1765 sregs
->ftime
+= T_FADDs
;
1768 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1769 sregs
->ftime
+= T_FADDd
;
1773 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1775 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1777 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1781 sregs
->fsr
|= 0x0C00;
1782 sregs
->fsr
&= ~(fcc
<< 10);
1783 sregs
->ftime
+= T_FCMPs
;
1784 sregs
->frd
= 32; /* rd ignored */
1785 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1786 sregs
->fpstate
= FP_EXC_PE
;
1787 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1792 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1794 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1796 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1800 sregs
->fsr
|= 0x0C00;
1801 sregs
->fsr
&= ~(fcc
<< 10);
1802 sregs
->ftime
+= T_FCMPd
;
1803 sregs
->frd
= 32; /* rd ignored */
1804 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1805 sregs
->fpstate
= FP_EXC_PE
;
1806 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1810 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1811 sregs
->ftime
+= T_FDIVs
;
1814 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1815 sregs
->ftime
+= T_FDIVd
;
1818 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1819 sregs
->ftime
+= T_FMOVs
;
1820 sregs
->frs1
= 32; /* rs1 ignored */
1823 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1824 sregs
->ftime
+= T_FMULs
;
1827 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1828 sregs
->ftime
+= T_FMULd
;
1831 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1832 sregs
->ftime
+= T_FNEGs
;
1833 sregs
->frs1
= 32; /* rs1 ignored */
1836 if (sregs
->fs
[rs2
] < 0.0) {
1837 sregs
->fpstate
= FP_EXC_PE
;
1838 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1839 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1842 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1843 sregs
->ftime
+= T_FSQRTs
;
1844 sregs
->frs1
= 32; /* rs1 ignored */
1847 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1848 sregs
->fpstate
= FP_EXC_PE
;
1849 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1850 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1853 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1854 sregs
->ftime
+= T_FSQRTd
;
1855 sregs
->frs1
= 32; /* rs1 ignored */
1858 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1859 sregs
->ftime
+= T_FSUBs
;
1862 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1863 sregs
->ftime
+= T_FSUBd
;
1866 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1867 sregs
->ftime
+= T_FdTOi
;
1868 sregs
->frs1
= 32; /* rs1 ignored */
1871 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1872 sregs
->ftime
+= T_FdTOs
;
1873 sregs
->frs1
= 32; /* rs1 ignored */
1876 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1877 sregs
->ftime
+= T_FiTOs
;
1878 sregs
->frs1
= 32; /* rs1 ignored */
1881 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1882 sregs
->ftime
+= T_FiTOd
;
1883 sregs
->frs1
= 32; /* rs1 ignored */
1886 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1887 sregs
->ftime
+= T_FsTOi
;
1888 sregs
->frs1
= 32; /* rs1 ignored */
1891 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1892 sregs
->ftime
+= T_FsTOd
;
1893 sregs
->frs1
= 32; /* rs1 ignored */
1897 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1898 sregs
->fpstate
= FP_EXC_PE
;
1903 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1904 sregs
->fpstate
= FP_EXC_PE
;
1905 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1910 accex
= get_accex();
1912 #ifdef HOST_LITTLE_ENDIAN
1921 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1922 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1927 if (sregs
->fpstate
== FP_EXC_PE
) {
1928 sregs
->fpq
[0] = sregs
->pc
;
1929 sregs
->fpq
[1] = sregs
->inst
;
1930 sregs
->fsr
|= FSR_QNE
;
1932 tem
= (sregs
->fsr
>> 23) & 0x1f;
1934 sregs
->fpstate
= FP_EXC_PE
;
1935 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1936 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1938 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1940 if (sregs
->fpstate
== FP_EXC_PE
) {
1941 sregs
->fpq
[0] = sregs
->pc
;
1942 sregs
->fpq
[1] = sregs
->inst
;
1943 sregs
->fsr
|= FSR_QNE
;
1954 chk_asi(struct pstate
*sregs
, uint32_t *asi
, uint32_t op3
)
1956 if (!(sregs
->psr
& PSR_S
)) {
1957 sregs
->trap
= TRAP_PRIVI
;
1959 } else if (sregs
->inst
& INST_I
) {
1960 sregs
->trap
= TRAP_UNIMP
;
1963 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1968 execute_trap(struct pstate
*sregs
)
1972 if (sregs
->trap
== 256) {
1976 } else if (sregs
->trap
== 257) {
1980 if ((sregs
->psr
& PSR_ET
) == 0)
1983 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1985 sregs
->psr
&= ~PSR_ET
;
1986 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1988 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1989 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1990 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1991 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1992 sregs
->psr
|= PSR_S
;
1993 sregs
->pc
= sregs
->tbr
;
1994 sregs
->npc
= sregs
->tbr
+ 4;
1996 if ( 0 != (1 & sregs
->asr17
) ) {
1997 /* single vector trapping! */
1998 sregs
->pc
= sregs
->tbr
& 0xfffff000;
1999 sregs
->npc
= sregs
->pc
+ 4;
2002 /* Increase simulator time */
2003 sregs
->icnt
= TRAP_C
;
2012 extern struct irqcell irqarr
[16];
2015 check_interrupts(struct pstate
*sregs
)
2019 sregs
->trap
= errtt
;
2020 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2025 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2026 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2027 if (sregs
->trap
== 0) {
2028 sregs
->trap
= 16 + ext_irl
;
2029 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2037 init_regs(struct pstate
*sregs
)
2042 sregs
->psr
&= 0x00f03fdf;
2043 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2044 sregs
->breakpoint
= 0;
2046 sregs
->fpstate
= FP_EXE_MODE
;
2050 sregs
->err_mode
= 0;
2053 #ifdef HOST_LITTLE_ENDIAN
2054 sregs
->fdp
= (float32
*) sregs
->fd
;
2055 sregs
->fsi
= (int32_t *) sregs
->fs
;
2057 sregs
->fs
= (float32
*) sregs
->fd
;
2058 sregs
->fsi
= (int32_t *) sregs
->fd
;
2061 sregs
->fpu_pres
= !nfp
;
2062 set_fsr(sregs
->fsr
);
2070 sregs
->rett_err
= 0;
2071 sregs
->jmpltime
= 0;