Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!mcvax!kth!sunic!liuida!mikpa
From: mikpa@massormetrix.ida.liu.se (Mikael Patel)
Newsgroups: comp.lang.forth
Subject: The Minimal Forth Machine
Keywords: virtual machine
Message-ID: <1330@massormetrix.ida.liu.se>
Date: 11 Aug 89 09:53:01 GMT
Organization: Dept of Comp and Info Science, Univ of Linkoping, Sweden
Lines: 105

Hi, Forth Lovers, how about a distributed problem solving session?

The quest is to find `the minimal Forth Machine'. What is the minimal set
of operations such a machine must implement? 

I have started to attach this problem. My first group of operations to
study is the arithmetric operations, thus the sub-problem is; What is
the minimal set of operation to realize + - * /mod mod /?

Sofar I need:
   not xor 
   0> 0< 0= 
   1+ 1- 
   dup swap rot drop 
   >r r> 
   if else then
   tail-recurse ( compiles a branch to the beginning of the definition)

This list can be minimized further by defining control structure, 
stack, logical, and memory operations.

The goal is to design this minimal machine and the definitions need
so that any teacher out there can take a net-list description of the
machine and a memory specification (in for instance EDIF) and hand it
over to students in a computer architecture/digital design classes.

"Forth for the Masses" -- Mikael Patel

----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----

( Arithmetric operations with a small set of primitives, Mikael Patel, 1989)

( Requires: not xor 0> 0< 0= 1+ 1- dup swap rot drop >r r> if else then)
( Implements: 0 1 negate abs + - * /mod / mod)

0 constant 0				( A bit crazy but...)
1 constant 1				( ...you an't seen nothing yet)

: negate ( x -- y)
  not 1+ ;				( Invert and increment)

: abs ( x -- y)
  dup 0< if negate then ;		( Absolute value)

: + ( x y -- z)
  dup 0=				( Check if there is still more to do)
  if drop				( Return result)
  else
    dup 0>				( Check direction)
    if 1- swap 1+ swap			( Decrement and increment)
    else
      1+ swap 1- swap			( Increment and decrement)
    then
    tail-recurse			( And go again)
  then ;

: - ( x y -- z)
  negate + ;				( Negate and add)

: (*) ( a x y -- z)
  dup 0>				( Check if there is still more to do)
  if 1-					( Decrement counter)
    swap rot over + swap rot		( Add to result and put back in order )
    tail-recurse			( And go again)
  else
    drop drop				( Drop temporary parameters)
  then ;

: sign ( x y -- s)
  0> swap 0> xor ;			( Return sign of arithmetric operation)

: * ( x y -- z)
  dup 0=				( Check for zero)
  if swap drop				( Drop parameter and return zero)
  else
    over over sign >r			( Save the sign of the result)
    0 rot abs rot abs (*)		( Do it the hard way)
    r> if negate then			( Check if negative then negate)
  then ;

: (/mod) ( q r y -- r q)
  swap over - dup 0< not		( Generate next reminder and check)
  if swap				( Put reminer back into place)
    rot 1+ rot rot			( Increment quotient)
    tail-recurse			( And go again)
  else
    + swap				( Restore and return result)
  then ;

: /mod ( x y -- r q)
  dup 0=				( Check if divide by zero)
  if drop drop 0 0			( Return zero)
  else
    over >r				( Save sign of divident)
    over over sign >r			( Save sign of result)
    0 rot abs rot abs (/mod)		( Setup initial quotient)
    r> if negate then			( Check sign of quotient)
    r> if swap negate swap then		( Check sign of reminder)
 then ;

: / ( x y -- q)
  /mod swap drop ;			( Do it and drop reminder)

: mod ( x y -- r)
  /mod drop ;				( Do it and drop quotient)