4

The other day I came across a clever way of implementing variable-length extended precision, dated 1967 (on the BESM-6, apparently as part of the system software available at the time of introduction of the machine, but that is beside the point).

Given the precision extension factor T ≥ 2, the starting address S of the code to be executed, and data offset Δ, the routine would consider the instructions starting with S, until the "exit back to native execution" pseudo-code is encountered.

It would execute the instructions not involving the f. p., literally, and would treat all f. p. operations as performed with T-fold precision, using memory locations A+Δ, A+2*Δ, etc. to load/store the tail of the mantissa for instructions referring to memory location A, and modeling the FPU registers accordingly.

In addition to interpreting floating point instructions, a "system call" to print f. p. values in full precision was provided.

This way a developer of a numerical algorithm in the machine code or an assembly language could easily experiment with their algorithm and see how numerically (un)stable it is.

Here is an artificial example written in a hypothetical assembly code for an accumulator-based machine:

     SET   0(R1)  flag (0 - native, 1 - interpreted)
* ===========
SQRT LDR   R0     R0 is const 0: clears ACC ...
* ... and its emulated mantissa tail in interp.
     OR    =E'2'  literal 2.0
     SQRT
     ST    RES        store computed sqrt(2)
     SVC   PRINT,ARG1 the only interpreted sys call.
     BRZ   R1,EXTP    if native, go to ext. precision
* ===========
* An undefined opcode signifies exit from interp.
     XXX   EXIT
EXTP SET   1(R1)      set the flag to indicate interpretation mode
* The sys call gets the ID of the standard procedure to load,
* the user address to load it, and the address of the parameter pack.
     SVC   STPROC,MPREC,BUF,ARG2
EXIT SVC   EXIT
* Address range to print, format, precision
ARG1 DATA  A(RES),A(RES),REAL,36
* Δ, start address to execute, T, work area 
ARG2 DATA  1,A(SQRT),3,A(AREA)
RES  BSS   3 
AREA BSS   23    3*T + 14 per instruction
BUF  BSS   768   length of the interpreter in words per instruction

Here the piece of code between the "======" will be executed twice. The first time it will run natively, computing the single-precision sqrt(2) and printing it using a facility provided by the OS.

Upon reaching the BRZ (branch if register is zero), it will jump to EXTP. After setting R1 to 1, invoking the system call SVC STPROC,MPREC will load the multi-precision routine and pass it the arguments, including the starting address SQRT.

The routine would initialize the simulated state of the CPU transferring values of all registers, as they were at the point of SVC STPROC,MPREC, to the simulated state of the CPU, then it would start interpreting instructions as follows:

  • LDR R0 zeroes out the accumulator (Acc) as it would natively, and also it zeroes out the simulated extension of Acc as a special case.
  • OR =E'2' loads the floating point representation of 2.0 into Acc. As the instruction does not involve floating point, its interpretation is identical to its native functionality.
  • SQRT is interpreted, computing the extended precision result in simulated Acc and its extension.
  • ST RES stores the full-length result to memory
  • SVC PRINT,ARG1 is interpreted. The number(s) are converted to a text format, then the native SVC PRINT syscall would be called to print the resulting text.
  • BRZ R1,EXTP is interpreted in a way identical to its native semantics. At that time the value of R1 is 1, therefore BRZ is not taken.
  • XXX EXIT, where XXX is one of invalid opcodes, is treated as exiting the interpreter by jumping to the label EXIT.

The program then terminates.

This would print, on the BESM-6 (manually aligned for ease of comparison),

     +141421356237187865190207958221435546⏨+01
+0001+1414213562373095048801688724209698079

For reference, the value of sqrt(2) with precision 37 is

     1.4142135623730950488016887242096980785

The printed f. p. format is, perhaps, deliberately different.


Are there examples of similar techniques used on contemporary Western computers?

13
  • 2
    Do you mean variants of "native machine code executing machine-like pseudo code with better capabilities"? There are plenty of examples for this, e.g. Apple II Sweet 16 (16-bit operations), UCSD p-Code, Java bytecode, IBM 5100, Stantec Zebra "simple code", ... also arguably complete languages like Forth.
    – dirkt
    Commented Jun 21 at 5:15
  • 1
    @Tommy Not the (hardware) processor, but the software interpreter. I could have included an example, but I'm afraid it will need to include too many irrelevant ISA-specific details.
    – Leo B.
    Commented Jun 21 at 18:02
  • 1
    @Tommy Please see an example in the updated question.
    – Leo B.
    Commented Jun 21 at 21:14
  • 1
    @dirkt No, the flag is only for the demo code to decide where to go the first time, and where to go the second time. The first pass through the SQRT instruction is native, the second pass is interpreted by the SVC STPROC,MPREC call.
    – Leo B.
    Commented Jun 22 at 5:43
  • 1
    You really need to describe this a bit better, for "hypothetical" assembler code it is a bit hard to guess what it does. So you basically have an additional interpreter for native assembly code, probably one that uses a special instruction to execute single other instructions, but then traps on some instructions and executes them differently? And you can run the code straight, or through the interpreter? There are quite a few ISAs that include such a special instruction, so I guess it'd possible to write an interpreter like this, but I am not aware of any existing one.
    – dirkt
    Commented Jun 22 at 5:53

0

You must log in to answer this question.

Browse other questions tagged .