Forth was ported to an HP-2100 in 1972, by Elizabeth Rather, so had early
history on HP hardware, though from what I can it it was never a product
available from HP.
I don't know if Forth Inc ever supported Forth on HP machines.
Anthony Pepin provided a Forth to the HP3000 Contributed Library in
September 1982, though I think his looks like a virtual machine, I don't
remember trying it in the day.
Thanks to Gavin Scott's "system" and J. David Bryan's SIMH HP-3000
emulator,
I can look at it now.
As Anthony Pepin observed, Forth implementations at the time assumed a
von Neumann architecture. The HP 3000 with a Harvard architecture implying
read-only code with a different address space, needs more thought.
Why Forth?
I've never been a Forth programmer, but as I understand it,
compilers/interpreters weren't standard with HP 3000 Systems, nor were
there
scripting languages like awk, sed & perhaps the Bourne shell on Unix.
A Forth interpreter supporting the HP 3000's supported types & the
mathematical
functions in SL.PUB.SYS (the system shared library), even without
compilation,
would have been bettered by the Unix dc (RPN calculator) only for it's
multi-precision maths.
HP 3000 types (using kludged C <stdint.h> style
int16_t => INTEGER, uint16_t => LOGICAL, int32_t => DOUBLE
f32_hp3k_t = REAL, f48_hp3k_t => LONG REAL
COMPLEX & Packed Decimal?
A Forth supporting code compiled to Data space would have been a useful tool
for learning & testing & perhaps as a scripting language.
With Date & Actuarial procedures added, I suspect our Actuarial students
would
have found it useful. Don't know if it would have been seen as useful at
educational institutions like RMIT here in Melbourne, Australia that had
3000s.
Assemblers in Forth seem to be a common thing, it would be possible to
assemble the Data space code with minor peephole optimization, and the
necessary
translation from modifying the Next Data instruction variable to
branches in the
code. That and the Dictionary entry could then be written out as an
input file
for PATCH.PUB.SYS, allowing the interpreter to be extended without
understanding
the USL format.
I've finally read some of Koopman, Philip (1989) "Stack Computers: The
New Wave" looked a little at his Harris RTX-2000 MS-DOS Emulator source,
and at
James Bowman "J1: a small Forth CPU Core for FPGAs".
Like the HP 3000, the Harris RTX-20[01]0 & the J1 are 16-bit machines with a
16-bit instruction width (soley for the Harris & J1).
Other than the HP 3000, the architecture use the sign bit to use the
instruction
value as a call-target address or decode an ALU operation with some Forth
special sauce.
I've wondered for a while whether the HP 3000 XEQ instruction which
executes a
stack adressable 16-bit word (0..15 deep on the Stack-Up stack (S register))
has been used for anything other than exiting to clean up the stack on a
Ctl-Y
trap.
A virtual Forth machine where negative int16_t values give a negated call
address, with the least-significant bit selecting Code or Data.
Almost all 16-bit HP 3000 instructions are positive.
Below is an SPL sketch of the virtual machine interpreter
Nonsense @ characters are *Fix Me*s
equate Deepest = 15, Dict'Sz = 1024, Padded'Dict'Sz = Dict'Sz + 16;
integer X = X;
logical PB'Address; << Poor Name>>
logical bu'S'15;
pointer restore'S'15;
logical S'15 = S - 15;
logical D'Dict'Used := 0;
logical Code'Offset;
label Next'Word, Execute'TOS, ...
integer array D'Dict(Padded'Dict'Sz);
<< Code must immediately follow, need to access padding perhaps >>
Next'Word:
TOS := D'Dict(Code'Offset);
if < then begin << Call (int16_t < 0) >>
Return'Stack'X := Return'Stack'X + 1;
Return'Stack(Return'Stack'X) := -((Code'Offset + 1) &
LSL(1)));
assemble(NEG, DUP);
if TOS then begin << Odd => PB (Code) address >>
PB'Address := TOS & LSR(1);
Assemble (@); << Indirect Jump through PB'Address Variable >>
else begin << Even Data Address >>
TOS := TOS & LSR(1);
assemble(DUP);
if TOS >= D'Dict'Used then begin
Error(@);
end
else begin
Code'Offset := TOS; << Weak bounds check >>
goto Next'Word;
end;
end
else begin << (int16_t >= 0), HP-3000 16-bit instruction >>
Execute'TOS:
bu'S'15 := S'15; << Needs testing, backup the value >>
@restore'S'15 := @S'15; << Save Data address of stack element
>>
S'15 := TOS; << Save the instruction as deep as possible >>
assemble(XEQ 14); << Needs testing probably wrong depth number >>
<< Execute the instruction just deposited >>
restore'S'15 := bu'S'15;
Code'Offset := Code'Offset + 1;
goto Next'Word;
end;
<< Not sure how to handle end of the Forth code in Data
Could call to a PB (Code) address or do an indirect branch through
a procedure local to the handle code. So in data, a sentinal of
sorts>>
<< Have Execute'TOS as a label for flexibily >>
<< Basically, Search the DB (Data) Forth dictionary, if found interpret
the data
code, otherwise search the PB (Code) Forth dictionary, if found jump to and
execute the the code directly. >>
<<Restoring & Saving the Status register around each XEQ instruction use,
would be better as a teaching tool & allow using Condition Code effects
when the
Forth word is compiled to Code space. >>
--
The output from BUILDINT.PUB.SYS over a copy of SPLINTR.PUB.SYS gives
the type
signatures of the System Intrinsics and compiler library routines.
This could be curated & processed to generate shims for calling from the
Forth
interpreter, though the Option Variable Procedures would take some thought.
There seem to be ~600 declarations, some of which are duplicate entry points
for the Fortran compiler library for REAL & LONG REAL functions. (ie
RAND & RAND' etc), so you'd need 3 or
more code segments to get around ~256 STT (Segment Transfer Table) limit to
call everything.
Virtual Stack machines executing directly on the HP 3000 stack was what
our COCAM
language did.
Comments? Were HP doing anything like this in the labs?
Philip Koopman's Stack page at CMU
http://users.ece.cmu.edu/~koopman/stack.html