ORCA/C is no longer used at all.

This commit is contained in:
Scott Duensing 2026-06-25 02:41:37 -05:00
parent 181516c32a
commit c745821c7d
14 changed files with 24150 additions and 22517 deletions

View file

@ -79,6 +79,7 @@ fi
"$PROJECT_ROOT/runtime/softDouble.o" \ "$PROJECT_ROOT/runtime/softDouble.o" \
"$PROJECT_ROOT/runtime/iigsGsos.o" \ "$PROJECT_ROOT/runtime/iigsGsos.o" \
"$PROJECT_ROOT/runtime/iigsToolbox.o" \ "$PROJECT_ROOT/runtime/iigsToolbox.o" \
"$PROJECT_ROOT/runtime/iigsToolboxExtra.o" \
"$PROJECT_ROOT/runtime/desktop.o" \ "$PROJECT_ROOT/runtime/desktop.o" \
"$PROJECT_ROOT/runtime/sound.o" \ "$PROJECT_ROOT/runtime/sound.o" \
"$PROJECT_ROOT/runtime/cursor.o" \ "$PROJECT_ROOT/runtime/cursor.o" \

View file

@ -98,7 +98,7 @@ fi
"$RT/libc.o" "$RT/snprintf.o" "$RT/extras.o" \ "$RT/libc.o" "$RT/snprintf.o" "$RT/extras.o" \
"$RT/softFloat.o" "$RT/softDouble.o" \ "$RT/softFloat.o" "$RT/softDouble.o" \
"$RT/math.o" \ "$RT/math.o" \
"$RT/iigsToolbox.o" \ "$RT/iigsToolbox.o" "$RT/iigsToolboxExtra.o" \
"$RT/libgcc.o" \ "$RT/libgcc.o" \
"$RT/libcxxabi.o" "$RT/libcxxabiSjlj.o" "$RT/libunwindStub.o" "$RT/libcxxabi.o" "$RT/libcxxabiSjlj.o" "$RT/libunwindStub.o"

View file

@ -23,7 +23,7 @@ After install, the `llvm816/` directory tree contains everything:
| `tools/llvm-mos-build/` | 1.4 GB | Compiled clang/llc/llvm-mc binaries. This is where you actually run the compiler from. | | `tools/llvm-mos-build/` | 1.4 GB | Compiled clang/llc/llvm-mc binaries. This is where you actually run the compiler from. |
| `tools/llvm-mos-sdk/` | 400 MB | Prebuilt llvm-mos SDK (the original 6502 distribution). Mostly unused by us; kept as a reference baseline. | | `tools/llvm-mos-sdk/` | 400 MB | Prebuilt llvm-mos SDK (the original 6502 distribution). Mostly unused by us; kept as a reference baseline. |
| `tools/calypsi/` | 580 MB | Commercial Calypsi 5.16 65816 C compiler — installed for output-quality comparisons in `compare/`. | | `tools/calypsi/` | 580 MB | Commercial Calypsi 5.16 65816 C compiler — installed for output-quality comparisons in `compare/`. |
| `tools/orca-c/` | 10 MB | Apple's official ORCA/C compiler source — header reference for the IIgs Toolbox bindings. | | `tools/nlist/` | 68 KB | Dave Lyons' NiftyList toolbox catalog (`NList.Data.txt`). Source of truth for the IIgs toolbox bindings auto-generated into `runtime/include/iigs/toolbox.h`. |
| `tools/gsos/` | 13 MB | Apple GS/OS 6.0.2 / 6.0.4 disk images for booting under MAME. | | `tools/gsos/` | 13 MB | Apple GS/OS 6.0.2 / 6.0.4 disk images for booting under MAME. |
| `tools/mame/roms/` | 1.5 MB | Apple IIgs ROM 01 + ROM 03 (downloaded from archive.org). | | `tools/mame/roms/` | 1.5 MB | Apple IIgs ROM 01 + ROM 03 (downloaded from archive.org). |
| **Total** | **~7-8 GB** | | | **Total** | **~7-8 GB** | |
@ -104,7 +104,7 @@ That's it. `setup.sh` runs five stages in order:
| 2/5 | `installLlvmMos.sh` | Clone `llvm-mos` source (5 GB), download prebuilt llvm-mos SDK (400 MB), **apply our W65816 backend** (symlinks + patches), **build clang/llc/llvm-mc with W65816 target enabled**, **build `link816` + `omfEmit`**, and **build the runtime libraries** (`libc.o`, `crt0.o`, `libgcc.o`, soft-float, etc.). After this stage you have a working W65816 toolchain end-to-end. | ~30-60 min (first time; LLVM build is the long pole) | | 2/5 | `installLlvmMos.sh` | Clone `llvm-mos` source (5 GB), download prebuilt llvm-mos SDK (400 MB), **apply our W65816 backend** (symlinks + patches), **build clang/llc/llvm-mc with W65816 target enabled**, **build `link816` + `omfEmit`**, and **build the runtime libraries** (`libc.o`, `crt0.o`, `libgcc.o`, soft-float, etc.). After this stage you have a working W65816 toolchain end-to-end. | ~30-60 min (first time; LLVM build is the long pole) |
| 3/5 | `installMame.sh` | Install MAME via apt, download `apple2gs.zip` (ROM 03) and `apple2gsr1.zip` (ROM 01) into `tools/mame/roms/`. | ~30 s | | 3/5 | `installMame.sh` | Install MAME via apt, download `apple2gs.zip` (ROM 03) and `apple2gsr1.zip` (ROM 01) into `tools/mame/roms/`. | ~30 s |
| 4/5 | `installCalypsi.sh` | Download Calypsi 5.16 .deb, extract its payload into `tools/calypsi/` (no system-wide install). | ~30 s | | 4/5 | `installCalypsi.sh` | Download Calypsi 5.16 .deb, extract its payload into `tools/calypsi/` (no system-wide install). | ~30 s |
| 5/5 | `installOrcaC.sh` | Shallow clone of byteworksinc's ORCA/C repo into `tools/orca-c/` for toolbox header reference. | ~15 s | | 5/5 | `installGno.sh` | Fetch GNO/ME 2.0.6 + GS/OS 6.0.4 disk images for shell-command testing under MAME. | ~30 s |
After each stage, the script prints `=== N/5 stage-name ===` so you After each stage, the script prints `=== N/5 stage-name ===` so you
can follow progress. At the end it runs `verify.sh` which sanity- can follow progress. At the end it runs `verify.sh` which sanity-
@ -131,7 +131,6 @@ LLVM build didn't include the W65816 target. Re-run
| `--skip-llvm` | Skip the LLVM clone + build + runtime. Useful for iterating on other parts. | | `--skip-llvm` | Skip the LLVM clone + build + runtime. Useful for iterating on other parts. |
| `--skip-mame` | Skip MAME + ROM download. | | `--skip-mame` | Skip MAME + ROM download. |
| `--skip-calypsi` | Skip Calypsi (saves 580 MB if you don't need the comparison benchmarks). | | `--skip-calypsi` | Skip Calypsi (saves 580 MB if you don't need the comparison benchmarks). |
| `--skip-orca` | Skip ORCA/C (saves ~10 MB; only needed if you regenerate `iigs/toolbox.h`). |
| `--skip-verify` | Don't run the post-install verification check. | | `--skip-verify` | Don't run the post-install verification check. |
| `--verify-only` | Just run the verification check, don't install anything. | | `--verify-only` | Just run the verification check, don't install anything. |
| `--build-llvm` | Deprecated alias — the LLVM build is now always part of stage 2/5 (without it we wouldn't have a usable W65816 compiler). | | `--build-llvm` | Deprecated alias — the LLVM build is now always part of stage 2/5 (without it we wouldn't have a usable W65816 compiler). |
@ -182,7 +181,7 @@ llvm816/ ← your repo checkout
├── omfEmit (~70 KB) — OMF v2.1 emitter for GS/OS Loader ├── omfEmit (~70 KB) — OMF v2.1 emitter for GS/OS Loader
├── cadius/ — Apple ProDOS / GS/OS disk image tool ├── cadius/ — Apple ProDOS / GS/OS disk image tool
├── calypsi/ (580 MB) — Calypsi 5.16 reference compiler ├── calypsi/ (580 MB) — Calypsi 5.16 reference compiler
├── orca-c/ (10 MB) — ORCA/C compiler (header reference) ├── nlist/ (68 KB) — NList.Data (toolbox-binding catalog)
├── gsos/ (13 MB) — GS/OS 6.0.2 / 6.0.4 disk images ├── gsos/ (13 MB) — GS/OS 6.0.2 / 6.0.4 disk images
├── mame/ ├── mame/
│ └── roms/ (1.5 MB) — apple2gs ROM 01 + ROM 03 │ └── roms/ (1.5 MB) — apple2gs ROM 01 + ROM 03
@ -240,12 +239,11 @@ bash scripts/installLlvmMos.sh # llvm-mos clone + prebuilt SDK
bash scripts/installLlvmMos.sh --build # also build clang/llc (slow) bash scripts/installLlvmMos.sh --build # also build clang/llc (slow)
bash scripts/installMame.sh # MAME + apple2gs ROMs bash scripts/installMame.sh # MAME + apple2gs ROMs
bash scripts/installCalypsi.sh # reference compiler (optional) bash scripts/installCalypsi.sh # reference compiler (optional)
bash scripts/installOrcaC.sh # reference compiler (optional)
bash scripts/verify.sh # sanity-check everything bash scripts/verify.sh # sanity-check everything
``` ```
If you only want to *build* C programs (no benchmarks, no comparisons), If you only want to *build* C programs (no benchmarks, no comparisons),
`installCalypsi.sh` and `installOrcaC.sh` are skippable. `installCalypsi.sh` is skippable.
### Building W65816 clang from source ### Building W65816 clang from source
@ -315,7 +313,7 @@ If you want a fully clean rebuild (e.g., to chase a "stale .o" bug):
```bash ```bash
rm -rf tools/llvm-mos-build rm -rf tools/llvm-mos-build
./setup.sh --skip-deps --skip-mame --skip-calypsi --skip-orca ./setup.sh --skip-deps --skip-mame --skip-calypsi
``` ```
--- ---

View file

@ -68,7 +68,7 @@ llvm816/ ← repo root; everything is contained here
│ ├── mame/ ← Apple IIgs ROMs for MAME │ ├── mame/ ← Apple IIgs ROMs for MAME
│ ├── gsos/ ← GS/OS 6.0.2 / 6.0.4 disk images │ ├── gsos/ ← GS/OS 6.0.2 / 6.0.4 disk images
│ ├── calypsi/ ← reference compiler for comparison (~580 MB) │ ├── calypsi/ ← reference compiler for comparison (~580 MB)
│ └── orca-c/ ← reference compiler (header sources) │ └── nlist/ ← NList.Data toolbox-binding catalog
├── demos/ ← example IIgs programs ├── demos/ ← example IIgs programs
├── benchmarks/ ← cycle-count benchmarks ├── benchmarks/ ← cycle-count benchmarks
├── compare/ ← side-by-side ours-vs-Calypsi assembly ├── compare/ ← side-by-side ours-vs-Calypsi assembly

View file

@ -79,6 +79,11 @@ cc "$SRC/uiBuilder.c"
cc "$SRC/resource.c" cc "$SRC/resource.c"
asm "$SRC/iigsGsos.s" asm "$SRC/iigsGsos.s"
asm "$SRC/iigsToolbox.s" asm "$SRC/iigsToolbox.s"
# Hand-written wrappers that don't fit genToolbox.py's standard shape
# (struct-returning toolbox calls, etc.). Linked alongside the auto-
# generated iigsToolbox.s so a `python3 scripts/genToolbox.py` regen
# doesn't clobber them. See runtime/src/iigsToolboxExtra.s.
asm "$SRC/iigsToolboxExtra.s"
# softDouble.c builds at -O2. dpack is noinline to dodge a backend # softDouble.c builds at -O2. dpack is noinline to dodge a backend
# stack-slot aliasing bug; dclass stays inline because pointer-arg # stack-slot aliasing bug; dclass stays inline because pointer-arg
# stores from a noinline boundary use DBR-relative addressing (broken # stores from a noinline boundary use DBR-relative addressing (broken

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,56 @@
; iigsToolboxExtra.s — hand-written toolbox wrappers that don't fit the
; standard genToolbox.py shape and therefore aren't auto-generated.
; Anything in this file is preserved across regenerations of
; iigsToolbox.s.
;
; Keep it small. Each wrapper should justify its custom existence in
; the leading comment block (typically: struct-returning toolbox call
; whose Pascal-on-stack result needs explicit memcpy into a caller
; buffer).
.text
; iigsReadTimeHex(unsigned char *buf8) -> void
; tool 0x0D03, set 0x03 (MiscTools). Returns 8 bytes of broken-down
; time via a stack-allocated result area: second, minute, hour, (pad),
; year-1900, day, month, weekday. ORCA's misctool.h declares this as
; returning a TimeRec struct, so genToolbox.py skips it (no inline()
; macro on the prototype). We expose a C-friendly wrapper that copies
; the 8 bytes into a caller-provided buffer.
;
; ABI: arg0 (the destination pointer) arrives in A/X (lo word in A,
; hi word in X), matching the LLVM W65816 first-arg-in-AX convention.
; We stash A/X to DP $E0..$E3 to form a 32-bit pointer and use
; sta [dp],y (DP-indirect-long-Y) so writes reach the buffer's bank.
.section .text.iigsReadTimeHex,"ax"
.globl iigsReadTimeHex
iigsReadTimeHex:
; --- stash arg0 (destination pointer) at DP $E0..$E3 ---
sta 0xE0 ; A -> $E0:$E1 (lo16 of pointer)
stx 0xE2 ; X -> $E2:$E3 (hi16; only $E2 = bank used)
; --- 8-byte result space (4 words) ---
pea 0
pea 0
pea 0
pea 0
ldx #0x0D03
jsl 0xe10000
; --- copy 8 bytes from stack into the caller's buffer ---
; PLA at M=16 pops the 4 result words in reverse push order, which
; is the same order as the TimeRec layout (lowest-addr word first).
ldy #0
pla
sta [0xE0], y ; bytes 0,1: second, minute
iny
iny
pla
sta [0xE0], y ; bytes 2,3: hour, pad
iny
iny
pla
sta [0xE0], y ; bytes 4,5: year-1900, day
iny
iny
pla
sta [0xE0], y ; bytes 6,7: month, weekday
rtl

View file

@ -1,29 +1,25 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# genToolbox.py — generate IIgs toolbox wrappers from ORCA-C headers. # genToolbox.py — generate IIgs toolbox wrappers from NList.Data.
# #
# Reads ORCA's extern declarations of the form: # Reads Dave Lyons' NiftyList database (`tools/nlist/NList.Data.txt`),
# extern pascal RetType FuncName(ArgType, ArgType) inline(0xNNTT, dispatcher); # which catalogues every IIgs toolbox call and GS/OS call with tool
# and emits two outputs: # number, parameter sizes, and return-value size. Emits two outputs:
# - C header with `static inline` wrappers using clang inline-asm # - C header with `static inline` wrappers using clang inline-asm
# - .s file with extern wrapper bodies for multi-arg routines that # - .s file with extern wrapper bodies for multi-arg routines that
# can't fit in inline asm (our backend's constraints don't take # can't fit in inline asm (our backend's constraints don't take
# memory operands). # memory operands).
# #
# Tool number convention: 0xNNTT high byte = function, low byte = tool set # NList line format (see tools/nlist/README.md):
# Dispatcher: JSL $E10000 for normal toolbox; JSL $E100A8 for GS/OS # TTTT [NS:]FuncName([N:]arg[/sz], ...)[:ret[/sz]]
# (only the ProDOS-16 / GS/OS calls use _CallBackVector).
# #
# Calling convention conversion: ORCA uses Pascal (args pushed L-to-R), # Tool number convention: TTTT loaded into X; low byte = tool-set,
# our C ABI passes arg0 in A and arg1+ on stack RTL. Each generated # high byte = function code. Dispatcher: JSL $E10000 for normal
# wrapper re-pushes args in toolbox order. # toolbox; JSL $E100A8 for GS/OS (entries prefixed `GS/OS:`).
# #
# Type widths (matching ORCA): # Calling convention: C ABI passes arg0 (i16) in A, arg0 (i32) in A:X,
# Word, Boolean, Integer, Char, Byte = 2 bytes (16-bit) # arg1+ on stack RTL. Each generated wrapper re-pushes args in toolbox
# LongWord, Long, Handle, Pointer = 4 bytes (32-bit) # (Pascal-style L-to-R) order, with result space first (if any), then
# Ptr, Ref, ResType = 4 bytes # JSL the dispatcher, then pops result.
# (Pointer is 4 bytes in ORCA -- it's a far/24-bit pointer. Our backend
# uses 16-bit pointers, but the toolbox expects 32-bit on the stack;
# we extend with a zero high word.)
# #
# Output files are written to the runtime tree. # Output files are written to the runtime tree.
@ -31,7 +27,7 @@ import re
import sys import sys
from pathlib import Path from pathlib import Path
ORCA_DIR = Path("/home/scott/claude/llvm816/tools/orca-c/ORCACDefs") NLIST_PATH = Path("/home/scott/claude/llvm816/tools/nlist/NList.Data.txt")
OUT_HEADER = Path("/home/scott/claude/llvm816/runtime/include/iigs/toolbox.h") OUT_HEADER = Path("/home/scott/claude/llvm816/runtime/include/iigs/toolbox.h")
OUT_ASM = Path("/home/scott/claude/llvm816/runtime/src/iigsToolbox.s") OUT_ASM = Path("/home/scott/claude/llvm816/runtime/src/iigsToolbox.s")
@ -106,32 +102,128 @@ TOOLSET_NAME = {
} }
def parseLine(line): # NList default sizes. Pointer (`@name`) is 4 bytes; an explicit `/N`
"""Parse `extern pascal RetType Name(args) inline(0xNNTT, dispatcher);` # suffix overrides. Also: a handle abbreviation (bare `H`, or any
Returns dict or None if not a toolbox decl. # trailing capital `H` on a short name like `StateH`, `MsgH`) is 4
# bytes — that's NList's convention for `:H`-style return values
# (NewHandle, GetMsgHandle, SaveTextState all use it). Everything
# else defaults to 2 bytes (Word).
_HANDLE_SHORTHAND_RE = re.compile(r"^[A-Z][a-zA-Z]*H$")
def parseSize(rawName):
"""Strip a trailing /N size suffix and return (bareName, size, isPtr).
isPtr is True when the source spelling implied a pointer/handle (the
`@` prefix or an `H`-shorthand for handle); the generator then picks
`void *` rather than `unsigned long` as the C type.
""" """
m = re.match( rawName = rawName.strip()
r'^\s*extern\s+pascal\s+(\w+)\s+(\w+)\s*\((.*?)\)\s+inline\(0x([0-9A-Fa-f]+)\s*,\s*(\w+)\)\s*;', if not rawName:
line, return ("", 0, False)
) sz = None
m = re.search(r"/(\d+)$", rawName)
if m:
sz = int(m.group(1))
rawName = rawName[: m.start()].strip()
isPtr = rawName.startswith("@")
if isPtr:
rawName = rawName[1:]
isHandle = rawName == "H" or bool(_HANDLE_SHORTHAND_RE.match(rawName))
if sz is None:
if isPtr:
sz = 4
elif isHandle:
sz = 4
else:
sz = 2
return (rawName, sz, isPtr or (sz == 4 and isHandle))
_ENTRY_RE = re.compile(
r"^([0-9A-Fa-f]{4})\s+"
r"(?:(GS/OS|P8|P16|Shell|\w+:[\w/]+):)?" # optional namespace prefix(es)
r"(\w+)\s*" # function name
r"\(([^)]*)\)" # arg list
r"(?::([^,\s]+(?:,[^,\s]+)*))?\s*$" # optional :ret(,ret2,...)
)
def parseLine(line):
"""Parse an NList.Data line into a toolbox decl dict.
Returns None for comments, section dividers, unfilled stubs, or
non-toolbox namespaces (P8 / P16 / Shell).
"""
line = line.rstrip()
if not line:
return None
# Comment forms: `* ...`, `fff9 | ...`, `TTTT === name ===`.
head4 = line[:4]
rest = line[4:].lstrip() if len(line) > 4 else ""
if not re.fullmatch(r"[0-9A-Fa-f]{4}", head4):
return None
if rest.startswith("|") or rest.startswith("==="):
return None
if rest.startswith("(...)") or "(...)" in rest:
return None
# Filter by namespace. Standard toolbox calls have no prefix.
# GS/OS calls have `GS/OS:` and dispatch via $E100A8. Skip P8/P16/
# Shell — they use other dispatchers we don't currently expose.
dispatcher = "dispatcher" # → JSL $E10000
nsMatch = re.match(r"^([A-Za-z][\w/]*):", rest)
if nsMatch:
ns = nsMatch.group(1)
if ns == "GS/OS":
dispatcher = "_CallBackVector" # → JSL $E100A8
rest = rest[nsMatch.end():]
elif ns in ("P8", "P16", "Shell"):
return None
else:
# Sub-prefix like `P8:ATLK:...` — already filtered above by
# the outer P8; anything else unknown gets skipped.
return None
m = re.match(r"^(\w+)\s*\(([^)]*)\)(.*)$", rest)
if not m: if not m:
return None return None
retType, name, args, toolHex, dispatcher = m.group(1, 2, 3, 4, 5) name, argsRaw, tail = m.group(1, 2, 3)
toolNum = int(toolHex, 16) toolNum = int(head4, 16)
# Return type lives after `:`. Strip optional leading whitespace.
# Multi-value returns (e.g. `:Created,Type`) sum sizes; if any
# element looked pointer-ish, the overall return type is `void *`
# (handle-style returns are the dominant 4-byte case).
retSize = 0
retIsPtr = False
tail = tail.strip()
if tail.startswith(":"):
retSpec = tail[1:].strip()
for r in retSpec.split(","):
_, sz, isPtr = parseSize(r)
retSize += sz
retIsPtr = retIsPtr or isPtr
# Arg list: strip optional leading arg-count `N:` (e.g. `1-7:` or
# `4or84:`) and split on commas.
argsRaw = argsRaw.strip()
if ":" in argsRaw:
head, sep, body = argsRaw.partition(":")
if re.fullmatch(r"[\d\-or ]+", head.strip()):
argsRaw = body.strip()
argSpec = []
if argsRaw and argsRaw != "void":
for a in argsRaw.split(","):
_, sz, isPtr = parseSize(a)
if sz == 0:
return None
argSpec.append((sz, isPtr))
# Parse arg types (just the types, no names since ORCA omits them).
args = args.strip()
argTypes = []
if args and args != "void":
for a in args.split(","):
a = a.strip()
# ORCA may have type-only or "type name"; take the first word.
t = a.split()[0]
argTypes.append(t)
return { return {
"ret": retType,
"name": name, "name": name,
"args": argTypes, "argSpec": argSpec, # list of (size, isPtr)
"retSize": retSize,
"retIsPtr": retIsPtr,
"tool": toolNum, "tool": toolNum,
"dispatcher": dispatcher, "dispatcher": dispatcher,
} }
@ -145,14 +237,40 @@ def typeInfo(t):
return (4, "void *") return (4, "void *")
# Map an (NList byte size, isPtr) tuple to a (stack-size, c-type) tuple.
# NList only carries sizes — no semantic type names — so the generator
# picks a generic C type. isPtr=True (NList `@name` prefix or `H`
# shorthand) selects `void *` for 4-byte slots; otherwise 4-byte
# non-pointer args become `unsigned long` so the common
# `NewHandle(0x900UL, ...)` pattern compiles without a pointer cast.
def sizeInfo(sz, isPtr=False):
"""Return (effective-size, c-type) for an NList byte size."""
if sz == 0:
return (0, "void")
if sz == 1:
return (2, "unsigned char") # widened on stack
if sz == 2:
return (2, "unsigned short")
if sz == 3:
return (4, "unsigned long") # rare; widened to 4
if sz == 4:
return (4, "void *" if isPtr else "unsigned long")
if sz == 8:
return (8, "long long")
if sz == 10:
return (10, "long double")
return (4, "void *")
def emit(decls): def emit(decls):
"""Generate C header and .s file from parsed decls.""" """Generate C header and .s file from parsed decls."""
cLines = [ cLines = [
"// AUTOGENERATED by scripts/genToolbox.py from ORCA-C ORCACDefs/.", "// AUTOGENERATED by scripts/genToolbox.py from NList.Data.",
"// DO NOT EDIT by hand — regenerate to update.", "// DO NOT EDIT by hand — regenerate to update.",
"// Source: tools/nlist/NList.Data.txt (Dave Lyons' NiftyList database).",
"//", "//",
"// Complete IIgs toolbox: ~1300 routines across 35 tool sets.", "// Complete IIgs toolbox + GS/OS surface (~2000 routines).",
"// Names match Apple's IIgs Toolbox Reference (TLStartUp,", "// Names match Apple's IIgs Toolbox Reference (TLStartUp,",
"// MMStartUp, NewWindow, SysBeep, etc.). Multi-arg wrappers", "// MMStartUp, NewWindow, SysBeep, etc.). Multi-arg wrappers",
"// (those whose stub body uses memory operands) live in", "// (those whose stub body uses memory operands) live in",
@ -177,8 +295,9 @@ def emit(decls):
] ]
sLines = [ sLines = [
"; AUTOGENERATED by scripts/genToolbox.py from ORCA-C ORCACDefs/.", "; AUTOGENERATED by scripts/genToolbox.py from NList.Data.",
"; DO NOT EDIT by hand — regenerate to update.", "; DO NOT EDIT by hand — regenerate to update.",
"; Source: tools/nlist/NList.Data.txt (Dave Lyons' NiftyList database).",
";", ";",
"; IIgs toolbox multi-arg wrappers.", "; IIgs toolbox multi-arg wrappers.",
";", ";",
@ -201,20 +320,36 @@ def emit(decls):
for d in decls: for d in decls:
name = d["name"] name = d["name"]
if name in seenNames: if name in seenNames:
continue # duplicate from header re-include, etc. continue # duplicate (e.g. P16 / GS/OS overload of same name).
seenNames.add(name) seenNames.add(name)
retType = d["ret"]
argTypes = d["args"]
tool = d["tool"] tool = d["tool"]
dispatcher = d["dispatcher"] dispatcher = d["dispatcher"]
# Check if all types are known. # Translate NList byte sizes into (effective-size, c-type) tuples
retSize, retC = typeInfo(retType) # the emit logic expects. argTypes is rebuilt for the diagnostic
argInfo = [typeInfo(a) for a in argTypes] # comment only. Pointer detection follows NList's signal: an
if any(ai is None for ai in argInfo): # `@name` prefix or `H`/`*H`-shorthand → `void *`; an explicit
skipped.append((name, "unknown arg type")) # `/4` without those markers → `unsigned long`. That matches
continue # how the NList catalog distinguishes integer Long/LongWord
# values (TickCount → :Ticks/4) from pointers/handles
# (NewHandle → :H, GetCursorAdr → :@Curs).
retSize, retC = sizeInfo(d["retSize"], d["retIsPtr"])
argInfo = [sizeInfo(sz, isPtr) for (sz, isPtr) in d["argSpec"]]
argTypes = [
"Pointer" if ai[1] == "void *" else
"LongWord" if ai[0] == 4 else
"Word" if ai[0] == 2 else
f"{ai[0]}B"
for ai in argInfo
]
retType = (
"Pointer" if retC == "void *" else
"LongWord" if retSize == 4 else
"Word" if retSize == 2 else
"void" if retSize == 0 else
f"{retSize}B"
)
# Build C-style arg list. # Build C-style arg list.
cArgs = ", ".join(f"{ai[1]} a{i}" for i, ai in enumerate(argInfo)) cArgs = ", ".join(f"{ai[1]} a{i}" for i, ai in enumerate(argInfo))
@ -448,12 +583,14 @@ def emit(decls):
def main(): def main():
decls = [] decls = []
for h in sorted(ORCA_DIR.glob("*.h")): if not NLIST_PATH.exists():
for line in h.read_text().splitlines(): print(f"error: {NLIST_PATH} not found", file=sys.stderr)
d = parseLine(line) sys.exit(1)
if d: for line in NLIST_PATH.read_text().splitlines():
decls.append(d) d = parseLine(line)
print(f"parsed {len(decls)} declarations from {ORCA_DIR}") if d:
decls.append(d)
print(f"parsed {len(decls)} declarations from {NLIST_PATH}")
emit(decls) emit(decls)

View file

@ -1,19 +0,0 @@
#!/usr/bin/env bash
# Clone ORCA/C as an on-disk reference. It's an on-machine compiler — we only
# need the source to study codegen choices, not to build.
set -euo pipefail
source "$(dirname "$0")/common.sh"
ORCA_DIR="$TOOLS_DIR/orca-c"
ORCA_URL="https://github.com/byteworksinc/ORCA-C.git"
if [ -d "$ORCA_DIR/.git" ]; then
log "orca-c already cloned; pulling latest"
git -C "$ORCA_DIR" pull --ff-only
else
log "cloning ORCA/C reference source"
git clone --depth=1 "$ORCA_URL" "$ORCA_DIR"
fi
log "orca-c reference at $ORCA_DIR"

View file

@ -5526,8 +5526,8 @@ EOF
# real ROM dispatcher, smoke runs in bare-CPU mode); just check # real ROM dispatcher, smoke runs in bare-CPU mode); just check
# the codegen. # the codegen.
# iigs/toolbox.h — autogenerated wrappers for the entire IIgs # iigs/toolbox.h — autogenerated wrappers for the entire IIgs
# toolbox (~1300 routines from 35 tool sets, sourced from ORCA-C # toolbox (~1900 routines from 35 tool sets, sourced from Dave
# ORCACDefs/ via scripts/genToolbox.py). Names match Apple's # Lyons' NList.Data via scripts/genToolbox.py). Names match Apple's
# IIgs Toolbox Reference (TLStartUp, MMStartUp, NewWindow, # IIgs Toolbox Reference (TLStartUp, MMStartUp, NewWindow,
# SysBeep, ...). Verify the header compiles, the multi-arg # SysBeep, ...). Verify the header compiles, the multi-arg
# asm bodies in iigsToolbox.s assemble, and that linking # asm bodies in iigsToolbox.s assemble, and that linking
@ -5567,7 +5567,7 @@ EOF
if ! grep -qE '\bjsl\s+0xe10000\b' "$sToolFile"; then if ! grep -qE '\bjsl\s+0xe10000\b' "$sToolFile"; then
die "iigs/toolbox.h: JSL \$E10000 (Tool Locator) not emitted" die "iigs/toolbox.h: JSL \$E10000 (Tool Locator) not emitted"
fi fi
# SysBeep tool number $2C03 per ORCA (function $2C of Misc Tools $03). # SysBeep tool number $2C03 (function $2C of Misc Tools $03).
# Match case-insensitively — clang lowercases hex constants. # Match case-insensitively — clang lowercases hex constants.
if ! grep -qiE '\bldx\s+#0x2c03\b' "$sToolFile"; then if ! grep -qiE '\bldx\s+#0x2c03\b' "$sToolFile"; then
die "iigs/toolbox.h: SysBeep tool number 0x2C03 not in output" die "iigs/toolbox.h: SysBeep tool number 0x2C03 not in output"
@ -6496,7 +6496,7 @@ EOF
"$PROJECT_ROOT/runtime/softFloat.o" \ "$PROJECT_ROOT/runtime/softFloat.o" \
"$PROJECT_ROOT/runtime/softDouble.o" \ "$PROJECT_ROOT/runtime/softDouble.o" \
"$PROJECT_ROOT/runtime/iigsGsos.o" \ "$PROJECT_ROOT/runtime/iigsGsos.o" \
"$PROJECT_ROOT/runtime/iigsToolbox.o" \ "$PROJECT_ROOT/runtime/iigsToolbox.o" "$PROJECT_ROOT/runtime/iigsToolboxExtra.o" \
"$PROJECT_ROOT/runtime/libgcc.o" 2>/tmp/gsosfopen-link.err >/dev/null \ "$PROJECT_ROOT/runtime/libgcc.o" 2>/tmp/gsosfopen-link.err >/dev/null \
|| die "GS/OS file smoke: link failed: $(cat /tmp/gsosfopen-link.err)" || die "GS/OS file smoke: link failed: $(cat /tmp/gsosfopen-link.err)"
"$PROJECT_ROOT/tools/omfEmit" --input "$binGsf" --map "$mapGsf" \ "$PROJECT_ROOT/tools/omfEmit" --input "$binGsf" --map "$mapGsf" \
@ -6619,7 +6619,7 @@ EOF
"$PROJECT_ROOT/runtime/softFloat.o" \ "$PROJECT_ROOT/runtime/softFloat.o" \
"$PROJECT_ROOT/runtime/softDouble.o" \ "$PROJECT_ROOT/runtime/softDouble.o" \
"$PROJECT_ROOT/runtime/iigsGsos.o" \ "$PROJECT_ROOT/runtime/iigsGsos.o" \
"$PROJECT_ROOT/runtime/iigsToolbox.o" \ "$PROJECT_ROOT/runtime/iigsToolbox.o" "$PROJECT_ROOT/runtime/iigsToolboxExtra.o" \
"$PROJECT_ROOT/runtime/libgcc.o" 2>/tmp/stkprobe-link.err >/dev/null \ "$PROJECT_ROOT/runtime/libgcc.o" 2>/tmp/stkprobe-link.err >/dev/null \
|| die "stack-size smoke: link failed: $(cat /tmp/stkprobe-link.err)" || die "stack-size smoke: link failed: $(cat /tmp/stkprobe-link.err)"
# WITH --stack-size 0x4000 (16 KB chunk; Loader places at $0800, # WITH --stack-size 0x4000 (16 KB chunk; Loader places at $0800,

View file

@ -60,10 +60,9 @@ if [ -d "$TOOLS_DIR/calypsi" ]; then
test -x "$TOOLS_DIR/calypsi/usr/local/lib/calypsi-65816-5.16/bin/cc65816" test -x "$TOOLS_DIR/calypsi/usr/local/lib/calypsi-65816-5.16/bin/cc65816"
fi fi
# ORCA/C reference (optional; --skip-orca skips this). # Toolbox bindings come from NList.Data (Dave Lyons' NiftyList catalog
if [ -d "$TOOLS_DIR/orca-c" ]; then # at tools/nlist/NList.Data.txt) — no ORCA/OPUS source required.
check "orca-c source" test -d "$TOOLS_DIR/orca-c/.git" check "nlist data" test -s "$PROJECT_ROOT/tools/nlist/NList.Data.txt"
fi
# End-to-end smoke: compile a tiny C program for W65816 to prove the # End-to-end smoke: compile a tiny C program for W65816 to prove the
# toolchain actually produces machine code. # toolchain actually produces machine code.

View file

@ -2,23 +2,25 @@
# Top-level installer for the llvm816 project. Installs everything into # Top-level installer for the llvm816 project. Installs everything into
# ./tools/ so the tree is self-contained and deletable. # ./tools/ so the tree is self-contained and deletable.
# #
# Stages (6/6): # Stages (5/5):
# 1. apt dependencies # 1. apt dependencies
# 2. llvm-mos clone + W65816 backend apply + cmake/ninja build of # 2. llvm-mos clone + W65816 backend apply + cmake/ninja build of
# clang/llc/llvm-mc + build link816/omfEmit + build runtime (.o) # clang/llc/llvm-mc + build link816/omfEmit + build runtime (.o)
# 3. MAME + apple2gs ROMs # 3. MAME + apple2gs ROMs
# 4. Calypsi 5.16 (reference compiler — optional) # 4. Calypsi 5.16 (reference compiler — optional)
# 5. ORCA/C source (header reference — optional) # 5. GNO/ME 2.0.6 + GS/OS 6.0.4 (shell-command runtime — optional;
# 6. GNO/ME 2.0.6 + GS/OS 6.0.4 (shell-command runtime — optional;
# cadius + .shk archives + system disks for runInGno.sh) # cadius + .shk archives + system disks for runInGno.sh)
# #
# Toolbox bindings (iigs/toolbox.h) are generated from NList.Data — a
# non-ORCA, non-OPUS toolbox database checked into tools/nlist/. No
# Byte Works / ORCA / OPUS sources are required or installed.
#
# Usage: # Usage:
# ./setup.sh # install + build everything (~30-60 min) # ./setup.sh # install + build everything (~30-60 min)
# ./setup.sh --skip-deps # skip apt packages # ./setup.sh --skip-deps # skip apt packages
# ./setup.sh --skip-llvm # skip stage 2 (clang/runtime/link816) # ./setup.sh --skip-llvm # skip stage 2 (clang/runtime/link816)
# ./setup.sh --skip-mame # skip MAME + ROM fetch # ./setup.sh --skip-mame # skip MAME + ROM fetch
# ./setup.sh --skip-calypsi # skip Calypsi # ./setup.sh --skip-calypsi # skip Calypsi
# ./setup.sh --skip-orca # skip ORCA/C reference
# ./setup.sh --skip-gno # skip GNO/ME + GS/OS 6.0.4 fetch # ./setup.sh --skip-gno # skip GNO/ME + GS/OS 6.0.4 fetch
# ./setup.sh --skip-verify # skip the post-install verification # ./setup.sh --skip-verify # skip the post-install verification
# ./setup.sh --verify-only # run verification only # ./setup.sh --verify-only # run verification only
@ -33,7 +35,6 @@ doDeps=1
doLlvm=1 doLlvm=1
doMame=1 doMame=1
doCalypsi=1 doCalypsi=1
doOrca=1
doGno=1 doGno=1
doVerify=1 doVerify=1
buildLlvm=0 buildLlvm=0
@ -45,7 +46,6 @@ for arg in "$@"; do
--skip-llvm) doLlvm=0 ;; --skip-llvm) doLlvm=0 ;;
--skip-mame) doMame=0 ;; --skip-mame) doMame=0 ;;
--skip-calypsi) doCalypsi=0 ;; --skip-calypsi) doCalypsi=0 ;;
--skip-orca) doOrca=0 ;;
--skip-gno) doGno=0 ;; --skip-gno) doGno=0 ;;
--skip-verify) doVerify=0 ;; --skip-verify) doVerify=0 ;;
--build-llvm) buildLlvm=1 ;; --build-llvm) buildLlvm=1 ;;
@ -85,17 +85,12 @@ if [ "$doMame" -eq 1 ]; then
fi fi
if [ "$doCalypsi" -eq 1 ]; then if [ "$doCalypsi" -eq 1 ]; then
log "=== 4/6 calypsi ===" log "=== 4/5 calypsi ==="
bash "$SCRIPT_DIR/scripts/installCalypsi.sh" bash "$SCRIPT_DIR/scripts/installCalypsi.sh"
fi fi
if [ "$doOrca" -eq 1 ]; then
log "=== 5/6 orca-c reference ==="
bash "$SCRIPT_DIR/scripts/installOrcaC.sh"
fi
if [ "$doGno" -eq 1 ]; then if [ "$doGno" -eq 1 ]; then
log "=== 6/6 gno/me + gs/os 6.0.4 ===" log "=== 5/5 gno/me + gs/os 6.0.4 ==="
bash "$SCRIPT_DIR/scripts/installGno.sh" bash "$SCRIPT_DIR/scripts/installGno.sh"
fi fi

View file

@ -50,7 +50,7 @@ echo "link: -> $BASE.bin"
"$RT/libc.o" "$RT/snprintf.o" "$RT/extras.o" \ "$RT/libc.o" "$RT/snprintf.o" "$RT/extras.o" \
"$RT/softFloat.o" "$RT/softDouble.o" \ "$RT/softFloat.o" "$RT/softDouble.o" \
"$RT/math.o" \ "$RT/math.o" \
"$RT/iigsToolbox.o" \ "$RT/iigsToolbox.o" "$RT/iigsToolboxExtra.o" \
"$RT/libgcc.o" \ "$RT/libgcc.o" \
"$RT/libcxxabi.o" "$RT/libcxxabiSjlj.o" "$RT/libcxxabi.o" "$RT/libcxxabiSjlj.o"