Native UniDOS and cross tools for MC6800/HD6303, with MC68HC11 assembly support.
Assembler is based on MOS Technology 6502 assembler for BBC Micro by A.J.Travis and J.G.Harston
Small-C is based on Ron Cain's Small-C V1.1 adapted for Flex by S. Stepanoff
The original assemblers do not support HD6303 extended commands. In addition, they cannot assemble the source texts of system programs without cross-compiling, due to lack of memory. In this regard, it was decided to write a new assembler that is compatible with UniCROSS, but works both in cross compilation mode and native mode in UniDOS.
Usage:
unias [-m hd6303|hc11] [-c] [-D IDENT] [-l [prog.lst]] [-o prog[.cmd|.pgm|.obj]] prog.asm
HD6303 remains the default. -m hc11 selects MC68HC11 and defines
__HC11__. Aliases 68hc11 and MC68HC11 are accepted. CMD, PGM and
separate OBJ/LIB modules use the existing formats and relocation machinery.
Select HC11 consistently for every module containing HC11 instructions;
the linker does not translate one instruction set into another.
HC11 supports Y addressing, prefix pages 18/1A/CD, CPD/CPY, IDIV/FDIV, STOP and bit operations. Examples:
ldy #buffer
ldaa 7,y
cpd #$1234
bset $80,#$40
bclr 5,y,#1
brset 0,y,#$80,readyOffsets for indexed X/Y addressing and masks must be absolute 0..255.
Bit syntax is address (optionally followed by X/Y), mask, then branch target;
# before the mask is optional. HC11 rejects HD6303-only AIM/OIM/EIM/TIM
and SLP. XGDX is 8F in HC11 and 18 in HD6303. TEST/factory MCU modes and
on-chip peripherals are outside the Pyldin CPU extension.
make test-hc11 compares 101 forms against fixed manual-derived opcode
bytes, checks invalid operands and verifies relocation after all prefix
pages, including BSS, CMD/PGM, OBJ and LIB linking. make test retains the
existing HD6303/MC6800 regressions. Native UniAS uses the same encoder.
Where:
-D IDENT Specify an identifier to use with the .ifdef and .ifndef directives.
-l [prog.lst] - listing output (if no file is specified, it is displayed on the screen).
-o prog[.cmd|.pgm] - output file name, extensions are created automatically, depending on compilation mode.
UniAS writes ready-to-load PGM files, including the BSS size and entry point.
SECTION without an address starts relative, uninitialized BSS; ENDS
returns to code. An open section is closed at end of source. Absolute
SECTION $E0 workspace keeps its old meaning. No host BSS trimming is needed.
END label or MAIN selects the entry point. ORG selects absolute CMD/ROM.
-c, a .OBJ output name, PUBLIC or EXTERN selects UniCROSS OBJ version 1.
The original 32-byte header, big-endian words, public/external tables and
LSB/MSB/word relocation records are retained; the BSS length is at offset 16.
RADIX, MAIN, PUBLIC, EXTERN and the CHKSUM alias are supported.
External symbols must be bare operands, as in UniCROSS; external arithmetic,
external EQU aliases and relative branches to external labels are rejected.
Use a separately exported field label for an external structure offset.
Private symbols may be longer, but exported/imported names are at most 15
characters. Relative BSS and code expressions retain their relocation type.
User manual for UniCROSS
Small-C is a subset of the C language and is optimized for use on systems with limited resources. It is used to build the UniAS assembler and itself.
Usage:
unicc [-c] [-ctext] [-errstop] [-o outputfile] inputfile
Where:
-c - emit separate-module ASM for UniAS OBJ output
-ctext - include program lines in assembler listing comments
-errstop - stop compilation on error
-o outputfile - output file name
Usage example
Using a text editor, create a hello.c program with the following content:
main()
{
puts("Hello, world!");
}
Compile the program:
unicc -o HELLO.ASM HELLO.C
Assemble the resulting assembler file into binary:
unias -o HELLO.CMD HELLO.ASM
Run the compiled program:
hello
The host VM uses 16-bit two's-complement integers. Division truncates toward
zero, remainder has the dividend's sign, and right shift is arithmetic.
Shift counts use the low five bits; left shifts of 16..31 yield zero.
-32768 / -1 wraps to -32768. Division by zero and unsupported native inline
code fail explicitly. Character helpers follow the ROM's ASCII/identifier ABI.
The bootstrap compiler seed is rebuilt from SMALL-C/SMALLCX.C with the
-32768 decimal-output fix. UniAS expression division/remainder remain unsigned
16-bit operations, independently of the C VM's signed operations.
make
make test
make pyldin
make pyldin creates three 8192-byte ROM modules: ZVM6800.ROM, ZVM6303.ROM
and ZVMHC11.ROM,
plus native UNICC.CMD, UNIAS.CMD and SYSTEM.H in pyldin/. These use INT EF,
ABI 1: A=0 returns A=1, B=0/1/2 (MC6800/HD6303/MC68HC11), X=5A56; A=1 executes the
bytecode at X and returns through the normal ramloader SWI gateway. The
Lilith/default SYSTEM.H and ZCODE.ROM retain INT E8. FPGA startup is selected
by -D PYLDIN601; the distributed pyldin/SYSTEM.H enables it by default.
Copy all three ROMs and RAMLOAD.PGM/RAMLOAD.H11 from pyldin601-fpga to one directory. Run
RAMLOAD /CVM from the main UniDOS shell before NC. It reads the FPGA CPU
selection and installs only the matching ROM in a pinned RAMMAN bank.
No FPGA rebuild or additional fixed ROM page is required.
The HC11 interpreter uses IDIV for signed C division/remainder after sign
normalization. C bytecode remains shared; native inserts require the selected ISA.
C bytecode and the C104..C18C library entry table are shared between CPUs. The MC6800 variant uses no HD6303 extensions. VM state, original direct page E0..FF, BREAK and critical-error vectors are restored after each invocation, including nested calls. A module cannot be unloaded while it is executing. Normal exit, division by zero, malformed bytecode and BREAK return through the gateway. Native inline assembly still must match the selected CPU.
Compile in a directory containing the generated SYSTEM.H:
UNICC -o HELLO.ASM HELLO.C
UNIAS -o HELLO.CMD HELLO.ASM
HELLO
This remains Small-C, not a full ISO C implementation: source lines are at
most 79 characters, string literals do not process C backslash escapes, and
integer/character sizes and the existing library ABI are unchanged. Native
UniDOS also rejects launching a second absolute CMD while one is running;
system() can execute internal shell commands and relocatable PGM programs.
Both programs are written in this UniCC dialect and run as native CMD files on either VM. The host wrappers execute the same C bytecode. No host linker or PGM postprocessor is used.
unias -c -o MAIN.OBJ MAIN.ASM
unias -c -o HELP.OBJ HELP.ASM
unild [-o APP.PGM] MAIN.OBJ HELP.OBJ
uniar r UTIL.LIB HELP.OBJ
unild -o APP.PGM MAIN.OBJ UTIL.LIB
uniar t UTIL.LIB
uniar x UTIL.LIB HELP
uniar d UTIL.LIB HELP
UniLD accepts OBJ versions 0 and 1, original UniLIB containers, extensionless
names (OBJ then LIB), /c for CMD at $0100, /p for module page alignment,
combined /cp, and @list response files. The root module must have an entry
point. Legacy v0 objects have no reliable no-entry marker: the first plain
v0 OBJ supplies the entry, later v0 modules are treated as helpers.
Code and BSS segments are selected through actual relocation dependencies;
unused library code is omitted, including unreferenced EXTERN declarations.
Code streams and relocation tables stay on disk. Limits are 32 input files,
256 modules, 512 public definitions, 255 imports/exports per OBJ, 31-character
paths, and 65535 bytes per OBJ or combined program memory. Library file
positions are 32-bit, so a LIB can exceed 64 KiB. CMD does not allocate BSS;
the application must check and reserve its own data memory.
-z BYTES zero-pads code to an exact decimal extent before placing BSS.
It rejects a smaller extent, overflow, and non-page-aligned values with /p.
This permits interchangeable standard PGM overlays with identical BSS
addresses; neither OBJ nor PGM gains a new record type. -b can package
several such PGMs after a resident supervisor. Existing commands are unchanged.
-m APP.MAP writes a textual link map (module code/BSS ranges and public
symbols). It is optional metadata and does not change the PGM. BSS-only
modules are included. -b -o COMBINED.PGM PREFIX.PGM CHILD.PGM concatenates
validated, complete PGM files for a streaming bootstrap. The prefix remains
an ordinary loadable PGM; the bootstrap loads the following child itself.
Each header and relocation table is preserved byte-for-byte. Both options
are implemented in the native linker and work equally on all platforms.
UniAR uses the original 0BB0 UniLIB format, preserving each member OBJ
byte-for-byte. Operations are r create/replace, a append without replacing,
d delete, t list and x extract. Member names are uppercase, eight
characters, padded with spaces; they are not Unix ar names. Up to 256
members and @list input are supported. Linker output, archive updates and
extracted members are published through temporary files; a failed operation
preserves the old destination.
make all pyldin test builds and tests all four tools. Native outputs are
pyldin/UNIAS.CMD, UNICC.CMD, UNILD.CMD and UNIAR.CMD. Expand the UniDOS
handle table with HANDLES 16 before RAMLOAD /CVM for large assemblies.
The assembler uses a bounded symbol pool and a small shared-prefix dictionary;
XONIX fits without occupying a second RAMMAN bank.
tests/test_objects.py checks PGM/BSS, byte and word relocations, CMD/page
alignment, legacy UniCROSS and UniLIB fixtures, archive replacement/deletion/
extraction, a library larger than 64 KiB, and invalid/truncated inputs.
The pyldin601-fpga suite additionally executes the original native ULINK and
compares native UniCC/UniAS/UniLD/UniAR outputs with host outputs.
The historical ULINK binary has a defect resolving absolute PUBLIC values;
UniLD retains their full 16-bit value. Avoid that historical defect when
comparing old ULINK outputs. Native tests use fresh ULINK output names.
The reference ULINK also underallocates PGM relocation space for a library member with internal relocations (reproduced with original UniLIB output). Its PGM outputs with byte-only relocations may contain harmless padding between the relocation table and code. Tests compare loaded code, relocation entries, entry point and BSS in that case. The separate no-internal-relocation library case has identical loaded contents; UniLD correctly links both kinds.
unicc -c -o PART.ASM PART.C emits module ASM for unias -c, with
PUBLIC/EXTERN declarations and relative BSS. extern variables/arrays,
empty K&R function declarations, typed K&R definitions and file static
are supported. The existing eight-character identifier limit is retained.
Compiler errors now return a failure status; module source errors preserve
an existing output ASM. .UCT is reserved for the module body temporary.
unicc -c -o MAIN.ASM MAIN.C
unicc -c -o HELP.ASM HELP.C
unias -c -o MAIN.OBJ MAIN.ASM
unias -c -o HELP.OBJ HELP.ASM
unild -o APP.PGM CSTART.OBJ MAIN.OBJ HELP.OBJ CRT.LIB
uniar r UTIL.LIB HELP.OBJ
unild -o APP.PGM CSTART.OBJ MAIN.OBJ UTIL.LIB CRT.LIB
scvm APP.PGM
scvm -b 0x8000 APP.PGM
Use runtime objects/headers from pyldin/ for the FPGA target. CSTART must
be first and CRT.LIB last: they bound and clear the combined BSS using the
existing OBJ format. Legacy complete-CMD compilation remains available.
The compiler still emits ASM; each tool remains a separate native CMD.
Function addresses are ordinary relocated 16-bit VM entry addresses.
C-visible native wrappers begin with DB 86 and return using JMP RTSC.
The new FPGA INT EF A=2 / native cvcall entry accepts a function/argument
pointer descriptor and returns a 16-bit result, with no argc/argv setup.
It preserves the parent VM context for recursive C/native/C callbacks.
All three CPU ROMs keep the existing query/program-entry ABI and VM scratch
layout. Old Lilith E8 entry remains supported. The host VM loads linked
PGMs but still rejects arbitrary machine-code inserts; mixed execution is
verified on the FPGA project's CPU harness.
CVMOBJ.TXT specifies commands, storage/linkage rules, call
frames, descriptor layout, bounds, errors, host limitations and the test
plan. tests/test_cmodules.py covers linking and execution; the FPGA
test-c-modules compares native ASM/OBJ/LIB/PGM/maps on both models/CPUs.
It also executes the original ULINK against C objects and a compatible
library case. Its existing documented defects are not hidden.
The FPGA UNIAS.CMD reserves 13000 bytes of conventional symbol storage. Its overflow pool uses the unused CC10..DEFF range in the same pinned VM bank (4848 bytes); it does not allocate another RAMMAN bank. All three CPU ROMs advertise this writable scratch area with a VW/version-1 descriptor at CC00. The interpreter rejects a build that would overlap the descriptor. The arena is temporary, shared by invocations, and is not preserved across nested VM applications. UniAS does not invoke child C applications.
Host and default/Lilith UniAS retain 16200 bytes in conventional RAM. The EPROM target does not advertise writable ROM storage. Older FPGA VM ROMs remain usable for smaller assemblies with the 13000-byte main pool; update all three FPGA ROM files and reload/reset the resident VM for large assemblies. The symbol walks, PUBLIC/EXTERN output and BSS rebasing handle both pools.
The FPGA HG regression mounts the real resident HG.PGM against the C host folder backend, loads the VM and tools from HG/CVM, and compares all OBJ, LIB and PGM outputs with cross builds. It also assembles XONIX directly and as modules while checking that the VM-bank pool is used and its descriptor is intact. This catches a CMD that fits on SD but cannot load alongside HG.