Fixes #23 RTT/RTI too trusting

This commit is contained in:
outofmbufs 2025-04-08 22:16:48 -05:00
parent b7da554118
commit bbaf5e8bc6
2 changed files with 43 additions and 23 deletions

View file

@ -956,29 +956,13 @@ class PDP1170(PDP11):
# could test if necessary but it's just easier to do this every time
self._syncregs() # in case any mode/regset changes
# prevent UNDEFINED_MODE from entering the PSW (current mode)
m = (value >> 14) & 3
if m == self.UNDEFINED_MODE:
d = self._psw2dict(value)
if self.UNDEFINED_MODE in (d['curmode'], d['prevmode']):
raise PDPTraps.ReservedInstruction
self.psw_curmode = m
# prevent UNDEFINED_MODE from entering the PSW (previous mode)
m = (value >> 12) & 3
if m == self.UNDEFINED_MODE:
raise PDPTraps.ReservedInstruction
self.psw_prevmode = m
prevregset = self.psw_regset
self.psw_regset = (value >> 11) & 1
newpri = (value >> 5) & 7
self.psw_pri = newpri
self.psw_trap = (value >> 4) & 1
self.psw_n = (value >> 3) & 1
self.psw_z = (value >> 2) & 1
self.psw_v = (value >> 1) & 1
self.psw_c = value & 1
for attr, val in d.items():
setattr(self, 'psw_' + attr, val)
# set up the correct register file and install correct SP
self.r = self.registerfiles[self.psw_regset]
@ -986,6 +970,30 @@ class PDP1170(PDP11):
# the PC was already sync'd in syncregs()
_pswfields = {
'curmode': (14, 3), # bits 14:15
'prevmode': (12, 3), # bits 12:13
'regset': (11, 1), # bit 11
# 8 9 10 unused
'pri': (5, 7), # bits: 5:7
'trap': (4, 1),
'n': (3, 1),
'z': (2, 1),
'v': (1, 1),
'c': (0, 1),
}
def _psw2dict(self, pswval):
return {attr: (pswval >> bi[0]) & bi[1]
for attr, bi in self._pswfields.items()}
def _dict2psw(self, d):
psw = 0
for attr, val in d.items():
shf, mask = self._pswfields[attr]
psw |= (val & mask) << shf
return psw
@property
def logging_hack(self):
return self.logger.level

View file

@ -48,7 +48,19 @@ def op_wait(cpu, inst):
def op_rtt(cpu, inst):
cpu.r[cpu.PC] = cpu.stackpop()
cpu.psw = cpu.stackpop()
newpsw_d = cpu._psw2dict(cpu.stackpop())
# this knows KERNEL < SUPERVISOR < USER
newpsw_d['curmode'] = max(cpu.psw_curmode, newpsw_d['curmode'])
newpsw_d['prevmode'] = max(cpu.psw_prevmode, newpsw_d['prevmode'])
# if not in kernel mode, cannot change pri
if cpu.psw_curmode != cpu.KERNEL:
newpsw_d['pri'] = cpu.psw_pri
# Regset cannot be changed to zero if it is currently 1
newpsw_d['pri'] |= (cpu.psw_regset | newpsw_d['pri'])
cpu.psw = cpu._dict2psw(newpsw_d)
def op_02xx(cpu, inst):
@ -115,7 +127,7 @@ def op000_dispatcher(cpu, inst):
if inst == 0:
op_halt(cpu, inst)
elif inst == 6 or inst == 2: # RTI and RTT are identical!!
op_rtt(cpu, inst)
op_rtt(cpu, inst) # (because trace not implemented)
elif inst == 1:
op_wait(cpu, inst)
elif inst == 3: