]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/erc32/exec.c
8daf759514ecd04b1b58315e24583fe19f6354de
1 /* This file is part of SIS (SPARC instruction simulator)
3 Copyright (C) 1995-2021 Free Software Foundation, Inc.
4 Contributed by Jiri Gaisler, European Space Agency
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 extern int32 sis_verbose
, sparclite
;
27 /* Load/store interlock delay */
30 /* Load delay (delete if unwanted - speeds up simulation) */
41 #define FSR_QNE 0x2000
73 #define PSR_N 0x0800000
74 #define PSR_Z 0x0400000
75 #define PSR_V 0x0200000
76 #define PSR_C 0x0100000
77 #define PSR_CC 0x0F00000
79 #define PSR_PIL 0x0f00
81 #define ICC_N (icc >> 3)
82 #define ICC_Z (icc >> 2)
83 #define ICC_V (icc >> 1)
86 #define FP_PRES (sregs->fpu_pres)
98 #define TRAP_DIV0 0x2a
100 #define FSR_TT 0x1C000
101 #define FP_IEEE 0x04000
102 #define FP_UNIMP 0x0C000
103 #define FP_SEQ_ERR 0x10000
122 #define INST_SIMM13 0x1fff
123 #define INST_RS2 0x1f
124 #define INST_I 0x2000
131 #define TADDCCTV 0x22
132 #define TSUBCCTV 0x23
212 #define SIGN_BIT 0x80000000
214 /* # of cycles overhead when a trap is taken */
217 /* Forward declarations */
219 static uint32
sub_cc (uint32 psr
, int32 operand1
, int32 operand2
,
221 static uint32
add_cc (uint32 psr
, int32 operand1
, int32 operand2
,
223 static void log_cc (int32 result
, struct pstate
*sregs
);
224 static int fpexec (uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
,
225 struct pstate
*sregs
);
226 static int chk_asi (struct pstate
*sregs
, uint32
*asi
, uint32 op3
);
229 extern struct estate ebase
;
230 extern int32 nfp
,ift
;
233 extern uint32 errtt
, errftt
;
237 sub_cc(uint32 psr
, int32 operand1
, int32 operand2
, int32 result
)
239 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
244 psr
= (psr
& ~PSR_V
) | ((((operand1
& ~operand2
& ~result
) |
245 (~operand1
& operand2
& result
)) >> 10) & PSR_V
);
246 psr
= (psr
& ~PSR_C
) | ((((~operand1
& operand2
) |
247 ((~operand1
| operand2
) & result
)) >> 11) & PSR_C
);
252 add_cc(uint32 psr
, int32 operand1
, int32 operand2
, int32 result
)
254 psr
= ((psr
& ~PSR_N
) | ((result
>> 8) & PSR_N
));
259 psr
= (psr
& ~PSR_V
) | ((((operand1
& operand2
& ~result
) |
260 (~operand1
& ~operand2
& result
)) >> 10) & PSR_V
);
261 psr
= (psr
& ~PSR_C
) | ((((operand1
& operand2
) |
262 ((operand1
| operand2
) & ~result
)) >> 11) & PSR_C
);
267 log_cc(int32 result
, struct pstate
*sregs
)
269 sregs
->psr
&= ~(PSR_CC
); /* Zero CC bits */
270 sregs
->psr
= (sregs
->psr
| ((result
>> 8) & PSR_N
));
275 /* Add two unsigned 32-bit integers, and calculate the carry out. */
278 add32 (uint32 n1
, uint32 n2
, int *carry
)
280 uint32 result
= n1
+ n2
;
282 *carry
= result
< n1
|| result
< n2
;
286 /* Multiply two 32-bit integers. */
289 mul64 (uint32 n1
, uint32 n2
, uint32
*result_hi
, uint32
*result_lo
, int msigned
)
291 uint32 lo
, mid1
, mid2
, hi
, reg_lo
, reg_hi
;
295 /* If this is a signed multiply, calculate the sign of the result
296 and make the operands positive. */
299 sign
= (n1
^ n2
) & SIGN_BIT
;
307 /* We can split the 32x32 into four 16x16 operations. This ensures
308 that we do not lose precision on 32bit only hosts: */
309 lo
= ((n1
& 0xFFFF) * (n2
& 0xFFFF));
310 mid1
= ((n1
& 0xFFFF) * ((n2
>> 16) & 0xFFFF));
311 mid2
= (((n1
>> 16) & 0xFFFF) * (n2
& 0xFFFF));
312 hi
= (((n1
>> 16) & 0xFFFF) * ((n2
>> 16) & 0xFFFF));
314 /* We now need to add all of these results together, taking care
315 to propogate the carries from the additions: */
316 reg_lo
= add32 (lo
, (mid1
<< 16), &carry
);
318 reg_lo
= add32 (reg_lo
, (mid2
<< 16), &carry
);
319 reg_hi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
321 /* Negate result if necessary. */
335 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
336 that the host compiler supports long long operations. */
339 div64 (uint32 n1_hi
, uint32 n1_low
, uint32 n2
, uint32
*result
, int msigned
)
343 n1
= ((uint64
) n1_hi
) << 32;
344 n1
|= ((uint64
) n1_low
) & 0xffffffff;
348 int64 n1_s
= (int64
) n1
;
349 int32 n2_s
= (int32
) n2
;
356 *result
= (uint32
) (n1
& 0xffffffff);
361 extract_short (uint32 data
, uint32 address
)
363 return ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
367 extract_short_signed (uint32 data
, uint32 address
)
369 uint32 tmp
= ((data
>> ((2 - (address
& 2)) * 8)) & 0xffff);
376 extract_byte (uint32 data
, uint32 address
)
378 return ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
382 extract_byte_signed (uint32 data
, uint32 address
)
384 uint32 tmp
= ((data
>> ((3 - (address
& 3)) * 8)) & 0xff);
391 dispatch_instruction(struct pstate
*sregs
)
394 uint32 cwp
, op
, op2
, op3
, asi
, rd
, cond
, rs1
,
397 int32 operand1
, operand2
, *rdd
, result
, eicc
,
399 int32 pc
, npc
, data
, address
, ws
, mexc
, fcc
;
403 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
404 op
= sregs
->inst
>> 30;
406 npc
= sregs
->npc
+ 4;
407 op3
= rd
= rs1
= operand2
= eicc
= 0;
411 op3
= (sregs
->inst
>> 19) & 0x3f;
412 rs1
= (sregs
->inst
>> 14) & 0x1f;
413 rd
= (sregs
->inst
>> 25) & 0x1f;
417 /* Check if load dependecy is possible */
418 if (ebase
.simtime
<= sregs
->ildtime
)
419 ldep
= (((op3
& 0x38) != 0x28) && ((op3
& 0x3e) != 0x34) && (sregs
->ildreg
!= 0));
422 if (sregs
->inst
& INST_I
) {
423 if (ldep
&& (sregs
->ildreg
== rs1
))
425 operand2
= sregs
->inst
;
426 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
428 rs2
= sregs
->inst
& INST_RS2
;
430 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
432 operand2
= sregs
->g
[rs2
];
433 if (ldep
&& ((sregs
->ildreg
== rs1
) || (sregs
->ildreg
== rs2
)))
437 if (sregs
->inst
& INST_I
) {
438 operand2
= sregs
->inst
;
439 operand2
= ((operand2
<< 19) >> 19); /* sign extend */
441 rs2
= sregs
->inst
& INST_RS2
;
443 operand2
= sregs
->r
[(cwp
+ rs2
) & 0x7f];
445 operand2
= sregs
->g
[rs2
];
450 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
452 rdd
= &(sregs
->g
[rd
]);
454 rs1
= sregs
->r
[(cwp
+ rs1
) & 0x7f];
460 op2
= (sregs
->inst
>> 22) & 0x7;
463 rd
= (sregs
->inst
>> 25) & 0x1f;
465 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
467 rdd
= &(sregs
->g
[rd
]);
468 *rdd
= sregs
->inst
<< 10;
474 icc
= sregs
->psr
>> 20;
475 cond
= ((sregs
->inst
>> 25) & 0x0f);
484 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
487 eicc
= (ICC_N
^ ICC_V
);
490 eicc
= ICC_C
| ICC_Z
;
503 if (sregs
->inst
& 0x20000000)
510 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
513 eicc
= ~(ICC_N
^ ICC_V
);
516 eicc
= ~(ICC_C
| ICC_Z
);
529 operand1
= sregs
->inst
;
530 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
531 npc
= sregs
->pc
+ operand1
;
533 if (sregs
->inst
& 0x20000000)
541 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
542 sregs
->trap
= TRAP_FPDIS
;
545 if (ebase
.simtime
< sregs
->ftime
) {
546 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
;
548 cond
= ((sregs
->inst
>> 25) & 0x0f);
549 fcc
= (sregs
->fsr
>> 10) & 0x3;
555 eicc
= (fcc
!= FCC_E
);
558 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_G
);
561 eicc
= (fcc
== FCC_L
) || (fcc
== FCC_U
);
564 eicc
= (fcc
== FCC_L
);
567 eicc
= (fcc
== FCC_G
) || (fcc
== FCC_U
);
570 eicc
= (fcc
== FCC_G
);
573 eicc
= (fcc
== FCC_U
);
577 if (sregs
->inst
& 0x20000000)
581 eicc
= !(fcc
!= FCC_E
);
584 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_G
));
587 eicc
= !((fcc
== FCC_L
) || (fcc
== FCC_U
));
590 eicc
= !(fcc
== FCC_L
);
593 eicc
= !((fcc
== FCC_G
) || (fcc
== FCC_U
));
596 eicc
= !(fcc
== FCC_G
);
599 eicc
= !(fcc
== FCC_U
);
603 operand1
= sregs
->inst
;
604 operand1
= ((operand1
<< 10) >> 8); /* sign extend */
605 npc
= sregs
->pc
+ operand1
;
607 if (sregs
->inst
& 0x20000000)
613 sregs
->trap
= TRAP_UNIMP
;
621 sregs
->r
[(cwp
+ 15) & 0x7f] = sregs
->pc
;
622 npc
= sregs
->pc
+ (sregs
->inst
<< 2);
626 if ((op3
>> 1) == 0x1a) {
627 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
628 sregs
->trap
= TRAP_FPDIS
;
630 rs1
= (sregs
->inst
>> 14) & 0x1f;
631 rs2
= sregs
->inst
& 0x1f;
632 sregs
->trap
= fpexec(op3
, rd
, rs1
, rs2
, sregs
);
638 icc
= sregs
->psr
>> 20;
639 cond
= ((sregs
->inst
>> 25) & 0x0f);
648 eicc
= ICC_Z
| (ICC_N
^ ICC_V
);
651 eicc
= (ICC_N
^ ICC_V
);
654 eicc
= ICC_C
| ICC_Z
;
672 eicc
= ~(ICC_Z
| (ICC_N
^ ICC_V
));
675 eicc
= ~(ICC_N
^ ICC_V
);
678 eicc
= ~(ICC_C
| ICC_Z
);
691 sregs
->trap
= (0x80 | ((rs1
+ operand2
) & 0x7f));
697 (((sregs
->psr
& PSR_V
) ^ ((sregs
->psr
& PSR_N
) >> 2))
699 if ((sregs
->y
& 1) == 0)
701 *rdd
= operand1
+ operand2
;
702 sregs
->y
= (rs1
<< 31) | (sregs
->y
>> 1);
703 sregs
->psr
= add_cc(sregs
->psr
, operand1
, operand2
, *rdd
);
708 uint32 result
, remainder
;
712 sregs
->trap
= TRAP_UNIMP
;
716 sign
= ((sregs
->psr
& PSR_V
) != 0) ^ ((sregs
->psr
& PSR_N
) != 0);
718 remainder
= (sregs
->y
<< 1) | (rs1
>> 31);
720 /* If true sign is positive, calculate remainder - divisor.
721 Otherwise, calculate remainder + divisor. */
723 operand2
= ~operand2
+ 1;
724 result
= remainder
+ operand2
;
726 /* The SPARClite User's Manual is not clear on how
727 the "carry out" of the above ALU operation is to
728 be calculated. From trial and error tests
729 on the the chip itself, it appears that it is
730 a normal addition carry, and not a subtraction borrow,
731 even in cases where the divisor is subtracted
732 from the remainder. FIXME: get the true story
734 c0
= result
< (uint32
) remainder
735 || result
< (uint32
) operand2
;
737 if (result
& 0x80000000)
740 sregs
->psr
&= ~PSR_N
;
742 y31
= (sregs
->y
& 0x80000000) == 0x80000000;
744 if (result
== 0 && sign
== y31
)
747 sregs
->psr
&= ~PSR_Z
;
749 sign
= (sign
&& !y31
) || (!c0
&& (sign
|| !y31
));
751 if (sign
^ (result
>> 31))
754 sregs
->psr
&= ~PSR_V
;
759 sregs
->psr
&= ~PSR_C
;
764 *rdd
= (rs1
<< 1) | !sign
;
769 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 1);
776 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 1);
778 if (result
& 0x80000000)
781 sregs
->psr
&= ~PSR_N
;
786 sregs
->psr
&= ~PSR_Z
;
793 mul64 (rs1
, operand2
, &sregs
->y
, rdd
, 0);
800 mul64 (rs1
, operand2
, &sregs
->y
, &result
, 0);
802 if (result
& 0x80000000)
805 sregs
->psr
&= ~PSR_N
;
810 sregs
->psr
&= ~PSR_Z
;
818 sregs
->trap
= TRAP_UNIMP
;
823 sregs
->trap
= TRAP_DIV0
;
827 div64 (sregs
->y
, rs1
, operand2
, rdd
, 1);
835 sregs
->trap
= TRAP_UNIMP
;
840 sregs
->trap
= TRAP_DIV0
;
844 div64 (sregs
->y
, rs1
, operand2
, &result
, 1);
846 if (result
& 0x80000000)
849 sregs
->psr
&= ~PSR_N
;
854 sregs
->psr
&= ~PSR_Z
;
856 /* FIXME: should set overflow flag correctly. */
857 sregs
->psr
&= ~(PSR_C
| PSR_V
);
865 sregs
->trap
= TRAP_UNIMP
;
870 sregs
->trap
= TRAP_DIV0
;
874 div64 (sregs
->y
, rs1
, operand2
, rdd
, 0);
882 sregs
->trap
= TRAP_UNIMP
;
887 sregs
->trap
= TRAP_DIV0
;
891 div64 (sregs
->y
, rs1
, operand2
, &result
, 0);
893 if (result
& 0x80000000)
896 sregs
->psr
&= ~PSR_N
;
901 sregs
->psr
&= ~PSR_Z
;
903 /* FIXME: should set overflow flag correctly. */
904 sregs
->psr
&= ~(PSR_C
| PSR_V
);
910 *rdd
= rs1
^ ~operand2
;
913 *rdd
= rs1
^ ~operand2
;
917 *rdd
= rs1
^ operand2
;
920 *rdd
= rs1
^ operand2
;
924 *rdd
= rs1
| operand2
;
927 *rdd
= rs1
| operand2
;
931 *rdd
= rs1
| ~operand2
;
934 *rdd
= rs1
| ~operand2
;
938 *rdd
= rs1
& ~operand2
;
942 *rdd
= rs1
& ~operand2
;
945 *rdd
= rs1
& operand2
;
948 *rdd
= rs1
& operand2
;
952 *rdd
= rs1
- operand2
;
955 *rdd
= rs1
- operand2
;
956 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
959 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
962 *rdd
= rs1
- operand2
- ((sregs
->psr
>> 20) & 1);
963 sregs
->psr
= sub_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
966 *rdd
= rs1
+ operand2
;
969 *rdd
= rs1
+ operand2
;
970 sregs
->psr
= add_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
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
980 *rdd
= rs1
+ operand2
;
981 sregs
->psr
= add_cc(sregs
->psr
, rs1
, operand2
, *rdd
);
982 if ((rs1
| operand2
) & 0x3)
986 *rdd
= rs1
- operand2
;
987 sregs
->psr
= sub_cc (sregs
->psr
, rs1
, operand2
, *rdd
);
988 if ((rs1
| operand2
) & 0x3)
992 *rdd
= rs1
+ operand2
;
993 result
= add_cc(0, rs1
, operand2
, *rdd
);
994 if ((rs1
| operand2
) & 0x3)
996 if (result
& PSR_V
) {
997 sregs
->trap
= TRAP_TAG
;
999 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1003 *rdd
= rs1
- operand2
;
1004 result
= add_cc (0, rs1
, operand2
, *rdd
);
1005 if ((rs1
| operand2
) & 0x3)
1009 sregs
->trap
= TRAP_TAG
;
1013 sregs
->psr
= (sregs
->psr
& ~PSR_CC
) | result
;
1017 *rdd
= rs1
<< (operand2
& 0x1f);
1020 *rdd
= rs1
>> (operand2
& 0x1f);
1023 *rdd
= ((int) rs1
) >> (operand2
& 0x1f);
1026 if (ift
) sregs
->trap
= TRAP_UNIMP
;
1029 new_cwp
= ((sregs
->psr
& PSR_CWP
) - 1) & PSR_CWP
;
1030 if (sregs
->wim
& (1 << new_cwp
)) {
1031 sregs
->trap
= TRAP_WOFL
;
1035 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1036 *rdd
= rs1
+ operand2
;
1037 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1041 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1042 if (sregs
->wim
& (1 << new_cwp
)) {
1043 sregs
->trap
= TRAP_WUFL
;
1047 rdd
= &(sregs
->r
[((new_cwp
<< 4) + rd
) & 0x7f]);
1048 *rdd
= rs1
+ operand2
;
1049 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
;
1052 if (!(sregs
->psr
& PSR_S
)) {
1053 sregs
->trap
= TRAP_PRIVI
;
1062 int rs1_is_asr
= (sregs
->inst
>> 14) & 0x1f;
1063 if ( 0 == rs1_is_asr
)
1065 else if ( 17 == rs1_is_asr
)
1066 *rdd
= sregs
->asr17
;
1068 sregs
->trap
= TRAP_UNIMP
;
1074 if (!(sregs
->psr
& PSR_S
)) {
1075 sregs
->trap
= TRAP_PRIVI
;
1081 if (!(sregs
->psr
& PSR_S
)) {
1082 sregs
->trap
= TRAP_PRIVI
;
1088 if ((sregs
->psr
& 0x1f) > 7) {
1089 sregs
->trap
= TRAP_UNIMP
;
1092 if (!(sregs
->psr
& PSR_S
)) {
1093 sregs
->trap
= TRAP_PRIVI
;
1096 sregs
->psr
= (sregs
->psr
& 0xff000000) |
1097 (rs1
^ operand2
) & 0x00f03fff;
1100 if (!(sregs
->psr
& PSR_S
)) {
1101 sregs
->trap
= TRAP_PRIVI
;
1104 sregs
->wim
= (rs1
^ operand2
) & 0x0ff;
1107 if (!(sregs
->psr
& PSR_S
)) {
1108 sregs
->trap
= TRAP_PRIVI
;
1111 sregs
->tbr
= (sregs
->tbr
& 0x00000ff0) |
1112 ((rs1
^ operand2
) & 0xfffff000);
1116 sregs
->y
= (rs1
^ operand2
);
1119 sregs
->y
= (rs1
^ operand2
);
1120 else if ( 17 == rd
)
1121 sregs
->asr17
= (rs1
^ operand2
);
1123 sregs
->trap
= TRAP_UNIMP
;
1133 sregs
->icnt
= T_JMPL
; /* JMPL takes two cycles */
1135 sregs
->trap
= TRAP_UNALI
;
1139 npc
= rs1
+ operand2
;
1142 address
= rs1
+ operand2
;
1143 new_cwp
= ((sregs
->psr
& PSR_CWP
) + 1) & PSR_CWP
;
1144 sregs
->icnt
= T_RETT
; /* RETT takes two cycles */
1145 if (sregs
->psr
& PSR_ET
) {
1146 sregs
->trap
= TRAP_UNIMP
;
1149 if (!(sregs
->psr
& PSR_S
)) {
1150 sregs
->trap
= TRAP_PRIVI
;
1153 if (sregs
->wim
& (1 << new_cwp
)) {
1154 sregs
->trap
= TRAP_WUFL
;
1157 if (address
& 0x3) {
1158 sregs
->trap
= TRAP_UNALI
;
1161 sregs
->psr
= (sregs
->psr
& ~PSR_CWP
) | new_cwp
| PSR_ET
;
1163 (sregs
->psr
& ~PSR_S
) | ((sregs
->psr
& PSR_PS
) << 1);
1169 uint32 result
, mask
;
1173 sregs
->trap
= TRAP_UNIMP
;
1176 mask
= (operand2
& 0x80000000) | (operand2
>> 1);
1177 result
= rs1
^ mask
;
1179 for (i
= 0; i
< 32; i
++) {
1180 if (result
& 0x80000000)
1185 *rdd
= i
== 32 ? 63 : i
;
1190 sregs
->trap
= TRAP_UNIMP
;
1195 case 3: /* Load/store instructions */
1197 address
= rs1
+ operand2
;
1199 if (sregs
->psr
& PSR_S
)
1205 sregs
->icnt
= T_ST
; /* Set store instruction count */
1210 sregs
->icnt
= T_LD
; /* Set load instruction count */
1216 /* Decode load/store instructions */
1220 if (!chk_asi(sregs
, &asi
, op3
)) break;
1222 if (address
& 0x7) {
1223 sregs
->trap
= TRAP_UNALI
;
1229 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1231 rdd
= &(sregs
->g
[rd
]);
1233 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1235 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1237 sregs
->icnt
= T_LDD
;
1239 sregs
->trap
= TRAP_DEXC
;
1244 sregs
->nload
++; /* Double load counts twice */
1250 if (!chk_asi(sregs
, &asi
, op3
)) break;
1252 if (address
& 0x3) {
1253 sregs
->trap
= TRAP_UNALI
;
1256 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1259 sregs
->trap
= TRAP_DEXC
;
1265 if (!chk_asi(sregs
, &asi
, op3
)) break;
1267 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1269 sregs
->icnt
= T_LDST
;
1271 sregs
->trap
= TRAP_DEXC
;
1274 data
= extract_byte (data
, address
);
1277 mexc
= memory_write(asi
, address
, &data
, 0, &ws
);
1280 sregs
->trap
= TRAP_DEXC
;
1288 if (!chk_asi(sregs
, &asi
, op3
)) break;
1291 mexc
= memory_read(asi
, address
, &data
, 0, &ws
);
1294 sregs
->trap
= TRAP_DEXC
;
1298 data
= extract_byte_signed (data
, address
);
1300 data
= extract_byte (data
, address
);
1305 if (!chk_asi(sregs
, &asi
, op3
)) break;
1308 if (address
& 0x1) {
1309 sregs
->trap
= TRAP_UNALI
;
1312 mexc
= memory_read(asi
, address
, &data
, 1, &ws
);
1315 sregs
->trap
= TRAP_DEXC
;
1319 data
= extract_short_signed (data
, address
);
1321 data
= extract_short (data
, address
);
1325 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1326 sregs
->trap
= TRAP_FPDIS
;
1329 if (address
& 0x3) {
1330 sregs
->trap
= TRAP_UNALI
;
1333 if (ebase
.simtime
< sregs
->ftime
) {
1334 if ((sregs
->frd
== rd
) || (sregs
->frs1
== rd
) ||
1335 (sregs
->frs2
== rd
))
1336 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1338 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1341 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1342 sregs
->hold
+ sregs
->fhold
;
1344 sregs
->trap
= TRAP_DEXC
;
1346 sregs
->fs
[rd
] = *((float32
*) & data
);
1350 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1351 sregs
->trap
= TRAP_FPDIS
;
1354 if (address
& 0x7) {
1355 sregs
->trap
= TRAP_UNALI
;
1358 if (ebase
.simtime
< sregs
->ftime
) {
1359 if (((sregs
->frd
>> 1) == (rd
>> 1)) ||
1360 ((sregs
->frs1
>> 1) == (rd
>> 1)) ||
1361 ((sregs
->frs2
>> 1) == (rd
>> 1)))
1362 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1364 mexc
= memory_read (asi
, address
, ddata
, 2, &ws
);
1366 mexc
|= memory_read (asi
, address
+4, &ddata
[1], 2, &ws
);
1368 sregs
->icnt
= T_LDD
;
1370 sregs
->trap
= TRAP_DEXC
;
1374 sregs
->fs
[rd
] = *((float32
*) & ddata
[0]);
1376 sregs
->nload
++; /* Double load counts twice */
1378 sregs
->fs
[rd
+ 1] = *((float32
*) & ddata
[1]);
1379 sregs
->ltime
= ebase
.simtime
+ sregs
->icnt
+ FLSTHOLD
+
1380 sregs
->hold
+ sregs
->fhold
;
1384 if (ebase
.simtime
< sregs
->ftime
) {
1385 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1387 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1388 sregs
->trap
= TRAP_FPDIS
;
1391 if (address
& 0x3) {
1392 sregs
->trap
= TRAP_UNALI
;
1395 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1398 sregs
->trap
= TRAP_DEXC
;
1401 (sregs
->fsr
& 0x7FF000) | (data
& ~0x7FF000);
1402 set_fsr(sregs
->fsr
);
1406 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1407 sregs
->trap
= TRAP_FPDIS
;
1410 if (address
& 0x3) {
1411 sregs
->trap
= TRAP_UNALI
;
1414 if (ebase
.simtime
< sregs
->ftime
) {
1415 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1417 mexc
= memory_write(asi
, address
, &sregs
->fsr
, 2, &ws
);
1420 sregs
->trap
= TRAP_DEXC
;
1425 if (!chk_asi(sregs
, &asi
, op3
)) break;
1427 if (address
& 0x3) {
1428 sregs
->trap
= TRAP_UNALI
;
1431 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1434 sregs
->trap
= TRAP_DEXC
;
1438 if (!chk_asi(sregs
, &asi
, op3
)) break;
1440 mexc
= memory_write(asi
, address
, rdd
, 0, &ws
);
1443 sregs
->trap
= TRAP_DEXC
;
1447 if (!chk_asi(sregs
, &asi
, op3
)) break;
1449 if (address
& 0x7) {
1450 sregs
->trap
= TRAP_UNALI
;
1456 rdd
= &(sregs
->r
[(cwp
+ rd
) & 0x7f]);
1458 rdd
= &(sregs
->g
[rd
]);
1460 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1462 sregs
->icnt
= T_STD
;
1464 sregs
->nstore
++; /* Double store counts twice */
1467 sregs
->trap
= TRAP_DEXC
;
1472 if ((sregs
->psr
& 0x1f) > 7) {
1473 sregs
->trap
= TRAP_UNIMP
;
1476 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1477 sregs
->trap
= TRAP_FPDIS
;
1480 if (address
& 0x7) {
1481 sregs
->trap
= TRAP_UNALI
;
1484 if (!(sregs
->fsr
& FSR_QNE
)) {
1485 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1488 rdd
= &(sregs
->fpq
[0]);
1489 mexc
= memory_write(asi
, address
, rdd
, 3, &ws
);
1491 sregs
->icnt
= T_STD
;
1493 sregs
->nstore
++; /* Double store counts twice */
1496 sregs
->trap
= TRAP_DEXC
;
1499 sregs
->fsr
&= ~FSR_QNE
;
1500 sregs
->fpstate
= FP_EXE_MODE
;
1504 if (!chk_asi(sregs
, &asi
, op3
)) break;
1506 if (address
& 0x1) {
1507 sregs
->trap
= TRAP_UNALI
;
1510 mexc
= memory_write(asi
, address
, rdd
, 1, &ws
);
1513 sregs
->trap
= TRAP_DEXC
;
1517 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1518 sregs
->trap
= TRAP_FPDIS
;
1521 if (address
& 0x3) {
1522 sregs
->trap
= TRAP_UNALI
;
1525 if (ebase
.simtime
< sregs
->ftime
) {
1526 if (sregs
->frd
== rd
)
1527 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1529 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 2, &ws
);
1532 sregs
->trap
= TRAP_DEXC
;
1536 if (!((sregs
->psr
& PSR_EF
) && FP_PRES
)) {
1537 sregs
->trap
= TRAP_FPDIS
;
1540 if (address
& 0x7) {
1541 sregs
->trap
= TRAP_UNALI
;
1545 if (ebase
.simtime
< sregs
->ftime
) {
1546 if ((sregs
->frd
== rd
) || (sregs
->frd
+ 1 == rd
))
1547 sregs
->fhold
+= (sregs
->ftime
- ebase
.simtime
);
1549 mexc
= memory_write(asi
, address
, &sregs
->fsi
[rd
], 3, &ws
);
1551 sregs
->icnt
= T_STD
;
1553 sregs
->nstore
++; /* Double store counts twice */
1556 sregs
->trap
= TRAP_DEXC
;
1560 if (!chk_asi(sregs
, &asi
, op3
)) break;
1562 if (address
& 0x3) {
1563 sregs
->trap
= TRAP_UNALI
;
1566 mexc
= memory_read(asi
, address
, &data
, 2, &ws
);
1569 sregs
->trap
= TRAP_DEXC
;
1572 mexc
= memory_write(asi
, address
, rdd
, 2, &ws
);
1574 sregs
->icnt
= T_LDST
;
1576 sregs
->trap
= TRAP_DEXC
;
1587 sregs
->trap
= TRAP_UNIMP
;
1594 sregs
->ildtime
= ebase
.simtime
+ sregs
->hold
+ sregs
->icnt
;
1596 if ((op3
| 0x10) == 0x13)
1597 sregs
->ildreg
|= 1; /* Double load, odd register loaded
1604 sregs
->trap
= TRAP_UNIMP
;
1663 fpexec(uint32 op3
, uint32 rd
, uint32 rs1
, uint32 rs2
, struct pstate
*sregs
)
1665 uint32 opf
, tem
, accex
;
1669 if (sregs
->fpstate
== FP_EXC_MODE
) {
1670 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_SEQ_ERR
;
1671 sregs
->fpstate
= FP_EXC_PE
;
1674 if (sregs
->fpstate
== FP_EXC_PE
) {
1675 sregs
->fpstate
= FP_EXC_MODE
;
1678 opf
= (sregs
->inst
>> 5) & 0x1ff;
1681 * Check if we already have an FPop in the pipe. If so, halt until it is
1682 * finished by incrementing fhold with the remaining execution time
1685 if (ebase
.simtime
< sregs
->ftime
) {
1686 sregs
->fhold
= (sregs
->ftime
- ebase
.simtime
);
1690 /* Check load dependencies. */
1692 if (ebase
.simtime
< sregs
->ltime
) {
1694 /* Don't check rs1 if single operand instructions */
1696 if (((opf
>> 6) == 0) || ((opf
>> 6) == 3))
1699 /* Adjust for double floats */
1702 if (!(((sregs
->flrd
- rs1
) >> ldadj
) && ((sregs
->flrd
- rs2
) >> ldadj
)))
1709 sregs
->frs1
= rs1
; /* Store src and dst for dependecy check */
1713 sregs
->ftime
= ebase
.simtime
+ sregs
->hold
+ sregs
->fhold
;
1715 /* SPARC is big-endian - swap double floats if host is little-endian */
1716 /* This is ugly - I know ... */
1718 /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1719 but what about machines where float values are different endianness
1720 from integer values? */
1722 #ifdef HOST_LITTLE_ENDIAN
1734 sregs
->fdp
[rs1
| 1] = sregs
->fs
[rs1
& ~1];
1735 sregs
->fdp
[rs1
& ~1] = sregs
->fs
[rs1
| 1];
1736 sregs
->fdp
[rs2
| 1] = sregs
->fs
[rs2
& ~1];
1737 sregs
->fdp
[rs2
& ~1] = sregs
->fs
[rs2
| 1];
1747 sregs
->fs
[rd
] = fabs(sregs
->fs
[rs2
]);
1748 sregs
->ftime
+= T_FABSs
;
1749 sregs
->frs1
= 32; /* rs1 ignored */
1752 sregs
->fs
[rd
] = sregs
->fs
[rs1
] + sregs
->fs
[rs2
];
1753 sregs
->ftime
+= T_FADDs
;
1756 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] + sregs
->fd
[rs2
>> 1];
1757 sregs
->ftime
+= T_FADDd
;
1761 if (sregs
->fs
[rs1
] == sregs
->fs
[rs2
])
1763 else if (sregs
->fs
[rs1
] < sregs
->fs
[rs2
])
1765 else if (sregs
->fs
[rs1
] > sregs
->fs
[rs2
])
1769 sregs
->fsr
|= 0x0C00;
1770 sregs
->fsr
&= ~(fcc
<< 10);
1771 sregs
->ftime
+= T_FCMPs
;
1772 sregs
->frd
= 32; /* rd ignored */
1773 if ((fcc
== 0) && (opf
== FCMPEs
)) {
1774 sregs
->fpstate
= FP_EXC_PE
;
1775 sregs
->fsr
= (sregs
->fsr
& ~0x1C000) | (1 << 14);
1780 if (sregs
->fd
[rs1
>> 1] == sregs
->fd
[rs2
>> 1])
1782 else if (sregs
->fd
[rs1
>> 1] < sregs
->fd
[rs2
>> 1])
1784 else if (sregs
->fd
[rs1
>> 1] > sregs
->fd
[rs2
>> 1])
1788 sregs
->fsr
|= 0x0C00;
1789 sregs
->fsr
&= ~(fcc
<< 10);
1790 sregs
->ftime
+= T_FCMPd
;
1791 sregs
->frd
= 32; /* rd ignored */
1792 if ((fcc
== 0) && (opf
== FCMPEd
)) {
1793 sregs
->fpstate
= FP_EXC_PE
;
1794 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1798 sregs
->fs
[rd
] = sregs
->fs
[rs1
] / sregs
->fs
[rs2
];
1799 sregs
->ftime
+= T_FDIVs
;
1802 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] / sregs
->fd
[rs2
>> 1];
1803 sregs
->ftime
+= T_FDIVd
;
1806 sregs
->fs
[rd
] = sregs
->fs
[rs2
];
1807 sregs
->ftime
+= T_FMOVs
;
1808 sregs
->frs1
= 32; /* rs1 ignored */
1811 sregs
->fs
[rd
] = sregs
->fs
[rs1
] * sregs
->fs
[rs2
];
1812 sregs
->ftime
+= T_FMULs
;
1815 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] * sregs
->fd
[rs2
>> 1];
1816 sregs
->ftime
+= T_FMULd
;
1819 sregs
->fs
[rd
] = -sregs
->fs
[rs2
];
1820 sregs
->ftime
+= T_FNEGs
;
1821 sregs
->frs1
= 32; /* rs1 ignored */
1824 if (sregs
->fs
[rs2
] < 0.0) {
1825 sregs
->fpstate
= FP_EXC_PE
;
1826 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1827 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1830 sregs
->fs
[rd
] = sqrt(sregs
->fs
[rs2
]);
1831 sregs
->ftime
+= T_FSQRTs
;
1832 sregs
->frs1
= 32; /* rs1 ignored */
1835 if (sregs
->fd
[rs2
>> 1] < 0.0) {
1836 sregs
->fpstate
= FP_EXC_PE
;
1837 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1838 sregs
->fsr
= (sregs
->fsr
& 0x1f) | 0x10;
1841 sregs
->fd
[rd
>> 1] = sqrt(sregs
->fd
[rs2
>> 1]);
1842 sregs
->ftime
+= T_FSQRTd
;
1843 sregs
->frs1
= 32; /* rs1 ignored */
1846 sregs
->fs
[rd
] = sregs
->fs
[rs1
] - sregs
->fs
[rs2
];
1847 sregs
->ftime
+= T_FSUBs
;
1850 sregs
->fd
[rd
>> 1] = sregs
->fd
[rs1
>> 1] - sregs
->fd
[rs2
>> 1];
1851 sregs
->ftime
+= T_FSUBd
;
1854 sregs
->fsi
[rd
] = (int) sregs
->fd
[rs2
>> 1];
1855 sregs
->ftime
+= T_FdTOi
;
1856 sregs
->frs1
= 32; /* rs1 ignored */
1859 sregs
->fs
[rd
] = (float32
) sregs
->fd
[rs2
>> 1];
1860 sregs
->ftime
+= T_FdTOs
;
1861 sregs
->frs1
= 32; /* rs1 ignored */
1864 sregs
->fs
[rd
] = (float32
) sregs
->fsi
[rs2
];
1865 sregs
->ftime
+= T_FiTOs
;
1866 sregs
->frs1
= 32; /* rs1 ignored */
1869 sregs
->fd
[rd
>> 1] = (float64
) sregs
->fsi
[rs2
];
1870 sregs
->ftime
+= T_FiTOd
;
1871 sregs
->frs1
= 32; /* rs1 ignored */
1874 sregs
->fsi
[rd
] = (int) sregs
->fs
[rs2
];
1875 sregs
->ftime
+= T_FsTOi
;
1876 sregs
->frs1
= 32; /* rs1 ignored */
1879 sregs
->fd
[rd
>> 1] = sregs
->fs
[rs2
];
1880 sregs
->ftime
+= T_FsTOd
;
1881 sregs
->frs1
= 32; /* rs1 ignored */
1885 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_UNIMP
;
1886 sregs
->fpstate
= FP_EXC_PE
;
1891 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | (errftt
<< 14);
1892 sregs
->fpstate
= FP_EXC_PE
;
1893 if (sis_verbose
) printf("Inserted fpu error %X\n",errftt
);
1898 accex
= get_accex();
1900 #ifdef HOST_LITTLE_ENDIAN
1909 sregs
->fs
[rd
& ~1] = sregs
->fdp
[rd
| 1];
1910 sregs
->fs
[rd
| 1] = sregs
->fdp
[rd
& ~1];
1915 if (sregs
->fpstate
== FP_EXC_PE
) {
1916 sregs
->fpq
[0] = sregs
->pc
;
1917 sregs
->fpq
[1] = sregs
->inst
;
1918 sregs
->fsr
|= FSR_QNE
;
1920 tem
= (sregs
->fsr
>> 23) & 0x1f;
1922 sregs
->fpstate
= FP_EXC_PE
;
1923 sregs
->fsr
= (sregs
->fsr
& ~FSR_TT
) | FP_IEEE
;
1924 sregs
->fsr
= ((sregs
->fsr
& ~0x1f) | accex
);
1926 sregs
->fsr
= ((((sregs
->fsr
>> 5) | accex
) << 5) | accex
);
1928 if (sregs
->fpstate
== FP_EXC_PE
) {
1929 sregs
->fpq
[0] = sregs
->pc
;
1930 sregs
->fpq
[1] = sregs
->inst
;
1931 sregs
->fsr
|= FSR_QNE
;
1942 chk_asi(struct pstate
*sregs
, uint32
*asi
, uint32 op3
)
1944 if (!(sregs
->psr
& PSR_S
)) {
1945 sregs
->trap
= TRAP_PRIVI
;
1947 } else if (sregs
->inst
& INST_I
) {
1948 sregs
->trap
= TRAP_UNIMP
;
1951 *asi
= (sregs
->inst
>> 5) & 0x0ff;
1956 execute_trap(struct pstate
*sregs
)
1960 if (sregs
->trap
== 256) {
1964 } else if (sregs
->trap
== 257) {
1968 if ((sregs
->psr
& PSR_ET
) == 0)
1971 sregs
->tbr
= (sregs
->tbr
& 0xfffff000) | (sregs
->trap
<< 4);
1973 sregs
->psr
&= ~PSR_ET
;
1974 sregs
->psr
|= ((sregs
->psr
& PSR_S
) >> 1);
1976 sregs
->psr
= (((sregs
->psr
& PSR_CWP
) - 1) & 0x7) | (sregs
->psr
& ~PSR_CWP
);
1977 cwp
= ((sregs
->psr
& PSR_CWP
) << 4);
1978 sregs
->r
[(cwp
+ 17) & 0x7f] = sregs
->pc
;
1979 sregs
->r
[(cwp
+ 18) & 0x7f] = sregs
->npc
;
1980 sregs
->psr
|= PSR_S
;
1981 sregs
->pc
= sregs
->tbr
;
1982 sregs
->npc
= sregs
->tbr
+ 4;
1984 if ( 0 != (1 & sregs
->asr17
) ) {
1985 /* single vector trapping! */
1986 sregs
->pc
= sregs
->tbr
& 0xfffff000;
1987 sregs
->npc
= sregs
->pc
+ 4;
1990 /* Increase simulator time */
1991 sregs
->icnt
= TRAP_C
;
2000 extern struct irqcell irqarr
[16];
2003 check_interrupts(struct pstate
*sregs
)
2007 sregs
->trap
= errtt
;
2008 if (sis_verbose
) printf("Inserted error trap 0x%02X\n",errtt
);
2013 if ((ext_irl
) && (sregs
->psr
& PSR_ET
) &&
2014 ((ext_irl
== 15) || (ext_irl
> (int) ((sregs
->psr
& PSR_PIL
) >> 8)))) {
2015 if (sregs
->trap
== 0) {
2016 sregs
->trap
= 16 + ext_irl
;
2017 irqarr
[ext_irl
& 0x0f].callback(irqarr
[ext_irl
& 0x0f].arg
);
2025 init_regs(struct pstate
*sregs
)
2030 sregs
->psr
&= 0x00f03fdf;
2031 sregs
->psr
|= 0x11000080; /* Set supervisor bit */
2032 sregs
->breakpoint
= 0;
2034 sregs
->fpstate
= FP_EXE_MODE
;
2038 sregs
->err_mode
= 0;
2041 #ifdef HOST_LITTLE_ENDIAN
2042 sregs
->fdp
= (float32
*) sregs
->fd
;
2043 sregs
->fsi
= (int32
*) sregs
->fs
;
2045 sregs
->fs
= (float32
*) sregs
->fd
;
2046 sregs
->fsi
= (int32
*) sregs
->fd
;
2049 sregs
->fpu_pres
= !nfp
;
2050 set_fsr(sregs
->fsr
);
2058 sregs
->rett_err
= 0;
2059 sregs
->jmpltime
= 0;