[← Home](../README.md) · [Toolchain](README.md) # SAS/C 6.x — Compiler Reference ## Overview SAS/C (originally Lattice C) was the dominant commercial C compiler for AmigaOS from the mid-1980s through the mid-1990s. Version **6.58** is the final release. It produces highly optimized 68k code with deep AmigaOS integration, including pragma-based system calls, SAS-specific debug formats, and a built-in profiler. Most existing Amiga source code and documentation assumes SAS/C conventions. Understanding its idioms is essential for working with legacy codebases. --- ## Key Features | Feature | Description | |---|---| | **Register args** | Automatic register parameter passing for small functions | | **Pragmas** | `#pragma libcall` for direct library LVO calls — no stub library needed | | **Small data model** | A4-relative addressing for global variables (faster, smaller code) | | **Large data model** | Absolute addressing for globals (no 64 KB limit) | | **Profiler** | Built-in `sprof` function-level profiler | | **Debug format** | SAS stabs (`=APS` tag in `HUNK_DEBUG`) | | **Global optimizer** | `lc -O` with peephole, dead code elimination, CSE | | **Code generation** | 68000 through 68060 + 68881/68882 FPU | | **Integrated linker** | `blink` — faster than generic linkers, understands Amiga hunks | --- ## Pragma Format Pragmas tell the compiler how to call AmigaOS library functions directly via JSR through the library base, with arguments in specific registers: ```c /* dos_pragmas.h — generated from FD files: */ #pragma libcall DOSBase Open 1e 2102 /* ^^ ^^^^ LVO register encoding LVO $1E = -30 (decimal) = offset in jump table Register encoding: read RIGHT to LEFT: 2 = D2 (not used here) 0 = D0 (return value) 1 = D1 (first arg) 2 = D2 (second arg) Last digit = number of arguments */ #pragma libcall DOSBase Close 24 101 /* LVO -$24 (-36), 1 arg in D1, returns in D0 */ #pragma libcall DOSBase Read 2a 32103 /* LVO -$2A (-42), 3 args: D1=fh, D2=buffer, D3=length */ ``` ### Register Encoding | Digit | Register | Digit | Register | |---|---|---|---| | 0 | D0 | 8 | (unused) | | 1 | D1 | 9 | A0 | | 2 | D2 | A | A1 | | 3 | D3 | B | A2 | | 4 | D4 | C | A3 | | 5 | D5 | D | A4 | | 6 | D6 | E | A5 | | 7 | D7 | F | (unused) | The rightmost digit is always the result register, next digit is number of args, then args are listed left-to-right. --- ## Compilation Workflow ``` Source (.c) → lc (compile) → Object (.o) → blink (link) → Executable ``` ```bash # Compile a single file: lc -v -O -b0 main.c # Link: blink main.o util.o TO myapp LIB lib:sc.lib lib:amiga.lib # Compile + link in one step: lc -v -O -b0 -j73 main.c util.c LINK TO myapp ``` ### Compiler Flags | Flag | Meaning | |---|---| | `-v` | Verbose output | | `-O` | Enable global optimizer | | `-b0` | Small data model (A4-relative, max 64 KB globals) | | `-b1` | Large data model (absolute addressing) | | `-j30` | Generate 68030 code | | `-j40` | Generate 68040 code | | `-j73` | Generate 68020 + 68881 FPU code | | `-d0` | No debug info | | `-d2` | Full debug info (SAS stabs) | | `-r` | Generate resident/reentrant code | | `-L` | Disable auto-open of amiga.lib | | `-w` | Suppress warnings | | `-E` | Preprocess only | ### Linker Flags (blink) | Flag | Meaning | |---|---| | `TO name` | Output file name | | `LIB libs` | Link libraries | | `DEBUG` | Include debug hunks | | `STRIPDEBUG` | Remove debug hunks | | `SMALLCODE` | PC-relative addressing | | `SMALLDATA` | A4-relative data | | `MAP file` | Generate link map | | `NODEBUG` | Omit all debug info | --- ## SAS/C-Specific Idioms ```c /* Register parameters: */ ULONG __asm MyFunc(register __d0 ULONG arg1, register __a0 APTR arg2); /* Interrupt-safe function: */ void __interrupt __saveds MyInterrupt(void); /* Resident code: */ LONG __saveds __asm LibOpen(register __a6 struct Library *base); /* __saveds: saves/restores A4 (small data base) on entry/exit */ /* __interrupt: preserves all registers */ /* __asm: use register calling convention */ ``` ### Differences from GCC | Feature | SAS/C | GCC (m68k-amigaos) | |---|---|---| | Register args | `register __d0 ULONG x` | `ULONG x __asm("d0")` | | Small data base | A4 (automatic with `-b0`) | `-fbaserel` (A4) | | Library pragmas | `#pragma libcall` | Inline asm stubs in `` | | Startup | `cres.o` (resident) / `c.o` (standard) | `libnix` or `ixemul` | | String constants | Pooled by default | `-fmerge-constants` | --- ## References - SAS/C 6.x User Manual and Reference Manual - NDK39 pragma files: `NDK_3.9/Include/pragmas/` - See also: [pragmas.md](pragmas.md) — pragma/inline mechanism in depth - See also: [gcc_amiga.md](gcc_amiga.md) — GCC cross-compiler (modern alternative)