From page 6-6 of DEC STD 032 (the VAX architecture spec):
"Execution of MTPR src, #PR$_ASTLVL with src<31:0> GEQU 5 results in
UNDEFINED behavior. The preferred implementation is to cause a reserved
operand fault." MicroVAX II, CVAX, and Rigel all conform to the preferred
behavior, as does the current simulator, which was written from the CVAX
microcode. NVAX masks to 3b and does not take an exception on a value
GEQU 5.
The 1982 Architecture Handbook describes ASTLVL as a 3b register, with
src<31:3> ignored/read as zero, and exceptions taken on values GEQU 5.
The780 microcode masks the input value to 3b before doing the GEQU 5 test.
The ASTLVL test needs to be model specific.
I suspect the behavior became undefined when MicroVAX II simplified the
original test to save a microword. I do not see how the code fragment Matt
references could work on a MicroVAX II, which was supported under 4.5.
Perhaps the device Matt mentions couldn't exist on a MicroVAX II?
For those who wants the gory details... uVAX, CVAX, and Rigel do an
unsigned compare on the unmasked src and the constant 5. Carry out
means reserved operand. Overflow is ignored. So an input of 0x80000002 -
0x00000005 (done in the data path as 0x80000002 + 0xFFFFFFFB) generates overflow (ignored) and carry out.
# Conflicts:
# VAX/vaxmod_defs.h
Modified the UBA750 simulation, incorporating these comments. Ultrix
appears to access the non-existant datapath registers and given that this
works on the real hardware the most likely option seems to be read 0
and write NOP. I think this will be true for any access to the UBI outside
of the known registers.
Whilst working on a new video device I ran into a few problems with the
LKxxx keyboard and I noticed there are already some open issues against
the keyboard and mouse devices. These changes should resolve#320 and
may help with #272 (although I think that is an SDL issue). I've tested these
changes with VWS, UWS and DECwindows with both captured and
uncaptured input modes.
the opcode table first word consists of bits:
<7> = FPD is legal for this opcode.
<4:6> = number of specifiers for unimplemented opcodes (VAX subsets)
<3> = unused
<0:2> = number of specifiers
The mask used to be 0x70. The convention is that x_M_y is a mask value
<right-justified>, for a macro like:
#define get_foo(x) (((x) >> x_V_foo) & x_M_foo)
For a subset VAX (like the 3900), the unimplemented opcodes are those
Many of the intermediate state variables are captured by the instruction
history mechanism. Make sure that these don't come into and out of
scope between instruction executions.
IPL_UBA already has the subtract built in:
So it shouldn't be extracted again.
The whole routine looks a little strange, but the way it works is
that an interrupt from the UBA itself sets <bit 31> in the returned vector.
Because the vector is read by code and not used by hardware, the flag
bit is "harmless."
UBA interrupts occur only under strange circumstances, like bad map
pages and device NXMs. Under the simulator, with a debugged OS, they
never happen.
IPL_UBA already has the subtract built in:
So it shouldn't be extracted again.
The whole routine looks a little strange, but the way it works is
that an interrupt from the UBA itself sets <bit 31> in the returned vector.
Because the vector is read by code and not used by hardware, the flag
bit is "harmless."
UBA interrupts occur only under strange circumstances, like bad map
pages and device NXMs. Under the simulator, with a debugged OS, they
never happen.
Add consistent debug options to track TODR activities and the values which
are set. Debug data will display the VMS time related to the values set and
read.
Previously sim_interval was adjusted by 1 plus the total number of bytes
referenced in string instructions (SCANC, SPANC, LOCC, SKPC, CMPC3,
CMPC5, MOVC3, MOVC5). Since the amount of data that a string
instruction can reference is arbitrarily large (32bit size), the adjustment
to sim_interval could be ridiculously excessive. This can result in wild
variances in clock calibration when large string data are referenced.
Various boot ROM activities, including testing the Interval Timers, presume
that ROM based code execute instructions at 1 instruction per usec.
To accommodate this, we not only throttle memory accesses to ROM space,
but we also use instruction based delays when the interval timers are
programmed from the ROM for short duration delays.
The original idling model called sim_idle() within the context of a scheduled
event running on the CPU unit. The overhead of scheduling and the related
dispatch serve no specific purpose.
Meanwhile, the 'work' involved in determing if idling is possible is about
equivalent to the work of executing an additional instruction. Therefore
sim_idle is invoked with an argument which causes the sim_interval to be
adjusted by 1 on each call that doesn't actually perform an idle sleep. This
adjustment keeps the calibrated instruction execution rate consistent with
other purely non-idle instruction mixes.
Clock ticks for these simulatrs are performed by programmatic setup of the
interval timer device (TMR) and have nothing to do with the TODR which
increments at 100Hz, but doesn't generate ticks to the simulated system.
Removing pseudo ticking of the TODR improves simulator behavior
when idling. As previously implement, the timing of the TODR and TMR
ticks weren't aligned and and idle simulator would have to wake up to
service both tick activities.
The real hardware has a TODR which changes every 10ms to reflect changes
to wall clock time. This is already completely achieved by referencing the
host system time whenever the TODR register is referenced. No need for
to simulate pseudo ticking.
The real interval timer hardware generates ticks a the rate specifically
programmed in the interval timer device registers. The common cases
programmed the ticks at 10 ms intervals (100Hz), but real operating systems
exist which programmed ticks at 16667 usecs (60Hz).