From afdf6057b15e149c8079f5c9bf444b05bbba85cb Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 12 Oct 2007 00:00:00 -0400 Subject: [PATCH] FP exceptions, -DNOREG for -O0 and -DBG compiles, perf tweaks, gcov reworked ring/register fix so that Primos nevers sees RP faulted but we don't have to do extra tests in the fetch loop changed EAxxx routines to use RP segno when EA = register added FP exception fault to ieeepr8 and all FP routines added round flag to ieeepr8 (though not sure it's rounding correctly) used gcov info to reorder some stuff in ea16s, ea32s, ea32r64r changed warn() and fatal() to use get16t; prevpc might be a register IMPORTANT NOTE: to compile with -O0, also use -DNOREG (gcc bug) --- ea64v.h | 52 ++++--- em.c | 457 ++++++++++++++++++++++++++++++-------------------------- emdev.h | 6 +- fp.h | 49 +++--- regs.h | 2 +- 5 files changed, 310 insertions(+), 256 deletions(-) mode change 100644 => 100755 em.c diff --git a/ea64v.h b/ea64v.h index 3bbe530..b643178 100644 --- a/ea64v.h +++ b/ea64v.h @@ -42,14 +42,9 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { if (inst & 0400) { TRACE(T_EAV, " Short LB relative, LB=%o/%o\n", crs[LBH], crs[LBL]); eap = &gvp->brp[LBBR]; -#if 1 ea_s = crs[LBH] | (ea_s & RINGMASK16); ea_w += crs[LBL]; return MAKEVA(ea_s, ea_w); -#else - ea_w += crs[LBL]; - return (((*(int *)(crs+LBH) | (earp & RINGMASK32)) & 0xFFFF0000) | ea_w); -#endif } if (ea_w >= gvp->livereglim) { eap = &gvp->brp[SBBR]; @@ -59,7 +54,11 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { return MAKEVA(ea_s, ea_w); } TRACE(T_EAV, " Live register '%o\n", ea_w); - return 0x80000000 | ea_w | (RP & RINGMASK32); +#if 0 + return 0x80000000 | ea_w; +#else + return 0x80000000 | (rph << 16) | ea_w; +#endif } i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ @@ -101,17 +100,23 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { TRACE(T_EAV, " Postindex, new ea_w=%o\n", ea_w); } + /* if ea_w is within RP's brp cache page, set eap to match; + otherwise, use PB's cache page */ + if (ea_w >= gvp->livereglim) { - if ((ea_w ^ RPL) & 0xFC00) - eap = &gvp->brp[PBBR]; + if (((ea_w ^ RPL) & 0xFC00) == 0) + eap = &gvp->brp[RPBR]; /* occurs 80% */ else - eap = &gvp->brp[RPBR]; + eap = &gvp->brp[PBBR]; /* occurs 20% */ return MAKEVA(ea_s, ea_w); } TRACE(T_EAV, " Live register '%o\n", ea_w); - return 0x80000000 | ea_w | (RP & RINGMASK32); - +#if 0 + return 0x80000000 | ea_w; +#else + return 0x80000000 | (rph << 16) | ea_w; +#endif /* here for long, 2-word, V-mode memory reference */ @@ -137,15 +142,20 @@ labB: ea_w = crs[PBL+br*2] + a; if (xok) - if (ixy == 1 || ixy == 4) - ea_w += crs[Y]; - else if (ixy == 2 || ixy == 6) + if (ixy == 2 || ixy == 6) ea_w += crs[X]; + else if (ixy == 1 || ixy == 4) + ea_w += crs[Y]; - /* if this is a PB% address, use RPBR instead if it's in range */ +#if 0 + /* if this is a PB% address, use RPBR instead if it's in range - if (br == 0 && ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) == gvp->brp[RPBR].vpn)) - eap = &gvp->brp[RPBR]; + NOTE: this has been disabled, because gcov showed it only + occurred 0.5% of the time */ + + if (br == 0 && ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) == gvp->brp[RPBR].vpn)) + eap = &gvp->brp[RPBR]; +#endif if (ixy >= 3) { ea = MAKEVA(ea_s, ea_w); @@ -165,12 +175,12 @@ labB: eap = &gvp->brp[UNBR]; } if (xok) - if (ixy == 5) { - TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, crs[Y], *(short *)(crs+Y)); - ea_w += crs[Y]; - } else if (ixy == 7) { + if (ixy == 7) { TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, crs[X], *(short *)(crs+X)); ea_w += crs[X]; + } else if (ixy == 5) { + TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, crs[Y], *(short *)(crs+Y)); + ea_w += crs[Y]; } return MAKEVA(ea_s, ea_w); } diff --git a/em.c b/em.c old mode 100644 new mode 100755 index 695ee9e..e602b48 --- a/em.c +++ b/em.c @@ -511,7 +511,7 @@ typedef struct { static gv_t gv; -#if 1 +#ifndef NOREGS register gv_t *gvp asm ("r28"); register brp_t *eap asm ("r27"); /* effective address brp pointer */ #else @@ -839,6 +839,9 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { /* map virtual address if segmentation is enabled */ + if (ea & 0x80000000) + fatal("mapva: fault bit set on EA"); + if (crs[MODALS] & 4) { #ifndef NOTRACE gvp->mapvacalls++; @@ -1068,8 +1071,10 @@ static inline unsigned short get16(ea_t ea) { unsigned short access; #if DBG - if (ea & 0x80000000) - warn("address trap in get16"); + if (ea & 0x80000000) { + printf("address trap in get16, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif #if 0 @@ -1129,8 +1134,10 @@ static unsigned short get16r(ea_t ea, ea_t rpring) { unsigned short access; #if DBG - if (ea & 0x80000000) - warn("address trap in get16r"); + if (ea & 0x80000000) { + printf("address trap in get16r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif /* if passed-in ring == RP ring, use get16 and maybe avoid mapva; @@ -1152,8 +1159,10 @@ static unsigned int get32m(ea_t ea) { unsigned short m[2]; #if DBG - if (ea & 0x80000000) /* check for live register access */ - warn("address trap in get32m"); + if (ea & 0x80000000) { + printf("address trap in get32m, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif #ifndef NOTRACE @@ -1173,8 +1182,10 @@ static inline unsigned int get32(ea_t ea) { pa_t pa; #if DBG - if (ea & 0x80000000) /* check for live register access */ - warn("address trap in get32"); + if (ea & 0x80000000) { + printf("address trap in get32, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif #ifdef FAST @@ -1200,8 +1211,10 @@ static unsigned int get32r(ea_t ea, ea_t rpring) { unsigned short access; #if DBG - if (ea & 0x80000000) /* check for live register access */ - warn("address trap in get32r"); + if (ea & 0x80000000) { + printf("address trap in get32r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif /* if passed-in ring == RP ring, use get32 and maybe avoid mapva */ @@ -1223,8 +1236,10 @@ static long long get64r(ea_t ea, ea_t rpring) { /* check for live register access */ #if DBG - if (ea & 0x80000000) - warn("address trap in get64"); + if (ea & 0x80000000) { + printf("address trap in get64r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif pa = mapva(ea, rpring, RACC, &access); @@ -1293,7 +1308,7 @@ static long long get64r(ea_t ea, ea_t rpring) { unsigned short iget16t(ea_t ea) { unsigned short access; - if (*(int *)&ea > 0) { + if (*(int *)&ea >= 0) { gvp->brp[RPBR].memp = MEM + (mapva(ea, RP, RACC, &access) & 0xFFFFFC00); gvp->brp[RPBR].vpn = (ea & 0x0FFFFC00) | (access << 28); return gvp->brp[RPBR].memp[ea & 0x3FF]; @@ -1319,8 +1334,10 @@ static inline put16(unsigned short value, ea_t ea) { unsigned short access; #if DBG - if (ea & 0x80000000) - warn("address trap in put16"); + if (ea & 0x80000000) { + printf("address trap in put16, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif #ifdef FAST @@ -1352,8 +1369,10 @@ static put16r(unsigned short value, ea_t ea, ea_t rpring) { unsigned short access; #if DBG - if (ea & 0x80000000) - warn("address trap in put16r"); + if (ea & 0x80000000) { + printf("address trap in put16r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif /* if passed-in ring == RP ring, use put16 and maybe avoid mapva */ @@ -1368,11 +1387,6 @@ static put16r(unsigned short value, ea_t ea, ea_t rpring) { static put16trap(unsigned short value, ea_t ea) { -#ifdef DBG - if (*(int *)&ea >= 0) - warn("real EA in put16trap"); -#endif - ea = ea & 0xFFFF; if (ea < 7) crs[memtocrs[ea]] = value; @@ -1408,8 +1422,10 @@ static put32(unsigned int value, ea_t ea) { unsigned short *m; #if DBG - if (ea & 0x80000000) /* check for live register access */ - warn("address trap in put32"); + if (ea & 0x80000000) { + printf("address trap in put32, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif #ifdef FAST @@ -1450,8 +1466,10 @@ static put32r(unsigned int value, ea_t ea, ea_t rpring) { unsigned short *m; #if DBG - if (ea & 0x80000000) /* check for live register access */ - warn("address trap in put32"); + if (ea & 0x80000000) { + printf("address trap in put32r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif /* if passed-in ring == RP ring, use put32 and maybe avoid mapva */ @@ -1477,8 +1495,10 @@ static put64r(long long value, ea_t ea, ea_t rpring) { /* check for live register access */ #if DBG - if (ea & 0x80000000) - warn("address trap in put64"); + if (ea & 0x80000000) { + printf("address trap in put64r, ea=%o/%o\n", ea>>16, ea&0xffff); + fatal(NULL); + } #endif pa = mapva(ea, rpring, WACC, &access); @@ -1685,16 +1705,24 @@ static int (*devmap[64])(int, int, int) = { static void warn(char *msg) { - printf("emulator warning:\n instruction #%d at %o/%o: %o %o keys=%o, modals=%o\n %s\n", gvp->instcount, gvp->prevpc >> 16, gvp->prevpc & 0xFFFF, get16(gvp->prevpc), get16(gvp->prevpc+1),crs[KEYS], crs[MODALS], msg); + printf("emulator warning:\n instruction #%d at %o/%o: %o %o keys=%o, modals=%o\n %s\n", gvp->instcount, gvp->prevpc >> 16, gvp->prevpc & 0xFFFF, get16t(gvp->prevpc), get16t(gvp->prevpc+1),crs[KEYS], crs[MODALS], msg); } static void fatal(char *msg) { + static int fatal_called = 0; ea_t pcbp, csea; unsigned short first,next,last,this; unsigned short cs[6]; int i; + if (fatal_called) { + printf("Nested call to fatal()\n"); + exit(1); + } + + fatal_called = 1; + stopwatch_stop(&sw_all); printf("\n"); stopwatch_report(&sw_all); @@ -1714,7 +1742,7 @@ static void fatal(char *msg) { printf("Fatal error"); if (msg) printf(": %s", msg); - printf("\ninstruction #%d at %o/%o %s: %o %o\nowner=%o %s, keys=%o, modals=%o\n", gvp->instcount, gvp->prevpc >> 16, gvp->prevpc & 0xFFFF, searchloadmap(gvp->prevpc,' '), get16(gvp->prevpc), get16(gvp->prevpc+1), crs[OWNERL], searchloadmap(*(unsigned int *)(crs+OWNER),' '), crs[KEYS], crs[MODALS]); + printf("\ninstruction #%d at %o/%o %s: %o %o\nowner=%o %s, keys=%o, modals=%o\n", gvp->instcount, gvp->prevpc >> 16, gvp->prevpc & 0xFFFF, searchloadmap(gvp->prevpc,' '), get16t(gvp->prevpc), get16t(gvp->prevpc+1), crs[OWNERL], searchloadmap(*(unsigned int *)(crs+OWNER),' '), crs[KEYS], crs[MODALS]); /* dump concealed stack entries */ @@ -1808,6 +1836,14 @@ static void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { else faultrp = gvp->prevpc; + /* NOTE: RP may have the fault bit set if executing from registers. + This is an emulator-ism to let us know we're executing registers + without having to do tests on every instruction fetch. But this + can confuse Primos (dmstk for example), so don't ever store it + this way. */ + + faultrp &= 0x7FFFFFFF; + /* save RP, keys in regfile, fcode and faddr in crs */ regs.sym.pswpb = faultrp; @@ -1882,7 +1918,7 @@ static void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { TRACE(T_FAULT, "fault: jumping to fault table entry at RP=%o/%o\n", RPH, RPL); } else { /* process exchange is disabled */ - //TRACE(T_FAULT, "fault '%o occurred at %o/%o, instruction=%o, modals=%o\n", fvec, faultrp>>16, faultrp&0xffff, get16(faultrp), crs[MODALS]); + //TRACE(T_FAULT, "fault '%o occurred at %o/%o, instruction=%o, modals=%o\n", fvec, faultrp>>16, faultrp&0xffff, get16t(faultrp), crs[MODALS]); /* XXX: need to check for standard/vectored interrupt mode here... */ m = get16(fvec); if (m != 0) { @@ -1906,17 +1942,26 @@ static void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { } -/* 16S Addressing Mode */ +/* 16S Addressing Mode + + NOTE: when fetching indirect words via address traps, ie, the word + is in a register, the segment and ring bits are unimportant. But + when returning the final EA, seg and ring are important: if a JMP + instruction is executing, and the target of the jump is a register, + the seg and ring fields of RP must be maintained. Otherwise, a + restricted instruction like HLT executed from a register would + actually halt the machine. Yes, this actually happened to me! :-) +*/ static ea_t ea16s (unsigned short inst) { - unsigned short ea, m, rpl, amask, i, x; - ea_t va; + unsigned short rpl, amask, i, x; + ea_t ea, va; i = inst & 0100000; /* indirect */ x = ((inst & 036000) != 032000) ? (inst & 040000) : 0; amask = 037777; - rpl = gvp->prevpc; + rpl = gvp->prevpc; /* S-mode uses backed PC! */ if (inst & 001000) ea = (rpl & 037000) | (inst & 0777); /* current sector */ else @@ -1926,17 +1971,17 @@ static ea_t ea16s (unsigned short inst) { ea += crs[X]; if (!i) /* not indirect */ break; - if (ea < gvp->livereglim) - m = get16t(0x80000000|ea); - else - m = get16t(MAKEVA(RPH,ea)); - i = m & 0100000; - x = m & 040000; - ea = m & 037777; /* go indirect */ + ea &= amask; + if (ea < gvp->livereglim) /* flag live register ea */ + ea |= 0x80000000; + ea = get16t(ea); /* get indirect word */ + i = ea & 0100000; + x = ea & 040000; } + ea &= amask; va = MAKEVA(RPH, ea); if (ea < gvp->livereglim) /* flag live register ea */ - return 0x80000000 | va | (RP & RINGMASK32); + va |= 0x80000000; return va; } @@ -1945,8 +1990,8 @@ static ea_t ea16s (unsigned short inst) { static ea_t ea32s (unsigned short inst) { - unsigned short ea, m,rpl, amask, i, x; - ea_t va; + unsigned short rpl, amask, i, x; + ea_t ea, va; i = inst & 0100000; /* indirect */ x = ((inst & 036000) != 032000) ? (inst & 040000) : 0; @@ -1962,23 +2007,21 @@ static ea_t ea32s (unsigned short inst) { } } while (i) { - if (ea < gvp->livereglim) - m = get16t(0x80000000|ea); - else - m = get16t(MAKEVA(RPH,ea)); - i = m & 0100000; - ea = m & 077777; /* go indirect */ + ea &= amask; + if (ea < gvp->livereglim) /* flag live register ea */ + ea |= 0x80000000; + ea = get16t(ea); /* go indirect */ + i = ea & 0100000; } if (x) /* postindex */ ea += crs[X]; ea &= amask; va = MAKEVA(RPH, ea); if (ea < gvp->livereglim) /* flag live register ea */ - return 0x80000000 | va | (RP & RINGMASK32); + va |= 0x80000000; return va; } - /* NOTE: the difference between 32R and 64R, besides the extra address bit, is that 32R indirect words have an indirect bit for multi-level indirects */ @@ -2015,16 +2058,17 @@ static inline ea_t ea32r64r (ea_t earp, unsigned short inst) { x = 0; } } + ea &= amask; while (i) { if (ea >= gvp->livereglim) m = get16(MAKEVA(rph,ea)); else m = get16trap(ea); TRACE(T_EAR, " Indirect, old ea=%o, [ea]=%o\n", ea, m); - if ((crs[KEYS] & 016000) == 06000) /* 32R mode? */ - i = m & 0100000; /* yes, multiple indirects */ + if ((crs[KEYS] & 016000) == 04000) /* 64R mode? */ + i = 0; /* yes, single indirect */ else - i = 0; /* no, 64R mode, single indirect */ + i = m & 0100000; /* 32R - multiple indirects */ ea = m & amask; /* go indirect */ TRACE(T_EAR, " Indirect, new i=%d, new ea=%o\n", i!=0, ea); eap = &gvp->brp[UNBR]; @@ -2038,7 +2082,7 @@ static inline ea_t ea32r64r (ea_t earp, unsigned short inst) { ea &= amask; va = MAKEVA(rph, ea); if (ea < gvp->livereglim) /* flag live register ea */ - return 0x80000000 | va | (RP & RINGMASK32); + va |= 0x80000000; return va; special: @@ -2069,10 +2113,10 @@ special: else m = get16trap(ea); TRACE(T_EAR, " Indirect, old ea=%o, [ea]=%o\n", ea, m); - if ((crs[KEYS] & 016000) == 06000) - i = m & 0100000; - else + if ((crs[KEYS] & 016000) == 04000) i = 0; + else + i = m & 0100000; ea = m & amask; TRACE(T_EAR, " Indirect, new i=%d, new ea=%o\n", i!=0, ea); eap = &gvp->brp[UNBR]; @@ -2093,10 +2137,10 @@ special: else m = get16trap(ea); TRACE(T_EAR, " Indirect, ea=%o, [ea]=%o\n", ea, m); - if ((crs[KEYS] & 016000) == 06000) - i = m & 0100000; - else + if ((crs[KEYS] & 016000) == 04000) i = 0; + else + i = m & 0100000; ea = m & amask; TRACE(T_EAR, " Indirect, new i=%d, new ea=%o\n", i!=0, ea); } @@ -2126,10 +2170,10 @@ special: m = get16(MAKEVA(rph,ea)); else m = get16trap(ea); - if ((crs[KEYS] & 016000) == 06000) - i = m & 0100000; - else + if ((crs[KEYS] & 016000) == 04000) i = 0; + else + i = m & 0100000; ea = m & amask; eap = &gvp->brp[UNBR]; } @@ -2140,9 +2184,9 @@ special: } ea &= amask; va = MAKEVA(rph, ea); - if (ea >= gvp->livereglim) - return va; - return 0x80000000 | va | (RP & RINGMASK32); /* flag live register ea */ + if (ea < gvp->livereglim) /* flag live register ea */ + va |= 0x80000000; + return va; } #include "ea64v.h" @@ -3152,7 +3196,7 @@ static dispatcher() { /* save RP in current register set before possibly switching */ - *(unsigned int *)(crs+PB) = RP; + *(unsigned int *)(crs+PB) = (RP & 0x7FFFFFFF); /* find a register set for this process */ @@ -3217,6 +3261,13 @@ static dispatcher() { } RP = *(unsigned int *)(crs+PB); + + /* if we were executing from registers and not in I-mode, make sure + the fault bit is set again on RP. We try to hide this hack from + Primos. */ + + if (RPL < gvp->livereglim && ((crs[KEYS] & 0016000) != 010000)) + RP |= 0x80000000; crs[PBL] = 0; crs[KEYS] &= ~3; /* erase "in dispatcher" and "save done" */ TRACE(T_PX, "disp: returning from dispatcher, running process %o/%o at %o/%o, modals=%o, ppa=%o, pla=%o, ppb=%o, plb=%o\n", crs[OWNERH], crs[OWNERL], RPH, RPL, crs[MODALS], regs.sym.pcba, regs.sym.pla, regs.sym.pcbb, regs.sym.plb); @@ -3284,7 +3335,7 @@ unready: I'm not first on the ready list TRACE(T_PX, "unready: new rl bol/eol = %o/%o\n", rl>>16, rl&0xFFFF); put16r0(newlink, pcbp+1); /* update my pcb link */ put32r0(waitlist, pcbp+2); /* update my pcb wait address */ - *(unsigned int *)(crs+PB) = RP; + *(unsigned int *)(crs+PB) = (RP & 0x7FFFFFFF); pxregsave(1); regs.sym.pcba = 0; } @@ -3479,9 +3530,11 @@ static nfy(unsigned short inst) { if (inst & 2) /* clear active interrupt */ gvp->intvec = -1; /* not sure about all this... Case 85/87 */ - RP = regs.sym.pswpb; - crs[PBH] = RPH; newkeys(regs.sym.pswkeys); + RP = regs.sym.pswpb; + crs[PBH] = RPH; /* NOTE: won't have fault bit */ + if (RPL < gvp->livereglim && ((crs[KEYS] & 0016000) != 010000)) + RP |= 0x80000000; } if (resched || (inst & 4)) @@ -4264,7 +4317,7 @@ main (int argc, char **argv) { gvp->traceflags |= TB_RIO; else if (strcmp(argv[i],"all") == 0) gvp->traceflags = ~0; - else if (isdigit(argv[i][0]) && strlen(argv[i]) < 2 && sscanf(argv[i],"%d", &templ) == 1) + else if (isdigit(argv[i][0]) && strlen(argv[i]) <= 2 && sscanf(argv[i],"%d", &templ) == 1) gvp->traceuser = 0100000 | (templ<<6); /* form OWNERL for user # */ else if (strlen(argv[i]) == 6 && sscanf(argv[i],"%o", &templ) == 1) gvp->traceuser = templ; /* specify OWNERL directly */ @@ -4345,11 +4398,12 @@ main (int argc, char **argv) { /* initialize all devices */ - for (i=0; i<64; i++) + for (i=0; i<64; i++) { if (devmap[i](-1, 0, i)) { /* if initialization fails, */ devmap[i] = devnone; /* remove device */ fprintf(stderr, "emulator: device '%o failed initialization - device removed\n", i); } + } /* if a filename follows -boot, load and execute this R-mode runfile @@ -4651,7 +4705,7 @@ fetch: if (gvp->inhcount == 0) { //printf("fetch: taking interrupt vector '%o, modals='%o\n", gvp->intvec, crs[MODALS]); TRACE(T_FLOW, "\nfetch: taking interrupt vector '%o, modals='%o\n", gvp->intvec, crs[MODALS]); - regs.sym.pswpb = RP; + regs.sym.pswpb = RP & 0x7FFFFFFF; regs.sym.pswkeys = crs[KEYS]; if (crs[MODALS] & 010) { /* PX enabled */ @@ -4715,6 +4769,12 @@ fetch: this check on every instruction fetch is more overhead. Setting the HO bit of RP does expose this to Primos when a fault occurs while executing code in registers. + + NOTE 2: clear A, JMP# 1, and instead of getting a program halt + or restricted instruction signal raised, a pointer fault occurs + because Primos can't handle 160000/000001 as the fault address. + So maybe this code should be enabled (?), along with the 5 jump + instructions. */ inst = iget16(RP | ((RPL >= gvp->livereglim || (crs[KEYS] & 0016000) == 010000) ? 0 : 0x80000000)); @@ -4727,14 +4787,14 @@ fetch: /* while a process is running, RP is the real program counter, PBH is the active procedure segment, and PBL is zero. When a process stops running, RP is copied to PB. When a process - starts running again, PB is copied to RP. */ + starts running again, PB is copied to RP. + XXX: it'd be nice to remove this, if possible. */ + + *(int *)(crs+PBH) = RP & 0x7FFF0000; + + /* earp is used for RP-relative address calculations. It is the + same as RP, except during an xec instruction. See d_xec */ -#ifdef FAST - *(int *)(crs+PBH) = RP & 0xFFFF0000; -#else - crs[PBH] = RPH; - crs[PBL] = 0; -#endif earp = RP; @@ -5717,19 +5777,17 @@ d_dbgill: /* 001700, 001701 */ SAS 1 interrupts enabled? 1702 no, they should be, die - Update: this is the "slow halt" instruction. Ewan explained - that if a HLT instruction is encountered, any DMX in progress - will stop, leading to partial disk records being written. - Using this instruction instead lets Primos delay the halt - until DMX has completed. + Update: this is the "slow halt" instruction. Ewan Milne + explained that if a HLT instruction is encountered on some + machines,, any DMX in progress will stop, possibly leading to + partial disk records being written. Using this illegal + instruction instead of HLT lets Primos delay the halt until + DMX has completed. */ d_pbug: /* 001702 */ TRACE(T_FLOW, " 1702?\n", inst); - if (RP & RINGMASK32) - fault(ILLINSTFAULT, RPL, RP); - else - fatal("Primos software assertion failure"); + fault(ILLINSTFAULT, RPL, RP); fatal(NULL); /* just in case of a bogus return (coding error) */ d_irtn: /* 000601 */ @@ -5737,9 +5795,11 @@ d_irtn: /* 000601 */ RESTRICT(); //fatal("IRTN causes a loop in CPU.CACHE Case 4"); irtn: + newkeys(regs.sym.pswkeys); RP = regs.sym.pswpb; crs[PBH] = RPH; - newkeys(regs.sym.pswkeys); + if (RPL < gvp->livereglim && ((crs[KEYS] & 0016000) != 010000)) + RP |= 0x80000000; crs[MODALS] |= 0100000; #if 0 if (regs.sym.pcba != 0) { @@ -5828,9 +5888,8 @@ d_cea: /* 000111 */ ea += crs[X]; if (!i) /* not indirect */ break; - /* XXX: should this be gvp->livereglim? */ - if (ea < 040) - m = get16(0x80000000|ea); + if (ea < gvp->livereglim) + m = get16trap(ea); else m = get16(MAKEVA(RPH,ea)); i = m & 0100000; @@ -5843,9 +5902,8 @@ d_cea: /* 000111 */ case 3: /* 32R */ while (crs[A] & 0100000) { ea = crs[A] & 077777; - /* XXX: should this be gvp->livereglim? */ - if (ea < 040) - crs[A] = get16(0x80000000|ea); + if (ea < gvp->livereglim) + crs[A] = get16trap(ea); else crs[A] = get16(MAKEVA(RPH,ea)); } @@ -6657,7 +6715,7 @@ d_inta: /* 0140531 */ d_flta: /* 0140532 */ TRACE(T_FLOW, " FLTA\n"); tempd = *(short *)(crs+A); - *(double *)(crs+FLTH) = ieeepr8(tempd); + ieeepr8(tempd, (long long *)(crs+FLTH), 0); goto fetch; d_intl: /* 0140533 */ @@ -8193,7 +8251,6 @@ imode: case 6: dr &= 2; TRACE(T_FLOW, " FA\n"); - CLEARC; if (*(int *)&ea >= 0) { immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); @@ -8203,14 +8260,15 @@ imode: tempa1 = crsl[FAC0+dr+1] & 0xffff; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC0+dr, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1+tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC0+dr, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); - else if (tempa1 < tempa2) - *(long long *)(crsl+FAC0+dr) = immu64; - } else + else if (tempa1 < tempa2) + *(long long *)(crsl+FAC0+dr) = immu64; + } else *(long long *)(crsl+FAC0+dr) = immu64; else if (*(int *)(crsl+FAC0+dr) == 0) *(long long *)(crsl+FAC0+dr) = 0; @@ -8220,15 +8278,15 @@ imode: case 7: dr &= 2; TRACE(T_FLOW, " DFA\n"); - CLEARC; if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC0+dr)) - if (prieee8(crsl+FAC0+dr, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1+tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC0+dr, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_DFP_OFLOW, ea); else *(long long *)(crsl+FAC0+dr) = immu64; @@ -8310,7 +8368,6 @@ imode: case 2: dr &= 2; TRACE(T_FLOW, " FS\n"); - CLEARC; if (*(int *)&ea >= 0) { immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); @@ -8320,10 +8377,11 @@ imode: tempa1 = crsl[FAC0+dr+1] & 0xffff; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC0+dr, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1-tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC0+dr, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else if (tempa1 < tempa2) { *(long long *)(crsl+FAC0+dr) = immu64; @@ -8341,15 +8399,15 @@ imode: case 3: dr &= 2; TRACE(T_FLOW, " DFS\n"); - CLEARC; if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC0+dr)) - if (prieee8(crsl+FAC0+dr, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1-tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC0+dr, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_DFP_OFLOW, ea); else { *(long long *)(crsl+FAC0+dr) = immu64; @@ -8363,17 +8421,17 @@ imode: case 6: dr &= 2; TRACE(T_FLOW, " FM\n"); - CLEARC; if (*(int *)(crsl+FAC0+dr)) { if (*(int *)&ea >= 0) { immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); } if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC0+dr, &tempd1)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1*tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC0+dr, &tempd1) + && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else /* operand = 0.0: no multiply */ *(long long *)(crsl+FAC0+dr) = 0; @@ -8385,15 +8443,15 @@ imode: case 7: dr &= 2; TRACE(T_FLOW, " DFM\n"); - CLEARC; if (*(int *)(crsl+FAC0+dr)) { if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC0+dr, &tempd1)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1*tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC0+dr, &tempd1) + && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC0+dr), 0)) + CLEARC; + else mathexception('f', FC_DFP_OFLOW, ea); else /* operand = 0.0: no multiply */ *(long long *)(crsl+FAC0+dr) = 0; @@ -8460,17 +8518,17 @@ imode: case 2: dr &= 2; TRACE(T_FLOW, " FD\n"); - CLEARC; if (*(int *)&ea >= 0) { immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); } if (*(int *)&immu64) if (*(int *)(crsl+FAC0+dr)) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC0+dr, &tempd1)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1/tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC0+dr, &tempd1) + && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC0+dr), 1)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else /* operand = 0.0 */ *(long long *)(crsl+FAC0+dr) = 0; @@ -8482,15 +8540,15 @@ imode: case 3: dr &= 2; TRACE(T_FLOW, " DFD\n"); - CLEARC; if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC0+dr)) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC0+dr, &tempd1)) { - *(double *)(crsl+FAC0+dr) = ieeepr8(tempd1/tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC0+dr, &tempd1) + && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC0+dr), 1)) + CLEARC; + else mathexception('f', FC_DFP_OFLOW, ea); else *(long long *)(crsl+FAC0+dr) = 0; @@ -8986,12 +9044,7 @@ d_stadst: /* 00400 (R-mode) */ d_jmp: /* 00100 */ TRACE(T_FLOW, " JMP\n"); -#if 0 - if (*(int *)&ea < 0) /* jumping to register address */ - RPL = ea; /* preserve segment number in RP */ - else -#endif - RP = ea; + RP = ea; goto fetch; d_ana: /* 00300 */ @@ -9094,12 +9147,7 @@ d_jst: /* 01000 */ else m = (get16t(ea) & ~gvp->amask) | RPL; put16t(m, ea); -#if 0 - if (*(int *)&ea < 0) /* jumping to register address */ - RPL = ea; /* preserve segment number in RP */ - else -#endif - RP = ea; + RP = ea; INCRP; gvp->brp[RPBR] = *eap; if ((RP & RINGMASK32) == 0) @@ -9162,23 +9210,13 @@ d_ima: /* 01300 */ d_jsy: /* 01400 */ TRACE(T_FLOW, " JSY\n"); crs[Y] = RPL; -#if 0 - if (*(int *)&ea < 0) /* jumping to register address */ - RPL = ea; /* preserve segment number in RP */ - else -#endif - RP = ea; + RP = ea; goto fetch; d_jsxb: /* 01402 */ TRACE(T_FLOW, " JSXB\n"); *(unsigned int *)(crs+XB) = RP; -#if 0 - if (*(int *)&ea < 0) /* jumping to register address */ - RPL = ea; /* preserve segment number in RP */ - else -#endif - RP = ea; + RP = ea; goto fetch; d_stx: /* 01500 */ @@ -9405,12 +9443,7 @@ d_ldy: /* 03501 */ d_jsx: /* 03503 */ TRACE(T_FLOW, " JSX\n"); crs[X] = RPL; -#if 0 - if (*(int *)&ea < 0) /* jumping to register address */ - RPL = ea; /* preserve segment number in RP */ - else -#endif - RP = ea; + RP = ea; goto fetch; /* XXX: this should set the L bit like subtract */ @@ -9431,7 +9464,6 @@ d_cls: /* 01103 */ d_fad: /* 00601 */ TRACE(T_FLOW, " FAD\n"); - CLEARC; immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) @@ -9439,10 +9471,11 @@ d_fad: /* 00601 */ tempa1 = crs[FEXP]; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC1, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC1) = ieeepr8(tempd1+tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC1, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC1), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else if (tempa1 < tempa2) *(long long *)(crsl+FAC1) = immu64; @@ -9462,15 +9495,15 @@ d_fcs: /* 01101 */ d_fdv: /* 01701 */ TRACE(T_FLOW, " FDV\n"); - CLEARC; immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) if (*(int *)(crsl+FAC1)) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC1, &tempd1)) { - *(double *)(crsl+FAC1) = ieeepr8(tempd1/tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC1, &tempd1) + && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC1), 1)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else /* operand = 0.0 */ *(long long *)(crsl+FAC1) = 0; @@ -9487,15 +9520,15 @@ d_fld: /* 0201 */ d_fmp: /* 01601 */ TRACE(T_FLOW, " FMP\n"); - CLEARC; if (*(int *)(crsl+FAC1)) { immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC1, &tempd1)) { - *(double *)(crsl+FAC1) = ieeepr8(tempd1*tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC1, &tempd1) + && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC1), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else /* operand = 0.0: no multiply */ *(long long *)(crsl+FAC1) = 0; @@ -9505,7 +9538,6 @@ d_fmp: /* 01601 */ d_fsb: /* 00701 */ TRACE(T_FLOW, " FSB\n"); - CLEARC; immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) @@ -9513,10 +9545,11 @@ d_fsb: /* 00701 */ tempa1 = crs[FEXP]; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC1, &tempd1) && prieee8(&immu64, &tempd2)) { - *(double *)(crsl+FAC1) = ieeepr8(tempd1-tempd2); - XCLEARC; /* XXX: test overflow */ - } else + if (prieee8(crsl+FAC1, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC1), 0)) + CLEARC; + else mathexception('f', FC_SFP_OFLOW, ea); else if (tempa1 < tempa2) { *(long long *)(crsl+FAC1) = immu64; @@ -9543,15 +9576,15 @@ d_fst: /* 0401 */ d_dfad: /* 0602 */ TRACE(T_FLOW, " DFAD\n"); - CLEARC; immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC1)) - if (prieee8(crsl+FAC1, &tempd1) && prieee8(&immu64, &tempd2)) { + if (prieee8(crsl+FAC1, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC1), 0)) { + CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) + %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); - *(double *)(crsl+FAC1) = ieeepr8(tempd1+tempd2); TRACE(T_FLOW, " = %f ('%o %o %o %o)\n", tempd1+tempd2, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP]); - XCLEARC; /* XXX: test overflow */ } else mathexception('f', FC_DFP_OFLOW, ea); else @@ -9568,16 +9601,16 @@ d_dfcs: /* 01102 */ d_dfdv: /* 01702 */ TRACE(T_FLOW, " DFDV\n"); - CLEARC; if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC1)) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC1, &tempd1)) { + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC1, &tempd1) + && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC1), 1)) { + CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) / %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); - *(double *)(crsl+FAC1) = ieeepr8(tempd1/tempd2); TRACE(T_FLOW, " = %f ('%o %o %o %o)\n", tempd1/tempd2, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP]); - XCLEARC; /* XXX: test overflow */ } else mathexception('f', FC_DFP_OFLOW, ea); else @@ -9598,15 +9631,15 @@ d_dfld: /* 0202 */ d_dfmp: /* 01602 */ TRACE(T_FLOW, " DFMP\n"); - CLEARC; if (*(int *)(crsl+FAC1)) { immu64 = get64(ea); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) && prieee8(crsl+FAC1, &tempd1)) { - TRACE(T_FLOW, " %f ('%o %o %o %o) / %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); - *(double *)(crsl+FAC1) = ieeepr8(tempd1*tempd2); + if (prieee8(&immu64, &tempd2) + && prieee8(crsl+FAC1, &tempd1) + && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC1), 0)) { + CLEARC; + TRACE(T_FLOW, " %f ('%o %o %o %o) * %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); TRACE(T_FLOW, " = %f ('%o %o %o %o)\n", tempd1*tempd2, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP]); - XCLEARC; /* XXX: test overflow */ } else mathexception('f', FC_DFP_OFLOW, ea); else /* operand = 0.0: no multiply */ @@ -9617,15 +9650,15 @@ d_dfmp: /* 01602 */ d_dfsb: /* 0702 */ TRACE(T_FLOW, " DFSB\n"); - CLEARC; immu64 = get64(ea); if (*(int *)&immu64) if (*(int *)(crsl+FAC1)) - if (prieee8(crsl+FAC1, &tempd1) && prieee8(&immu64, &tempd2)) { - TRACE(T_FLOW, " %f ('%o %o %o %o) / %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); - *(double *)(crsl+FAC1) = ieeepr8(tempd1-tempd2); + if (prieee8(crsl+FAC1, &tempd1) + && prieee8(&immu64, &tempd2) + && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC1), 0)) { + CLEARC; + TRACE(T_FLOW, " %f ('%o %o %o %o) - %f (%o %o %o %o)\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP], tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); TRACE(T_FLOW, " = %f ('%o %o %o %o)\n", tempd1-tempd2, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP]); - XCLEARC; /* XXX: test overflow */ } else mathexception('f', FC_DFP_OFLOW, ea); else { diff --git a/emdev.h b/emdev.h index 6ab5111..e0bfa79 100644 --- a/emdev.h +++ b/emdev.h @@ -450,8 +450,8 @@ readasr: if (gvp->savetraceflags == 0) { TRACEA("\nTRACE ENABLED:\n\n"); gvp->savetraceflags = ~TB_MAP; - gvp->savetraceflags = TB_FLOW; gvp->savetraceflags = ~0; + gvp->savetraceflags = TB_FLOW; } else { TRACEA("\nTRACE DISABLED:\n\n"); gvp->savetraceflags = 0; @@ -1504,11 +1504,10 @@ int devcp (int class, int func, int device) { the correct time. In addition to lowering overhead, slower clock tick rates make catching up much faster. */ -#ifndef FIXEDCLOCK if (abs(ticks-targetticks) > 5000 && datnowea != 0) ticks = -1; else if (ticks < targetticks) - devpoll[device] = 200; /* behind, so catch-up */ + devpoll[device] = 100; /* behind, so catch-up */ else if (ticks > targetticks) devpoll[device] = devpoll[device]*2; /* ahead, so slow down */ else { /* just right! */ @@ -1517,7 +1516,6 @@ int devcp (int class, int func, int device) { ticks = 0; } } -#endif /* update instpermsec every 5 seconds. Check for instcount overflow and reset when it occurs. diff --git a/fp.h b/fp.h index 4c6e83d..7546b02 100644 --- a/fp.h +++ b/fp.h @@ -33,6 +33,8 @@ http://tima-cmp.imag.fr/~guyot/Cours/Oparithm/english/Op_Ar2.htm */ +#include + #define GETFRAC(d) (*(long long *)&(d) & 0xFFFFFFFFFFFF0000LL) /* getdp unpacks a Prime DPFP into 48-bit sign + mantissa (left @@ -138,29 +140,38 @@ int prieee8(void *dp, double *d) { this conversion cannot overflow/underflow, but precision may be lost */ -double ieeepr8(double d) { +int ieeepr8(double d, long long *p, int round) { long long frac64; - int exp32, neg; + int exp32, neg, okay; + + okay = 1; /* unpack IEEE DPFP */ +retry: *(double *)&frac64 = d; neg = frac64 < 0; exp32 = (frac64 >> 52) & 0x7ff; frac64 &= 0xfffffffffffffLL; //printf("dp=%llx, neg=%d, frac64=%llx, exp32=%d, \n", *(long long *)dp, neg, frac64, exp32); - /* special case: NaN & +-infinity (these shouldn't happen!) */ + /* special case: NaN & +-infinity */ if (exp32 == 0x7ff) { + okay = 0; if (frac64 == 0) - if (neg) + if (neg) { printf("em: +infinity in ieeepr8\n"); - else + d = DBL_MAX; + } else { printf("em: -infinity in ieeepr8\n"); - else + d = DBL_MIN; + } + else { printf("em: NaN in ieeepr8\n"); - return 0.0; + d = 0.0; + } + goto retry; } /* add back the hidden "1" bit except for the special cases +-0.0 @@ -168,9 +179,10 @@ double ieeepr8(double d) { if (exp32 != 0) /* typical IEEE normalized */ frac64 |= 0x10000000000000LL; - else if (frac64 == 0) /* IEEE +-0.0 (zero exp+frac) */ - return 0.0; /* IEEE and Prime zero are the same */ - else + else if (frac64 == 0) { /* IEEE +-0.0 (zero exp+frac) */ + *p = 0; /* IEEE and Prime zero are the same */ + return okay; + } else ; /* subnormal: no hidden 1 bit */ /* adjust exponent, change sign-magnitude to 2's complement, @@ -195,8 +207,6 @@ double ieeepr8(double d) { } #endif -#if 0 - /* round the fraction to 48 bits, ensuring no overflow IMPORTANT NOTE: this rounding was disabled because it screws up @@ -206,15 +216,18 @@ double ieeepr8(double d) { process ends up adding 1 to the original variable, making the RUN command fail because the call to TSRC$$ has the pathname length 1 too big. + + But it needs to be enabled for FP divide, since Prime specifies + that FP divide always rounds. */ - if ((frac64 & 0x8000) && ((frac64 & 0x7fffffffffff0000LL) != 0x7fffffffffff0000LL)) - /* XXX: should this be a subtract for negative numbers? */ - frac64 += 0x10000; -#endif + if (round) + if ((frac64 & 0x8000) && ((frac64 & 0x7fffffffffff0000LL) != 0x7fffffffffff0000LL)) + /* XXX: should this be a subtract for negative numbers? */ + frac64 += 0x10000; - frac64 = (frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff); - return *(double *)&frac64; + *p = (frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff); + return okay; } diff --git a/regs.h b/regs.h index 4976c8c..df96ff7 100644 --- a/regs.h +++ b/regs.h @@ -179,7 +179,7 @@ static union { Putting them in dedicated registers gives about an 11% performance boost and reduces the code size from 146K to 136K */ -#if 1 +#ifndef NOREGS /* store RP and crsl in dedicated registers 29-30 (Power PC) */