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.
29 extern int32 sis_verbose, sparclite;
32 /* Load/store interlock delay */
35 /* Load delay (delete if unwanted - speeds up simulation) */
46 #define FSR_QNE 0x2000
78 #define PSR_N 0x0800000
79 #define PSR_Z 0x0400000
80 #define PSR_V 0x0200000
81 #define PSR_C 0x0100000
82 #define PSR_CC 0x0F00000
84 #define PSR_PIL 0x0f00
86 #define ICC_N (icc >> 3)
87 #define ICC_Z (icc >> 2)
88 #define ICC_V (icc >> 1)
91 #define FP_PRES (sregs->fpu_pres)
103 #define TRAP_DIV0 0x2a
105 #define FSR_TT 0x1C000
106 #define FP_IEEE 0x04000
107 #define FP_UNIMP 0x0C000
108 #define FP_SEQ_ERR 0x10000
127 #define INST_SIMM13 0x1fff
128 #define INST_RS2 0x1f
129 #define INST_I 0x2000
136 #define TADDCCTV 0x22
137 #define TSUBCCTV 0x23
217 #define SIGN_BIT 0x80000000
219 /* # of cycles overhead when a trap is taken */
222 /* Forward declarations */
224 static uint32 sub_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,
226 static uint32 add_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,
228 static void log_cc PARAMS ((int32 result, struct pstate *sregs));
229 static int fpexec PARAMS ((uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
230 struct pstate *sregs));
231 static int chk_asi PARAMS ((struct pstate *sregs, uint32 *asi, uint32 op3));
234 extern struct estate ebase;
235 extern int32 nfp,ift;
238 extern uint32 errtt, errftt;
242 sub_cc(psr, operand1, operand2, result)
248 psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
253 psr = (psr & ~PSR_V) | ((((operand1 & ~operand2 & ~result) |
254 (~operand1 & operand2 & result)) >> 10) & PSR_V);
255 psr = (psr & ~PSR_C) | ((((~operand1 & operand2) |
256 ((~operand1 | operand2) & result)) >> 11) & PSR_C);
261 add_cc(psr, operand1, operand2, result)
267 psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
272 psr = (psr & ~PSR_V) | ((((operand1 & operand2 & ~result) |
273 (~operand1 & ~operand2 & result)) >> 10) & PSR_V);
274 psr = (psr & ~PSR_C) | ((((operand1 & operand2) |
275 ((operand1 | operand2) & ~result)) >> 11) & PSR_C);
280 log_cc(result, sregs)
282 struct pstate *sregs;
284 sregs->psr &= ~(PSR_CC); /* Zero CC bits */
285 sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));
290 /* Add two unsigned 32-bit integers, and calculate the carry out. */
293 add32 (uint32 n1, uint32 n2, int *carry)
295 uint32 result = n1 + n2;
297 *carry = result < n1 || result < n1;
301 /* Multiply two 32-bit integers. */
304 mul64 (uint32 n1, uint32 n2, uint32 *result_hi, uint32 *result_lo, int msigned)
306 uint32 lo, mid1, mid2, hi, reg_lo, reg_hi;
310 /* If this is a signed multiply, calculate the sign of the result
311 and make the operands positive. */
314 sign = (n1 ^ n2) & SIGN_BIT;
322 /* We can split the 32x32 into four 16x16 operations. This ensures
323 that we do not lose precision on 32bit only hosts: */
324 lo = ((n1 & 0xFFFF) * (n2 & 0xFFFF));
325 mid1 = ((n1 & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
326 mid2 = (((n1 >> 16) & 0xFFFF) * (n2 & 0xFFFF));
327 hi = (((n1 >> 16) & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
329 /* We now need to add all of these results together, taking care
330 to propogate the carries from the additions: */
331 reg_lo = add32 (lo, (mid1 << 16), &carry);
333 reg_lo = add32 (reg_lo, (mid2 << 16), &carry);
334 reg_hi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
336 /* Negate result if necessary. */
350 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
351 that the host compiler supports long long operations. */
354 div64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned)
358 n1 = ((uint64) n1_hi) << 32;
359 n1 |= ((uint64) n1_low) & 0xffffffff;
363 int64 n1_s = (int64) n1;
364 int32 n2_s = (int32) n2;
371 *result = (uint32) (n1 & 0xffffffff);
376 dispatch_instruction(sregs)
377 struct pstate *sregs;
380 uint32 cwp, op, op2, op3, asi, rd, cond, rs1,
383 int32 operand1, operand2, *rdd, result, eicc,
385 int32 pc, npc, data, address, ws, mexc, fcc;
389 cwp = ((sregs->psr & PSR_CWP) << 4);
390 op = sregs->inst >> 30;
392 npc = sregs->npc + 4;
393 op3 = rd = rs1 = operand2 = eicc = 0;
397 op3 = (sregs->inst >> 19) & 0x3f;
398 rs1 = (sregs->inst >> 14) & 0x1f;
399 rd = (sregs->inst >> 25) & 0x1f;
403 /* Check if load dependecy is possible */
404 if (ebase.simtime <= sregs->ildtime)
405 ldep = (((op3 & 0x38) != 0x28) && ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));
408 if (sregs->inst & INST_I) {
409 if (ldep && (sregs->ildreg == rs1))
411 operand2 = sregs->inst;
412 operand2 = ((operand2 << 19) >> 19); /* sign extend */
414 rs2 = sregs->inst & INST_RS2;
416 operand2 = sregs->r[(cwp + rs2) & 0x7f];
418 operand2 = sregs->g[rs2];
419 if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))
423 if (sregs->inst & INST_I) {
424 operand2 = sregs->inst;
425 operand2 = ((operand2 << 19) >> 19); /* sign extend */
427 rs2 = sregs->inst & INST_RS2;
429 operand2 = sregs->r[(cwp + rs2) & 0x7f];
431 operand2 = sregs->g[rs2];
436 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
438 rdd = &(sregs->g[rd]);
440 rs1 = sregs->r[(cwp + rs1) & 0x7f];
446 op2 = (sregs->inst >> 22) & 0x7;
449 rd = (sregs->inst >> 25) & 0x1f;
451 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
453 rdd = &(sregs->g[rd]);
454 *rdd = sregs->inst << 10;
460 icc = sregs->psr >> 20;
461 cond = ((sregs->inst >> 25) & 0x0f);
470 eicc = ICC_Z | (ICC_N ^ ICC_V);
473 eicc = (ICC_N ^ ICC_V);
476 eicc = ICC_C | ICC_Z;
489 if (sregs->inst & 0x20000000)
496 eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
499 eicc = ~(ICC_N ^ ICC_V);
502 eicc = ~(ICC_C | ICC_Z);
515 operand1 = sregs->inst;
516 operand1 = ((operand1 << 10) >> 8); /* sign extend */
517 npc = sregs->pc + operand1;
519 if (sregs->inst & 0x20000000)
527 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
528 sregs->trap = TRAP_FPDIS;
531 if (ebase.simtime < sregs->ftime) {
532 sregs->ftime = ebase.simtime + sregs->hold;
534 cond = ((sregs->inst >> 25) & 0x0f);
535 fcc = (sregs->fsr >> 10) & 0x3;
541 eicc = (fcc != FCC_E);
544 eicc = (fcc == FCC_L) || (fcc == FCC_G);
547 eicc = (fcc == FCC_L) || (fcc == FCC_U);
550 eicc = (fcc == FCC_L);
553 eicc = (fcc == FCC_G) || (fcc == FCC_U);
556 eicc = (fcc == FCC_G);
559 eicc = (fcc == FCC_U);
563 if (sregs->inst & 0x20000000)
567 eicc = !(fcc != FCC_E);
570 eicc = !((fcc == FCC_L) || (fcc == FCC_G));
573 eicc = !((fcc == FCC_L) || (fcc == FCC_U));
576 eicc = !(fcc == FCC_L);
579 eicc = !((fcc == FCC_G) || (fcc == FCC_U));
582 eicc = !(fcc == FCC_G);
585 eicc = !(fcc == FCC_U);
589 operand1 = sregs->inst;
590 operand1 = ((operand1 << 10) >> 8); /* sign extend */
591 npc = sregs->pc + operand1;
593 if (sregs->inst & 0x20000000)
599 sregs->trap = TRAP_UNIMP;
607 sregs->r[(cwp + 15) & 0x7f] = sregs->pc;
608 npc = sregs->pc + (sregs->inst << 2);
612 if ((op3 >> 1) == 0x1a) {
613 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
614 sregs->trap = TRAP_FPDIS;
616 rs1 = (sregs->inst >> 14) & 0x1f;
617 rs2 = sregs->inst & 0x1f;
618 sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);
624 icc = sregs->psr >> 20;
625 cond = ((sregs->inst >> 25) & 0x0f);
634 eicc = ICC_Z | (ICC_N ^ ICC_V);
637 eicc = (ICC_N ^ ICC_V);
640 eicc = ICC_C | ICC_Z;
658 eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
661 eicc = ~(ICC_N ^ ICC_V);
664 eicc = ~(ICC_C | ICC_Z);
677 sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
683 (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
685 if ((sregs->y & 1) == 0)
687 *rdd = operand1 + operand2;
688 sregs->y = (rs1 << 31) | (sregs->y >> 1);
689 sregs->psr = add_cc(sregs->psr, operand1, operand2, *rdd);
694 uint32 result, remainder;
698 sregs->trap = TRAP_UNIMP;
702 sign = ((sregs->psr & PSR_V) != 0) ^ ((sregs->psr & PSR_N) != 0);
704 remainder = (sregs->y << 1) | (rs1 >> 31);
706 /* If true sign is positive, calculate remainder - divisor.
707 Otherwise, calculate remainder + divisor. */
709 operand2 = ~operand2 + 1;
710 result = remainder + operand2;
712 /* The SPARClite User's Manual is not clear on how
713 the "carry out" of the above ALU operation is to
714 be calculated. From trial and error tests
715 on the the chip itself, it appears that it is
716 a normal addition carry, and not a subtraction borrow,
717 even in cases where the divisor is subtracted
718 from the remainder. FIXME: get the true story
720 c0 = result < (uint32) remainder
721 || result < (uint32) operand2;
723 if (result & 0x80000000)
726 sregs->psr &= ~PSR_N;
728 y31 = (sregs->y & 0x80000000) == 0x80000000;
730 if (result == 0 && sign == y31)
733 sregs->psr &= ~PSR_Z;
735 sign = (sign && !y31) || (!c0 && (sign || !y31));
737 if (sign ^ (result >> 31))
740 sregs->psr &= ~PSR_V;
745 sregs->psr &= ~PSR_C;
750 *rdd = (rs1 << 1) | !sign;
755 mul64 (rs1, operand2, &sregs->y, rdd, 1);
762 mul64 (rs1, operand2, &sregs->y, &result, 1);
764 if (result & 0x80000000)
767 sregs->psr &= ~PSR_N;
772 sregs->psr &= ~PSR_Z;
779 mul64 (rs1, operand2, &sregs->y, rdd, 0);
786 mul64 (rs1, operand2, &sregs->y, &result, 0);
788 if (result & 0x80000000)
791 sregs->psr &= ~PSR_N;
796 sregs->psr &= ~PSR_Z;
804 sregs->trap = TRAP_UNIMP;
809 sregs->trap = TRAP_DIV0;
813 div64 (sregs->y, rs1, operand2, rdd, 1);
821 sregs->trap = TRAP_UNIMP;
826 sregs->trap = TRAP_DIV0;
830 div64 (sregs->y, rs1, operand2, &result, 1);
832 if (result & 0x80000000)
835 sregs->psr &= ~PSR_N;
840 sregs->psr &= ~PSR_Z;
842 /* FIXME: should set overflow flag correctly. */
843 sregs->psr &= ~(PSR_C | PSR_V);
851 sregs->trap = TRAP_UNIMP;
856 sregs->trap = TRAP_DIV0;
860 div64 (sregs->y, rs1, operand2, rdd, 0);
868 sregs->trap = TRAP_UNIMP;
873 sregs->trap = TRAP_DIV0;
877 div64 (sregs->y, rs1, operand2, &result, 0);
879 if (result & 0x80000000)
882 sregs->psr &= ~PSR_N;
887 sregs->psr &= ~PSR_Z;
889 /* FIXME: should set overflow flag correctly. */
890 sregs->psr &= ~(PSR_C | PSR_V);
896 *rdd = rs1 ^ ~operand2;
899 *rdd = rs1 ^ ~operand2;
903 *rdd = rs1 ^ operand2;
906 *rdd = rs1 ^ operand2;
910 *rdd = rs1 | operand2;
913 *rdd = rs1 | operand2;
917 *rdd = rs1 | ~operand2;
920 *rdd = rs1 | ~operand2;
924 *rdd = rs1 & ~operand2;
928 *rdd = rs1 & ~operand2;
931 *rdd = rs1 & operand2;
934 *rdd = rs1 & operand2;
938 *rdd = rs1 - operand2;
941 *rdd = rs1 - operand2;
942 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
945 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
948 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
949 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
952 *rdd = rs1 + operand2;
955 *rdd = rs1 + operand2;
956 sregs->psr = add_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 = add_cc(sregs->psr, rs1, operand2, *rdd);
966 *rdd = rs1 + operand2;
967 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
968 if ((rs1 | operand2) & 0x3)
972 *rdd = rs1 - operand2;
973 sregs->psr = sub_cc (sregs->psr, rs1, operand2, *rdd);
974 if ((rs1 | operand2) & 0x3)
978 *rdd = rs1 + operand2;
979 result = add_cc(0, rs1, operand2, *rdd);
980 if ((rs1 | operand2) & 0x3)
982 if (result & PSR_V) {
983 sregs->trap = TRAP_TAG;
985 sregs->psr = (sregs->psr & ~PSR_CC) | result;
989 *rdd = rs1 - operand2;
990 result = add_cc (0, rs1, operand2, *rdd);
991 if ((rs1 | operand2) & 0x3)
995 sregs->trap = TRAP_TAG;
999 sregs->psr = (sregs->psr & ~PSR_CC) | result;
1003 *rdd = rs1 << (operand2 & 0x1f);
1006 *rdd = rs1 >> (operand2 & 0x1f);
1009 *rdd = ((int) rs1) >> (operand2 & 0x1f);
1012 if (ift) sregs->trap = TRAP_UNIMP;
1015 new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
1016 if (sregs->wim & (1 << new_cwp)) {
1017 sregs->trap = TRAP_WOFL;
1021 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1022 *rdd = rs1 + operand2;
1023 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1027 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1028 if (sregs->wim & (1 << new_cwp)) {
1029 sregs->trap = TRAP_WUFL;
1033 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1034 *rdd = rs1 + operand2;
1035 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1038 if (!(sregs->psr & PSR_S)) {
1039 sregs->trap = TRAP_PRIVI;
1048 int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
1049 if ( 0 == rs1_is_asr )
1051 else if ( 17 == rs1_is_asr )
1052 *rdd = sregs->asr17;
1054 sregs->trap = TRAP_UNIMP;
1060 if (!(sregs->psr & PSR_S)) {
1061 sregs->trap = TRAP_PRIVI;
1067 if (!(sregs->psr & PSR_S)) {
1068 sregs->trap = TRAP_PRIVI;
1074 if ((sregs->psr & 0x1f) > 7) {
1075 sregs->trap = TRAP_UNIMP;
1078 if (!(sregs->psr & PSR_S)) {
1079 sregs->trap = TRAP_PRIVI;
1082 sregs->psr = (rs1 ^ operand2) & 0x00f03fff;
1085 if (!(sregs->psr & PSR_S)) {
1086 sregs->trap = TRAP_PRIVI;
1089 sregs->wim = (rs1 ^ operand2) & 0x0ff;
1092 if (!(sregs->psr & PSR_S)) {
1093 sregs->trap = TRAP_PRIVI;
1096 sregs->tbr = (sregs->tbr & 0x00000ff0) |
1097 ((rs1 ^ operand2) & 0xfffff000);
1101 sregs->y = (rs1 ^ operand2);
1104 sregs->y = (rs1 ^ operand2);
1105 else if ( 17 == rd )
1106 sregs->asr17 = (rs1 ^ operand2);
1108 sregs->trap = TRAP_UNIMP;
1118 sregs->icnt = T_JMPL; /* JMPL takes two cycles */
1120 sregs->trap = TRAP_UNALI;
1124 npc = rs1 + operand2;
1127 address = rs1 + operand2;
1128 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1129 sregs->icnt = T_RETT; /* RETT takes two cycles */
1130 if (sregs->psr & PSR_ET) {
1131 sregs->trap = TRAP_UNIMP;
1134 if (!(sregs->psr & PSR_S)) {
1135 sregs->trap = TRAP_PRIVI;
1138 if (sregs->wim & (1 << new_cwp)) {
1139 sregs->trap = TRAP_WUFL;
1142 if (address & 0x3) {
1143 sregs->trap = TRAP_UNALI;
1146 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
1148 (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
1154 uint32 result, mask;
1158 sregs->trap = TRAP_UNIMP;
1161 mask = (operand2 & 0x80000000) | (operand2 >> 1);
1162 result = rs1 ^ mask;
1164 for (i = 0; i < 32; i++) {
1165 if (result & 0x80000000)
1170 *rdd = i == 32 ? 63 : i;
1175 sregs->trap = TRAP_UNIMP;
1180 case 3: /* Load/store instructions */
1182 address = rs1 + operand2;
1184 if (sregs->psr & PSR_S)
1190 sregs->icnt = T_ST; /* Set store instruction count */
1195 sregs->icnt = T_LD; /* Set load instruction count */
1201 /* Decode load/store instructions */
1205 if (!chk_asi(sregs, &asi, op3)) break;
1207 if (address & 0x7) {
1208 sregs->trap = TRAP_UNALI;
1214 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1216 rdd = &(sregs->g[rd]);
1218 mexc = memory_read(asi, address, ddata, 3, &ws);
1219 sregs->hold += ws * 2;
1220 sregs->icnt = T_LDD;
1222 sregs->trap = TRAP_DEXC;
1227 sregs->nload++; /* Double load counts twice */
1233 if (!chk_asi(sregs, &asi, op3)) break;
1235 if (address & 0x3) {
1236 sregs->trap = TRAP_UNALI;
1239 mexc = memory_read(asi, address, &data, 2, &ws);
1242 sregs->trap = TRAP_DEXC;
1248 if (!chk_asi(sregs, &asi, op3)) break;
1250 mexc = memory_read(asi, address, &data, 0, &ws);
1252 sregs->icnt = T_LDST;
1254 sregs->trap = TRAP_DEXC;
1259 mexc = memory_write(asi, address, &data, 0, &ws);
1262 sregs->trap = TRAP_DEXC;
1270 if (!chk_asi(sregs, &asi, op3)) break;
1273 mexc = memory_read(asi, address, &data, 0, &ws);
1276 sregs->trap = TRAP_DEXC;
1279 if ((op3 == LDSB) && (data & 0x80))
1285 if (!chk_asi(sregs, &asi, op3)) break;
1288 if (address & 0x1) {
1289 sregs->trap = TRAP_UNALI;
1292 mexc = memory_read(asi, address, &data, 1, &ws);
1295 sregs->trap = TRAP_DEXC;
1298 if ((op3 == LDSH) && (data & 0x8000))
1303 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1304 sregs->trap = TRAP_FPDIS;
1307 if (address & 0x3) {
1308 sregs->trap = TRAP_UNALI;
1311 if (ebase.simtime < sregs->ftime) {
1312 if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
1313 (sregs->frs2 == rd))
1314 sregs->fhold += (sregs->ftime - ebase.simtime);
1316 mexc = memory_read(asi, address, &data, 2, &ws);
1319 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1320 sregs->hold + sregs->fhold;
1322 sregs->trap = TRAP_DEXC;
1324 sregs->fs[rd] = *((float32 *) & data);
1328 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1329 sregs->trap = TRAP_FPDIS;
1332 if (address & 0x7) {
1333 sregs->trap = TRAP_UNALI;
1336 if (ebase.simtime < sregs->ftime) {
1337 if (((sregs->frd >> 1) == (rd >> 1)) ||
1338 ((sregs->frs1 >> 1) == (rd >> 1)) ||
1339 ((sregs->frs2 >> 1) == (rd >> 1)))
1340 sregs->fhold += (sregs->ftime - ebase.simtime);
1342 mexc = memory_read(asi, address, ddata, 3, &ws);
1343 sregs->hold += ws * 2;
1344 sregs->icnt = T_LDD;
1346 sregs->trap = TRAP_DEXC;
1350 sregs->fs[rd] = *((float32 *) & ddata[0]);
1352 sregs->nload++; /* Double load counts twice */
1354 sregs->fs[rd + 1] = *((float32 *) & ddata[1]);
1355 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1356 sregs->hold + sregs->fhold;
1360 if (ebase.simtime < sregs->ftime) {
1361 sregs->fhold += (sregs->ftime - ebase.simtime);
1363 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1364 sregs->trap = TRAP_FPDIS;
1367 if (address & 0x3) {
1368 sregs->trap = TRAP_UNALI;
1371 mexc = memory_read(asi, address, &data, 2, &ws);
1374 sregs->trap = TRAP_DEXC;
1377 (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
1378 set_fsr(sregs->fsr);
1382 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1383 sregs->trap = TRAP_FPDIS;
1386 if (address & 0x3) {
1387 sregs->trap = TRAP_UNALI;
1390 if (ebase.simtime < sregs->ftime) {
1391 sregs->fhold += (sregs->ftime - ebase.simtime);
1393 mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
1396 sregs->trap = TRAP_DEXC;
1401 if (!chk_asi(sregs, &asi, op3)) break;
1403 if (address & 0x3) {
1404 sregs->trap = TRAP_UNALI;
1407 mexc = memory_write(asi, address, rdd, 2, &ws);
1410 sregs->trap = TRAP_DEXC;
1414 if (!chk_asi(sregs, &asi, op3)) break;
1416 mexc = memory_write(asi, address, rdd, 0, &ws);
1419 sregs->trap = TRAP_DEXC;
1423 if (!chk_asi(sregs, &asi, op3)) break;
1425 if (address & 0x7) {
1426 sregs->trap = TRAP_UNALI;
1432 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1434 rdd = &(sregs->g[rd]);
1436 mexc = memory_write(asi, address, rdd, 3, &ws);
1438 sregs->icnt = T_STD;
1440 sregs->nstore++; /* Double store counts twice */
1443 sregs->trap = TRAP_DEXC;
1448 if ((sregs->psr & 0x1f) > 7) {
1449 sregs->trap = TRAP_UNIMP;
1452 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1453 sregs->trap = TRAP_FPDIS;
1456 if (address & 0x7) {
1457 sregs->trap = TRAP_UNALI;
1460 if (!(sregs->fsr & FSR_QNE)) {
1461 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1464 rdd = &(sregs->fpq[0]);
1465 mexc = memory_write(asi, address, rdd, 3, &ws);
1467 sregs->icnt = T_STD;
1469 sregs->nstore++; /* Double store counts twice */
1472 sregs->trap = TRAP_DEXC;
1475 sregs->fsr &= ~FSR_QNE;
1476 sregs->fpstate = FP_EXE_MODE;
1480 if (!chk_asi(sregs, &asi, op3)) break;
1482 if (address & 0x1) {
1483 sregs->trap = TRAP_UNALI;
1486 mexc = memory_write(asi, address, rdd, 1, &ws);
1489 sregs->trap = TRAP_DEXC;
1493 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1494 sregs->trap = TRAP_FPDIS;
1497 if (address & 0x3) {
1498 sregs->trap = TRAP_UNALI;
1501 if (ebase.simtime < sregs->ftime) {
1502 if (sregs->frd == rd)
1503 sregs->fhold += (sregs->ftime - ebase.simtime);
1505 mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
1508 sregs->trap = TRAP_DEXC;
1512 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1513 sregs->trap = TRAP_FPDIS;
1516 if (address & 0x7) {
1517 sregs->trap = TRAP_UNALI;
1521 if (ebase.simtime < sregs->ftime) {
1522 if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
1523 sregs->fhold += (sregs->ftime - ebase.simtime);
1525 mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);
1527 sregs->icnt = T_STD;
1529 sregs->nstore++; /* Double store counts twice */
1532 sregs->trap = TRAP_DEXC;
1536 if (!chk_asi(sregs, &asi, op3)) break;
1538 if (address & 0x3) {
1539 sregs->trap = TRAP_UNALI;
1542 mexc = memory_read(asi, address, &data, 2, &ws);
1545 sregs->trap = TRAP_DEXC;
1548 mexc = memory_write(asi, address, rdd, 2, &ws);
1550 sregs->icnt = T_LDST;
1552 sregs->trap = TRAP_DEXC;
1563 sregs->trap = TRAP_UNIMP;
1570 sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
1572 if ((op3 | 0x10) == 0x13)
1573 sregs->ildreg |= 1; /* Double load, odd register loaded
1580 sregs->trap = TRAP_UNIMP;
1639 fpexec(op3, rd, rs1, rs2, sregs)
1640 uint32 op3, rd, rs1, rs2;
1641 struct pstate *sregs;
1643 uint32 opf, tem, accex;
1647 if (sregs->fpstate == FP_EXC_MODE) {
1648 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1649 sregs->fpstate = FP_EXC_PE;
1652 if (sregs->fpstate == FP_EXC_PE) {
1653 sregs->fpstate = FP_EXC_MODE;
1654 return (TRAP_FPEXC);
1656 opf = (sregs->inst >> 5) & 0x1ff;
1659 * Check if we already have an FPop in the pipe. If so, halt until it is
1660 * finished by incrementing fhold with the remaining execution time
1663 if (ebase.simtime < sregs->ftime) {
1664 sregs->fhold = (sregs->ftime - ebase.simtime);
1668 /* Check load dependencies. */
1670 if (ebase.simtime < sregs->ltime) {
1672 /* Don't check rs1 if single operand instructions */
1674 if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1677 /* Adjust for double floats */
1680 if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1687 sregs->frs1 = rs1; /* Store src and dst for dependecy check */
1691 sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1693 /* SPARC is big-endian - swap double floats if host is little-endian */
1694 /* This is ugly - I know ... */
1696 /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1697 but what about machines where float values are different endianness
1698 from integer values? */
1700 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1712 sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
1713 sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
1714 sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
1715 sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
1725 sregs->fs[rd] = fabs(sregs->fs[rs2]);
1726 sregs->ftime += T_FABSs;
1727 sregs->frs1 = 32; /* rs1 ignored */
1730 sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
1731 sregs->ftime += T_FADDs;
1734 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
1735 sregs->ftime += T_FADDd;
1739 if (sregs->fs[rs1] == sregs->fs[rs2])
1741 else if (sregs->fs[rs1] < sregs->fs[rs2])
1743 else if (sregs->fs[rs1] > sregs->fs[rs2])
1747 sregs->fsr |= 0x0C00;
1748 sregs->fsr &= ~(fcc << 10);
1749 sregs->ftime += T_FCMPs;
1750 sregs->frd = 32; /* rd ignored */
1751 if ((fcc == 0) && (opf == FCMPEs)) {
1752 sregs->fpstate = FP_EXC_PE;
1753 sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
1758 if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
1760 else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
1762 else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
1766 sregs->fsr |= 0x0C00;
1767 sregs->fsr &= ~(fcc << 10);
1768 sregs->ftime += T_FCMPd;
1769 sregs->frd = 32; /* rd ignored */
1770 if ((fcc == 0) && (opf == FCMPEd)) {
1771 sregs->fpstate = FP_EXC_PE;
1772 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1776 sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
1777 sregs->ftime += T_FDIVs;
1780 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
1781 sregs->ftime += T_FDIVd;
1784 sregs->fs[rd] = sregs->fs[rs2];
1785 sregs->ftime += T_FMOVs;
1786 sregs->frs1 = 32; /* rs1 ignored */
1789 sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
1790 sregs->ftime += T_FMULs;
1793 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
1794 sregs->ftime += T_FMULd;
1797 sregs->fs[rd] = -sregs->fs[rs2];
1798 sregs->ftime += T_FNEGs;
1799 sregs->frs1 = 32; /* rs1 ignored */
1802 if (sregs->fs[rs2] < 0.0) {
1803 sregs->fpstate = FP_EXC_PE;
1804 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1805 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1808 sregs->fs[rd] = sqrt(sregs->fs[rs2]);
1809 sregs->ftime += T_FSQRTs;
1810 sregs->frs1 = 32; /* rs1 ignored */
1813 if (sregs->fd[rs2 >> 1] < 0.0) {
1814 sregs->fpstate = FP_EXC_PE;
1815 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1816 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1819 sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
1820 sregs->ftime += T_FSQRTd;
1821 sregs->frs1 = 32; /* rs1 ignored */
1824 sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
1825 sregs->ftime += T_FSUBs;
1828 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
1829 sregs->ftime += T_FSUBd;
1832 sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
1833 sregs->ftime += T_FdTOi;
1834 sregs->frs1 = 32; /* rs1 ignored */
1837 sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
1838 sregs->ftime += T_FdTOs;
1839 sregs->frs1 = 32; /* rs1 ignored */
1842 sregs->fs[rd] = (float32) sregs->fsi[rs2];
1843 sregs->ftime += T_FiTOs;
1844 sregs->frs1 = 32; /* rs1 ignored */
1847 sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
1848 sregs->ftime += T_FiTOd;
1849 sregs->frs1 = 32; /* rs1 ignored */
1852 sregs->fsi[rd] = (int) sregs->fs[rs2];
1853 sregs->ftime += T_FsTOi;
1854 sregs->frs1 = 32; /* rs1 ignored */
1857 sregs->fd[rd >> 1] = sregs->fs[rs2];
1858 sregs->ftime += T_FsTOd;
1859 sregs->frs1 = 32; /* rs1 ignored */
1863 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1864 sregs->fpstate = FP_EXC_PE;
1869 sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);
1870 sregs->fpstate = FP_EXC_PE;
1871 if (sis_verbose) printf("Inserted fpu error %X\n",errftt);
1876 accex = get_accex();
1878 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1887 sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
1888 sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
1893 if (sregs->fpstate == FP_EXC_PE) {
1894 sregs->fpq[0] = sregs->pc;
1895 sregs->fpq[1] = sregs->inst;
1896 sregs->fsr |= FSR_QNE;
1898 tem = (sregs->fsr >> 23) & 0x1f;
1900 sregs->fpstate = FP_EXC_PE;
1901 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1902 sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
1904 sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
1906 if (sregs->fpstate == FP_EXC_PE) {
1907 sregs->fpq[0] = sregs->pc;
1908 sregs->fpq[1] = sregs->inst;
1909 sregs->fsr |= FSR_QNE;
1920 chk_asi(sregs, asi, op3)
1921 struct pstate *sregs;
1925 if (!(sregs->psr & PSR_S)) {
1926 sregs->trap = TRAP_PRIVI;
1928 } else if (sregs->inst & INST_I) {
1929 sregs->trap = TRAP_UNIMP;
1932 *asi = (sregs->inst >> 5) & 0x0ff;
1938 struct pstate *sregs;
1942 if (sregs->trap == 256) {
1946 } else if (sregs->trap == 257) {
1950 if ((sregs->psr & PSR_ET) == 0)
1953 sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
1955 sregs->psr &= ~PSR_ET;
1956 sregs->psr |= ((sregs->psr & PSR_S) >> 1);
1958 sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
1959 cwp = ((sregs->psr & PSR_CWP) << 4);
1960 sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
1961 sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
1962 sregs->psr |= PSR_S;
1963 sregs->pc = sregs->tbr;
1964 sregs->npc = sregs->tbr + 4;
1966 if ( 0 != (1 & sregs->asr17) ) {
1967 /* single vector trapping! */
1968 sregs->pc = sregs->tbr & 0xfffff000;
1969 sregs->npc = sregs->pc + 4;
1972 /* Increase simulator time */
1973 sregs->icnt = TRAP_C;
1982 extern struct irqcell irqarr[16];
1985 check_interrupts(sregs)
1986 struct pstate *sregs;
1990 sregs->trap = errtt;
1991 if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);
1996 if ((ext_irl) && (sregs->psr & PSR_ET) &&
1997 ((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) {
1998 if (sregs->trap == 0) {
1999 sregs->trap = 16 + ext_irl;
2000 irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
2009 struct pstate *sregs;
2014 sregs->psr &= 0x00f03fdf;
2015 sregs->psr |= 0x080; /* Set supervisor bit */
2016 sregs->breakpoint = 0;
2018 sregs->fpstate = FP_EXE_MODE;
2022 sregs->err_mode = 0;
2025 #ifdef HOST_LITTLE_ENDIAN_FLOAT
2026 sregs->fdp = (float32 *) sregs->fd;
2027 sregs->fsi = (int32 *) sregs->fs;
2029 sregs->fs = (float32 *) sregs->fd;
2030 sregs->fsi = (int32 *) sregs->fd;
2033 sregs->fpu_pres = !nfp;
2034 set_fsr(sregs->fsr);
2042 sregs->rett_err = 0;
2043 sregs->jmpltime = 0;