mirror of
https://github.com/prirun/p50em.git
synced 2026-01-17 16:33:54 +00:00
invalidate instruction cache page (instvpn) whenever OWNER might change
removed OWNER tests from instruction fetch
This commit is contained in:
parent
6afd8f2c52
commit
98417e5835
93
em.c
93
em.c
@ -394,9 +394,8 @@ typedef struct {
|
||||
|
||||
unsigned long instcount; /* global instruction count */
|
||||
|
||||
unsigned int prevowner; /* OWNERH|OWNERL */
|
||||
unsigned short *prevppa; /* mem[] physical page address */
|
||||
ea_t prevvpn; /* virtual page address */
|
||||
unsigned short *instmemp; /* mem[] physical page address */
|
||||
ea_t instvpn; /* instruction virtual page address */
|
||||
|
||||
unsigned short inhcount; /* number of instructions to stay inhibited */
|
||||
|
||||
@ -1071,29 +1070,47 @@ static long long get64r(ea_t ea, ea_t rpring) {
|
||||
}
|
||||
|
||||
/* Instruction version of get16 (can be replaced by get16 too...)
|
||||
This needs to be checked more... not sure it actually improves
|
||||
performance all that much and is potentially incompatible, ie,
|
||||
iget16t isn't implemented (V-mode executing from registers) */
|
||||
|
||||
To avoid mapva on every instruction word fetch, two pointers are kept
|
||||
in the hot global variable structure: instvpn and instmemp. These
|
||||
variables track the virtual page address we're currently executing
|
||||
(instvpn) and the corresponding pointer in the Prime physical memory
|
||||
array mem (instmemp). Whenever a process exchange occurs or the STLB
|
||||
is changed, these are invalidated and will be reloaded with the long
|
||||
version of iget16: iget16t.
|
||||
|
||||
Bit 1 of the EA is checked below so that if we're executing code from
|
||||
registers, iget16t will be called, and eventually, get16t, to handle
|
||||
the address trap. Since bit 1 is never stored in instvpn, EA < 0
|
||||
will always end up in get16t to load the instruction from a register.
|
||||
|
||||
The effect of this mechanism is that virtual->physical address
|
||||
translation and access protection checks are only done once per
|
||||
page instead of on every 16-bit fetch from the instruction stream.
|
||||
*/
|
||||
|
||||
#ifdef FAST
|
||||
#define iget16t(ea) iget16((ea))
|
||||
|
||||
unsigned short iget16(ea_t ea) {
|
||||
unsigned short iget16t(ea_t ea) {
|
||||
unsigned short access;
|
||||
ea_t thisvpn;
|
||||
|
||||
if (*(int *)&ea >= 0) {
|
||||
thisvpn = ea & 0x0FFFFC00; /* segment and page number */
|
||||
if ((thisvpn == gvp->prevvpn) && (!(ea & 0x08000000) || (crsl[OWNER32] == gvp->prevowner)))
|
||||
return gvp->prevppa[ea & 0x3FF];
|
||||
|
||||
gvp->prevvpn = thisvpn;
|
||||
gvp->prevowner = crsl[OWNER32];
|
||||
gvp->prevppa = mem + (mapva(ea, RP, RACC, &access) & 0xFFFFFC00);
|
||||
return gvp->prevppa[ea & 0x3FF];
|
||||
if (*(int *)&ea > 0) {
|
||||
gvp->instvpn = ea & 0x0FFFFC00;
|
||||
gvp->instmemp = mem + (mapva(ea, RP, RACC, &access) & 0xFFFFFC00);
|
||||
return gvp->instmemp[ea & 0x3FF];
|
||||
}
|
||||
return get16t(ea);
|
||||
}
|
||||
|
||||
static inline unsigned short iget16(ea_t ea) {
|
||||
unsigned short access;
|
||||
|
||||
if ((ea & 0x8FFFFC00) == gvp->instvpn)
|
||||
return gvp->instmemp[ea & 0x3FF];
|
||||
else
|
||||
return iget16t(ea);
|
||||
}
|
||||
|
||||
#else
|
||||
#define iget16(ea) get16((ea))
|
||||
#define iget16t(ea) get16t((ea))
|
||||
@ -2683,14 +2700,17 @@ static ors(unsigned short pcbw) {
|
||||
rs = (modals & 0340) >> 5;
|
||||
#endif
|
||||
crsl = regs.sym.userregs[rs];
|
||||
//NOTE: following is unnecessary because crs is an alias for crsl
|
||||
//crs = (void *)crsl;
|
||||
crs[MODALS] = modals;
|
||||
TRACE(T_PX, "ors: rs = %d, reg set in modals = %d, modals = %o\n", rs, (crs[MODALS] & 0340)>>5, crs[MODALS]);
|
||||
#if 0
|
||||
if (rs > 1)
|
||||
gvp->savetraceflags = ~0;
|
||||
#endif
|
||||
|
||||
/* invalidate the instruction translation cache mechanism */
|
||||
|
||||
gvp->instvpn = 0x000000FF;
|
||||
gvp->instmemp = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -3137,11 +3157,9 @@ static lpsw() {
|
||||
m = get16(INCVA(ea,3));
|
||||
if ((m & 0340) != (crs[MODALS] & 0340)) {
|
||||
TRACE(T_PX, "LPSW: WARNING: changed current register set: current modals=%o, new modals=%o\n", crs[MODALS], m);
|
||||
#if 1
|
||||
/* not sure about doing this... */
|
||||
printf("WARNING: LPSW changed current register set: current modals=%o, new modals=%o\n", crs[MODALS], m);
|
||||
crsl = regs.sym.userregs[(m & 0340) >> 5];
|
||||
#endif
|
||||
}
|
||||
|
||||
crs[MODALS] = m;
|
||||
@ -3731,9 +3749,8 @@ main (int argc, char **argv) {
|
||||
gvp->livereglim = 040;
|
||||
gvp->mapvacalls = 0;
|
||||
gvp->mapvamisses = 0;
|
||||
gvp->prevowner = 0xFFFFFFFF;
|
||||
gvp->prevppa = NULL;
|
||||
gvp->prevvpn = 0xFFFFFC00;
|
||||
gvp->instmemp = NULL;
|
||||
gvp->instvpn = 0x000000FF; /* bogus - nothing will match this */
|
||||
|
||||
/* ignore SIGPIPE signals (sockets) or they'll kill the emulator */
|
||||
|
||||
@ -4296,21 +4313,7 @@ fetch:
|
||||
ea = 0x80000000 | (ea & 0xFFFF);
|
||||
#endif
|
||||
|
||||
/* the Prime allows executing instructions from register locations in
|
||||
R-mode (BASIC TRACE ON does this), so iget16t is needed here
|
||||
|
||||
The next couple of lines are manually inlined from iget16, and check
|
||||
that the virtual page being executed is the same as before and RP isn't
|
||||
less than zero (not executing from registers). The 2nd part makes sure
|
||||
that either the segment number is shared (not private) or, if it is
|
||||
private, that the currently executing owner is the same as the last
|
||||
owner when the page addess was translated.
|
||||
*/
|
||||
|
||||
if ((RP & 0x8FFFFC00) == gvp->prevvpn && (!(RP & 0x08000000) || (crsl[OWNER32] == gvp->prevowner)))
|
||||
inst = gvp->prevppa[RP & 0x3FF];
|
||||
else
|
||||
inst = iget16t(RP);
|
||||
inst = iget16(RP);
|
||||
INCRP;
|
||||
gvp->instcount++;
|
||||
|
||||
@ -5263,6 +5266,11 @@ d_liot: /* 000044 */
|
||||
TRACE(T_INST, " invalidated STLB index %d\n", utempa);
|
||||
mapva(ea, RP, RACC, &access);
|
||||
TRACE(T_INST, " loaded STLB for %o/%o\n", ea>>16, ea&0xffff);
|
||||
|
||||
/* invalidate the instruction translation cache mechanism */
|
||||
|
||||
gvp->instvpn = 0x000000FF;
|
||||
gvp->instmemp = NULL;
|
||||
goto fetch;
|
||||
|
||||
d_ptlb: /* 000064 */
|
||||
@ -5295,6 +5303,11 @@ d_itlb: /* 000615 */
|
||||
if (((utempl >> 16) & 07777) < 4)
|
||||
gvp->iotlb[(utempl >> 10) & 0xFF].valid = 0;
|
||||
}
|
||||
|
||||
/* invalidate the instruction translation cache mechanism */
|
||||
|
||||
gvp->instvpn = 0x000000FF;
|
||||
gvp->instmemp = NULL;
|
||||
goto fetch;
|
||||
|
||||
d_lpsw: /* 000711 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user