1 /* Copyright (C) 1995-2015 Free Software Foundation, Inc.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 3 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 extern int32 sis_verbose
, sparclite
;
24 /* Load/store interlock delay */
27 /* Load delay (delete if unwanted - speeds up simulation) */
38 #define FSR_QNE 0x2000
70 #define PSR_N 0x0800000
71 #define PSR_Z 0x0400000
72 #define PSR_V 0x0200000
73 #define PSR_C 0x0100000
74 #define PSR_CC 0x0F00000
76 #define PSR_PIL 0x0f00
78 #define ICC_N (icc >> 3)
79 #define ICC_Z (icc >> 2)
80 #define ICC_V (icc >> 1)
83 #define FP_PRES (sregs->fpu_pres)
95 #define TRAP_DIV0 0x2a
97 #define FSR_TT 0x1C000
98 #define FP_IEEE 0x04000
99 #define FP_UNIMP 0x0C000
100 #define FP_SEQ_ERR 0x10000
119 #define INST_SIMM13 0x1fff
120 #define INST_RS2 0x1f
121 #define INST_I 0x2000
128 #define TADDCCTV 0x22
129 #define TSUBCCTV 0x23
209 #define SIGN_BIT 0x80000000
211 /* # of cycles overhead when a trap is taken */
214 /* Forward declarations */
216 static uint32
sub_cc (uint32 psr
, int32 operand1
, int32 operand2
,
218 static uint32
add_cc (uint32 psr
, int32 operand1
, int32 operand2
,
220 static void log_cc (int32 result
, struct pstate
*sregs
);
221 static int fpexec (uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
,
222 struct pstate
*sregs
);
223 static int chk_asi (struct pstate
*sregs
, uint32
*asi
, uint32 op3
);
226 extern struct estate ebase
;
227 extern int32 nfp
,ift
;
230 extern uint32 errtt
, errftt
;
234 sub_cc(psr
, operand1
, operand2
, result
)
240 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
245 psr
= (psr
& ~PSR_V
) | ((((operand1
& ~operand2
& ~result
) |
246 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
247 psr
= (psr
& ~PSR_C
) | ((((~operand1
& operand2
) |
248 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
253 add_cc(psr
, operand1
, operand2
, result
)
259 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
264 psr
= (psr
& ~PSR_V
) | ((((operand1
& operand2
& ~result
) |
265 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
266 psr
= (psr
& ~PSR_C
) | ((((operand1
& operand2
) |
267 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
272 log_cc(result
, sregs
)
274 struct pstate
*sregs
;
276 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
277 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
282 /* Add two unsigned 32-bit integers, and calculate the carry out. */
285 add32 (uint32 n1
, uint32 n2
, int *carry
)
287 uint32 result
= n1
+ n2
;
289 *carry
= result
< n1
|| result
< n2
;
293 /* Multiply two 32-bit integers. */
296 mul64 (uint32 n1
, uint32 n2
, uint32
*result_hi
, uint32
*result_lo
, int msigned
)
298 uint32 lo
, mid1
, mid2
, hi
, reg_lo
, reg_hi
;
302 /* If this is a signed multiply, calculate the sign of the result
303 and make the operands positive. */
306 sign
= (n1
^ n2
) & SIGN_BIT
;
314 /* We can split the 32x32 into four 16x16 operations. This ensures
315 that we do not lose precision on 32bit only hosts: */
316 lo
= ((n1
& 0xFFFF) * (n2
& 0xFFFF));
317 mid1
= ((n1
& 0xFFFF) * ((n2
>> 16) & 0xFFFF));
318 mid2
= (((n1
>> 16) & 0xFFFF) * (n2
& 0xFFFF));
319 hi
= (((n1
>> 16) & 0xFFFF) * ((n2
>> 16) & 0xFFFF));
321 /* We now need to add all of these results together, taking care
322 to propogate the carries from the additions: */
323 reg_lo
= add32 (lo
, (mid1
<< 16), &carry
);
325 reg_lo
= add32 (reg_lo
, (mid2
<< 16), &carry
);
326 reg_hi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
328 /* Negate result if necessary. */
342 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
343 that the host compiler supports long long operations. */
346 div64 (uint32 n1_hi
, uint32 n1_low
, uint32 n2
, uint32
*result
, int msigned
)
350 n1
= ((uint64
) n1_hi
) << 32;
351 n1
|= ((uint64
) n1_low
) & 0xffffffff;
355 int64 n1_s
= (int64
) n1
;
356 int32 n2_s
= (int32
) n2
;
363 *result
= (uint32
) (n1
& 0xffffffff);
368 extract_short (uint32 data
, uint32 address
)
370 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
374 extract_short_signed (uint32 data
, uint32 address
)
376 uint32 tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
383 extract_byte (uint32 data
, uint32 address
)
385 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
389 extract_byte_signed (uint32 data
, uint32 address
)
391 uint32 tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
398 dispatch_instruction(sregs
)
399 struct pstate
*sregs
;
402 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
405 int32 operand1
, operand2
, *rdd
, result
, eicc
,
407 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
411 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
412 op
= sregs
->inst
>> 30;
414 npc
= sregs
->npc
+ 4;
415 op3
= rd
= rs1
= operand2
= eicc
= 0;
419 op3
= (sregs
->inst
>> 19) & 0x3f;
420 rs1
= (sregs
->inst
>> 14) & 0x1f;
421 rd
= (sregs
->inst
>> 25) & 0x1f;
425 /* Check if load dependecy is possible */
426 if (ebase
.simtime
<= sregs
->ildtime
)
427 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
430 if (sregs
->inst
& INST_I
) {
431 if (ldep
&& (sregs
->ildreg
== rs1
))
433 operand2
= sregs
->inst
;
434 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
436 rs2
= sregs
->inst
& INST_RS2
;
438 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
440 operand2
= sregs
->g
[rs2
];
441 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
445 if (sregs
->inst
& INST_I
) {
446 operand2
= sregs
->inst
;
447 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
449 rs2
= sregs
->inst
& INST_RS2
;
451 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
453 operand2
= sregs
->g
[rs2
];
458 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
460 rdd
= &(sregs
->g
[rd
]);
462 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
468 op2
= (sregs
->inst
>> 22) & 0x7;
471 rd
= (sregs
->inst
>> 25) & 0x1f;
473 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
475 rdd
= &(sregs
->g
[rd
]);
476 *rdd
= sregs
->inst
<< 10;
482 icc
= sregs
->psr
>> 20;
483 cond
= ((sregs
->inst
>> 25) & 0x0f);
492 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
495 eicc
= (ICC_N
^ ICC_V
);
498 eicc
= ICC_C
| ICC_Z
;
511 if (sregs
->inst
& 0x20000000)
518 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
521 eicc
= ~(ICC_N
^ ICC_V
);
524 eicc
= ~(ICC_C
| ICC_Z
);
537 operand1
= sregs
->inst
;
538 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
539 npc
= sregs
->pc
+ operand1
;
541 if (sregs
->inst
& 0x20000000)
549 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
550 sregs
->trap
= TRAP_FPDIS
;
553 if (ebase
.simtime
< sregs
->ftime
) {
554 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
556 cond
= ((sregs
->inst
>> 25) & 0x0f);
557 fcc
= (sregs
->fsr
>> 10) & 0x3;
563 eicc
= (fcc
!= FCC_E
);
566 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
569 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
572 eicc
= (fcc
== FCC_L
);
575 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
578 eicc
= (fcc
== FCC_G
);
581 eicc
= (fcc
== FCC_U
);
585 if (sregs
->inst
& 0x20000000)
589 eicc
= !(fcc
!= FCC_E
);
592 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
595 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
598 eicc
= !(fcc
== FCC_L
);
601 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
604 eicc
= !(fcc
== FCC_G
);
607 eicc
= !(fcc
== FCC_U
);
611 operand1
= sregs
->inst
;
612 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
613 npc
= sregs
->pc
+ operand1
;
615 if (sregs
->inst
& 0x20000000)
621 sregs
->trap
= TRAP_UNIMP
;
629 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
630 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
634 if ((op3
>> 1) == 0x1a) {
635 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
636 sregs
->trap
= TRAP_FPDIS
;
638 rs1
= (sregs
->inst
>> 14) & 0x1f;
639 rs2
= sregs
->inst
& 0x1f;
640 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
646 icc
= sregs
->psr
>> 20;
647 cond
= ((sregs
->inst
>> 25) & 0x0f);
656 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
659 eicc
= (ICC_N
^ ICC_V
);
662 eicc
= ICC_C
| ICC_Z
;
680 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
683 eicc
= ~(ICC_N
^ ICC_V
);
686 eicc
= ~(ICC_C
| ICC_Z
);
699 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
705 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
707 if ((sregs
->y
& 1) == 0)
709 *rdd
= operand1
+ operand2
;
710 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
711 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
716 uint32 result
, remainder
;
720 sregs
->trap
= TRAP_UNIMP
;
724 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
726 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
728 /* If true sign is positive, calculate remainder - divisor.
729 Otherwise, calculate remainder + divisor. */
731 operand2
= ~operand2
+ 1;
732 result
= remainder
+ operand2
;
734 /* The SPARClite User's Manual is not clear on how
735 the "carry out" of the above ALU operation is to
736 be calculated. From trial and error tests
737 on the the chip itself, it appears that it is
738 a normal addition carry, and not a subtraction borrow,
739 even in cases where the divisor is subtracted
740 from the remainder. FIXME: get the true story
742 c0
= result
< (uint32
) remainder
743 || result
< (uint32
) operand2
;
745 if (result
& 0x80000000)
748 sregs
->psr
&= ~PSR_N
;
750 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
752 if (result
== 0 && sign
== y31
)
755 sregs
->psr
&= ~PSR_Z
;
757 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
759 if (sign
^ (result
>> 31))
762 sregs
->psr
&= ~PSR_V
;
767 sregs
->psr
&= ~PSR_C
;
772 *rdd
= (rs1
<< 1) | !sign
;
777 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
784 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
786 if (result
& 0x80000000)
789 sregs
->psr
&= ~PSR_N
;
794 sregs
->psr
&= ~PSR_Z
;
801 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
808 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
810 if (result
& 0x80000000)
813 sregs
->psr
&= ~PSR_N
;
818 sregs
->psr
&= ~PSR_Z
;
826 sregs
->trap
= TRAP_UNIMP
;
831 sregs
->trap
= TRAP_DIV0
;
835 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
843 sregs
->trap
= TRAP_UNIMP
;
848 sregs
->trap
= TRAP_DIV0
;
852 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
854 if (result
& 0x80000000)
857 sregs
->psr
&= ~PSR_N
;
862 sregs
->psr
&= ~PSR_Z
;
864 /* FIXME: should set overflow flag correctly. */
865 sregs
->psr
&= ~(PSR_C
| PSR_V
);
873 sregs
->trap
= TRAP_UNIMP
;
878 sregs
->trap
= TRAP_DIV0
;
882 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
890 sregs
->trap
= TRAP_UNIMP
;
895 sregs
->trap
= TRAP_DIV0
;
899 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
901 if (result
& 0x80000000)
904 sregs
->psr
&= ~PSR_N
;
909 sregs
->psr
&= ~PSR_Z
;
911 /* FIXME: should set overflow flag correctly. */
912 sregs
->psr
&= ~(PSR_C
| PSR_V
);
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
;
942 *rdd
= rs1
| ~operand2
;
946 *rdd
= rs1
& ~operand2
;
950 *rdd
= rs1
& ~operand2
;
953 *rdd
= rs1
& operand2
;
956 *rdd
= rs1
& operand2
;
960 *rdd
= rs1
- operand2
;
963 *rdd
= rs1
- operand2
;
964 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
967 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
970 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
971 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
974 *rdd
= rs1
+ operand2
;
977 *rdd
= rs1
+ operand2
;
978 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
981 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
984 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
985 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
988 *rdd
= rs1
+ operand2
;
989 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
990 if ((rs1
| operand2
) & 0x3)
994 *rdd
= rs1
- operand2
;
995 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
996 if ((rs1
| operand2
) & 0x3)
1000 *rdd
= rs1
+ operand2
;
1001 result
= add_cc(0, rs1
, operand2
, *rdd
);
1002 if ((rs1
| operand2
) & 0x3)
1004 if (result
& PSR_V
) {
1005 sregs
->trap
= TRAP_TAG
;
1007 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1011 *rdd
= rs1
- operand2
;
1012 result
= add_cc (0, rs1
, operand2
, *rdd
);
1013 if ((rs1
| operand2
) & 0x3)
1017 sregs
->trap
= TRAP_TAG
;
1021 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1025 *rdd
= rs1
<< (operand2
& 0x1f);
1028 *rdd
= rs1
>> (operand2
& 0x1f);
1031 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1034 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1037 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1038 if (sregs
->wim
& (1 << new_cwp
)) {
1039 sregs
->trap
= TRAP_WOFL
;
1043 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1044 *rdd
= rs1
+ operand2
;
1045 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1049 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1050 if (sregs
->wim
& (1 << new_cwp
)) {
1051 sregs
->trap
= TRAP_WUFL
;
1055 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1056 *rdd
= rs1
+ operand2
;
1057 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1060 if (!(sregs
->psr
& PSR_S
)) {
1061 sregs
->trap
= TRAP_PRIVI
;
1070 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1071 if ( 0 == rs1_is_asr
)
1073 else if ( 17 == rs1_is_asr
)
1074 *rdd
= sregs
->asr17
;
1076 sregs
->trap
= TRAP_UNIMP
;
1082 if (!(sregs
->psr
& PSR_S
)) {
1083 sregs
->trap
= TRAP_PRIVI
;
1089 if (!(sregs
->psr
& PSR_S
)) {
1090 sregs
->trap
= TRAP_PRIVI
;
1096 if ((sregs
->psr
& 0x1f) > 7) {
1097 sregs
->trap
= TRAP_UNIMP
;
1100 if (!(sregs
->psr
& PSR_S
)) {
1101 sregs
->trap
= TRAP_PRIVI
;
1104 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1105 (rs1
^ operand2
) & 0x00f03fff;
1108 if (!(sregs
->psr
& PSR_S
)) {
1109 sregs
->trap
= TRAP_PRIVI
;
1112 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1115 if (!(sregs
->psr
& PSR_S
)) {
1116 sregs
->trap
= TRAP_PRIVI
;
1119 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1120 ((rs1
^ operand2
) & 0xfffff000);
1124 sregs
->y
= (rs1
^ operand2
);
1127 sregs
->y
= (rs1
^ operand2
);
1128 else if ( 17 == rd
)
1129 sregs
->asr17
= (rs1
^ operand2
);
1131 sregs
->trap
= TRAP_UNIMP
;
1141 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1143 sregs
->trap
= TRAP_UNALI
;
1147 npc
= rs1
+ operand2
;
1150 address
= rs1
+ operand2
;
1151 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1152 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1153 if (sregs
->psr
& PSR_ET
) {
1154 sregs
->trap
= TRAP_UNIMP
;
1157 if (!(sregs
->psr
& PSR_S
)) {
1158 sregs
->trap
= TRAP_PRIVI
;
1161 if (sregs
->wim
& (1 << new_cwp
)) {
1162 sregs
->trap
= TRAP_WUFL
;
1165 if (address
& 0x3) {
1166 sregs
->trap
= TRAP_UNALI
;
1169 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1171 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1177 uint32 result
, mask
;
1181 sregs
->trap
= TRAP_UNIMP
;
1184 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1185 result
= rs1
^ mask
;
1187 for (i
= 0; i
< 32; i
++) {
1188 if (result
& 0x80000000)
1193 *rdd
= i
== 32 ? 63 : i
;
1198 sregs
->trap
= TRAP_UNIMP
;
1203 case 3: /* Load/store instructions */
1205 address
= rs1
+ operand2
;
1207 if (sregs
->psr
& PSR_S
)
1213 sregs
->icnt
= T_ST
; /* Set store instruction count */
1218 sregs
->icnt
= T_LD
; /* Set load instruction count */
1224 /* Decode load/store instructions */
1228 if (!chk_asi(sregs
, &asi
, op3
)) break;
1230 if (address
& 0x7) {
1231 sregs
->trap
= TRAP_UNALI
;
1237 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1239 rdd
= &(sregs
->g
[rd
]);
1241 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1243 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1245 sregs
->icnt
= T_LDD
;
1247 sregs
->trap
= TRAP_DEXC
;
1252 sregs
->nload
++; /* Double load counts twice */
1258 if (!chk_asi(sregs
, &asi
, op3
)) break;
1260 if (address
& 0x3) {
1261 sregs
->trap
= TRAP_UNALI
;
1264 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1267 sregs
->trap
= TRAP_DEXC
;
1273 if (!chk_asi(sregs
, &asi
, op3
)) break;
1275 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1277 sregs
->icnt
= T_LDST
;
1279 sregs
->trap
= TRAP_DEXC
;
1282 data
= extract_byte (data
, address
);
1285 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1288 sregs
->trap
= TRAP_DEXC
;
1296 if (!chk_asi(sregs
, &asi
, op3
)) break;
1299 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1302 sregs
->trap
= TRAP_DEXC
;
1306 data
= extract_byte_signed (data
, address
);
1308 data
= extract_byte (data
, address
);
1313 if (!chk_asi(sregs
, &asi
, op3
)) break;
1316 if (address
& 0x1) {
1317 sregs
->trap
= TRAP_UNALI
;
1320 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1323 sregs
->trap
= TRAP_DEXC
;
1327 data
= extract_short_signed (data
, address
);
1329 data
= extract_short (data
, address
);
1333 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1334 sregs
->trap
= TRAP_FPDIS
;
1337 if (address
& 0x3) {
1338 sregs
->trap
= TRAP_UNALI
;
1341 if (ebase
.simtime
< sregs
->ftime
) {
1342 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1343 (sregs
->frs2
== rd
))
1344 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1346 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1349 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1350 sregs
->hold
+ sregs
->fhold
;
1352 sregs
->trap
= TRAP_DEXC
;
1354 sregs
->fs
[rd
] = *((float32
*) & data
);
1358 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1359 sregs
->trap
= TRAP_FPDIS
;
1362 if (address
& 0x7) {
1363 sregs
->trap
= TRAP_UNALI
;
1366 if (ebase
.simtime
< sregs
->ftime
) {
1367 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1368 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1369 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1370 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1372 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1374 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1376 sregs
->icnt
= T_LDD
;
1378 sregs
->trap
= TRAP_DEXC
;
1382 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1384 sregs
->nload
++; /* Double load counts twice */
1386 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1387 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1388 sregs
->hold
+ sregs
->fhold
;
1392 if (ebase
.simtime
< sregs
->ftime
) {
1393 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1395 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1396 sregs
->trap
= TRAP_FPDIS
;
1399 if (address
& 0x3) {
1400 sregs
->trap
= TRAP_UNALI
;
1403 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1406 sregs
->trap
= TRAP_DEXC
;
1409 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1410 set_fsr(sregs
->fsr
);
1414 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1415 sregs
->trap
= TRAP_FPDIS
;
1418 if (address
& 0x3) {
1419 sregs
->trap
= TRAP_UNALI
;
1422 if (ebase
.simtime
< sregs
->ftime
) {
1423 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1425 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1428 sregs
->trap
= TRAP_DEXC
;
1433 if (!chk_asi(sregs
, &asi
, op3
)) break;
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;
1448 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1451 sregs
->trap
= TRAP_DEXC
;
1455 if (!chk_asi(sregs
, &asi
, op3
)) break;
1457 if (address
& 0x7) {
1458 sregs
->trap
= TRAP_UNALI
;
1464 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1466 rdd
= &(sregs
->g
[rd
]);
1468 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1470 sregs
->icnt
= T_STD
;
1472 sregs
->nstore
++; /* Double store counts twice */
1475 sregs
->trap
= TRAP_DEXC
;
1480 if ((sregs
->psr
& 0x1f) > 7) {
1481 sregs
->trap
= TRAP_UNIMP
;
1484 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1485 sregs
->trap
= TRAP_FPDIS
;
1488 if (address
& 0x7) {
1489 sregs
->trap
= TRAP_UNALI
;
1492 if (!(sregs
->fsr
& FSR_QNE
)) {
1493 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1496 rdd
= &(sregs
->fpq
[0]);
1497 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1499 sregs
->icnt
= T_STD
;
1501 sregs
->nstore
++; /* Double store counts twice */
1504 sregs
->trap
= TRAP_DEXC
;
1507 sregs
->fsr
&= ~FSR_QNE
;
1508 sregs
->fpstate
= FP_EXE_MODE
;
1512 if (!chk_asi(sregs
, &asi
, op3
)) break;
1514 if (address
& 0x1) {
1515 sregs
->trap
= TRAP_UNALI
;
1518 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1521 sregs
->trap
= TRAP_DEXC
;
1525 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1526 sregs
->trap
= TRAP_FPDIS
;
1529 if (address
& 0x3) {
1530 sregs
->trap
= TRAP_UNALI
;
1533 if (ebase
.simtime
< sregs
->ftime
) {
1534 if (sregs
->frd
== rd
)
1535 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1537 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1540 sregs
->trap
= TRAP_DEXC
;
1544 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1545 sregs
->trap
= TRAP_FPDIS
;
1548 if (address
& 0x7) {
1549 sregs
->trap
= TRAP_UNALI
;
1553 if (ebase
.simtime
< sregs
->ftime
) {
1554 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1555 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1557 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1559 sregs
->icnt
= T_STD
;
1561 sregs
->nstore
++; /* Double store counts twice */
1564 sregs
->trap
= TRAP_DEXC
;
1568 if (!chk_asi(sregs
, &asi
, op3
)) break;
1570 if (address
& 0x3) {
1571 sregs
->trap
= TRAP_UNALI
;
1574 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1577 sregs
->trap
= TRAP_DEXC
;
1580 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1582 sregs
->icnt
= T_LDST
;
1584 sregs
->trap
= TRAP_DEXC
;
1595 sregs
->trap
= TRAP_UNIMP
;
1602 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1604 if ((op3
| 0x10) == 0x13)
1605 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1612 sregs
->trap
= TRAP_UNIMP
;
1671 fpexec(op3
, rd
, rs1
, rs2
, sregs
)
1672 uint32 op3
, rd
, rs1
, rs2
;
1673 struct pstate
*sregs
;
1675 uint32 opf
, tem
, accex
;
1679 if (sregs
->fpstate
== FP_EXC_MODE
) {
1680 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1681 sregs
->fpstate
= FP_EXC_PE
;
1684 if (sregs
->fpstate
== FP_EXC_PE
) {
1685 sregs
->fpstate
= FP_EXC_MODE
;
1688 opf
= (sregs
->inst
>> 5) & 0x1ff;
1691 * Check if we already have an FPop in the pipe. If so, halt until it is
1692 * finished by incrementing fhold with the remaining execution time
1695 if (ebase
.simtime
< sregs
->ftime
) {
1696 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1700 /* Check load dependencies. */
1702 if (ebase
.simtime
< sregs
->ltime
) {
1704 /* Don't check rs1 if single operand instructions */
1706 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1709 /* Adjust for double floats */
1712 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1719 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1723 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1725 /* SPARC is big-endian - swap double floats if host is little-endian */
1726 /* This is ugly - I know ... */
1728 /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1729 but what about machines where float values are different endianness
1730 from integer values? */
1732 #ifdef HOST_LITTLE_ENDIAN
1744 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1745 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1746 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1747 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1757 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1758 sregs
->ftime
+= T_FABSs
;
1759 sregs
->frs1
= 32; /* rs1 ignored */
1762 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1763 sregs
->ftime
+= T_FADDs
;
1766 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1767 sregs
->ftime
+= T_FADDd
;
1771 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1773 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1775 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1779 sregs
->fsr
|= 0x0C00;
1780 sregs
->fsr
&= ~(fcc
<< 10);
1781 sregs
->ftime
+= T_FCMPs
;
1782 sregs
->frd
= 32; /* rd ignored */
1783 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1784 sregs
->fpstate
= FP_EXC_PE
;
1785 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1790 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1792 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1794 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1798 sregs
->fsr
|= 0x0C00;
1799 sregs
->fsr
&= ~(fcc
<< 10);
1800 sregs
->ftime
+= T_FCMPd
;
1801 sregs
->frd
= 32; /* rd ignored */
1802 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1803 sregs
->fpstate
= FP_EXC_PE
;
1804 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1808 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1809 sregs
->ftime
+= T_FDIVs
;
1812 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1813 sregs
->ftime
+= T_FDIVd
;
1816 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1817 sregs
->ftime
+= T_FMOVs
;
1818 sregs
->frs1
= 32; /* rs1 ignored */
1821 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1822 sregs
->ftime
+= T_FMULs
;
1825 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1826 sregs
->ftime
+= T_FMULd
;
1829 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1830 sregs
->ftime
+= T_FNEGs
;
1831 sregs
->frs1
= 32; /* rs1 ignored */
1834 if (sregs
->fs
[rs2
] < 0.0) {
1835 sregs
->fpstate
= FP_EXC_PE
;
1836 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1837 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1840 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1841 sregs
->ftime
+= T_FSQRTs
;
1842 sregs
->frs1
= 32; /* rs1 ignored */
1845 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1846 sregs
->fpstate
= FP_EXC_PE
;
1847 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1848 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1851 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1852 sregs
->ftime
+= T_FSQRTd
;
1853 sregs
->frs1
= 32; /* rs1 ignored */
1856 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1857 sregs
->ftime
+= T_FSUBs
;
1860 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1861 sregs
->ftime
+= T_FSUBd
;
1864 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1865 sregs
->ftime
+= T_FdTOi
;
1866 sregs
->frs1
= 32; /* rs1 ignored */
1869 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1870 sregs
->ftime
+= T_FdTOs
;
1871 sregs
->frs1
= 32; /* rs1 ignored */
1874 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1875 sregs
->ftime
+= T_FiTOs
;
1876 sregs
->frs1
= 32; /* rs1 ignored */
1879 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1880 sregs
->ftime
+= T_FiTOd
;
1881 sregs
->frs1
= 32; /* rs1 ignored */
1884 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1885 sregs
->ftime
+= T_FsTOi
;
1886 sregs
->frs1
= 32; /* rs1 ignored */
1889 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1890 sregs
->ftime
+= T_FsTOd
;
1891 sregs
->frs1
= 32; /* rs1 ignored */
1895 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1896 sregs
->fpstate
= FP_EXC_PE
;
1901 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1902 sregs
->fpstate
= FP_EXC_PE
;
1903 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1908 accex
= get_accex();
1910 #ifdef HOST_LITTLE_ENDIAN
1919 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1920 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1925 if (sregs
->fpstate
== FP_EXC_PE
) {
1926 sregs
->fpq
[0] = sregs
->pc
;
1927 sregs
->fpq
[1] = sregs
->inst
;
1928 sregs
->fsr
|= FSR_QNE
;
1930 tem
= (sregs
->fsr
>> 23) & 0x1f;
1932 sregs
->fpstate
= FP_EXC_PE
;
1933 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1934 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1936 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1938 if (sregs
->fpstate
== FP_EXC_PE
) {
1939 sregs
->fpq
[0] = sregs
->pc
;
1940 sregs
->fpq
[1] = sregs
->inst
;
1941 sregs
->fsr
|= FSR_QNE
;
1952 chk_asi(sregs
, asi
, op3
)
1953 struct pstate
*sregs
;
1957 if (!(sregs
->psr
& PSR_S
)) {
1958 sregs
->trap
= TRAP_PRIVI
;
1960 } else if (sregs
->inst
& INST_I
) {
1961 sregs
->trap
= TRAP_UNIMP
;
1964 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1970 struct pstate
*sregs
;
1974 if (sregs
->trap
== 256) {
1978 } else if (sregs
->trap
== 257) {
1982 if ((sregs
->psr
& PSR_ET
) == 0)
1985 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1987 sregs
->psr
&= ~PSR_ET
;
1988 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1990 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1991 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1992 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1993 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1994 sregs
->psr
|= PSR_S
;
1995 sregs
->pc
= sregs
->tbr
;
1996 sregs
->npc
= sregs
->tbr
+ 4;
1998 if ( 0 != (1 & sregs
->asr17
) ) {
1999 /* single vector trapping! */
2000 sregs
->pc
= sregs
->tbr
& 0xfffff000;
2001 sregs
->npc
= sregs
->pc
+ 4;
2004 /* Increase simulator time */
2005 sregs
->icnt
= TRAP_C
;
2014 extern struct irqcell irqarr
[16];
2017 check_interrupts(sregs
)
2018 struct pstate
*sregs
;
2022 sregs
->trap
= errtt
;
2023 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2028 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2029 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2030 if (sregs
->trap
== 0) {
2031 sregs
->trap
= 16 + ext_irl
;
2032 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2041 struct pstate
*sregs
;
2046 sregs
->psr
&= 0x00f03fdf;
2047 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2048 sregs
->breakpoint
= 0;
2050 sregs
->fpstate
= FP_EXE_MODE
;
2054 sregs
->err_mode
= 0;
2057 #ifdef HOST_LITTLE_ENDIAN
2058 sregs
->fdp
= (float32
*) sregs
->fd
;
2059 sregs
->fsi
= (int32
*) sregs
->fs
;
2061 sregs
->fs
= (float32
*) sregs
->fd
;
2062 sregs
->fsi
= (int32
*) sregs
->fd
;
2065 sregs
->fpu_pres
= !nfp
;
2066 set_fsr(sregs
->fsr
);
2074 sregs
->rett_err
= 0;
2075 sregs
->jmpltime
= 0;
This page took 0.131308 seconds and 5 git commands to generate.