mirror of
https://github.com/prirun/p50em.git
synced 2026-01-11 23:42:56 +00:00
Mixed tabs/spaces gets hairy. I've expanded the tabs on the basis of 8-position tabstops.
187 lines
5.9 KiB
C
187 lines
5.9 KiB
C
/* this version is derived from the flowchart in the preliminary P400
|
|
release notes */
|
|
|
|
static inline ea_t ea64v (unsigned short inst, ea_t earp) {
|
|
|
|
ea_t ea; /* full seg/word va */
|
|
unsigned short ea_s; /* eff address segno */
|
|
unsigned short ea_w; /* eff address wordno */
|
|
unsigned short br;
|
|
unsigned short i;
|
|
unsigned short x;
|
|
unsigned short xok;
|
|
unsigned short a;
|
|
unsigned short ixy;
|
|
unsigned short m;
|
|
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
|
|
case of an XEC instruction; in that case, earp points to 1
|
|
after the instruction being executed */
|
|
|
|
rph = earp >> 16;
|
|
rpl = earp & 0xFFFF;
|
|
//TRACE(T_EAV, " inst=%o, rph=%o, rpl=%o\n", inst, rph, rpl);
|
|
|
|
ea_s = rph;
|
|
|
|
/* first check for long, 2-word, V-mode memory references. About
|
|
half 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 = &gv.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=%#05o, br=%d, ixy=%d, xok=%d\n", opcode, br, ixy, xok);
|
|
#endif
|
|
|
|
ea_s = getcrs16(PBH+br*2) | (ea_s & RINGMASK16);
|
|
ea_w = getcrs16(PBL+br*2) + a;
|
|
|
|
if (xok)
|
|
if (ixy == 2 || ixy == 6)
|
|
ea_w += getcrs16(X);
|
|
else if (ixy == 1 || ixy == 4)
|
|
ea_w += getcrs16(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)) == gv.brp[RPBR].vpn))
|
|
eap = &gv.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 = &gv.brp[UNBR];
|
|
|
|
if (xok)
|
|
if (ixy == 7) {
|
|
TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
|
|
ea_w += getcrs16(X);
|
|
} else if (ixy == 5) {
|
|
TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, getcrs16(Y), getcrs16s(Y));
|
|
ea_w += getcrs16(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);
|
|
if (x) {
|
|
TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
|
|
ea_w += getcrs16(X);
|
|
TRACE(T_EAV, " Postindex, new ea_w=%o\n", ea_w);
|
|
}
|
|
if (inst & 0400) {
|
|
TRACE(T_EAV, " Short LB relative, LB=%o/%o\n", getcrs16(LBH), getcrs16(LBL));
|
|
eap = &gv.brp[LBBR];
|
|
ea_s = getcrs16(LBH) | (ea_s & RINGMASK16);
|
|
ea_w += getcrs16(LBL);
|
|
return MAKEVA(ea_s, ea_w);
|
|
}
|
|
if (ea_w >= gv.livereglim) {
|
|
eap = &gv.brp[SBBR];
|
|
ea_s = getcrs16(SBH) | (ea_s & RINGMASK16);
|
|
ea_w += getcrs16(SBL);
|
|
TRACE(T_EAV, " Short SB relative, SB=%o/%o\n", getcrs16(SBH), getcrs16(SBL));
|
|
return MAKEVA(ea_s, ea_w);
|
|
}
|
|
TRACE(T_EAV, " Live register '%o\n", ea_w);
|
|
return 0x80000000 | (rph << 16) | ea_w;
|
|
}
|
|
|
|
/* 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? */
|
|
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 = &gv.brp[RPBR];
|
|
|
|
} else {
|
|
#if DBG
|
|
if (!i)
|
|
fatal ("ea64v: i not set?");
|
|
#endif
|
|
eap = &gv.brp[S0BR];
|
|
ea_w = (inst & 0777); /* sector 0 */
|
|
TRACE(T_EAV, " Sector 0, new ea_w=%o\n", ea_w);
|
|
if (ea_w < 0100 && x) { /* preindex by X */
|
|
TRACE(T_EAV, " Preindex, ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
|
|
ea_w += getcrs16(X);
|
|
TRACE(T_EAV, " Preindex, new ea_w=%o\n", ea_w);
|
|
x = 0;
|
|
}
|
|
}
|
|
|
|
if (i) {
|
|
if (ea_w >= gv.livereglim) {
|
|
TRACE(T_EAV, " Indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w);
|
|
ea_w = get16(MAKEVA(ea_s, ea_w));
|
|
} else {
|
|
TRACE(T_EAV, " Indirect through live register '%o\n", ea_w);
|
|
ea_w = get16trap(ea_w);
|
|
}
|
|
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, getcrs16(X), getcrs16s(X));
|
|
ea_w += getcrs16(X);
|
|
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 >= gv.livereglim) {
|
|
if (((ea_w ^ RPL) & 0xFC00) == 0)
|
|
eap = &gv.brp[RPBR]; /* occurs 80% */
|
|
else
|
|
eap = &gv.brp[PBBR]; /* occurs 20% */
|
|
return MAKEVA(ea_s, ea_w);
|
|
}
|
|
|
|
TRACE(T_EAV, " Live register '%o\n", ea_w);
|
|
return 0x80000000 | (rph << 16) | ea_w;
|
|
}
|