[Simh] Fixing the FP11's use of MMR1

Bob Supnik bob at supnik.org
Tue Mar 24 17:07:08 EDT 2015


This issue, pointed out by Johnny Billquist, has been hanging fire for 
years.

Fixing the FP11's use of MMR1 - implementation proposal

As has been noted, the FP11 does not update MMR1, ever. Instead, on an 
abort,
general registers except the PC are unchanged from the values they held 
at the
start of the instruction.

We can distinguish three cases:

- A true abort (non-existent memory, memory management error, odd 
address trap).
   The general registers are unchanged. The PC has been updated. MMR2 
will hold
   the address of the instruction for a memory management abort, unless 
all the
   memory management registers were frozen.

- A floating point error. The instruction completes. The general registers
   have been updated. The PC points at the next instruction. A floating 
point
   trap may or may not be pending.

- A floating point error that stops execution of the instruction (divide by
   zero, invalid instruction, enabled trap on undefined variable). All
   instruction processing after the error is skipped. The instruction
   "completes". The general registers have been updated for address mode
   changes. The PC points at the next instruction. A floating point trap may
   or may not be pending.

Because the abort paths are common to all instructions (the J11 had multiple
abort paths), it's desirable not to introduce floating point fixup code into
abort processing. Instead, we'll take a cue out of the J11 microcode.

- Instead of using the standard integer addressing routine GeteaW, the FP11
   will use a specialized local copy, GeteaFW. (The J11 has duplicate 
integer
   address decode routines for floating point, to avoid touching MMR1.)

- Neither GeteaFW nor GeteaFP will change MMR1 or update non-PC general
   register state. Instead, they will record any general register change
   (there can be only one) in a local FP11 variable that is initialized 
to 0.

- At normal exit, these changes will be applied, UNLESS the instruction
   has itself overwritten the general register that was updated in the
   addressing phase. This can only happen on STFPS, STST, STEXP, and STCFi.

Now we have to make sure that all floating point error paths that can
update the general registers reach the normal exit point. There are three
cases, at present, that don't:

- Divide by zero. Instead of forcing a pseudo-abort, simply bypass
   the rest of instruction processing if the divisor is 0.

- Floating register source with register >= 6. It's safe to take the
   current pseudo-abort because no general register modifications have
   occurred (there is only one specifier, and it's mode 06 or 07).

- Floating undefined variable with enabled trap. At present, ReadFP
   doesn't return a value. Let it return a value of true for a valid
   floating point operand or disabled trap and false for an undefined
   variable with trap. Code that currently looks like this:

     ReadFP (...);
     more processing;
     break;

   instead becomes:

     if (ReadFP (...)) {
         more processing;
         }
     break;

   That is, unless the undefined variable trap will be taken, process
   the instruction; otherwise, skip it.

This approach has the advantage that nothing changes outside the FP11. 
Further,
very little overhead is introduced - just clearing the register change 
variable
at FP instruction start and testing it at exit.


More information about the Simh mailing list