mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
156 lines
4.8 KiB
Markdown
156 lines
4.8 KiB
Markdown
[← 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 `<inline/lib.h>` |
|
|
| 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)
|