docs: reconcile M2 plan with JAUC, returned, loader and .data alignment
This commit is contained in:
1 parent
0008d7be20
commit
b614e70851
1 file changed
+8
-8
@@ -20,12 +20,12 @@
|
||||
- Callee: save used A registers except A8 and the old FP on the system stack; `FP = STK`; `ADDI frame_bits,STK`; the first explicit argument is at `FP(-32)`, the second at `FP(-64)`, and so on; locally allocated objects are at positive FP offsets; restore `STK` from the saved slot; restore registers; `RETS 2` if the function has explicit arguments, `RETS 0` otherwise.
|
||||
- The saved old STK sits at `SP + (n+1)*32` after `n` system-stack pushes (return PC is at `SP + n*32`). `RETS N` pops the PC and advances SP by `32 + 16N`.
|
||||
- `FS1` must be 32 at function entry and after every call. Emit `SETF 32,0,1` in the prologue and immediately after each `CALLA`.
|
||||
- **M2 ABI scope:** `i32` and pointer arguments, each already a 32-bit stack slot; `void`, `i32` and pointer returns. Reject i8/i16 parameters (M3 adds the widen/truncate rules), i64, float/double, structs, vectors, varargs, `sret`, `byval`, `inreg`, `nest`, `returned`, tail calls, and indirect calls **loudly**, with a message beginning `M2`. Narrow loads/stores inside a function remain supported (M1's `MOVB`/FS0 `MOVE`).
|
||||
- **M2 ABI scope:** `i32` and pointer arguments, each already a 32-bit stack slot; `void`, `i32` and pointer returns. Reject i8/i16 parameters (M3 adds the widen/truncate rules), i64, float/double, structs, vectors, varargs, `sret`, `byval`, `inreg`, `nest`, tail calls, and indirect calls (the optimizer's `returned` hint is accepted: it is not ABI-affecting) **loudly**, with a message beginning `M2`. Narrow loads/stores inside a function remain supported (M1's `MOVB`/FS0 `MOVE`).
|
||||
- **M2 control-flow scope:** straight-line functions only. Conditional/unconditional branches, function pointers, spills requiring branch fixups, floats, structs and varargs are M3+. A branch that reaches ISel must fail loudly (`Cannot select: br` is acceptable).
|
||||
- Output is **assembly only**: `llc -march=tms34010 -filetype=asm`. No LLVM object writer, `MCCodeEmitter`, asm parser or linker in M2. GSPA assembles, GSPLNK links, the existing COFF loader loads.
|
||||
- M2 assembles with the **proven 1987 GSPA/GSPLNK 2.00 under DOSBox**, exactly as `scripts/m1/run.sh` does. Keep the linker command file CRLF. `.text` and `.data` link in the `prog` region at bit `018A0000`; `.bss` in `ram` at bit `018A9000`.
|
||||
- **`.data`/`.rodata`/string literals:** initialized globals and private constant data go to `.data` (the loader copies it); zero-initialized globals stay in `.bss`. The object format is GSPA 2.00, so emit `.byte` for i8 scalars/byte arrays, `.word` for i16 scalars, `.long` for i32 scalars/pointers, and symbol+bit-addend expressions; never ELF `.rodata`/`.asciz`/`.p2align`. A scalar's directive must match its width so the next global's offset is correct.
|
||||
- **ROM imports are per-ROM-revision.** v2.2 first. `symbols/vt1200-v22.syms` is the source of truth; M2 needs only `strlen 0x3FB458D0`, implemented as an absolute-jump stub (`_strlen: ja 3FB458D0h`) so the ROM's `RETS` returns directly to our caller. Do not add Xlib calls in M2.
|
||||
- **ROM imports are per-ROM-revision.** v2.2 first. `symbols/vt1200-v22.syms` is the source of truth; M2 needs only `strlen 0x3FB458D0`, implemented as an absolute-jump stub (`_strlen: jauc 3FB458D0h`; GSPA 2.00 rejects bare `ja`) so the ROM's `RETS` returns directly to our caller. Do not add Xlib calls in M2.
|
||||
- Symbols use the GSPA/TI leading underscore (`_main`, `_strlen`); code and data are position-dependent and linked at fixed bit addresses.
|
||||
- The M1 test suite and M1 GSPA harness encode the retired M1 register convention. On branch `m2` the lit suite is replaced by `m2-*` tests; `scripts/m1/` is retained as historical reference and is **not** an M2 gate. The `m1` branch keeps the original suite.
|
||||
- Tests: LLVM lit/FileCheck for asm; a GSPA/GSPLNK assemble-link step; a MAME run with marker words; a `dis34` round-trip; a stored TI-compiler golden check.
|
||||
@@ -46,7 +46,7 @@
|
||||
**Files:**
|
||||
- Delete: `build/llvm-clean/llvm/test/CodeGen/TMS34010/m1-*.ll` (compiler repo; the `m1` branch keeps them)
|
||||
- Create: `build/llvm-clean/llvm/test/CodeGen/TMS34010/m2-add.ll`, `m2-load.ll`, `m2-char.ll`, `m2-i16.ll`, `m2-store.ll`, `m2-global.ll`, `m2-late-gep.ll`, `m2-reject-i64.ll`, `m2-reject-struct.ll`, `m2-reject-vararg.ll`, `m2-reject-sret.ll`, `m2-reject-structret.ll`
|
||||
- Create: `m2-args.ll`, `m2-noret.ll`, `m2-locals.ll`, `m2-args-locals.ll`, `m2-call.ll`, `m2-call3.ll`, `m2-callee-save.ll`, `m2-fs1.ll`, `m2-spill.ll`, `m2-data.ll`, `m2-data-avail.ll`, `m2-string.ll`, `m2-ptrinit.ll`, `m2-reject-arg8.ll`, `m2-reject-i8ret.ll`, `m2-reject-float.ll`, `m2-reject-call-indirect.ll`, `m2-reject-call-arg8.ll`, `m2-reject-call-vararg.ll`
|
||||
- Create: `m2-args.ll`, `m2-noret.ll`, `m2-locals.ll`, `m2-args-locals.ll`, `m2-call.ll`, `m2-call3.ll`, `m2-callee-save.ll`, `m2-fs1.ll`, `m2-spill.ll`, `m2-data.ll`, `m2-data-avail.ll`, `m2-string.ll`, `m2-ptrinit.ll`, `m2-reject-arg8.ll`, `m2-reject-i8ret.ll`, `m2-reject-float.ll`, `m2-returned.ll`, `m2-data-align.ll`, `m2-reject-call-indirect.ll`, `m2-reject-call-arg8.ll`, `m2-reject-call-vararg.ll`
|
||||
- Test: the `m2-*` filter in `build/llvm-clean-build/test/CodeGen/TMS34010`
|
||||
|
||||
**Interfaces:**
|
||||
@@ -78,7 +78,7 @@ Delete the `m1-*.ll` files. Copy the still-valid positive tests from the `m1` br
|
||||
- `m2-store.ll`: same IR as `m1-store.ll`; both functions have arguments, so both endings are `CHECK: RETS 2`.
|
||||
- `m2-global.ll`: same IR as `m1-global.ll`; the return is A8, so `CHECK: MOVI _arr+32, A{{[0-9]+}}` and `CHECK: RETS 0`; keep `CHECK: .bss _arr,128,16`.
|
||||
- `m2-late-gep.ll`: same IR as `m1-late-gep.ll` (`CHECK: ADDI 24`, `CHECK-NOT: ADDI 192`).
|
||||
- `m2-reject-i64.ll`, `m2-reject-struct.ll`, `m2-reject-vararg.ll`, `m2-reject-sret.ll`, `m2-reject-structret.ll`: same IR as the corresponding `m1-*` negatives, with the `CHECK` messages changed to the M2 text in Task 2/3 (`M2 supports only i32 and pointer arguments`, `M2 does not support varargs`, `M2 supports only plain arguments (no sret/byval/inreg/nest/returned)`, `M2 supports only void/i32/pointer returns`). Keep both `-O0` and `-O2` RUN lines.
|
||||
- `m2-reject-i64.ll`, `m2-reject-struct.ll`, `m2-reject-vararg.ll`, `m2-reject-sret.ll`, `m2-reject-structret.ll`: same IR as the corresponding `m1-*` negatives, with the `CHECK` messages changed to the M2 text in Task 2/3 (`M2 supports only i32 and pointer arguments`, `M2 does not support varargs`, `M2 supports only plain arguments (no sret/byval/inreg/nest)`, `M2 supports only void/i32/pointer returns`). Keep both `-O0` and `-O2` RUN lines.
|
||||
|
||||
Add the new tests below. These are the red tests for Tasks 2–4.
|
||||
|
||||
@@ -549,7 +549,7 @@ if (N->getOpcode() == ISD::FrameIndex) {
|
||||
|
||||
`LowerFormalArguments`:
|
||||
|
||||
- Keep the M1 IR-signature validation, changing messages to `M2 ...`: reject varargs (`M2 does not support varargs`), i8/i16 parameters (`M2 supports only i32 and pointer arguments`), i64/float/double/aggregates/vectors (the same message), and `sret`/`byval`/`inreg`/`nest`/`returned` (`M2 supports only plain arguments (no sret/byval/inreg/nest/returned)`). Allow only i32 and pointers.
|
||||
- Keep the M1 IR-signature validation, changing messages to `M2 ...`: reject varargs (`M2 does not support varargs`), i8/i16 parameters (`M2 supports only i32 and pointer arguments`), i64/float/double/aggregates/vectors (the same message), and `sret`/`byval`/`inreg`/`nest`/`returned` (`M2 supports only plain arguments (no sret/byval/inreg/nest)`). Allow only i32 and pointers.
|
||||
- For argument `i` (0-based), create a fixed object of 4 bytes at byte offset `-(i+1)*4` (`MFI.CreateFixedObject(4, -(i+1)*4, true)`), load `i32` from it with alignment 2, and push the result to `InVals`. M2 supports only i32 and pointer arguments; the IR-signature validation above rejects narrow parameters.
|
||||
- Do not use M1's A0–A3 `CCValAssign` register path.
|
||||
|
||||
@@ -689,7 +689,7 @@ In `TMS34010AsmPrinter::emitGlobalVariable`:
|
||||
- Use `GV->hasLocalLinkage()`/`isConstant()` to decide whether to emit a global symbol attribute, as the `.bss` path does.
|
||||
- Fail loudly for any initializer shape M2 cannot print (e.g. floats, aggregates, vector constants) with `report_fatal_error("M2 .data supports only integer, pointer and byte-array initializers")`.
|
||||
- Map read-only/private constants to `.data`; do not emit `.rodata`, `.asciz`, `.p2align`, `.section` or ELF directives.
|
||||
- `.word` values use a leading `0` (`0%04Xh`) so high-bit values assemble; `.byte` lines wrap every 16 values; zero aggregates dispatch by element width (`.byte 0`/`.word 0`/`.long 0`).
|
||||
- `.word` values use a leading `0` (`0%04Xh`) so high-bit values assemble; `.byte` lines wrap every 16 values; zero aggregates dispatch by element width (`.byte 0`/`.word 0`/`.long 0`); emit `.even` before a `.data` global whose alignment is ≥16 bits so the label and the `.word`/`.long` agree.
|
||||
- Accept both `GEPOperator` and the normalized `inttoptr(add(ptrtoint(@sym), addend))` pointer-initializer shape (the `tms-bitaddr --normalize` form).
|
||||
- Skip `available_externally` globals (`isDeclarationForLinker()`); they are resolved externally, not definitions.
|
||||
- If GSPA rejects a private symbol whose name contains `.` — it does: `_.str:` gives `INVALID OPCODE` and `INVALID EXPRESSION` on the reference — sanitize private/local symbol names in `TMS34010ObjectFile` (replace `.` with `_`, or use a unique `Lstr<N>` label) and keep the `m2-string`/`m2-data` checks matching the sanitized name. GSPA 2.00 accepted `_.str` neither as a label nor in an expression; do not rely on ELF-style names.
|
||||
@@ -743,7 +743,7 @@ awk '
|
||||
name = $1
|
||||
addr = $2
|
||||
sub(/^0x/, "", addr)
|
||||
printf "\t.globl _%s\n_%s:\n\tja %sh\n", name, name, addr
|
||||
printf "\t.globl _%s\n_%s:\n\tjauc %sh\n", name, name, addr
|
||||
}
|
||||
' "$SYMS" >> "$OUT"
|
||||
```
|
||||
@@ -908,7 +908,7 @@ Print `M2: check=... first=... ...` and exactly `M2 MAME: PASS` on success.
|
||||
|
||||
`scripts/m2/dis-roundtrip.sh` adapts the M1 COFF parser and symbol lookup. It must require, at the linked addresses:
|
||||
|
||||
- `_strlen` stub: `ja 3FB458D0`
|
||||
- `_strlen` stub: `jauc 3FB458D0`
|
||||
- `_first`: `MOVEFP` materialisation (`MOVE A13, A?`) plus `ADDI -32`, and `RETS 2`
|
||||
- `_second`: `ADDI -64` and `RETS 2`
|
||||
- `_check` or `_keep`: `MOVE A14,-*SP,1`, `MOVE ...,*A14+,1`, `CALLA`, `SETF 32,0,1`, `MOVE *SP(...),A14,1`, `RETS 2`
|
||||
|
||||
Reference in new issue
Block a user