diff --git a/ea64v.h b/ea64v.h index b643178..b5286db 100644 --- a/ea64v.h +++ b/ea64v.h @@ -18,6 +18,7 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { unsigned short rph,rpl; + i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ x = ((inst & 036000) != 032000) ? (inst & 040000) : 0; /* earp is usually = RPH/RPL in the register file, except for the @@ -30,7 +31,76 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { ea_s = rph; - /* first check for direct short-form - the most commonly occurring case */ + /* first check for long, 2-word, V-mode memory references. About + 75% of V-mode references are in this form */ + + if ((inst & 01740) == 01400) { + a = iget16(RP); + INCRP; + TRACE(T_EAV, " 2-word format, a=%o\n", a); + ixy = (i >> 13) | (x >> 13) | ((inst & 020) >> 4); + xok = (inst & 036000) != 032000; /* true if indexing is okay */ + + br = (inst & 3); + eap = &gvp->brp[br]; + +#ifndef NOTRACE + int opcode; + + opcode = ((inst & 036000) != 032000) ? ((inst & 036000) >> 4) : ((inst & 076000) >> 4); + opcode |= ((inst >> 2) & 3); /* opcode extension */ + TRACE(T_EAV, " new opcode=%5#0o, y=%d, br=%d, ixy=%d, xok=%d\n", opcode, (y != 0), br, ixy, xok); +#endif + + ea_s = crs[PBH+br*2] | (ea_s & RINGMASK16); + ea_w = crs[PBL+br*2] + a; + + if (xok) + if (ixy == 2 || ixy == 6) + ea_w += crs[X]; + else if (ixy == 1 || ixy == 4) + ea_w += crs[Y]; + +#if 0 + /* if this is a PB% address, use RPBR instead if it's in range + + 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); + TRACE(T_EAV, " Long indirect, ea=%o/%o, ea_s=%o, ea_w=%o\n", ea>>16, ea&0xFFFF, ea_s, ea_w); + m = get16(ea); + if (m & 0x8000) + fault(POINTERFAULT, m, ea); + ea_s = m | (ea_s & RINGMASK16); + ea_w = get16(INCVA(ea,1)); + TRACE(T_EAV, " After indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w); + + /* when passing stack variables, callee references will be + SB%+20,*, which may still be in the same page. Don't switch to + UNBR if the new ea is still in the current page */ + + if ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) != (eap->vpn & 0x0FFFFFFF)) + eap = &gvp->brp[UNBR]; + + if (xok) + 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); + } + + /* now check for direct short-form - the 2nd-most frequent case */ if ((inst & 0101000) == 0) { ea_w = (inst & 0777); @@ -54,24 +124,26 @@ 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); -#if 0 - return 0x80000000 | ea_w; -#else return 0x80000000 | (rph << 16) | ea_w; -#endif } - i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ + /* here for short, PC-relative instructions: + - if bit 7 set, it's PC relative + - if bit 7 clear, it's sector 0 (or register) + - instruction may be indirect or not + - optionally, may be postindexed by X + */ - if (inst & 001000) /* sector bit 7 set? */ - if ((inst & 0740) != 0400) { /* PC relative? */ - ea_w = rpl + (((short) (inst << 7)) >> 7); /* yes, sign extend D */ - TRACE(T_EAV, " PC relative, P=%o, new ea_w=%o\n", rpl, ea_w); - eap = &gvp->brp[RPBR]; - } - else - goto labB; /* special cases */ - else if (i) { + if (inst & 001000) { /* sector bit 7 set? */ + ea_w = rpl + (((short) (inst << 7)) >> 7); /* yes, sign extend D */ + TRACE(T_EAV, " PC relative, P=%o, new ea_w=%o\n", rpl, ea_w); + eap = &gvp->brp[RPBR]; + + } else { +#if DBG + if (!i) + fatal ("ea64v: i not set?"); +#endif eap = &gvp->brp[S0BR]; ea_w = (inst & 0777); /* sector 0 */ TRACE(T_EAV, " Sector 0, new ea_w=%o\n", ea_w); @@ -81,8 +153,7 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { TRACE(T_EAV, " Preindex, new ea_w=%o\n", ea_w); x = 0; } - } else - fatal("goto labA?"); + } if (i) { if (ea_w >= gvp->livereglim) { @@ -94,6 +165,7 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { } TRACE(T_EAV, " After indirect, new ea_w=%o\n", ea_w); } + if (x) { TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, crs[X], *(short *)(crs+X)); ea_w += crs[X]; @@ -112,75 +184,5 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) { } TRACE(T_EAV, " Live register '%o\n", ea_w); -#if 0 - return 0x80000000 | ea_w; -#else return 0x80000000 | (rph << 16) | ea_w; -#endif - - /* here for long, 2-word, V-mode memory reference */ - -labB: - a = iget16(RP); - INCRP; - TRACE(T_EAV, " 2-word format, a=%o\n", a); - ixy = (i >> 13) | (x >> 13) | ((inst & 020) >> 4); - xok = (inst & 036000) != 032000; /* true if indexing is okay */ - - br = (inst & 3); - eap = &gvp->brp[br]; - -#ifndef NOTRACE - int opcode; - - opcode = ((inst & 036000) != 032000) ? ((inst & 036000) >> 4) : ((inst & 076000) >> 4); - opcode |= ((inst >> 2) & 3); /* opcode extension */ - TRACE(T_EAV, " new opcode=%5#0o, y=%d, br=%d, ixy=%d, xok=%d\n", opcode, (y != 0), br, ixy, xok); -#endif - - ea_s = crs[PBH+br*2] | (ea_s & RINGMASK16); - ea_w = crs[PBL+br*2] + a; - - if (xok) - if (ixy == 2 || ixy == 6) - ea_w += crs[X]; - else if (ixy == 1 || ixy == 4) - ea_w += crs[Y]; - -#if 0 - /* if this is a PB% address, use RPBR instead if it's in range - - 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); - TRACE(T_EAV, " Long indirect, ea=%o/%o, ea_s=%o, ea_w=%o\n", ea>>16, ea&0xFFFF, ea_s, ea_w); - m = get16(ea); - if (m & 0x8000) - fault(POINTERFAULT, m, ea); - ea_s = m | (ea_s & RINGMASK16); - ea_w = get16(INCVA(ea,1)); - TRACE(T_EAV, " After indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w); - - /* when passing stack variables, callee references will be - SB%+20,*, which may still be in the same page. Don't switch to - UNBR if the new ea is still in the current page */ - - if ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) != (eap->vpn & 0x0FFFFFFF)) - eap = &gvp->brp[UNBR]; - } - if (xok) - 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); }