e6ce6c52bbc6622c56fbc0d4864b8bbecf57d33a
2 * This file is part of SIS.
4 * SIS, SPARC instruction simulator V1.8 Copyright (C) 1995 Jiri Gaisler,
5 * European Space Agency
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 3 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, see <http://www.gnu.org/licenses/>.
27 extern int32 sis_verbose
, sparclite
;
30 /* Load/store interlock delay */
33 /* Load delay (delete if unwanted - speeds up simulation) */
44 #define FSR_QNE 0x2000
76 #define PSR_N 0x0800000
77 #define PSR_Z 0x0400000
78 #define PSR_V 0x0200000
79 #define PSR_C 0x0100000
80 #define PSR_CC 0x0F00000
82 #define PSR_PIL 0x0f00
84 #define ICC_N (icc >> 3)
85 #define ICC_Z (icc >> 2)
86 #define ICC_V (icc >> 1)
89 #define FP_PRES (sregs->fpu_pres)
101 #define TRAP_DIV0 0x2a
103 #define FSR_TT 0x1C000
104 #define FP_IEEE 0x04000
105 #define FP_UNIMP 0x0C000
106 #define FP_SEQ_ERR 0x10000
125 #define INST_SIMM13 0x1fff
126 #define INST_RS2 0x1f
127 #define INST_I 0x2000
134 #define TADDCCTV 0x22
135 #define TSUBCCTV 0x23
215 #define SIGN_BIT 0x80000000
217 /* # of cycles overhead when a trap is taken */
220 /* Forward declarations */
222 static uint32
sub_cc (uint32 psr
, int32 operand1
, int32 operand2
,
224 static uint32
add_cc (uint32 psr
, int32 operand1
, int32 operand2
,
226 static void log_cc (int32 result
, struct pstate
*sregs
);
227 static int fpexec (uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
,
228 struct pstate
*sregs
);
229 static int chk_asi (struct pstate
*sregs
, uint32
*asi
, uint32 op3
);
232 extern struct estate ebase
;
233 extern int32 nfp
,ift
;
236 extern uint32 errtt
, errftt
;
240 sub_cc(psr
, operand1
, operand2
, result
)
246 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
251 psr
= (psr
& ~PSR_V
) | ((((operand1
& ~operand2
& ~result
) |
252 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
253 psr
= (psr
& ~PSR_C
) | ((((~operand1
& operand2
) |
254 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
259 add_cc(psr
, operand1
, operand2
, result
)
265 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
270 psr
= (psr
& ~PSR_V
) | ((((operand1
& operand2
& ~result
) |
271 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
272 psr
= (psr
& ~PSR_C
) | ((((operand1
& operand2
) |
273 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
278 log_cc(result
, sregs
)
280 struct pstate
*sregs
;
282 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
283 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
288 /* Add two unsigned 32-bit integers, and calculate the carry out. */
291 add32 (uint32 n1
, uint32 n2
, int *carry
)
293 uint32 result
= n1
+ n2
;
295 *carry
= result
< n1
|| result
< n1
;
299 /* Multiply two 32-bit integers. */
302 mul64 (uint32 n1
, uint32 n2
, uint32
*result_hi
, uint32
*result_lo
, int msigned
)
304 uint32 lo
, mid1
, mid2
, hi
, reg_lo
, reg_hi
;
308 /* If this is a signed multiply, calculate the sign of the result
309 and make the operands positive. */
312 sign
= (n1
^ n2
) & SIGN_BIT
;
320 /* We can split the 32x32 into four 16x16 operations. This ensures
321 that we do not lose precision on 32bit only hosts: */
322 lo
= ((n1
& 0xFFFF) * (n2
& 0xFFFF));
323 mid1
= ((n1
& 0xFFFF) * ((n2
>> 16) & 0xFFFF));
324 mid2
= (((n1
>> 16) & 0xFFFF) * (n2
& 0xFFFF));
325 hi
= (((n1
>> 16) & 0xFFFF) * ((n2
>> 16) & 0xFFFF));
327 /* We now need to add all of these results together, taking care
328 to propogate the carries from the additions: */
329 reg_lo
= add32 (lo
, (mid1
<< 16), &carry
);
331 reg_lo
= add32 (reg_lo
, (mid2
<< 16), &carry
);
332 reg_hi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
334 /* Negate result if necessary. */
348 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
349 that the host compiler supports long long operations. */
352 div64 (uint32 n1_hi
, uint32 n1_low
, uint32 n2
, uint32
*result
, int msigned
)
356 n1
= ((uint64
) n1_hi
) << 32;
357 n1
|= ((uint64
) n1_low
) & 0xffffffff;
361 int64 n1_s
= (int64
) n1
;
362 int32 n2_s
= (int32
) n2
;
369 *result
= (uint32
) (n1
& 0xffffffff);
374 dispatch_instruction(sregs
)
375 struct pstate
*sregs
;
378 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
381 int32 operand1
, operand2
, *rdd
, result
, eicc
,
383 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
387 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
388 op
= sregs
->inst
>> 30;
390 npc
= sregs
->npc
+ 4;
391 op3
= rd
= rs1
= operand2
= eicc
= 0;
395 op3
= (sregs
->inst
>> 19) & 0x3f;
396 rs1
= (sregs
->inst
>> 14) & 0x1f;
397 rd
= (sregs
->inst
>> 25) & 0x1f;
401 /* Check if load dependecy is possible */
402 if (ebase
.simtime
<= sregs
->ildtime
)
403 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
406 if (sregs
->inst
& INST_I
) {
407 if (ldep
&& (sregs
->ildreg
== rs1
))
409 operand2
= sregs
->inst
;
410 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
412 rs2
= sregs
->inst
& INST_RS2
;
414 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
416 operand2
= sregs
->g
[rs2
];
417 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
421 if (sregs
->inst
& INST_I
) {
422 operand2
= sregs
->inst
;
423 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
425 rs2
= sregs
->inst
& INST_RS2
;
427 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
429 operand2
= sregs
->g
[rs2
];
434 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
436 rdd
= &(sregs
->g
[rd
]);
438 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
444 op2
= (sregs
->inst
>> 22) & 0x7;
447 rd
= (sregs
->inst
>> 25) & 0x1f;
449 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
451 rdd
= &(sregs
->g
[rd
]);
452 *rdd
= sregs
->inst
<< 10;
458 icc
= sregs
->psr
>> 20;
459 cond
= ((sregs
->inst
>> 25) & 0x0f);
468 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
471 eicc
= (ICC_N
^ ICC_V
);
474 eicc
= ICC_C
| ICC_Z
;
487 if (sregs
->inst
& 0x20000000)
494 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
497 eicc
= ~(ICC_N
^ ICC_V
);
500 eicc
= ~(ICC_C
| ICC_Z
);
513 operand1
= sregs
->inst
;
514 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
515 npc
= sregs
->pc
+ operand1
;
517 if (sregs
->inst
& 0x20000000)
525 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
526 sregs
->trap
= TRAP_FPDIS
;
529 if (ebase
.simtime
< sregs
->ftime
) {
530 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
532 cond
= ((sregs
->inst
>> 25) & 0x0f);
533 fcc
= (sregs
->fsr
>> 10) & 0x3;
539 eicc
= (fcc
!= FCC_E
);
542 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
545 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
548 eicc
= (fcc
== FCC_L
);
551 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
554 eicc
= (fcc
== FCC_G
);
557 eicc
= (fcc
== FCC_U
);
561 if (sregs
->inst
& 0x20000000)
565 eicc
= !(fcc
!= FCC_E
);
568 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
571 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
574 eicc
= !(fcc
== FCC_L
);
577 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
580 eicc
= !(fcc
== FCC_G
);
583 eicc
= !(fcc
== FCC_U
);
587 operand1
= sregs
->inst
;
588 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
589 npc
= sregs
->pc
+ operand1
;
591 if (sregs
->inst
& 0x20000000)
597 sregs
->trap
= TRAP_UNIMP
;
605 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
606 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
610 if ((op3
>> 1) == 0x1a) {
611 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
612 sregs
->trap
= TRAP_FPDIS
;
614 rs1
= (sregs
->inst
>> 14) & 0x1f;
615 rs2
= sregs
->inst
& 0x1f;
616 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
622 icc
= sregs
->psr
>> 20;
623 cond
= ((sregs
->inst
>> 25) & 0x0f);
632 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
635 eicc
= (ICC_N
^ ICC_V
);
638 eicc
= ICC_C
| ICC_Z
;
656 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
659 eicc
= ~(ICC_N
^ ICC_V
);
662 eicc
= ~(ICC_C
| ICC_Z
);
675 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
681 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
683 if ((sregs
->y
& 1) == 0)
685 *rdd
= operand1
+ operand2
;
686 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
687 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
692 uint32 result
, remainder
;
696 sregs
->trap
= TRAP_UNIMP
;
700 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
702 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
704 /* If true sign is positive, calculate remainder - divisor.
705 Otherwise, calculate remainder + divisor. */
707 operand2
= ~operand2
+ 1;
708 result
= remainder
+ operand2
;
710 /* The SPARClite User's Manual is not clear on how
711 the "carry out" of the above ALU operation is to
712 be calculated. From trial and error tests
713 on the the chip itself, it appears that it is
714 a normal addition carry, and not a subtraction borrow,
715 even in cases where the divisor is subtracted
716 from the remainder. FIXME: get the true story
718 c0
= result
< (uint32
) remainder
719 || result
< (uint32
) operand2
;
721 if (result
& 0x80000000)
724 sregs
->psr
&= ~PSR_N
;
726 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
728 if (result
== 0 && sign
== y31
)
731 sregs
->psr
&= ~PSR_Z
;
733 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
735 if (sign
^ (result
>> 31))
738 sregs
->psr
&= ~PSR_V
;
743 sregs
->psr
&= ~PSR_C
;
748 *rdd
= (rs1
<< 1) | !sign
;
753 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
760 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
762 if (result
& 0x80000000)
765 sregs
->psr
&= ~PSR_N
;
770 sregs
->psr
&= ~PSR_Z
;
777 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
784 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
786 if (result
& 0x80000000)
789 sregs
->psr
&= ~PSR_N
;
794 sregs
->psr
&= ~PSR_Z
;
802 sregs
->trap
= TRAP_UNIMP
;
807 sregs
->trap
= TRAP_DIV0
;
811 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
819 sregs
->trap
= TRAP_UNIMP
;
824 sregs
->trap
= TRAP_DIV0
;
828 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
830 if (result
& 0x80000000)
833 sregs
->psr
&= ~PSR_N
;
838 sregs
->psr
&= ~PSR_Z
;
840 /* FIXME: should set overflow flag correctly. */
841 sregs
->psr
&= ~(PSR_C
| PSR_V
);
849 sregs
->trap
= TRAP_UNIMP
;
854 sregs
->trap
= TRAP_DIV0
;
858 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
866 sregs
->trap
= TRAP_UNIMP
;
871 sregs
->trap
= TRAP_DIV0
;
875 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
877 if (result
& 0x80000000)
880 sregs
->psr
&= ~PSR_N
;
885 sregs
->psr
&= ~PSR_Z
;
887 /* FIXME: should set overflow flag correctly. */
888 sregs
->psr
&= ~(PSR_C
| PSR_V
);
894 *rdd
= rs1
^ ~operand2
;
897 *rdd
= rs1
^ ~operand2
;
901 *rdd
= rs1
^ operand2
;
904 *rdd
= rs1
^ operand2
;
908 *rdd
= rs1
| operand2
;
911 *rdd
= rs1
| operand2
;
915 *rdd
= rs1
| ~operand2
;
918 *rdd
= rs1
| ~operand2
;
922 *rdd
= rs1
& ~operand2
;
926 *rdd
= rs1
& ~operand2
;
929 *rdd
= rs1
& operand2
;
932 *rdd
= rs1
& operand2
;
936 *rdd
= rs1
- operand2
;
939 *rdd
= rs1
- operand2
;
940 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
943 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
946 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
947 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
950 *rdd
= rs1
+ operand2
;
953 *rdd
= rs1
+ operand2
;
954 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
957 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
960 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
961 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
964 *rdd
= rs1
+ operand2
;
965 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
966 if ((rs1
| operand2
) & 0x3)
970 *rdd
= rs1
- operand2
;
971 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
972 if ((rs1
| operand2
) & 0x3)
976 *rdd
= rs1
+ operand2
;
977 result
= add_cc(0, rs1
, operand2
, *rdd
);
978 if ((rs1
| operand2
) & 0x3)
980 if (result
& PSR_V
) {
981 sregs
->trap
= TRAP_TAG
;
983 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
987 *rdd
= rs1
- operand2
;
988 result
= add_cc (0, rs1
, operand2
, *rdd
);
989 if ((rs1
| operand2
) & 0x3)
993 sregs
->trap
= TRAP_TAG
;
997 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1001 *rdd
= rs1
<< (operand2
& 0x1f);
1004 *rdd
= rs1
>> (operand2
& 0x1f);
1007 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1010 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1013 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1014 if (sregs
->wim
& (1 << new_cwp
)) {
1015 sregs
->trap
= TRAP_WOFL
;
1019 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1020 *rdd
= rs1
+ operand2
;
1021 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1025 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1026 if (sregs
->wim
& (1 << new_cwp
)) {
1027 sregs
->trap
= TRAP_WUFL
;
1031 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1032 *rdd
= rs1
+ operand2
;
1033 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1036 if (!(sregs
->psr
& PSR_S
)) {
1037 sregs
->trap
= TRAP_PRIVI
;
1046 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1047 if ( 0 == rs1_is_asr
)
1049 else if ( 17 == rs1_is_asr
)
1050 *rdd
= sregs
->asr17
;
1052 sregs
->trap
= TRAP_UNIMP
;
1058 if (!(sregs
->psr
& PSR_S
)) {
1059 sregs
->trap
= TRAP_PRIVI
;
1065 if (!(sregs
->psr
& PSR_S
)) {
1066 sregs
->trap
= TRAP_PRIVI
;
1072 if ((sregs
->psr
& 0x1f) > 7) {
1073 sregs
->trap
= TRAP_UNIMP
;
1076 if (!(sregs
->psr
& PSR_S
)) {
1077 sregs
->trap
= TRAP_PRIVI
;
1080 sregs
->psr
= (rs1
^ operand2
) & 0x00f03fff;
1083 if (!(sregs
->psr
& PSR_S
)) {
1084 sregs
->trap
= TRAP_PRIVI
;
1087 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1090 if (!(sregs
->psr
& PSR_S
)) {
1091 sregs
->trap
= TRAP_PRIVI
;
1094 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1095 ((rs1
^ operand2
) & 0xfffff000);
1099 sregs
->y
= (rs1
^ operand2
);
1102 sregs
->y
= (rs1
^ operand2
);
1103 else if ( 17 == rd
)
1104 sregs
->asr17
= (rs1
^ operand2
);
1106 sregs
->trap
= TRAP_UNIMP
;
1116 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1118 sregs
->trap
= TRAP_UNALI
;
1122 npc
= rs1
+ operand2
;
1125 address
= rs1
+ operand2
;
1126 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1127 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1128 if (sregs
->psr
& PSR_ET
) {
1129 sregs
->trap
= TRAP_UNIMP
;
1132 if (!(sregs
->psr
& PSR_S
)) {
1133 sregs
->trap
= TRAP_PRIVI
;
1136 if (sregs
->wim
& (1 << new_cwp
)) {
1137 sregs
->trap
= TRAP_WUFL
;
1140 if (address
& 0x3) {
1141 sregs
->trap
= TRAP_UNALI
;
1144 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1146 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1152 uint32 result
, mask
;
1156 sregs
->trap
= TRAP_UNIMP
;
1159 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1160 result
= rs1
^ mask
;
1162 for (i
= 0; i
< 32; i
++) {
1163 if (result
& 0x80000000)
1168 *rdd
= i
== 32 ? 63 : i
;
1173 sregs
->trap
= TRAP_UNIMP
;
1178 case 3: /* Load/store instructions */
1180 address
= rs1
+ operand2
;
1182 if (sregs
->psr
& PSR_S
)
1188 sregs
->icnt
= T_ST
; /* Set store instruction count */
1193 sregs
->icnt
= T_LD
; /* Set load instruction count */
1199 /* Decode load/store instructions */
1203 if (!chk_asi(sregs
, &asi
, op3
)) break;
1205 if (address
& 0x7) {
1206 sregs
->trap
= TRAP_UNALI
;
1212 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1214 rdd
= &(sregs
->g
[rd
]);
1216 mexc
= memory_read(asi
, address
, ddata
, 3, &ws
);
1217 sregs
->hold
+= ws
* 2;
1218 sregs
->icnt
= T_LDD
;
1220 sregs
->trap
= TRAP_DEXC
;
1225 sregs
->nload
++; /* Double load counts twice */
1231 if (!chk_asi(sregs
, &asi
, op3
)) break;
1233 if (address
& 0x3) {
1234 sregs
->trap
= TRAP_UNALI
;
1237 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1240 sregs
->trap
= TRAP_DEXC
;
1246 if (!chk_asi(sregs
, &asi
, op3
)) break;
1248 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1250 sregs
->icnt
= T_LDST
;
1252 sregs
->trap
= TRAP_DEXC
;
1257 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1260 sregs
->trap
= TRAP_DEXC
;
1268 if (!chk_asi(sregs
, &asi
, op3
)) break;
1271 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1274 sregs
->trap
= TRAP_DEXC
;
1277 if ((op3
== LDSB
) && (data
& 0x80))
1283 if (!chk_asi(sregs
, &asi
, op3
)) break;
1286 if (address
& 0x1) {
1287 sregs
->trap
= TRAP_UNALI
;
1290 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1293 sregs
->trap
= TRAP_DEXC
;
1296 if ((op3
== LDSH
) && (data
& 0x8000))
1301 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1302 sregs
->trap
= TRAP_FPDIS
;
1305 if (address
& 0x3) {
1306 sregs
->trap
= TRAP_UNALI
;
1309 if (ebase
.simtime
< sregs
->ftime
) {
1310 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1311 (sregs
->frs2
== rd
))
1312 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1314 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1317 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1318 sregs
->hold
+ sregs
->fhold
;
1320 sregs
->trap
= TRAP_DEXC
;
1322 sregs
->fs
[rd
] = *((float32
*) & data
);
1326 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1327 sregs
->trap
= TRAP_FPDIS
;
1330 if (address
& 0x7) {
1331 sregs
->trap
= TRAP_UNALI
;
1334 if (ebase
.simtime
< sregs
->ftime
) {
1335 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1336 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1337 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1338 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1340 mexc
= memory_read(asi
, address
, ddata
, 3, &ws
);
1341 sregs
->hold
+= ws
* 2;
1342 sregs
->icnt
= T_LDD
;
1344 sregs
->trap
= TRAP_DEXC
;
1348 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1350 sregs
->nload
++; /* Double load counts twice */
1352 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1353 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1354 sregs
->hold
+ sregs
->fhold
;
1358 if (ebase
.simtime
< sregs
->ftime
) {
1359 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1361 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1362 sregs
->trap
= TRAP_FPDIS
;
1365 if (address
& 0x3) {
1366 sregs
->trap
= TRAP_UNALI
;
1369 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1372 sregs
->trap
= TRAP_DEXC
;
1375 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1376 set_fsr(sregs
->fsr
);
1380 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1381 sregs
->trap
= TRAP_FPDIS
;
1384 if (address
& 0x3) {
1385 sregs
->trap
= TRAP_UNALI
;
1388 if (ebase
.simtime
< sregs
->ftime
) {
1389 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1391 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1394 sregs
->trap
= TRAP_DEXC
;
1399 if (!chk_asi(sregs
, &asi
, op3
)) break;
1401 if (address
& 0x3) {
1402 sregs
->trap
= TRAP_UNALI
;
1405 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1408 sregs
->trap
= TRAP_DEXC
;
1412 if (!chk_asi(sregs
, &asi
, op3
)) break;
1414 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1417 sregs
->trap
= TRAP_DEXC
;
1421 if (!chk_asi(sregs
, &asi
, op3
)) break;
1423 if (address
& 0x7) {
1424 sregs
->trap
= TRAP_UNALI
;
1430 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1432 rdd
= &(sregs
->g
[rd
]);
1434 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1436 sregs
->icnt
= T_STD
;
1438 sregs
->nstore
++; /* Double store counts twice */
1441 sregs
->trap
= TRAP_DEXC
;
1446 if ((sregs
->psr
& 0x1f) > 7) {
1447 sregs
->trap
= TRAP_UNIMP
;
1450 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1451 sregs
->trap
= TRAP_FPDIS
;
1454 if (address
& 0x7) {
1455 sregs
->trap
= TRAP_UNALI
;
1458 if (!(sregs
->fsr
& FSR_QNE
)) {
1459 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1462 rdd
= &(sregs
->fpq
[0]);
1463 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1465 sregs
->icnt
= T_STD
;
1467 sregs
->nstore
++; /* Double store counts twice */
1470 sregs
->trap
= TRAP_DEXC
;
1473 sregs
->fsr
&= ~FSR_QNE
;
1474 sregs
->fpstate
= FP_EXE_MODE
;
1478 if (!chk_asi(sregs
, &asi
, op3
)) break;
1480 if (address
& 0x1) {
1481 sregs
->trap
= TRAP_UNALI
;
1484 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1487 sregs
->trap
= TRAP_DEXC
;
1491 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1492 sregs
->trap
= TRAP_FPDIS
;
1495 if (address
& 0x3) {
1496 sregs
->trap
= TRAP_UNALI
;
1499 if (ebase
.simtime
< sregs
->ftime
) {
1500 if (sregs
->frd
== rd
)
1501 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1503 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1506 sregs
->trap
= TRAP_DEXC
;
1510 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1511 sregs
->trap
= TRAP_FPDIS
;
1514 if (address
& 0x7) {
1515 sregs
->trap
= TRAP_UNALI
;
1519 if (ebase
.simtime
< sregs
->ftime
) {
1520 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1521 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1523 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1525 sregs
->icnt
= T_STD
;
1527 sregs
->nstore
++; /* Double store counts twice */
1530 sregs
->trap
= TRAP_DEXC
;
1534 if (!chk_asi(sregs
, &asi
, op3
)) break;
1536 if (address
& 0x3) {
1537 sregs
->trap
= TRAP_UNALI
;
1540 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1543 sregs
->trap
= TRAP_DEXC
;
1546 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1548 sregs
->icnt
= T_LDST
;
1550 sregs
->trap
= TRAP_DEXC
;
1561 sregs
->trap
= TRAP_UNIMP
;
1568 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1570 if ((op3
| 0x10) == 0x13)
1571 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1578 sregs
->trap
= TRAP_UNIMP
;
1637 fpexec(op3
, rd
, rs1
, rs2
, sregs
)
1638 uint32 op3
, rd
, rs1
, rs2
;
1639 struct pstate
*sregs
;
1641 uint32 opf
, tem
, accex
;
1645 if (sregs
->fpstate
== FP_EXC_MODE
) {
1646 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1647 sregs
->fpstate
= FP_EXC_PE
;
1650 if (sregs
->fpstate
== FP_EXC_PE
) {
1651 sregs
->fpstate
= FP_EXC_MODE
;
1654 opf
= (sregs
->inst
>> 5) & 0x1ff;
1657 * Check if we already have an FPop in the pipe. If so, halt until it is
1658 * finished by incrementing fhold with the remaining execution time
1661 if (ebase
.simtime
< sregs
->ftime
) {
1662 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1666 /* Check load dependencies. */
1668 if (ebase
.simtime
< sregs
->ltime
) {
1670 /* Don't check rs1 if single operand instructions */
1672 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1675 /* Adjust for double floats */
1678 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1685 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1689 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1691 /* SPARC is big-endian - swap double floats if host is little-endian */
1692 /* This is ugly - I know ... */
1694 /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1695 but what about machines where float values are different endianness
1696 from integer values? */
1698 #ifdef HOST_LITTLE_ENDIAN
1710 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1711 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1712 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1713 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1723 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1724 sregs
->ftime
+= T_FABSs
;
1725 sregs
->frs1
= 32; /* rs1 ignored */
1728 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1729 sregs
->ftime
+= T_FADDs
;
1732 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1733 sregs
->ftime
+= T_FADDd
;
1737 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1739 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1741 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1745 sregs
->fsr
|= 0x0C00;
1746 sregs
->fsr
&= ~(fcc
<< 10);
1747 sregs
->ftime
+= T_FCMPs
;
1748 sregs
->frd
= 32; /* rd ignored */
1749 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1750 sregs
->fpstate
= FP_EXC_PE
;
1751 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1756 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1758 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1760 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1764 sregs
->fsr
|= 0x0C00;
1765 sregs
->fsr
&= ~(fcc
<< 10);
1766 sregs
->ftime
+= T_FCMPd
;
1767 sregs
->frd
= 32; /* rd ignored */
1768 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1769 sregs
->fpstate
= FP_EXC_PE
;
1770 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1774 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1775 sregs
->ftime
+= T_FDIVs
;
1778 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1779 sregs
->ftime
+= T_FDIVd
;
1782 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1783 sregs
->ftime
+= T_FMOVs
;
1784 sregs
->frs1
= 32; /* rs1 ignored */
1787 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1788 sregs
->ftime
+= T_FMULs
;
1791 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1792 sregs
->ftime
+= T_FMULd
;
1795 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1796 sregs
->ftime
+= T_FNEGs
;
1797 sregs
->frs1
= 32; /* rs1 ignored */
1800 if (sregs
->fs
[rs2
] < 0.0) {
1801 sregs
->fpstate
= FP_EXC_PE
;
1802 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1803 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1806 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1807 sregs
->ftime
+= T_FSQRTs
;
1808 sregs
->frs1
= 32; /* rs1 ignored */
1811 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1812 sregs
->fpstate
= FP_EXC_PE
;
1813 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1814 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1817 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1818 sregs
->ftime
+= T_FSQRTd
;
1819 sregs
->frs1
= 32; /* rs1 ignored */
1822 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1823 sregs
->ftime
+= T_FSUBs
;
1826 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1827 sregs
->ftime
+= T_FSUBd
;
1830 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1831 sregs
->ftime
+= T_FdTOi
;
1832 sregs
->frs1
= 32; /* rs1 ignored */
1835 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1836 sregs
->ftime
+= T_FdTOs
;
1837 sregs
->frs1
= 32; /* rs1 ignored */
1840 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1841 sregs
->ftime
+= T_FiTOs
;
1842 sregs
->frs1
= 32; /* rs1 ignored */
1845 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1846 sregs
->ftime
+= T_FiTOd
;
1847 sregs
->frs1
= 32; /* rs1 ignored */
1850 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1851 sregs
->ftime
+= T_FsTOi
;
1852 sregs
->frs1
= 32; /* rs1 ignored */
1855 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1856 sregs
->ftime
+= T_FsTOd
;
1857 sregs
->frs1
= 32; /* rs1 ignored */
1861 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1862 sregs
->fpstate
= FP_EXC_PE
;
1867 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1868 sregs
->fpstate
= FP_EXC_PE
;
1869 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1874 accex
= get_accex();
1876 #ifdef HOST_LITTLE_ENDIAN
1885 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1886 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1891 if (sregs
->fpstate
== FP_EXC_PE
) {
1892 sregs
->fpq
[0] = sregs
->pc
;
1893 sregs
->fpq
[1] = sregs
->inst
;
1894 sregs
->fsr
|= FSR_QNE
;
1896 tem
= (sregs
->fsr
>> 23) & 0x1f;
1898 sregs
->fpstate
= FP_EXC_PE
;
1899 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1900 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1902 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1904 if (sregs
->fpstate
== FP_EXC_PE
) {
1905 sregs
->fpq
[0] = sregs
->pc
;
1906 sregs
->fpq
[1] = sregs
->inst
;
1907 sregs
->fsr
|= FSR_QNE
;
1918 chk_asi(sregs
, asi
, op3
)
1919 struct pstate
*sregs
;
1923 if (!(sregs
->psr
& PSR_S
)) {
1924 sregs
->trap
= TRAP_PRIVI
;
1926 } else if (sregs
->inst
& INST_I
) {
1927 sregs
->trap
= TRAP_UNIMP
;
1930 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1936 struct pstate
*sregs
;
1940 if (sregs
->trap
== 256) {
1944 } else if (sregs
->trap
== 257) {
1948 if ((sregs
->psr
& PSR_ET
) == 0)
1951 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1953 sregs
->psr
&= ~PSR_ET
;
1954 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1956 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1957 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1958 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1959 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1960 sregs
->psr
|= PSR_S
;
1961 sregs
->pc
= sregs
->tbr
;
1962 sregs
->npc
= sregs
->tbr
+ 4;
1964 if ( 0 != (1 & sregs
->asr17
) ) {
1965 /* single vector trapping! */
1966 sregs
->pc
= sregs
->tbr
& 0xfffff000;
1967 sregs
->npc
= sregs
->pc
+ 4;
1970 /* Increase simulator time */
1971 sregs
->icnt
= TRAP_C
;
1980 extern struct irqcell irqarr
[16];
1983 check_interrupts(sregs
)
1984 struct pstate
*sregs
;
1988 sregs
->trap
= errtt
;
1989 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
1994 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
1995 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
1996 if (sregs
->trap
== 0) {
1997 sregs
->trap
= 16 + ext_irl
;
1998 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2007 struct pstate
*sregs
;
2012 sregs
->psr
&= 0x00f03fdf;
2013 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2014 sregs
->breakpoint
= 0;
2016 sregs
->fpstate
= FP_EXE_MODE
;
2020 sregs
->err_mode
= 0;
2023 #ifdef HOST_LITTLE_ENDIAN
2024 sregs
->fdp
= (float32
*) sregs
->fd
;
2025 sregs
->fsi
= (int32
*) sregs
->fs
;
2027 sregs
->fs
= (float32
*) sregs
->fd
;
2028 sregs
->fsi
= (int32
*) sregs
->fd
;
2031 sregs
->fpu_pres
= !nfp
;
2032 set_fsr(sregs
->fsr
);
2040 sregs
->rett_err
= 0;
2041 sregs
->jmpltime
= 0;
This page took 0.152199 seconds and 4 git commands to generate.