Wang 600 Compiling

Wang 600 and 700 programs may be written in source code form and compiled using these tools. Each program must #include "wang600.h" and also should wrap the code section in BEGIN() and END().

Use of this facility requires GNU Compiler tools, and probably Linux (unless GCC is available for your platform).

The sample Makefile targets/actions use the following program file name suffixes:

w6c
Program module
w6h
Program header file (include) - usually defines the interface
w6e
Intermediate file already pre-processed
w6o
Object file (to be linked/loaded)
w6t
Tape image file, ready to load via tape drive
w6x
Expansion ROM image file, ready to install
w6r
Intermediate file for building Expansion ROM images. Contains relocation information.
w6s
Intermediate file for building Expansion ROM images. Contains symbol definitions, used to link user programs against (for use with) this ROM image.
txt
Text for use with model 607 Teletype or producing tape data image files, ASCII.

Some additional special macros allow for abstraction of statement labels and extended register assignment. These are:

ROM_EXTERNAL(label)
Designate 'label' as residing in program memory, not ROM (as is the default for all other labels defined, when producing a ROM image).
ROM_FEXTERNAL(flabel)
Designate function 'flabel' as residing in program memory, not ROM.
HW_FIXED_F0(flabel)
Designate function 'flabel' as being assigned to "10 00", (f0) which is the subroutine hard-coded by the Model 607 Teletype as the End Of Tape action. A "MARK(flabel)" must exist somewhere in the source module.

When a program is linked, a special statement label is generated followed by an END PROG code. The programmer should not place END PROG codes in the source files. Note, the END_PROG() macro produces a SEARCH(end_prog) and not an actual END PROG code.

Programming statements:

In general, these directly correspond to Wang 600 commands.

E(digit)
The codes E0 - E15 may be produced this way
DP()
Shorthand for E(10)
SET_EXP()
Shorthand for E(11)
CHANGE_SIGN()
Shorthand for E(12)
CLEAR()
Shorthand for E(14)
CLR_DISP()
Shorthand for E(15)

T(reg)
Total register 0-15
ADD(reg)
Add display to register 0-15
SUB(reg)
Subtract display from register 0-15
MULT(reg)
Multiply register 0-15 by display
DIV(reg)
Divide register 0-15 by display
ST(reg)
Store display in register 0-15
RE(reg)
Recall display from register 0-15

SEARCH(label)
'label' should be declared with LABEL(), EXTERNAL(), or the F* variants.
RECALL(longreg)
'longreg' should be declared with either UREG() or IREG_DATA()
PRINT(dp,tag)
Print using precision 'dp' and letter 'tag'. 'dp' is a numberic value, 'tag' may use constants tag_X, ... tag_M. Also, 'dp' constants exist for scientific notation (dp_sci) and blank (paper advance) (dp_blank).
GO()
J_IF_0()
Jump if zero
J_IF_P()
Jump if plus
SIN()
COS()
TAN()
RAD_DEG()
Convert from radians to degrees
LOG_E_X()
LogeX
E_X()
eX
X_2()
X2
SQRT()
√X
LOAD_PROG()
INV()
1/X

MARK(label)
Assign label to program step ('label' must be declared as above)
STORE(longreg)
'longreg' must be declared as described above
ALPHA(cmd)
STOP()
J_IF_N0()
Jump if not zero (letter enn followed by zero)
J_IF_ERR()
Jump if error
SIN_1()
Arc sine
COS_1()
Arc cosine
TAN_1()
Arc tangent
DEG_RAD()
Convert from degrees to radians
LOG_10_X()
Log10X
E10_X()
10X
INT()
Integer
ABS()
Absolute value
END_PROG()
SEARCH(end_prog), not actual END PROG
RETURN()

IO(func)
Issue I/O (func TBD)
INDIR(regop)
Indirect command of T(), ADD(), ...
GROUP1(func)
Group 1 I/O (func TBD)
GROUP2(func)
Group 2 I/O (func TBD)

Some extended functionality not directly accessible on the keyboard:

EXCHG(reg)
Exchange display and register 0-15
CALL(label)
Subroutine call to any label
J_IF_E()
"literal compare" reg 0 = display
J_IF_NE()
"literal compare" reg 0 ≠ display
KTRACE_ON()
Keyboard trace ON (ALPHA PRINT)
KTRACE_OFF()
Keyboard trace OFF
PTRACE_ON()
Program trace ON (ALPHA LOG_E_X)
PTRACE_OFF()
Program trace OFF
PAUSE()
1/2 second pause
PI()
Value of π
POW10(n)
Multiply display by 10n
POW_10(n)
Multiply display by 10-n
J_IF_EQ()
Jump if reg 0 = display
J_IF_GE()
Jump if reg 0 ≥ display
J_IF_LT()
Jump if reg 0 < display
JUMP(reg)
Add contents of 'reg' to program counter

Memory Layout:

Program memory is used as follows:

RegistersStepsUse
246...0000... Program steps from main and linked modules In tape image
Multiples of
8 steps
Initialized registers (aligned as required) from *IREG_DATA()
Consumes
1 register
Consumes
8 steps
END_PROG postample
Multiples of
8 steps
Uninitialized registers (aligned as required) from *UREG() Not in tape image *
  ...16 ...1847 (unused program steps - might have been assigned with RES_REG())
15...0 Dedicated registers, 00-15

* Note, tape images of register data may be created, and may be loaded into this space (including the dedicated registers).

Compiling ROM Images

The first step to producing a rom image is to develope a set of subroutines. These subroutines should have well-defined (and documented) register usage.

The compiler scripts allow a module to be setup to run in either Program Memory or ROM, with the final target being decided at link time. This means a library of subroutines can be both linked in to ordinary programs and also used to build a ROM image that other programs access.

The second step is to create a stub module to act as a starting point for linking the ROM image. This module would typically contain only ROM_EXTERNAL() directives (if ROM callbacks are required) and FORDERED() directives (if the ROM will be used from the keyboard, as opposed to linking with other programs).`

There are make rules in the wpcc Make.rules.user file to aid in building a ROM image, or at least provide an example to clone. These rules make the following assumptions:

Given these assumptions, and referring to the example in the Wang 600 sample programs, an example is:

Invoking the target "libplot.w6x" will result in the following actions:

Then, each user program that is written to use this ROM image will compile as follows:

In the sample programs, the following rules are used (consult actual makefile for the latest changes):

plot_sin.w6t: plot_sin.w6o libplot.w6s libplot.w6x
        $(CC) $(W6CCFLAGS) $(W6TLDFLAGS) \
                -Wl,--just-symbols=libplot.w6s \
                -o $(basename $@).w6$$ $<
        $(W6LDFIX) $(basename $@).w6$$
        @rm -f $(basename $@).w6$$

Because of the complexity of dependencies, this rule has not been abstracted to an implicit rule (yet).

Utilities

The following utilities are provided, both for building program images and for general use:

w6lst
List a program image, similar to the built-in list function on the buildt-in drum printer.

Example: w6lst foo.w6t

w6verify
Compute the VERIFY PROG value, using the same method as the VERIFY PROG function on the calculator. This allows computing the VERIFY PROG value without actually loading the image on the calculator (simulator).

Example: w6verify foo.w6t

w6cpp
The preprocessor (not to be confused with, and in addition to, the "C" preprocessor included with the GNU tools).

Synopsis: w6cpp <in-file >out-file

w6data2tape
Utility to convert an ASCII list of numbers (1 per line) into a tape image of register data. Such an image can be loaded using the Wang 600 ALPHA commands for loading registers from tape.

Synopsis: w6data2tape <in-file >tape-image

symbols2labels
Shell script to convert output from FORDERED() directives into linkers scripts and function label file. Produces the two linker scripts (fnordering1.ld and fnordering2.ld) in the current directory.

Synopsis: symbols2labels base-name 600 >label-file