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 2 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, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
28 extern int32 ext_irl
, irqpend
, iurev0
, sis_verbose
;
30 /* Load/store interlock delay */
33 /* Load delay (delete if unwanted - speeds up simulation) */
44 #define FSR_QNE 0x2000
68 #define PSR_N 0x0800000
69 #define PSR_Z 0x0400000
70 #define PSR_V 0x0200000
71 #define PSR_C 0x0100000
72 #define PSR_CC 0x0F00000
74 #define PSR_PIL 0x0f00
76 #define ICC_N sregs->psr
77 #define ICC_Z (sregs->psr << 1)
78 #define ICC_V (sregs->psr << 2)
79 #define ICC_C (sregs->psr << 3)
92 #define FSR_TT 0x1C000
93 #define FP_IEEE 0x04000
94 #define FP_UNIMP 0x0C000
95 #define FP_SEQ_ERR 0x10000
107 #define INST_SIMM13 0x1fff
108 #define INST_RS2 0x1f
109 #define INST_I 0x2000
115 #define TADDCCTV 0x22
184 /* # of cycles overhead when a trap is taken */
188 extern struct estate ebase
;
191 sub_cc(operand1
, operand2
, result
, sregs
)
195 struct pstate
*sregs
;
197 sregs
->psr
= ((sregs
->psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
199 sregs
->psr
&= ~PSR_Z
;
202 sregs
->psr
= (sregs
->psr
& ~PSR_V
) | ((
203 ((operand1
& ~operand2
& ~result
) |
204 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
205 sregs
->psr
= (sregs
->psr
& ~PSR_C
) | ((
206 ((~operand1
& operand2
) |
207 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
210 add_cc(operand1
, operand2
, result
, psr
)
216 *psr
= ((*psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
221 *psr
= (*psr
& ~PSR_V
) | ((
222 ((operand1
& operand2
& ~result
) |
223 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
224 *psr
= (*psr
& ~PSR_C
) | ((
225 ((operand1
& operand2
) |
226 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
229 log_cc(result
, sregs
)
231 struct pstate
*sregs
;
233 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
234 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
240 dispatch_instruction(sregs
)
241 struct pstate
*sregs
;
244 uint32 cwp
, op
, op2
, op3
, opf
, opc
, asi
, a
, rd
, cond
, rs1
,
247 int32 operand1
, operand2
, *rdd
, result
, i
, disp22
, eicc
,
249 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
253 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
254 op
= sregs
->inst
>> 30;
256 npc
= sregs
->npc
+ 4;
259 op3
= (sregs
->inst
>> 19) & 0x3f;
260 rs1
= (sregs
->inst
>> 14) & 0x1f;
261 rd
= (sregs
->inst
>> 25) & 0x1f;
265 /* Check if load dependecy is possible */
266 ldep
= ((ebase
.simtime
<= sregs
->ildtime
) && ((op3
& 0x38) != 0x28) &&
267 ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
268 if (sregs
->inst
& INST_I
) {
269 if (ldep
&& (sregs
->ildreg
== rs1
))
271 operand2
= sregs
->inst
& INST_SIMM13
;
272 if (operand2
> 0x0fff)
273 operand2
|= 0xfffff000;
275 rs2
= sregs
->inst
& INST_RS2
;
277 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
279 operand2
= sregs
->g
[rs2
];
280 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
284 if (sregs
->inst
& INST_I
) {
285 operand2
= sregs
->inst
& INST_SIMM13
;
286 if (operand2
> 0x0fff)
287 operand2
|= 0xfffff000;
289 rs2
= sregs
->inst
& INST_RS2
;
291 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
293 operand2
= sregs
->g
[rs2
];
298 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
300 rdd
= &(sregs
->g
[rd
]);
302 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
308 op2
= (sregs
->inst
>> 22) & 0x7;
311 rd
= (sregs
->inst
>> 25) & 0x1f;
313 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
315 rdd
= &(sregs
->g
[rd
]);
316 *rdd
= sregs
->inst
<< 10;
322 cond
= ((sregs
->inst
>> 25) & 0x0f);
323 switch (cond
& 0x7) {
331 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
334 eicc
= (ICC_N
^ ICC_V
);
337 eicc
= ICC_C
| ICC_Z
;
350 if (sregs
->inst
& 0x10000000)
352 a
= sregs
->inst
& 0x20000000;
354 operand1
= sregs
->inst
& 0x3fffff;
355 if (sregs
->inst
& 0x200000)
356 operand1
|= 0xffc00000;
357 npc
= sregs
->pc
+ (operand1
<< 2);
358 if ((cond
== BICC_BA
) && (a
))
369 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
370 sregs
->trap
= TRAP_FPDIS
;
373 if (ebase
.simtime
< sregs
->ftime
) {
374 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
376 cond
= ((sregs
->inst
>> 25) & 0x0f);
377 fcc
= (sregs
->fsr
>> 10) & 0x3;
378 switch (cond
& 0x7) {
383 eicc
= (fcc
!= FCC_E
);
386 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
389 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
392 eicc
= (fcc
== FCC_L
);
395 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
398 eicc
= (fcc
== FCC_G
);
401 eicc
= (fcc
== FCC_U
);
404 if (sregs
->inst
& 0x10000000)
406 a
= sregs
->inst
& 0x20000000;
408 operand1
= sregs
->inst
& 0x3fffff;
409 if (sregs
->inst
& 0x200000)
410 operand1
|= 0xffc00000;
411 npc
= sregs
->pc
+ (operand1
<< 2);
412 if ((cond
== FBA
) && (a
))
421 sregs
->trap
= TRAP_UNIMP
;
429 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
430 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
434 if ((op3
>> 1) == 0x1a) {
435 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
436 sregs
->trap
= TRAP_FPDIS
;
438 rs1
= (sregs
->inst
>> 14) & 0x1f;
439 rs2
= sregs
->inst
& 0x1f;
440 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
446 cond
= ((sregs
->inst
>> 25) & 0x0f);
447 switch (cond
& 0x7) {
455 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
458 eicc
= (ICC_N
^ ICC_V
);
461 eicc
= ICC_C
| ICC_Z
;
474 if (sregs
->inst
& 0x10000000)
477 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
483 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
485 if ((sregs
->y
& 1) == 0)
487 *rdd
= operand1
+ operand2
;
488 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
489 add_cc(operand1
, operand2
, *rdd
, &sregs
->psr
);
492 *rdd
= rs1
^ ~operand2
;
495 *rdd
= rs1
^ ~operand2
;
499 *rdd
= rs1
^ operand2
;
502 *rdd
= rs1
^ operand2
;
506 *rdd
= rs1
| operand2
;
509 *rdd
= rs1
| operand2
;
513 *rdd
= rs1
| ~operand2
;
516 *rdd
= rs1
| ~operand2
;
520 *rdd
= rs1
& ~operand2
;
524 *rdd
= rs1
& ~operand2
;
527 *rdd
= rs1
& operand2
;
530 *rdd
= rs1
& operand2
;
534 *rdd
= rs1
- operand2
;
537 *rdd
= rs1
- operand2
;
538 sub_cc(rs1
, operand2
, *rdd
, sregs
);
541 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
544 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
545 sub_cc(rs1
, operand2
, *rdd
, sregs
);
548 *rdd
= rs1
+ operand2
;
551 *rdd
= rs1
+ operand2
;
552 add_cc(rs1
, operand2
, *rdd
, &sregs
->psr
);
555 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
558 *rdd
= rs1
+ operand2
+ ((sregs
->psr
>> 20) & 1);
559 add_cc(rs1
, operand2
, *rdd
, &sregs
->psr
);
562 *rdd
= rs1
+ operand2
;
563 add_cc(rs1
, operand2
, *rdd
, &sregs
->psr
);
564 if ((rs1
| operand2
) & 0x3)
568 *rdd
= rs1
+ operand2
;
570 add_cc(rs1
, operand2
, *rdd
, &result
);
571 if ((rs1
| operand2
) & 0x3)
573 if (result
& PSR_V
) {
574 sregs
->trap
= TRAP_TAG
;
576 sregs
->psr
= (sregs
->psr
& PSR_CC
) | result
;
580 *rdd
= rs1
<< (operand2
& 0x1f);
583 *rdd
= rs1
>> (operand2
& 0x1f);
586 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
589 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
590 if (sregs
->wim
& (1 << new_cwp
)) {
591 sregs
->trap
= TRAP_WOFL
;
595 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
596 *rdd
= rs1
+ operand2
;
597 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
602 if ((iurev0
) && ((sregs
->jmpltime
+ 1) == sregs
->ninst
)) {
603 if (!(sregs
->rett_err
)) {
606 printf("IU rev.0 bug mode entered\n");
611 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
612 if (sregs
->wim
& (1 << new_cwp
)) {
613 sregs
->trap
= TRAP_WUFL
;
617 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
618 *rdd
= rs1
+ operand2
;
619 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
622 if (!(sregs
->psr
& PSR_S
)) {
623 sregs
->trap
= TRAP_PRIVI
;
629 if (iurev0
& sregs
->rett_err
) {
630 operand2
= sregs
->psr
;
633 *rdd
|= ((*rdd
& PSR_PS
) << 1);
635 if (operand2
!= *rdd
)
636 printf("rdpsr failed: %08X -> %08X\n", operand2
, *rdd
);
642 if (!(sregs
->psr
& PSR_S
)) {
643 sregs
->trap
= TRAP_PRIVI
;
649 if (!(sregs
->psr
& PSR_S
)) {
650 sregs
->trap
= TRAP_PRIVI
;
656 if (!(sregs
->psr
& PSR_S
)) {
657 sregs
->trap
= TRAP_PRIVI
;
663 if ((sregs
->psr
& 0x1f) > 7) {
664 sregs
->trap
= TRAP_UNIMP
;
667 if (!(sregs
->psr
& PSR_S
)) {
668 sregs
->trap
= TRAP_PRIVI
;
671 sregs
->psr
= (rs1
^ operand2
) & 0x00f03fff;
674 if (!(sregs
->psr
& PSR_S
)) {
675 sregs
->trap
= TRAP_PRIVI
;
678 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
681 if (!(sregs
->psr
& PSR_S
)) {
682 sregs
->trap
= TRAP_PRIVI
;
685 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
686 ((rs1
^ operand2
) & 0xfffff000);
689 sregs
->y
= (rs1
^ operand2
);
695 sregs
->jmpltime
= sregs
->ninst
;
700 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
702 sregs
->trap
= TRAP_UNALI
;
706 npc
= rs1
+ operand2
;
710 if (iurev0
&& sregs
->rett_err
) {
713 printf("IU rev.0 bug mode reset\n");
717 address
= rs1
+ operand2
;
718 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
719 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
720 if (sregs
->psr
& PSR_ET
) {
721 sregs
->trap
= TRAP_UNIMP
;
724 if (!(sregs
->psr
& PSR_S
)) {
725 sregs
->trap
= TRAP_PRIVI
;
728 if (sregs
->wim
& (1 << new_cwp
)) {
729 sregs
->trap
= TRAP_WUFL
;
733 sregs
->trap
= TRAP_UNALI
;
736 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
738 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
743 sregs
->trap
= TRAP_UNIMP
;
748 case 3: /* Load/store instructions */
750 address
= rs1
+ operand2
;
752 /* Check for load/store to alternate address space */
754 if ((op3
>> 4) == 1) {
755 if (!(sregs
->psr
& PSR_S
)) {
756 sregs
->trap
= TRAP_PRIVI
;
758 } else if (sregs
->inst
& INST_I
) {
759 sregs
->trap
= TRAP_UNIMP
;
762 asi
= (sregs
->inst
>> 5) & 0x0ff;
764 if (sregs
->psr
& PSR_S
)
769 if (iurev0
&& sregs
->rett_err
) {
771 asi
|= ((sregs
->psr
& PSR_PS
) >> 6);
777 sregs
->icnt
= T_ST
; /* Set store instruction count */
782 sregs
->icnt
= T_LD
; /* Set load instruction count */
788 /* Decode load/store instructions */
794 sregs
->trap
= TRAP_UNALI
;
800 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
802 rdd
= &(sregs
->g
[rd
]);
804 mexc
= memory_read(asi
, address
, &data
, &ws
);
808 sregs
->trap
= TRAP_DEXC
;
812 mexc
= memory_read(asi
, address
, &data
, &ws
);
815 sregs
->nload
++; /* Double load counts twice */
818 sregs
->trap
= TRAP_DEXC
;
828 sregs
->trap
= TRAP_UNALI
;
831 mexc
= memory_read(asi
, address
, &data
, &ws
);
834 sregs
->trap
= TRAP_DEXC
;
841 mexc
= memory_read(asi
, address
, &data
, &ws
);
843 sregs
->icnt
= T_LDST
;
845 sregs
->trap
= TRAP_DEXC
;
848 data
= (data
>> ((3 - (address
& 0x3)) << 3)) & 0x0ff;
851 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
854 sregs
->trap
= TRAP_DEXC
;
864 mexc
= memory_read(asi
, address
, &data
, &ws
);
867 sregs
->trap
= TRAP_DEXC
;
870 data
= (data
>> ((3 - (address
& 0x3)) << 3)) & 0x0ff;
871 if ((op3
== LDSB
) && (data
>> 7))
880 sregs
->trap
= TRAP_UNALI
;
883 mexc
= memory_read(asi
, address
, &data
, &ws
);
886 sregs
->trap
= TRAP_DEXC
;
889 if (!(address
& 0x2))
892 if ((op3
== LDSH
) && (data
>> 15))
897 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
898 sregs
->trap
= TRAP_FPDIS
;
902 sregs
->trap
= TRAP_UNALI
;
905 if (ebase
.simtime
< sregs
->ftime
) {
906 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
908 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
910 mexc
= memory_read(asi
, address
, &data
, &ws
);
913 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
914 sregs
->hold
+ sregs
->fhold
;
916 sregs
->trap
= TRAP_DEXC
;
918 sregs
->fs
[rd
] = *((float32
*) & data
);
922 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
923 sregs
->trap
= TRAP_FPDIS
;
927 sregs
->trap
= TRAP_UNALI
;
930 if (ebase
.simtime
< sregs
->ftime
) {
931 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
932 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
933 ((sregs
->frs2
>> 1) == (rd
>> 1)))
934 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
936 mexc
= memory_read(asi
, address
, &data
, &ws
);
940 sregs
->trap
= TRAP_DEXC
;
944 sregs
->fs
[rd
] = *((float32
*) & data
);
945 mexc
= memory_read(asi
, address
+ 4, &data
, &ws
);
948 sregs
->nload
++; /* Double load counts twice */
951 sregs
->trap
= TRAP_DEXC
;
953 sregs
->fs
[rd
+ 1] = *((float32
*) & data
);
954 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
955 sregs
->hold
+ sregs
->fhold
;
960 if (ebase
.simtime
< sregs
->ftime
) {
961 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
963 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
964 sregs
->trap
= TRAP_FPDIS
;
968 sregs
->trap
= TRAP_UNALI
;
971 mexc
= memory_read(asi
, address
, &data
, &ws
);
974 sregs
->trap
= TRAP_DEXC
;
977 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
982 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
983 sregs
->trap
= TRAP_FPDIS
;
987 sregs
->trap
= TRAP_UNALI
;
990 if (ebase
.simtime
< sregs
->ftime
) {
991 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
993 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
996 sregs
->trap
= TRAP_DEXC
;
1002 if (address
& 0x3) {
1003 sregs
->trap
= TRAP_UNALI
;
1006 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1009 sregs
->trap
= TRAP_DEXC
;
1014 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1017 sregs
->trap
= TRAP_DEXC
;
1022 if (address
& 0x7) {
1023 sregs
->trap
= TRAP_UNALI
;
1029 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1031 rdd
= &(sregs
->g
[rd
]);
1033 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1035 sregs
->icnt
= T_STD
;
1037 sregs
->nstore
++; /* Double store counts twice */
1040 sregs
->trap
= TRAP_DEXC
;
1045 if ((sregs
->psr
& 0x1f) > 7) {
1046 sregs
->trap
= TRAP_UNIMP
;
1049 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
1050 sregs
->trap
= TRAP_FPDIS
;
1053 if (address
& 0x7) {
1054 sregs
->trap
= TRAP_UNALI
;
1057 if (!(sregs
->fsr
& FSR_QNE
)) {
1058 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1061 rdd
= &(sregs
->fpq
[0]);
1062 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1064 sregs
->icnt
= T_STD
;
1066 sregs
->nstore
++; /* Double store counts twice */
1069 sregs
->trap
= TRAP_DEXC
;
1072 sregs
->fsr
&= ~FSR_QNE
;
1073 sregs
->fpstate
= FP_EXE_MODE
;
1078 if (address
& 0x1) {
1079 sregs
->trap
= TRAP_UNALI
;
1082 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1085 sregs
->trap
= TRAP_DEXC
;
1089 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
1090 sregs
->trap
= TRAP_FPDIS
;
1093 if (address
& 0x3) {
1094 sregs
->trap
= TRAP_UNALI
;
1097 if (ebase
.simtime
< sregs
->ftime
) {
1098 if (sregs
->frd
== rd
)
1099 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1101 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1104 sregs
->trap
= TRAP_DEXC
;
1108 if (!((sregs
->psr
& PSR_EF
) && chk_fp(sregs
))) {
1109 sregs
->trap
= TRAP_FPDIS
;
1112 if (address
& 0x7) {
1113 sregs
->trap
= TRAP_UNALI
;
1117 if (ebase
.simtime
< sregs
->ftime
) {
1118 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1119 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1121 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1123 sregs
->icnt
= T_STD
;
1125 sregs
->nstore
++; /* Double store counts twice */
1128 sregs
->trap
= TRAP_DEXC
;
1133 if (address
& 0x3) {
1134 sregs
->trap
= TRAP_UNALI
;
1137 mexc
= memory_read(asi
, address
, &data
, &ws
);
1140 sregs
->trap
= TRAP_DEXC
;
1143 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1145 sregs
->icnt
= T_LDST
;
1147 sregs
->trap
= TRAP_DEXC
;
1158 sregs
->trap
= TRAP_UNIMP
;
1165 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1167 if ((op3
| 0x10) == 0x13)
1168 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1175 sregs
->trap
= TRAP_UNIMP
;
1234 fpexec(op3
, rd
, rs1
, rs2
, sregs
)
1235 uint32 op3
, rd
, rs1
, rs2
;
1236 struct pstate
*sregs
;
1238 uint32 opf
, tem
, accex
;
1245 if (sregs
->fpstate
== FP_EXC_MODE
) {
1246 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1247 sregs
->fpstate
== FP_EXC_PE
;
1250 if (sregs
->fpstate
== FP_EXC_PE
) {
1251 sregs
->fpstate
= FP_EXC_MODE
;
1252 return (TRAP_FPEXC
);
1254 opf
= (sregs
->inst
>> 5) & 0x1ff;
1257 * Check if we already have an FPop in the pipe. If so, halt until it is
1258 * finished by incrementing fhold with the remaining execution time
1261 if (ebase
.simtime
< sregs
->ftime
) {
1262 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1266 /* Check load dependencies. */
1268 if (ebase
.simtime
< sregs
->ltime
) {
1270 /* Don't check rs1 if single operand instructions */
1272 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1275 /* Adjust for double floats */
1278 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1285 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1289 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1291 /* SPARC is big-endian - swap double floats if host is little-endian */
1292 /* This is ugly - I know ... */
1293 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1305 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1306 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1307 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1308 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1317 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1318 sregs
->ftime
+= T_FABSs
;
1319 sregs
->frs1
= 32; /* rs1 ignored */
1322 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1323 sregs
->ftime
+= T_FADDs
;
1326 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1327 sregs
->ftime
+= T_FADDd
;
1331 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1333 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1335 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1339 sregs
->fsr
|= 0x0C00;
1340 sregs
->fsr
&= ~(fcc
<< 10);
1341 sregs
->ftime
+= T_FCMPs
;
1342 sregs
->frd
= 32; /* rd ignored */
1343 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1344 sregs
->fpstate
== FP_EXC_PE
;
1345 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1350 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1352 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1354 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1358 sregs
->fsr
|= 0x0C00;
1359 sregs
->fsr
&= ~(fcc
<< 10);
1360 sregs
->ftime
+= T_FCMPd
;
1361 sregs
->frd
= 32; /* rd ignored */
1362 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1363 sregs
->fpstate
== FP_EXC_PE
;
1364 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1368 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1369 sregs
->ftime
+= T_FDIVs
;
1372 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1373 sregs
->ftime
+= T_FDIVd
;
1376 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1377 sregs
->ftime
+= T_FMOVs
;
1378 sregs
->frs1
= 32; /* rs1 ignored */
1381 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1382 sregs
->ftime
+= T_FMULs
;
1385 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1386 sregs
->ftime
+= T_FMULd
;
1389 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1390 sregs
->ftime
+= T_FNEGs
;
1391 sregs
->frs1
= 32; /* rs1 ignored */
1394 if (sregs
->fs
[rs2
] < 0.0) {
1395 sregs
->fpstate
== FP_EXC_PE
;
1396 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1397 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1400 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1401 sregs
->ftime
+= T_FSQRTs
;
1402 sregs
->frs1
= 32; /* rs1 ignored */
1405 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1406 sregs
->fpstate
== FP_EXC_PE
;
1407 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1408 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1411 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1412 sregs
->ftime
+= T_FSQRTd
;
1413 sregs
->frs1
= 32; /* rs1 ignored */
1416 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1417 sregs
->ftime
+= T_FSUBs
;
1420 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1421 sregs
->ftime
+= T_FSUBd
;
1424 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1425 sregs
->ftime
+= T_FdTOi
;
1426 sregs
->frs1
= 32; /* rs1 ignored */
1429 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1430 sregs
->ftime
+= T_FdTOs
;
1431 sregs
->frs1
= 32; /* rs1 ignored */
1434 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1435 sregs
->ftime
+= T_FiTOs
;
1436 sregs
->frs1
= 32; /* rs1 ignored */
1439 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1440 sregs
->ftime
+= T_FiTOd
;
1441 sregs
->frs1
= 32; /* rs1 ignored */
1444 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1445 sregs
->ftime
+= T_FsTOi
;
1446 sregs
->frs1
= 32; /* rs1 ignored */
1449 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1450 sregs
->ftime
+= T_FsTOd
;
1451 sregs
->frs1
= 32; /* rs1 ignored */
1455 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1456 sregs
->fpstate
== FP_EXC_PE
;
1459 accex
= get_accex();
1461 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1470 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1471 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1475 if (sregs
->fpstate
== FP_EXC_PE
) {
1476 sregs
->fpq
[0] = sregs
->pc
;
1477 sregs
->fpq
[1] = sregs
->inst
;
1478 sregs
->fsr
|= FSR_QNE
;
1480 tem
= (sregs
->fsr
>> 23) & 0x1f;
1482 sregs
->fpstate
= FP_EXC_PE
;
1483 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1484 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1486 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1488 if (sregs
->fpstate
== FP_EXC_PE
) {
1489 sregs
->fpq
[0] = sregs
->pc
;
1490 sregs
->fpq
[1] = sregs
->inst
;
1491 sregs
->fsr
|= FSR_QNE
;
1503 struct pstate
*sregs
;
1507 if (sregs
->trap
== 256) {
1513 if ((sregs
->psr
& PSR_ET
) == 0)
1516 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1518 sregs
->psr
&= ~PSR_ET
;
1519 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1521 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1522 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1523 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1524 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1525 sregs
->psr
|= PSR_S
;
1526 sregs
->pc
= sregs
->tbr
;
1527 sregs
->npc
= sregs
->tbr
+ 4;
1529 /* Increase simulator time */
1530 sregs
->icnt
= TRAP_C
;
1539 extern struct irqcell irqarr
[16];
1542 check_interrupts(sregs
)
1543 struct pstate
*sregs
;
1545 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
1546 ((ext_irl
== 15) || (ext_irl
> ((sregs
->psr
& PSR_PIL
) >> 8)))) {
1547 if (sregs
->trap
== 0) {
1548 sregs
->trap
= 16 + ext_irl
;
1549 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
1556 struct pstate
*sregs
;
1563 sregs
->psr
&= 0x00f03fdf;
1564 sregs
->psr
|= 0x080; /* Set supervisor bit */
1565 sregs
->breakpoint
= 0;
1567 sregs
->fpstate
= FP_EXE_MODE
;
1571 sregs
->err_mode
= 0;
1575 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1576 sregs
->fdp
= (float32
*) sregs
->fd
;
1577 sregs
->fsi
= (int32
*) sregs
->fs
;
1579 sregs
->fs
= (float32
*) sregs
->fd
;
1580 sregs
->fsi
= (int32
*) sregs
->fd
;
1583 sregs
->fpu_pres
= !nfp
;
1584 set_fsr(sregs
->fsr
);
1589 sregs
->rett_err
= 0;
1590 sregs
->jmpltime
= 0;
1594 struct pstate
*sregs
;
1596 return (sregs
->fpu_pres
);
This page took 0.064549 seconds and 4 git commands to generate.