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:
Registers | Steps | Use |
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:
- There is only one library to include in the ROM.
- The library is in a subdirectory of one level.
- The name of the library subdirectory and the stub file are the same.
Given these assumptions, and referring to the example in the Wang 600
sample programs, an example is:
- A library in "libplot/plibplot.a" (for reasons not discussed here,
the make rules must use the "exploded" object files, not the archive,
and so may re-compile all the object files if they were removed).
- A stub file named "libplot.w6c", which contains two ROM_EXTERNAL()
directives to establish callbacks for user-supplied graphing functions.
Invoking the target "libplot.w6x" will result in the following actions:
- Generate all object files as needed, i.e. "libplot/*.w6o" and "libplot.w6o".
- Link all object files into two intermediate files, "libplot.w6r" and
"libplot.w6s". The "w6r" file is used to produce the ROM image only,
and the "w6s" is preserved as the guide (symbol table) for
linking to programs.
- Process the file "libplot.w6r" into "libplot.w6x" (which is the actual
ROM image, loaded into the simulator).
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