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 sis_verbose, sparclite;
31 /* Load/store interlock delay */
34 /* Load delay (delete if unwanted - speeds up simulation) */
45 #define FSR_QNE 0x2000
77 #define PSR_N 0x0800000
78 #define PSR_Z 0x0400000
79 #define PSR_V 0x0200000
80 #define PSR_C 0x0100000
81 #define PSR_CC 0x0F00000
83 #define PSR_PIL 0x0f00
85 #define ICC_N (icc >> 3)
86 #define ICC_Z (icc >> 2)
87 #define ICC_V (icc >> 1)
90 #define FP_PRES (sregs->fpu_pres)
102 #define TRAP_DIV0 0x2a
104 #define FSR_TT 0x1C000
105 #define FP_IEEE 0x04000
106 #define FP_UNIMP 0x0C000
107 #define FP_SEQ_ERR 0x10000
126 #define INST_SIMM13 0x1fff
127 #define INST_RS2 0x1f
128 #define INST_I 0x2000
135 #define TADDCCTV 0x22
136 #define TSUBCCTV 0x23
216 #define SIGN_BIT 0x80000000
218 /* # of cycles overhead when a trap is taken */
221 /* Forward declarations */
223 static uint32 sub_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,
225 static uint32 add_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,
227 static void log_cc PARAMS ((int32 result, struct pstate *sregs));
228 static int fpexec PARAMS ((uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
229 struct pstate *sregs));
230 static int chk_asi PARAMS ((struct pstate *sregs, uint32 *asi, uint32 op3));
233 extern struct estate ebase;
234 extern int32 nfp,ift;
237 extern uint32 errtt, errftt;
241 sub_cc(psr, operand1, operand2, result)
247 psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
252 psr = (psr & ~PSR_V) | ((((operand1 & ~operand2 & ~result) |
253 (~operand1 & operand2 & result)) >> 10) & PSR_V);
254 psr = (psr & ~PSR_C) | ((((~operand1 & operand2) |
255 ((~operand1 | operand2) & result)) >> 11) & PSR_C);
260 add_cc(psr, operand1, operand2, result)
266 psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
271 psr = (psr & ~PSR_V) | ((((operand1 & operand2 & ~result) |
272 (~operand1 & ~operand2 & result)) >> 10) & PSR_V);
273 psr = (psr & ~PSR_C) | ((((operand1 & operand2) |
274 ((operand1 | operand2) & ~result)) >> 11) & PSR_C);
279 log_cc(result, sregs)
281 struct pstate *sregs;
283 sregs->psr &= ~(PSR_CC); /* Zero CC bits */
284 sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));
289 /* Add two unsigned 32-bit integers, and calculate the carry out. */
292 add32 (uint32 n1, uint32 n2, int *carry)
294 uint32 result = n1 + n2;
296 *carry = result < n1 || result < n1;
300 /* Multiply two 32-bit integers. */
303 mul64 (uint32 n1, uint32 n2, uint32 *result_hi, uint32 *result_lo, int msigned)
305 uint32 lo, mid1, mid2, hi, reg_lo, reg_hi;
309 /* If this is a signed multiply, calculate the sign of the result
310 and make the operands positive. */
313 sign = (n1 ^ n2) & SIGN_BIT;
321 /* We can split the 32x32 into four 16x16 operations. This ensures
322 that we do not lose precision on 32bit only hosts: */
323 lo = ((n1 & 0xFFFF) * (n2 & 0xFFFF));
324 mid1 = ((n1 & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
325 mid2 = (((n1 >> 16) & 0xFFFF) * (n2 & 0xFFFF));
326 hi = (((n1 >> 16) & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
328 /* We now need to add all of these results together, taking care
329 to propogate the carries from the additions: */
330 reg_lo = add32 (lo, (mid1 << 16), &carry);
332 reg_lo = add32 (reg_lo, (mid2 << 16), &carry);
333 reg_hi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
335 /* Negate result if necessary. */
349 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
350 that the host compiler supports long long operations. */
353 div64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned)
357 n1 = ((uint64) n1_hi) << 32;
358 n1 |= ((uint64) n1_low) & 0xffffffff;
362 int64 n1_s = (int64) n1;
363 int32 n2_s = (int32) n2;
370 *result = (uint32) (n1 & 0xffffffff);
375 dispatch_instruction(sregs)
376 struct pstate *sregs;
379 uint32 cwp, op, op2, op3, asi, rd, cond, rs1,
382 int32 operand1, operand2, *rdd, result, eicc,
384 int32 pc, npc, data, address, ws, mexc, fcc;
388 cwp = ((sregs->psr & PSR_CWP) << 4);
389 op = sregs->inst >> 30;
391 npc = sregs->npc + 4;
392 op3 = rd = rs1 = operand2 = eicc = 0;
396 op3 = (sregs->inst >> 19) & 0x3f;
397 rs1 = (sregs->inst >> 14) & 0x1f;
398 rd = (sregs->inst >> 25) & 0x1f;
402 /* Check if load dependecy is possible */
403 if (ebase.simtime <= sregs->ildtime)
404 ldep = (((op3 & 0x38) != 0x28) && ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));
407 if (sregs->inst & INST_I) {
408 if (ldep && (sregs->ildreg == rs1))
410 operand2 = sregs->inst;
411 operand2 = ((operand2 << 19) >> 19); /* sign extend */
413 rs2 = sregs->inst & INST_RS2;
415 operand2 = sregs->r[(cwp + rs2) & 0x7f];
417 operand2 = sregs->g[rs2];
418 if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))
422 if (sregs->inst & INST_I) {
423 operand2 = sregs->inst;
424 operand2 = ((operand2 << 19) >> 19); /* sign extend */
426 rs2 = sregs->inst & INST_RS2;
428 operand2 = sregs->r[(cwp + rs2) & 0x7f];
430 operand2 = sregs->g[rs2];
435 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
437 rdd = &(sregs->g[rd]);
439 rs1 = sregs->r[(cwp + rs1) & 0x7f];
445 op2 = (sregs->inst >> 22) & 0x7;
448 rd = (sregs->inst >> 25) & 0x1f;
450 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
452 rdd = &(sregs->g[rd]);
453 *rdd = sregs->inst << 10;
459 icc = sregs->psr >> 20;
460 cond = ((sregs->inst >> 25) & 0x0f);
469 eicc = ICC_Z | (ICC_N ^ ICC_V);
472 eicc = (ICC_N ^ ICC_V);
475 eicc = ICC_C | ICC_Z;
488 if (sregs->inst & 0x20000000)
495 eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
498 eicc = ~(ICC_N ^ ICC_V);
501 eicc = ~(ICC_C | ICC_Z);
514 operand1 = sregs->inst;
515 operand1 = ((operand1 << 10) >> 8); /* sign extend */
516 npc = sregs->pc + operand1;
518 if (sregs->inst & 0x20000000)
526 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
527 sregs->trap = TRAP_FPDIS;
530 if (ebase.simtime < sregs->ftime) {
531 sregs->ftime = ebase.simtime + sregs->hold;
533 cond = ((sregs->inst >> 25) & 0x0f);
534 fcc = (sregs->fsr >> 10) & 0x3;
540 eicc = (fcc != FCC_E);
543 eicc = (fcc == FCC_L) || (fcc == FCC_G);
546 eicc = (fcc == FCC_L) || (fcc == FCC_U);
549 eicc = (fcc == FCC_L);
552 eicc = (fcc == FCC_G) || (fcc == FCC_U);
555 eicc = (fcc == FCC_G);
558 eicc = (fcc == FCC_U);
562 if (sregs->inst & 0x20000000)
566 eicc = !(fcc != FCC_E);
569 eicc = !((fcc == FCC_L) || (fcc == FCC_G));
572 eicc = !((fcc == FCC_L) || (fcc == FCC_U));
575 eicc = !(fcc == FCC_L);
578 eicc = !((fcc == FCC_G) || (fcc == FCC_U));
581 eicc = !(fcc == FCC_G);
584 eicc = !(fcc == FCC_U);
588 operand1 = sregs->inst;
589 operand1 = ((operand1 << 10) >> 8); /* sign extend */
590 npc = sregs->pc + operand1;
592 if (sregs->inst & 0x20000000)
598 sregs->trap = TRAP_UNIMP;
606 sregs->r[(cwp + 15) & 0x7f] = sregs->pc;
607 npc = sregs->pc + (sregs->inst << 2);
611 if ((op3 >> 1) == 0x1a) {
612 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
613 sregs->trap = TRAP_FPDIS;
615 rs1 = (sregs->inst >> 14) & 0x1f;
616 rs2 = sregs->inst & 0x1f;
617 sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);
623 icc = sregs->psr >> 20;
624 cond = ((sregs->inst >> 25) & 0x0f);
633 eicc = ICC_Z | (ICC_N ^ ICC_V);
636 eicc = (ICC_N ^ ICC_V);
639 eicc = ICC_C | ICC_Z;
657 eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
660 eicc = ~(ICC_N ^ ICC_V);
663 eicc = ~(ICC_C | ICC_Z);
676 sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
682 (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
684 if ((sregs->y & 1) == 0)
686 *rdd = operand1 + operand2;
687 sregs->y = (rs1 << 31) | (sregs->y >> 1);
688 sregs->psr = add_cc(sregs->psr, operand1, operand2, *rdd);
693 uint32 result, remainder;
697 sregs->trap = TRAP_UNIMP;
701 sign = ((sregs->psr & PSR_V) != 0) ^ ((sregs->psr & PSR_N) != 0);
703 remainder = (sregs->y << 1) | (rs1 >> 31);
705 /* If true sign is positive, calculate remainder - divisor.
706 Otherwise, calculate remainder + divisor. */
708 operand2 = ~operand2 + 1;
709 result = remainder + operand2;
711 /* The SPARClite User's Manual is not clear on how
712 the "carry out" of the above ALU operation is to
713 be calculated. From trial and error tests
714 on the the chip itself, it appears that it is
715 a normal addition carry, and not a subtraction borrow,
716 even in cases where the divisor is subtracted
717 from the remainder. FIXME: get the true story
719 c0 = result < (uint32) remainder
720 || result < (uint32) operand2;
722 if (result & 0x80000000)
725 sregs->psr &= ~PSR_N;
727 y31 = (sregs->y & 0x80000000) == 0x80000000;
729 if (result == 0 && sign == y31)
732 sregs->psr &= ~PSR_Z;
734 sign = (sign && !y31) || (!c0 && (sign || !y31));
736 if (sign ^ (result >> 31))
739 sregs->psr &= ~PSR_V;
744 sregs->psr &= ~PSR_C;
749 *rdd = (rs1 << 1) | !sign;
754 mul64 (rs1, operand2, &sregs->y, rdd, 1);
761 mul64 (rs1, operand2, &sregs->y, &result, 1);
763 if (result & 0x80000000)
766 sregs->psr &= ~PSR_N;
771 sregs->psr &= ~PSR_Z;
778 mul64 (rs1, operand2, &sregs->y, rdd, 0);
785 mul64 (rs1, operand2, &sregs->y, &result, 0);
787 if (result & 0x80000000)
790 sregs->psr &= ~PSR_N;
795 sregs->psr &= ~PSR_Z;
803 sregs->trap = TRAP_UNIMP;
808 sregs->trap = TRAP_DIV0;
812 div64 (sregs->y, rs1, operand2, rdd, 1);
820 sregs->trap = TRAP_UNIMP;
825 sregs->trap = TRAP_DIV0;
829 div64 (sregs->y, rs1, operand2, &result, 1);
831 if (result & 0x80000000)
834 sregs->psr &= ~PSR_N;
839 sregs->psr &= ~PSR_Z;
841 /* FIXME: should set overflow flag correctly. */
842 sregs->psr &= ~(PSR_C | PSR_V);
850 sregs->trap = TRAP_UNIMP;
855 sregs->trap = TRAP_DIV0;
859 div64 (sregs->y, rs1, operand2, rdd, 0);
867 sregs->trap = TRAP_UNIMP;
872 sregs->trap = TRAP_DIV0;
876 div64 (sregs->y, rs1, operand2, &result, 0);
878 if (result & 0x80000000)
881 sregs->psr &= ~PSR_N;
886 sregs->psr &= ~PSR_Z;
888 /* FIXME: should set overflow flag correctly. */
889 sregs->psr &= ~(PSR_C | PSR_V);
895 *rdd = rs1 ^ ~operand2;
898 *rdd = rs1 ^ ~operand2;
902 *rdd = rs1 ^ operand2;
905 *rdd = rs1 ^ operand2;
909 *rdd = rs1 | operand2;
912 *rdd = rs1 | operand2;
916 *rdd = rs1 | ~operand2;
919 *rdd = rs1 | ~operand2;
923 *rdd = rs1 & ~operand2;
927 *rdd = rs1 & ~operand2;
930 *rdd = rs1 & operand2;
933 *rdd = rs1 & operand2;
937 *rdd = rs1 - operand2;
940 *rdd = rs1 - operand2;
941 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
944 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
947 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
948 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
951 *rdd = rs1 + operand2;
954 *rdd = rs1 + operand2;
955 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
958 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
961 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
962 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
965 *rdd = rs1 + operand2;
966 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
967 if ((rs1 | operand2) & 0x3)
971 *rdd = rs1 - operand2;
972 sregs->psr = sub_cc (sregs->psr, rs1, operand2, *rdd);
973 if ((rs1 | operand2) & 0x3)
977 *rdd = rs1 + operand2;
978 result = add_cc(0, rs1, operand2, *rdd);
979 if ((rs1 | operand2) & 0x3)
981 if (result & PSR_V) {
982 sregs->trap = TRAP_TAG;
984 sregs->psr = (sregs->psr & ~PSR_CC) | result;
988 *rdd = rs1 - operand2;
989 result = add_cc (0, rs1, operand2, *rdd);
990 if ((rs1 | operand2) & 0x3)
994 sregs->trap = TRAP_TAG;
998 sregs->psr = (sregs->psr & ~PSR_CC) | result;
1002 *rdd = rs1 << (operand2 & 0x1f);
1005 *rdd = rs1 >> (operand2 & 0x1f);
1008 *rdd = ((int) rs1) >> (operand2 & 0x1f);
1011 if (ift) sregs->trap = TRAP_UNIMP;
1014 new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
1015 if (sregs->wim & (1 << new_cwp)) {
1016 sregs->trap = TRAP_WOFL;
1020 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1021 *rdd = rs1 + operand2;
1022 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1026 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1027 if (sregs->wim & (1 << new_cwp)) {
1028 sregs->trap = TRAP_WUFL;
1032 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1033 *rdd = rs1 + operand2;
1034 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1037 if (!(sregs->psr & PSR_S)) {
1038 sregs->trap = TRAP_PRIVI;
1047 int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
1048 if ( 0 == rs1_is_asr )
1050 else if ( 17 == rs1_is_asr )
1051 *rdd = sregs->asr17;
1053 sregs->trap = TRAP_UNIMP;
1059 if (!(sregs->psr & PSR_S)) {
1060 sregs->trap = TRAP_PRIVI;
1066 if (!(sregs->psr & PSR_S)) {
1067 sregs->trap = TRAP_PRIVI;
1073 if ((sregs->psr & 0x1f) > 7) {
1074 sregs->trap = TRAP_UNIMP;
1077 if (!(sregs->psr & PSR_S)) {
1078 sregs->trap = TRAP_PRIVI;
1081 sregs->psr = (rs1 ^ operand2) & 0x00f03fff;
1084 if (!(sregs->psr & PSR_S)) {
1085 sregs->trap = TRAP_PRIVI;
1088 sregs->wim = (rs1 ^ operand2) & 0x0ff;
1091 if (!(sregs->psr & PSR_S)) {
1092 sregs->trap = TRAP_PRIVI;
1095 sregs->tbr = (sregs->tbr & 0x00000ff0) |
1096 ((rs1 ^ operand2) & 0xfffff000);
1100 sregs->y = (rs1 ^ operand2);
1103 sregs->y = (rs1 ^ operand2);
1104 else if ( 17 == rd )
1105 sregs->asr17 = (rs1 ^ operand2);
1107 sregs->trap = TRAP_UNIMP;
1117 sregs->icnt = T_JMPL; /* JMPL takes two cycles */
1119 sregs->trap = TRAP_UNALI;
1123 npc = rs1 + operand2;
1126 address = rs1 + operand2;
1127 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1128 sregs->icnt = T_RETT; /* RETT takes two cycles */
1129 if (sregs->psr & PSR_ET) {
1130 sregs->trap = TRAP_UNIMP;
1133 if (!(sregs->psr & PSR_S)) {
1134 sregs->trap = TRAP_PRIVI;
1137 if (sregs->wim & (1 << new_cwp)) {
1138 sregs->trap = TRAP_WUFL;
1141 if (address & 0x3) {
1142 sregs->trap = TRAP_UNALI;
1145 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
1147 (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
1153 uint32 result, mask;
1157 sregs->trap = TRAP_UNIMP;
1160 mask = (operand2 & 0x80000000) | (operand2 >> 1);
1161 result = rs1 ^ mask;
1163 for (i = 0; i < 32; i++) {
1164 if (result & 0x80000000)
1169 *rdd = i == 32 ? 63 : i;
1174 sregs->trap = TRAP_UNIMP;
1179 case 3: /* Load/store instructions */
1181 address = rs1 + operand2;
1183 if (sregs->psr & PSR_S)
1189 sregs->icnt = T_ST; /* Set store instruction count */
1194 sregs->icnt = T_LD; /* Set load instruction count */
1200 /* Decode load/store instructions */
1204 if (!chk_asi(sregs, &asi, op3)) break;
1206 if (address & 0x7) {
1207 sregs->trap = TRAP_UNALI;
1213 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1215 rdd = &(sregs->g[rd]);
1217 mexc = memory_read(asi, address, ddata, 3, &ws);
1218 sregs->hold += ws * 2;
1219 sregs->icnt = T_LDD;
1221 sregs->trap = TRAP_DEXC;
1226 sregs->nload++; /* Double load counts twice */
1232 if (!chk_asi(sregs, &asi, op3)) break;
1234 if (address & 0x3) {
1235 sregs->trap = TRAP_UNALI;
1238 mexc = memory_read(asi, address, &data, 2, &ws);
1241 sregs->trap = TRAP_DEXC;
1247 if (!chk_asi(sregs, &asi, op3)) break;
1249 mexc = memory_read(asi, address, &data, 0, &ws);
1251 sregs->icnt = T_LDST;
1253 sregs->trap = TRAP_DEXC;
1258 mexc = memory_write(asi, address, &data, 0, &ws);
1261 sregs->trap = TRAP_DEXC;
1269 if (!chk_asi(sregs, &asi, op3)) break;
1272 mexc = memory_read(asi, address, &data, 0, &ws);
1275 sregs->trap = TRAP_DEXC;
1278 if ((op3 == LDSB) && (data & 0x80))
1284 if (!chk_asi(sregs, &asi, op3)) break;
1287 if (address & 0x1) {
1288 sregs->trap = TRAP_UNALI;
1291 mexc = memory_read(asi, address, &data, 1, &ws);
1294 sregs->trap = TRAP_DEXC;
1297 if ((op3 == LDSH) && (data & 0x8000))
1302 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1303 sregs->trap = TRAP_FPDIS;
1306 if (address & 0x3) {
1307 sregs->trap = TRAP_UNALI;
1310 if (ebase.simtime < sregs->ftime) {
1311 if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
1312 (sregs->frs2 == rd))
1313 sregs->fhold += (sregs->ftime - ebase.simtime);
1315 mexc = memory_read(asi, address, &data, 2, &ws);
1318 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1319 sregs->hold + sregs->fhold;
1321 sregs->trap = TRAP_DEXC;
1323 sregs->fs[rd] = *((float32 *) & data);
1327 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1328 sregs->trap = TRAP_FPDIS;
1331 if (address & 0x7) {
1332 sregs->trap = TRAP_UNALI;
1335 if (ebase.simtime < sregs->ftime) {
1336 if (((sregs->frd >> 1) == (rd >> 1)) ||
1337 ((sregs->frs1 >> 1) == (rd >> 1)) ||
1338 ((sregs->frs2 >> 1) == (rd >> 1)))
1339 sregs->fhold += (sregs->ftime - ebase.simtime);
1341 mexc = memory_read(asi, address, ddata, 3, &ws);
1342 sregs->hold += ws * 2;
1343 sregs->icnt = T_LDD;
1345 sregs->trap = TRAP_DEXC;
1349 sregs->fs[rd] = *((float32 *) & ddata[0]);
1351 sregs->nload++; /* Double load counts twice */
1353 sregs->fs[rd + 1] = *((float32 *) & ddata[1]);
1354 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1355 sregs->hold + sregs->fhold;
1359 if (ebase.simtime < sregs->ftime) {
1360 sregs->fhold += (sregs->ftime - ebase.simtime);
1362 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1363 sregs->trap = TRAP_FPDIS;
1366 if (address & 0x3) {
1367 sregs->trap = TRAP_UNALI;
1370 mexc = memory_read(asi, address, &data, 2, &ws);
1373 sregs->trap = TRAP_DEXC;
1376 (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
1377 set_fsr(sregs->fsr);
1381 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1382 sregs->trap = TRAP_FPDIS;
1385 if (address & 0x3) {
1386 sregs->trap = TRAP_UNALI;
1389 if (ebase.simtime < sregs->ftime) {
1390 sregs->fhold += (sregs->ftime - ebase.simtime);
1392 mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
1395 sregs->trap = TRAP_DEXC;
1400 if (!chk_asi(sregs, &asi, op3)) break;
1402 if (address & 0x3) {
1403 sregs->trap = TRAP_UNALI;
1406 mexc = memory_write(asi, address, rdd, 2, &ws);
1409 sregs->trap = TRAP_DEXC;
1413 if (!chk_asi(sregs, &asi, op3)) break;
1415 mexc = memory_write(asi, address, rdd, 0, &ws);
1418 sregs->trap = TRAP_DEXC;
1422 if (!chk_asi(sregs, &asi, op3)) break;
1424 if (address & 0x7) {
1425 sregs->trap = TRAP_UNALI;
1431 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1433 rdd = &(sregs->g[rd]);
1435 mexc = memory_write(asi, address, rdd, 3, &ws);
1437 sregs->icnt = T_STD;
1439 sregs->nstore++; /* Double store counts twice */
1442 sregs->trap = TRAP_DEXC;
1447 if ((sregs->psr & 0x1f) > 7) {
1448 sregs->trap = TRAP_UNIMP;
1451 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1452 sregs->trap = TRAP_FPDIS;
1455 if (address & 0x7) {
1456 sregs->trap = TRAP_UNALI;
1459 if (!(sregs->fsr & FSR_QNE)) {
1460 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1463 rdd = &(sregs->fpq[0]);
1464 mexc = memory_write(asi, address, rdd, 3, &ws);
1466 sregs->icnt = T_STD;
1468 sregs->nstore++; /* Double store counts twice */
1471 sregs->trap = TRAP_DEXC;
1474 sregs->fsr &= ~FSR_QNE;
1475 sregs->fpstate = FP_EXE_MODE;
1479 if (!chk_asi(sregs, &asi, op3)) break;
1481 if (address & 0x1) {
1482 sregs->trap = TRAP_UNALI;
1485 mexc = memory_write(asi, address, rdd, 1, &ws);
1488 sregs->trap = TRAP_DEXC;
1492 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1493 sregs->trap = TRAP_FPDIS;
1496 if (address & 0x3) {
1497 sregs->trap = TRAP_UNALI;
1500 if (ebase.simtime < sregs->ftime) {
1501 if (sregs->frd == rd)
1502 sregs->fhold += (sregs->ftime - ebase.simtime);
1504 mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
1507 sregs->trap = TRAP_DEXC;
1511 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1512 sregs->trap = TRAP_FPDIS;
1515 if (address & 0x7) {
1516 sregs->trap = TRAP_UNALI;
1520 if (ebase.simtime < sregs->ftime) {
1521 if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
1522 sregs->fhold += (sregs->ftime - ebase.simtime);
1524 mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);
1526 sregs->icnt = T_STD;
1528 sregs->nstore++; /* Double store counts twice */
1531 sregs->trap = TRAP_DEXC;
1535 if (!chk_asi(sregs, &asi, op3)) break;
1537 if (address & 0x3) {
1538 sregs->trap = TRAP_UNALI;
1541 mexc = memory_read(asi, address, &data, 2, &ws);
1544 sregs->trap = TRAP_DEXC;
1547 mexc = memory_write(asi, address, rdd, 2, &ws);
1549 sregs->icnt = T_LDST;
1551 sregs->trap = TRAP_DEXC;
1562 sregs->trap = TRAP_UNIMP;
1569 sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
1571 if ((op3 | 0x10) == 0x13)
1572 sregs->ildreg |= 1; /* Double load, odd register loaded
1579 sregs->trap = TRAP_UNIMP;
1638 fpexec(op3, rd, rs1, rs2, sregs)
1639 uint32 op3, rd, rs1, rs2;
1640 struct pstate *sregs;
1642 uint32 opf, tem, accex;
1646 if (sregs->fpstate == FP_EXC_MODE) {
1647 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1648 sregs->fpstate = FP_EXC_PE;
1651 if (sregs->fpstate == FP_EXC_PE) {
1652 sregs->fpstate = FP_EXC_MODE;
1653 return (TRAP_FPEXC);
1655 opf = (sregs->inst >> 5) & 0x1ff;
1658 * Check if we already have an FPop in the pipe. If so, halt until it is
1659 * finished by incrementing fhold with the remaining execution time
1662 if (ebase.simtime < sregs->ftime) {
1663 sregs->fhold = (sregs->ftime - ebase.simtime);
1667 /* Check load dependencies. */
1669 if (ebase.simtime < sregs->ltime) {
1671 /* Don't check rs1 if single operand instructions */
1673 if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1676 /* Adjust for double floats */
1679 if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1686 sregs->frs1 = rs1; /* Store src and dst for dependecy check */
1690 sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1692 /* SPARC is big-endian - swap double floats if host is little-endian */
1693 /* This is ugly - I know ... */
1695 /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1696 but what about machines where float values are different endianness
1697 from integer values? */
1699 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1711 sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
1712 sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
1713 sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
1714 sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
1723 sregs->fs[rd] = fabs(sregs->fs[rs2]);
1724 sregs->ftime += T_FABSs;
1725 sregs->frs1 = 32; /* rs1 ignored */
1728 sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
1729 sregs->ftime += T_FADDs;
1732 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
1733 sregs->ftime += T_FADDd;
1737 if (sregs->fs[rs1] == sregs->fs[rs2])
1739 else if (sregs->fs[rs1] < sregs->fs[rs2])
1741 else if (sregs->fs[rs1] > sregs->fs[rs2])
1745 sregs->fsr |= 0x0C00;
1746 sregs->fsr &= ~(fcc << 10);
1747 sregs->ftime += T_FCMPs;
1748 sregs->frd = 32; /* rd ignored */
1749 if ((fcc == 0) && (opf == FCMPEs)) {
1750 sregs->fpstate = FP_EXC_PE;
1751 sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
1756 if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
1758 else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
1760 else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
1764 sregs->fsr |= 0x0C00;
1765 sregs->fsr &= ~(fcc << 10);
1766 sregs->ftime += T_FCMPd;
1767 sregs->frd = 32; /* rd ignored */
1768 if ((fcc == 0) && (opf == FCMPEd)) {
1769 sregs->fpstate = FP_EXC_PE;
1770 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1774 sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
1775 sregs->ftime += T_FDIVs;
1778 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
1779 sregs->ftime += T_FDIVd;
1782 sregs->fs[rd] = sregs->fs[rs2];
1783 sregs->ftime += T_FMOVs;
1784 sregs->frs1 = 32; /* rs1 ignored */
1787 sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
1788 sregs->ftime += T_FMULs;
1791 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
1792 sregs->ftime += T_FMULd;
1795 sregs->fs[rd] = -sregs->fs[rs2];
1796 sregs->ftime += T_FNEGs;
1797 sregs->frs1 = 32; /* rs1 ignored */
1800 if (sregs->fs[rs2] < 0.0) {
1801 sregs->fpstate = FP_EXC_PE;
1802 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1803 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1806 sregs->fs[rd] = sqrt(sregs->fs[rs2]);
1807 sregs->ftime += T_FSQRTs;
1808 sregs->frs1 = 32; /* rs1 ignored */
1811 if (sregs->fd[rs2 >> 1] < 0.0) {
1812 sregs->fpstate = FP_EXC_PE;
1813 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1814 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1817 sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
1818 sregs->ftime += T_FSQRTd;
1819 sregs->frs1 = 32; /* rs1 ignored */
1822 sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
1823 sregs->ftime += T_FSUBs;
1826 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
1827 sregs->ftime += T_FSUBd;
1830 sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
1831 sregs->ftime += T_FdTOi;
1832 sregs->frs1 = 32; /* rs1 ignored */
1835 sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
1836 sregs->ftime += T_FdTOs;
1837 sregs->frs1 = 32; /* rs1 ignored */
1840 sregs->fs[rd] = (float32) sregs->fsi[rs2];
1841 sregs->ftime += T_FiTOs;
1842 sregs->frs1 = 32; /* rs1 ignored */
1845 sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
1846 sregs->ftime += T_FiTOd;
1847 sregs->frs1 = 32; /* rs1 ignored */
1850 sregs->fsi[rd] = (int) sregs->fs[rs2];
1851 sregs->ftime += T_FsTOi;
1852 sregs->frs1 = 32; /* rs1 ignored */
1855 sregs->fd[rd >> 1] = sregs->fs[rs2];
1856 sregs->ftime += T_FsTOd;
1857 sregs->frs1 = 32; /* rs1 ignored */
1861 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1862 sregs->fpstate = FP_EXC_PE;
1867 sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);
1868 sregs->fpstate = FP_EXC_PE;
1869 if (sis_verbose) printf("Inserted fpu error %X\n",errftt);
1874 accex = get_accex();
1876 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1885 sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
1886 sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
1890 if (sregs->fpstate == FP_EXC_PE) {
1891 sregs->fpq[0] = sregs->pc;
1892 sregs->fpq[1] = sregs->inst;
1893 sregs->fsr |= FSR_QNE;
1895 tem = (sregs->fsr >> 23) & 0x1f;
1897 sregs->fpstate = FP_EXC_PE;
1898 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1899 sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
1901 sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
1903 if (sregs->fpstate == FP_EXC_PE) {
1904 sregs->fpq[0] = sregs->pc;
1905 sregs->fpq[1] = sregs->inst;
1906 sregs->fsr |= FSR_QNE;
1917 chk_asi(sregs, asi, op3)
1918 struct pstate *sregs;
1922 if (!(sregs->psr & PSR_S)) {
1923 sregs->trap = TRAP_PRIVI;
1925 } else if (sregs->inst & INST_I) {
1926 sregs->trap = TRAP_UNIMP;
1929 *asi = (sregs->inst >> 5) & 0x0ff;
1935 struct pstate *sregs;
1939 if (sregs->trap == 256) {
1943 } else if (sregs->trap == 257) {
1947 if ((sregs->psr & PSR_ET) == 0)
1950 sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
1952 sregs->psr &= ~PSR_ET;
1953 sregs->psr |= ((sregs->psr & PSR_S) >> 1);
1955 sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
1956 cwp = ((sregs->psr & PSR_CWP) << 4);
1957 sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
1958 sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
1959 sregs->psr |= PSR_S;
1960 sregs->pc = sregs->tbr;
1961 sregs->npc = sregs->tbr + 4;
1963 if ( 0 != (1 & sregs->asr17) ) {
1964 /* single vector trapping! */
1965 sregs->pc = sregs->tbr & 0xfffff000;
1966 sregs->npc = sregs->pc + 4;
1969 /* Increase simulator time */
1970 sregs->icnt = TRAP_C;
1979 extern struct irqcell irqarr[16];
1982 check_interrupts(sregs)
1983 struct pstate *sregs;
1987 sregs->trap = errtt;
1988 if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);
1993 if ((ext_irl) && (sregs->psr & PSR_ET) &&
1994 ((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) {
1995 if (sregs->trap == 0) {
1996 sregs->trap = 16 + ext_irl;
1997 irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
2006 struct pstate *sregs;
2011 sregs->psr &= 0x00f03fdf;
2012 sregs->psr |= 0x080; /* Set supervisor bit */
2013 sregs->breakpoint = 0;
2015 sregs->fpstate = FP_EXE_MODE;
2019 sregs->err_mode = 0;
2022 #ifdef HOST_LITTLE_ENDIAN_FLOAT
2023 sregs->fdp = (float32 *) sregs->fd;
2024 sregs->fsi = (int32 *) sregs->fs;
2026 sregs->fs = (float32 *) sregs->fd;
2027 sregs->fsi = (int32 *) sregs->fd;
2030 sregs->fpu_pres = !nfp;
2031 set_fsr(sregs->fsr);
2039 sregs->rett_err = 0;
2040 sregs->jmpltime = 0;