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);