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
< n2
;
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 extract_short (uint32 data
, uint32 address
)
376 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
380 extract_short_signed (uint32 data
, uint32 address
)
382 uint32 tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
389 extract_byte (uint32 data
, uint32 address
)
391 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
395 extract_byte_signed (uint32 data
, uint32 address
)
397 uint32 tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
404 dispatch_instruction(sregs
)
405 struct pstate
*sregs
;
408 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
411 int32 operand1
, operand2
, *rdd
, result
, eicc
,
413 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
417 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
418 op
= sregs
->inst
>> 30;
420 npc
= sregs
->npc
+ 4;
421 op3
= rd
= rs1
= operand2
= eicc
= 0;
425 op3
= (sregs
->inst
>> 19) & 0x3f;
426 rs1
= (sregs
->inst
>> 14) & 0x1f;
427 rd
= (sregs
->inst
>> 25) & 0x1f;
431 /* Check if load dependecy is possible */
432 if (ebase
.simtime
<= sregs
->ildtime
)
433 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
436 if (sregs
->inst
& INST_I
) {
437 if (ldep
&& (sregs
->ildreg
== rs1
))
439 operand2
= sregs
->inst
;
440 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
442 rs2
= sregs
->inst
& INST_RS2
;
444 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
446 operand2
= sregs
->g
[rs2
];
447 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
451 if (sregs
->inst
& INST_I
) {
452 operand2
= sregs
->inst
;
453 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
455 rs2
= sregs
->inst
& INST_RS2
;
457 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
459 operand2
= sregs
->g
[rs2
];
464 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
466 rdd
= &(sregs
->g
[rd
]);
468 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
474 op2
= (sregs
->inst
>> 22) & 0x7;
477 rd
= (sregs
->inst
>> 25) & 0x1f;
479 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
481 rdd
= &(sregs
->g
[rd
]);
482 *rdd
= sregs
->inst
<< 10;
488 icc
= sregs
->psr
>> 20;
489 cond
= ((sregs
->inst
>> 25) & 0x0f);
498 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
501 eicc
= (ICC_N
^ ICC_V
);
504 eicc
= ICC_C
| ICC_Z
;
517 if (sregs
->inst
& 0x20000000)
524 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
527 eicc
= ~(ICC_N
^ ICC_V
);
530 eicc
= ~(ICC_C
| ICC_Z
);
543 operand1
= sregs
->inst
;
544 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
545 npc
= sregs
->pc
+ operand1
;
547 if (sregs
->inst
& 0x20000000)
555 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
556 sregs
->trap
= TRAP_FPDIS
;
559 if (ebase
.simtime
< sregs
->ftime
) {
560 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
562 cond
= ((sregs
->inst
>> 25) & 0x0f);
563 fcc
= (sregs
->fsr
>> 10) & 0x3;
569 eicc
= (fcc
!= FCC_E
);
572 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
575 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
578 eicc
= (fcc
== FCC_L
);
581 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
584 eicc
= (fcc
== FCC_G
);
587 eicc
= (fcc
== FCC_U
);
591 if (sregs
->inst
& 0x20000000)
595 eicc
= !(fcc
!= FCC_E
);
598 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
601 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
604 eicc
= !(fcc
== FCC_L
);
607 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
610 eicc
= !(fcc
== FCC_G
);
613 eicc
= !(fcc
== FCC_U
);
617 operand1
= sregs
->inst
;
618 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
619 npc
= sregs
->pc
+ operand1
;
621 if (sregs
->inst
& 0x20000000)
627 sregs
->trap
= TRAP_UNIMP
;
635 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
636 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
640 if ((op3
>> 1) == 0x1a) {
641 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
642 sregs
->trap
= TRAP_FPDIS
;
644 rs1
= (sregs
->inst
>> 14) & 0x1f;
645 rs2
= sregs
->inst
& 0x1f;
646 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
652 icc
= sregs
->psr
>> 20;
653 cond
= ((sregs
->inst
>> 25) & 0x0f);
662 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
665 eicc
= (ICC_N
^ ICC_V
);
668 eicc
= ICC_C
| ICC_Z
;
686 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
689 eicc
= ~(ICC_N
^ ICC_V
);
692 eicc
= ~(ICC_C
| ICC_Z
);
705 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
711 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
713 if ((sregs
->y
& 1) == 0)
715 *rdd
= operand1
+ operand2
;
716 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
717 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
722 uint32 result
, remainder
;
726 sregs
->trap
= TRAP_UNIMP
;
730 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
732 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
734 /* If true sign is positive, calculate remainder - divisor.
735 Otherwise, calculate remainder + divisor. */
737 operand2
= ~operand2
+ 1;
738 result
= remainder
+ operand2
;
740 /* The SPARClite User's Manual is not clear on how
741 the "carry out" of the above ALU operation is to
742 be calculated. From trial and error tests
743 on the the chip itself, it appears that it is
744 a normal addition carry, and not a subtraction borrow,
745 even in cases where the divisor is subtracted
746 from the remainder. FIXME: get the true story
748 c0
= result
< (uint32
) remainder
749 || result
< (uint32
) operand2
;
751 if (result
& 0x80000000)
754 sregs
->psr
&= ~PSR_N
;
756 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
758 if (result
== 0 && sign
== y31
)
761 sregs
->psr
&= ~PSR_Z
;
763 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
765 if (sign
^ (result
>> 31))
768 sregs
->psr
&= ~PSR_V
;
773 sregs
->psr
&= ~PSR_C
;
778 *rdd
= (rs1
<< 1) | !sign
;
783 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
790 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
792 if (result
& 0x80000000)
795 sregs
->psr
&= ~PSR_N
;
800 sregs
->psr
&= ~PSR_Z
;
807 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
814 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
816 if (result
& 0x80000000)
819 sregs
->psr
&= ~PSR_N
;
824 sregs
->psr
&= ~PSR_Z
;
832 sregs
->trap
= TRAP_UNIMP
;
837 sregs
->trap
= TRAP_DIV0
;
841 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
849 sregs
->trap
= TRAP_UNIMP
;
854 sregs
->trap
= TRAP_DIV0
;
858 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
860 if (result
& 0x80000000)
863 sregs
->psr
&= ~PSR_N
;
868 sregs
->psr
&= ~PSR_Z
;
870 /* FIXME: should set overflow flag correctly. */
871 sregs
->psr
&= ~(PSR_C
| PSR_V
);
879 sregs
->trap
= TRAP_UNIMP
;
884 sregs
->trap
= TRAP_DIV0
;
888 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
896 sregs
->trap
= TRAP_UNIMP
;
901 sregs
->trap
= TRAP_DIV0
;
905 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
907 if (result
& 0x80000000)
910 sregs
->psr
&= ~PSR_N
;
915 sregs
->psr
&= ~PSR_Z
;
917 /* FIXME: should set overflow flag correctly. */
918 sregs
->psr
&= ~(PSR_C
| PSR_V
);
924 *rdd
= rs1
^ ~operand2
;
927 *rdd
= rs1
^ ~operand2
;
931 *rdd
= rs1
^ operand2
;
934 *rdd
= rs1
^ operand2
;
938 *rdd
= rs1
| operand2
;
941 *rdd
= rs1
| operand2
;
945 *rdd
= rs1
| ~operand2
;
948 *rdd
= rs1
| ~operand2
;
952 *rdd
= rs1
& ~operand2
;
956 *rdd
= rs1
& ~operand2
;
959 *rdd
= rs1
& operand2
;
962 *rdd
= rs1
& operand2
;
966 *rdd
= rs1
- operand2
;
969 *rdd
= rs1
- operand2
;
970 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
973 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
976 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
977 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
980 *rdd
= rs1
+ operand2
;
983 *rdd
= rs1
+ operand2
;
984 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
987 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
990 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
991 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
994 *rdd
= rs1
+ operand2
;
995 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
996 if ((rs1
| operand2
) & 0x3)
1000 *rdd
= rs1
- operand2
;
1001 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
1002 if ((rs1
| operand2
) & 0x3)
1003 sregs
->psr
|= PSR_V
;
1006 *rdd
= rs1
+ operand2
;
1007 result
= add_cc(0, rs1
, operand2
, *rdd
);
1008 if ((rs1
| operand2
) & 0x3)
1010 if (result
& PSR_V
) {
1011 sregs
->trap
= TRAP_TAG
;
1013 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1017 *rdd
= rs1
- operand2
;
1018 result
= add_cc (0, rs1
, operand2
, *rdd
);
1019 if ((rs1
| operand2
) & 0x3)
1023 sregs
->trap
= TRAP_TAG
;
1027 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1031 *rdd
= rs1
<< (operand2
& 0x1f);
1034 *rdd
= rs1
>> (operand2
& 0x1f);
1037 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1040 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1043 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1044 if (sregs
->wim
& (1 << new_cwp
)) {
1045 sregs
->trap
= TRAP_WOFL
;
1049 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1050 *rdd
= rs1
+ operand2
;
1051 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1055 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1056 if (sregs
->wim
& (1 << new_cwp
)) {
1057 sregs
->trap
= TRAP_WUFL
;
1061 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1062 *rdd
= rs1
+ operand2
;
1063 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1066 if (!(sregs
->psr
& PSR_S
)) {
1067 sregs
->trap
= TRAP_PRIVI
;
1076 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1077 if ( 0 == rs1_is_asr
)
1079 else if ( 17 == rs1_is_asr
)
1080 *rdd
= sregs
->asr17
;
1082 sregs
->trap
= TRAP_UNIMP
;
1088 if (!(sregs
->psr
& PSR_S
)) {
1089 sregs
->trap
= TRAP_PRIVI
;
1095 if (!(sregs
->psr
& PSR_S
)) {
1096 sregs
->trap
= TRAP_PRIVI
;
1102 if ((sregs
->psr
& 0x1f) > 7) {
1103 sregs
->trap
= TRAP_UNIMP
;
1106 if (!(sregs
->psr
& PSR_S
)) {
1107 sregs
->trap
= TRAP_PRIVI
;
1110 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1111 (rs1
^ operand2
) & 0x00f03fff;
1114 if (!(sregs
->psr
& PSR_S
)) {
1115 sregs
->trap
= TRAP_PRIVI
;
1118 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1121 if (!(sregs
->psr
& PSR_S
)) {
1122 sregs
->trap
= TRAP_PRIVI
;
1125 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1126 ((rs1
^ operand2
) & 0xfffff000);
1130 sregs
->y
= (rs1
^ operand2
);
1133 sregs
->y
= (rs1
^ operand2
);
1134 else if ( 17 == rd
)
1135 sregs
->asr17
= (rs1
^ operand2
);
1137 sregs
->trap
= TRAP_UNIMP
;
1147 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1149 sregs
->trap
= TRAP_UNALI
;
1153 npc
= rs1
+ operand2
;
1156 address
= rs1
+ operand2
;
1157 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1158 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1159 if (sregs
->psr
& PSR_ET
) {
1160 sregs
->trap
= TRAP_UNIMP
;
1163 if (!(sregs
->psr
& PSR_S
)) {
1164 sregs
->trap
= TRAP_PRIVI
;
1167 if (sregs
->wim
& (1 << new_cwp
)) {
1168 sregs
->trap
= TRAP_WUFL
;
1171 if (address
& 0x3) {
1172 sregs
->trap
= TRAP_UNALI
;
1175 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1177 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1183 uint32 result
, mask
;
1187 sregs
->trap
= TRAP_UNIMP
;
1190 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1191 result
= rs1
^ mask
;
1193 for (i
= 0; i
< 32; i
++) {
1194 if (result
& 0x80000000)
1199 *rdd
= i
== 32 ? 63 : i
;
1204 sregs
->trap
= TRAP_UNIMP
;
1209 case 3: /* Load/store instructions */
1211 address
= rs1
+ operand2
;
1213 if (sregs
->psr
& PSR_S
)
1219 sregs
->icnt
= T_ST
; /* Set store instruction count */
1224 sregs
->icnt
= T_LD
; /* Set load instruction count */
1230 /* Decode load/store instructions */
1234 if (!chk_asi(sregs
, &asi
, op3
)) break;
1236 if (address
& 0x7) {
1237 sregs
->trap
= TRAP_UNALI
;
1243 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1245 rdd
= &(sregs
->g
[rd
]);
1247 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1249 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1251 sregs
->icnt
= T_LDD
;
1253 sregs
->trap
= TRAP_DEXC
;
1258 sregs
->nload
++; /* Double load counts twice */
1264 if (!chk_asi(sregs
, &asi
, op3
)) break;
1266 if (address
& 0x3) {
1267 sregs
->trap
= TRAP_UNALI
;
1270 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1273 sregs
->trap
= TRAP_DEXC
;
1279 if (!chk_asi(sregs
, &asi
, op3
)) break;
1281 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1283 sregs
->icnt
= T_LDST
;
1285 sregs
->trap
= TRAP_DEXC
;
1288 data
= extract_byte (data
, address
);
1291 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1294 sregs
->trap
= TRAP_DEXC
;
1302 if (!chk_asi(sregs
, &asi
, op3
)) break;
1305 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1308 sregs
->trap
= TRAP_DEXC
;
1312 data
= extract_byte_signed (data
, address
);
1314 data
= extract_byte (data
, address
);
1319 if (!chk_asi(sregs
, &asi
, op3
)) break;
1322 if (address
& 0x1) {
1323 sregs
->trap
= TRAP_UNALI
;
1326 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1329 sregs
->trap
= TRAP_DEXC
;
1333 data
= extract_short_signed (data
, address
);
1335 data
= extract_short (data
, address
);
1339 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1340 sregs
->trap
= TRAP_FPDIS
;
1343 if (address
& 0x3) {
1344 sregs
->trap
= TRAP_UNALI
;
1347 if (ebase
.simtime
< sregs
->ftime
) {
1348 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1349 (sregs
->frs2
== rd
))
1350 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1352 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1355 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1356 sregs
->hold
+ sregs
->fhold
;
1358 sregs
->trap
= TRAP_DEXC
;
1360 sregs
->fs
[rd
] = *((float32
*) & data
);
1364 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1365 sregs
->trap
= TRAP_FPDIS
;
1368 if (address
& 0x7) {
1369 sregs
->trap
= TRAP_UNALI
;
1372 if (ebase
.simtime
< sregs
->ftime
) {
1373 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1374 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1375 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1376 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1378 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1380 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1382 sregs
->icnt
= T_LDD
;
1384 sregs
->trap
= TRAP_DEXC
;
1388 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1390 sregs
->nload
++; /* Double load counts twice */
1392 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1393 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1394 sregs
->hold
+ sregs
->fhold
;
1398 if (ebase
.simtime
< sregs
->ftime
) {
1399 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1401 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1402 sregs
->trap
= TRAP_FPDIS
;
1405 if (address
& 0x3) {
1406 sregs
->trap
= TRAP_UNALI
;
1409 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1412 sregs
->trap
= TRAP_DEXC
;
1415 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1416 set_fsr(sregs
->fsr
);
1420 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1421 sregs
->trap
= TRAP_FPDIS
;
1424 if (address
& 0x3) {
1425 sregs
->trap
= TRAP_UNALI
;
1428 if (ebase
.simtime
< sregs
->ftime
) {
1429 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1431 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1434 sregs
->trap
= TRAP_DEXC
;
1439 if (!chk_asi(sregs
, &asi
, op3
)) break;
1441 if (address
& 0x3) {
1442 sregs
->trap
= TRAP_UNALI
;
1445 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1448 sregs
->trap
= TRAP_DEXC
;
1452 if (!chk_asi(sregs
, &asi
, op3
)) break;
1454 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1457 sregs
->trap
= TRAP_DEXC
;
1461 if (!chk_asi(sregs
, &asi
, op3
)) break;
1463 if (address
& 0x7) {
1464 sregs
->trap
= TRAP_UNALI
;
1470 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1472 rdd
= &(sregs
->g
[rd
]);
1474 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1476 sregs
->icnt
= T_STD
;
1478 sregs
->nstore
++; /* Double store counts twice */
1481 sregs
->trap
= TRAP_DEXC
;
1486 if ((sregs
->psr
& 0x1f) > 7) {
1487 sregs
->trap
= TRAP_UNIMP
;
1490 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1491 sregs
->trap
= TRAP_FPDIS
;
1494 if (address
& 0x7) {
1495 sregs
->trap
= TRAP_UNALI
;
1498 if (!(sregs
->fsr
& FSR_QNE
)) {
1499 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1502 rdd
= &(sregs
->fpq
[0]);
1503 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1505 sregs
->icnt
= T_STD
;
1507 sregs
->nstore
++; /* Double store counts twice */
1510 sregs
->trap
= TRAP_DEXC
;
1513 sregs
->fsr
&= ~FSR_QNE
;
1514 sregs
->fpstate
= FP_EXE_MODE
;
1518 if (!chk_asi(sregs
, &asi
, op3
)) break;
1520 if (address
& 0x1) {
1521 sregs
->trap
= TRAP_UNALI
;
1524 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1527 sregs
->trap
= TRAP_DEXC
;
1531 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1532 sregs
->trap
= TRAP_FPDIS
;
1535 if (address
& 0x3) {
1536 sregs
->trap
= TRAP_UNALI
;
1539 if (ebase
.simtime
< sregs
->ftime
) {
1540 if (sregs
->frd
== rd
)
1541 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1543 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1546 sregs
->trap
= TRAP_DEXC
;
1550 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1551 sregs
->trap
= TRAP_FPDIS
;
1554 if (address
& 0x7) {
1555 sregs
->trap
= TRAP_UNALI
;
1559 if (ebase
.simtime
< sregs
->ftime
) {
1560 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1561 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1563 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1565 sregs
->icnt
= T_STD
;
1567 sregs
->nstore
++; /* Double store counts twice */
1570 sregs
->trap
= TRAP_DEXC
;
1574 if (!chk_asi(sregs
, &asi
, op3
)) break;
1576 if (address
& 0x3) {
1577 sregs
->trap
= TRAP_UNALI
;
1580 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1583 sregs
->trap
= TRAP_DEXC
;
1586 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1588 sregs
->icnt
= T_LDST
;
1590 sregs
->trap
= TRAP_DEXC
;
1601 sregs
->trap
= TRAP_UNIMP
;
1608 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1610 if ((op3
| 0x10) == 0x13)
1611 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1618 sregs
->trap
= TRAP_UNIMP
;
1677 fpexec(op3
, rd
, rs1
, rs2
, sregs
)
1678 uint32 op3
, rd
, rs1
, rs2
;
1679 struct pstate
*sregs
;
1681 uint32 opf
, tem
, accex
;
1685 if (sregs
->fpstate
== FP_EXC_MODE
) {
1686 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1687 sregs
->fpstate
= FP_EXC_PE
;
1690 if (sregs
->fpstate
== FP_EXC_PE
) {
1691 sregs
->fpstate
= FP_EXC_MODE
;
1694 opf
= (sregs
->inst
>> 5) & 0x1ff;
1697 * Check if we already have an FPop in the pipe. If so, halt until it is
1698 * finished by incrementing fhold with the remaining execution time
1701 if (ebase
.simtime
< sregs
->ftime
) {
1702 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1706 /* Check load dependencies. */
1708 if (ebase
.simtime
< sregs
->ltime
) {
1710 /* Don't check rs1 if single operand instructions */
1712 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1715 /* Adjust for double floats */
1718 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1725 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1729 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1731 /* SPARC is big-endian - swap double floats if host is little-endian */
1732 /* This is ugly - I know ... */
1734 /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1735 but what about machines where float values are different endianness
1736 from integer values? */
1738 #ifdef HOST_LITTLE_ENDIAN
1750 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1751 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1752 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1753 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1763 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1764 sregs
->ftime
+= T_FABSs
;
1765 sregs
->frs1
= 32; /* rs1 ignored */
1768 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1769 sregs
->ftime
+= T_FADDs
;
1772 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1773 sregs
->ftime
+= T_FADDd
;
1777 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1779 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1781 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1785 sregs
->fsr
|= 0x0C00;
1786 sregs
->fsr
&= ~(fcc
<< 10);
1787 sregs
->ftime
+= T_FCMPs
;
1788 sregs
->frd
= 32; /* rd ignored */
1789 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1790 sregs
->fpstate
= FP_EXC_PE
;
1791 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1796 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1798 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1800 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1804 sregs
->fsr
|= 0x0C00;
1805 sregs
->fsr
&= ~(fcc
<< 10);
1806 sregs
->ftime
+= T_FCMPd
;
1807 sregs
->frd
= 32; /* rd ignored */
1808 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1809 sregs
->fpstate
= FP_EXC_PE
;
1810 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1814 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1815 sregs
->ftime
+= T_FDIVs
;
1818 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1819 sregs
->ftime
+= T_FDIVd
;
1822 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1823 sregs
->ftime
+= T_FMOVs
;
1824 sregs
->frs1
= 32; /* rs1 ignored */
1827 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1828 sregs
->ftime
+= T_FMULs
;
1831 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1832 sregs
->ftime
+= T_FMULd
;
1835 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1836 sregs
->ftime
+= T_FNEGs
;
1837 sregs
->frs1
= 32; /* rs1 ignored */
1840 if (sregs
->fs
[rs2
] < 0.0) {
1841 sregs
->fpstate
= FP_EXC_PE
;
1842 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1843 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1846 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1847 sregs
->ftime
+= T_FSQRTs
;
1848 sregs
->frs1
= 32; /* rs1 ignored */
1851 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1852 sregs
->fpstate
= FP_EXC_PE
;
1853 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1854 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1857 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1858 sregs
->ftime
+= T_FSQRTd
;
1859 sregs
->frs1
= 32; /* rs1 ignored */
1862 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1863 sregs
->ftime
+= T_FSUBs
;
1866 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1867 sregs
->ftime
+= T_FSUBd
;
1870 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1871 sregs
->ftime
+= T_FdTOi
;
1872 sregs
->frs1
= 32; /* rs1 ignored */
1875 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1876 sregs
->ftime
+= T_FdTOs
;
1877 sregs
->frs1
= 32; /* rs1 ignored */
1880 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1881 sregs
->ftime
+= T_FiTOs
;
1882 sregs
->frs1
= 32; /* rs1 ignored */
1885 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1886 sregs
->ftime
+= T_FiTOd
;
1887 sregs
->frs1
= 32; /* rs1 ignored */
1890 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1891 sregs
->ftime
+= T_FsTOi
;
1892 sregs
->frs1
= 32; /* rs1 ignored */
1895 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1896 sregs
->ftime
+= T_FsTOd
;
1897 sregs
->frs1
= 32; /* rs1 ignored */
1901 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1902 sregs
->fpstate
= FP_EXC_PE
;
1907 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1908 sregs
->fpstate
= FP_EXC_PE
;
1909 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1914 accex
= get_accex();
1916 #ifdef HOST_LITTLE_ENDIAN
1925 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1926 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1931 if (sregs
->fpstate
== FP_EXC_PE
) {
1932 sregs
->fpq
[0] = sregs
->pc
;
1933 sregs
->fpq
[1] = sregs
->inst
;
1934 sregs
->fsr
|= FSR_QNE
;
1936 tem
= (sregs
->fsr
>> 23) & 0x1f;
1938 sregs
->fpstate
= FP_EXC_PE
;
1939 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1940 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1942 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1944 if (sregs
->fpstate
== FP_EXC_PE
) {
1945 sregs
->fpq
[0] = sregs
->pc
;
1946 sregs
->fpq
[1] = sregs
->inst
;
1947 sregs
->fsr
|= FSR_QNE
;
1958 chk_asi(sregs
, asi
, op3
)
1959 struct pstate
*sregs
;
1963 if (!(sregs
->psr
& PSR_S
)) {
1964 sregs
->trap
= TRAP_PRIVI
;
1966 } else if (sregs
->inst
& INST_I
) {
1967 sregs
->trap
= TRAP_UNIMP
;
1970 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1976 struct pstate
*sregs
;
1980 if (sregs
->trap
== 256) {
1984 } else if (sregs
->trap
== 257) {
1988 if ((sregs
->psr
& PSR_ET
) == 0)
1991 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1993 sregs
->psr
&= ~PSR_ET
;
1994 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1996 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1997 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1998 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1999 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
2000 sregs
->psr
|= PSR_S
;
2001 sregs
->pc
= sregs
->tbr
;
2002 sregs
->npc
= sregs
->tbr
+ 4;
2004 if ( 0 != (1 & sregs
->asr17
) ) {
2005 /* single vector trapping! */
2006 sregs
->pc
= sregs
->tbr
& 0xfffff000;
2007 sregs
->npc
= sregs
->pc
+ 4;
2010 /* Increase simulator time */
2011 sregs
->icnt
= TRAP_C
;
2020 extern struct irqcell irqarr
[16];
2023 check_interrupts(sregs
)
2024 struct pstate
*sregs
;
2028 sregs
->trap
= errtt
;
2029 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2034 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2035 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2036 if (sregs
->trap
== 0) {
2037 sregs
->trap
= 16 + ext_irl
;
2038 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2047 struct pstate
*sregs
;
2052 sregs
->psr
&= 0x00f03fdf;
2053 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2054 sregs
->breakpoint
= 0;
2056 sregs
->fpstate
= FP_EXE_MODE
;
2060 sregs
->err_mode
= 0;
2063 #ifdef HOST_LITTLE_ENDIAN
2064 sregs
->fdp
= (float32
*) sregs
->fd
;
2065 sregs
->fsi
= (int32
*) sregs
->fs
;
2067 sregs
->fs
= (float32
*) sregs
->fd
;
2068 sregs
->fsi
= (int32
*) sregs
->fd
;
2071 sregs
->fpu_pres
= !nfp
;
2072 set_fsr(sregs
->fsr
);
2080 sregs
->rett_err
= 0;
2081 sregs
->jmpltime
= 0;
This page took 0.075729 seconds and 4 git commands to generate.