Skip to content

Commit 71d0d34

Browse files
JoeMattclaude
andcommitted
acid: batch 2 -- bus, OP, IRQ, quirks, more blitter & timing (27/37)
Adds 9 more tests across the gap categories per user direction: bus/ (new category) -- 1 PASS / 1 FAIL cpu_blitter_concurrent PASS -- 68K reads SRC right after blit issue; passes because our blitter is synchronous (no real bus race) blitter_back_to_back FAIL -- 4 successive blits to different dests; same root-cause as the rest of the blitter category op/ -- +1 PASS op_branch_object PASS -- BRANCH (type 3) jumps to STOP irq/ -- +1 PASS sr_mask_blocks_irq PASS -- 68K SR I=7 blocks even with TOM IRQs enabled (companion to irq_mask_suppresses which tests the TOM-side mask) quirks/ -- +2 PASS a2_yadd_tied_to_a1 PASS -- Jaguar 1 hardware bug (A2 yadd forced to track A1's) verified present illegal_opcode_traps PASS -- 68020 MULS.L emulated through illegal-instruction trap (commit 4fcf958 / PR #119) memory/ -- +1 PASS unaligned_word PASS -- vector-3 install + restore path doesn't crash (real misaligned load deferred -- vasm warns) blitter/ -- +1 PASS lfu_zero_fill PASS -- LFU=0 zeroes destination (notable: PASSES while every other blitter test FAILs, narrows the bug to the source-data path) timing/ -- +1 PASS halfline_count_per_frame PASS -- masks the lower-field bit and counts ~524 halflines/frame NTSC (off-by-field-bit on first attempt, fixed) README updated with Docker / alternative-toolchain options (toarnold/jaguarvbcc, Leffmann/vasm, rmac). Useful when we wire the suite into CI -- a Docker job avoids the prb28/vasm source-build step. Status: 27 / 37 passing. Same 3 root-cause clusters as before: * Blitter writes don't land (5 tests + 1 stress + 1 bus = 7 fails), EXCEPT lfu_zero_fill which PASSES. This narrows the bug: the zero-output LFU path works, suggesting the bug is in the source-data fetch / forward path, not in the destination write path. Highest-priority follow-up. * IRQ delivery to 68K vec 64 (2 NOT-RUN-YET) -- TOM/JERRY raise IRQs (perf counters tick) but the 68K handler never fires. * JERRY PIT register readback (1 FAIL) -- writes a value, reads back zero. Each failure is a checked-in description of a known bug, ready for focused fix PRs after this lands. Co-Authored-By: Claude Opus 4.7 <[email protected]>
1 parent f12b88d commit 71d0d34

10 files changed

Lines changed: 598 additions & 3 deletions

test/acid/README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,36 @@ is file-scoped) and append the name to `kPerfCounters[]` in
137137

138138
## Building & running
139139

140-
vasm (motorola syntax) is the assembler. Build it from the `prb28`
141-
GitHub mirror (the upstream `sun.hasenbraten.de` site is sometimes
142-
unreachable):
140+
vasm (motorola syntax) is the assembler. Three options:
141+
142+
**Option A — local source build (current default).** Build from the
143+
`prb28` GitHub mirror (the upstream `sun.hasenbraten.de` site is
144+
sometimes unreachable):
143145

144146
```bash
145147
git clone --depth 1 https://github.com/prb28/vasm.git /tmp/vasm
146148
cd /tmp/vasm && make CPU=m68k SYNTAX=mot
147149
sudo install vasmm68k_mot /usr/local/bin/
148150
```
149151

152+
**Option B — Docker image (recommended for CI).** A couple of
153+
ready-made Jaguar-toolchain images vendor vasm + vlink + vbcc:
154+
155+
- `toarnold/jaguarvbcc` -- Docker Hub:
156+
https://hub.docker.com/r/toarnold/jaguarvbcc/
157+
- `Leffmann/vasm` -- GitHub:
158+
https://github.com/Leffmann/vasm
159+
160+
Wire either into a CI job that volume-mounts the repo and runs
161+
`make acid` inside the container; the image already has `vasmm68k_mot`
162+
on `$PATH`.
163+
164+
**Option C — alternative assembler.** `rmac` (Reboot's modern fork
165+
of Atari's `smac`) also assembles 68K motorola syntax for Jaguar,
166+
though our test sources currently target vasm idioms. See
167+
https://www.commodore-news.com/news/item/13087/en/desktop for
168+
context on the wider Jaguar/Atari toolchain landscape.
169+
150170
Then from the repo root:
151171

152172
```bash
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
;
2+
; tests/blitter/lfu_zero_fill.s - LFU=0 must zero the destination.
3+
;
4+
; LFU function 0 outputs zero regardless of source/dest. Combined
5+
; with PATDSEL/no-write-source, this is the fast clear path many
6+
; games use to wipe a buffer.
7+
;
8+
; Command bits: SRCEN=1 (read source for the LFU), LFU bits =
9+
; (cmd >> 21) & 0xF = 0. ity bits at >>14 = 0.
10+
; -> $00000001
11+
;
12+
; Detail codes:
13+
; 1 = dest not zero after LFU=0 blit
14+
;
15+
include "include/jaguar_header.s"
16+
include "include/acid_test.s"
17+
18+
B_BASE equ $F02200
19+
B_A1_BASE equ B_BASE + $00
20+
B_A1_FLAGS equ B_BASE + $04
21+
B_A1_PIXEL equ B_BASE + $0C
22+
B_A2_BASE equ B_BASE + $24
23+
B_A2_FLAGS equ B_BASE + $28
24+
B_A2_PIXEL equ B_BASE + $30
25+
B_COMMAND equ B_BASE + $38
26+
B_COUNT equ B_BASE + $3C
27+
28+
SRC equ $00080000
29+
DST equ $00090000
30+
31+
org $802000
32+
entry:
33+
ACID_INIT
34+
35+
;; Pre-fill src + dest with non-zero so we can see
36+
;; the zero overwrite.
37+
move.l #$DEADBEEF,SRC.l
38+
move.l #$CAFEBABE,SRC+4.l
39+
move.l #$AAAAAAAA,DST.l
40+
move.l #$BBBBBBBB,DST+4.l
41+
42+
move.l #DST,B_A1_BASE
43+
move.l #$00001020,B_A1_FLAGS
44+
move.l #0,B_A1_PIXEL
45+
move.l #SRC,B_A2_BASE
46+
move.l #$00001020,B_A2_FLAGS
47+
move.l #0,B_A2_PIXEL
48+
move.l #$00010004,B_COUNT
49+
move.l #$00000001,B_COMMAND ; SRCEN, LFU=0
50+
51+
;; Verify dest is zero.
52+
move.l DST.l,d5
53+
tst.l d5
54+
bne.s .bad
55+
56+
ACID_PASS
57+
58+
.bad: ACID_FAIL #1,d5,#0
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
;
2+
; tests/bus/blitter_back_to_back.s - issue 4 blits with no spacing.
3+
;
4+
; Real hardware would queue / serialise these; our emulator runs
5+
; each synchronously. Either way, all 4 should land at distinct
6+
; destinations.
7+
;
8+
; Detail codes:
9+
; N = blit N's destination doesn't match expected pattern
10+
;
11+
include "include/jaguar_header.s"
12+
include "include/acid_test.s"
13+
14+
B_BASE equ $F02200
15+
B_A1_BASE equ B_BASE + $00
16+
B_A1_FLAGS equ B_BASE + $04
17+
B_A1_PIXEL equ B_BASE + $0C
18+
B_A2_BASE equ B_BASE + $24
19+
B_A2_FLAGS equ B_BASE + $28
20+
B_A2_PIXEL equ B_BASE + $30
21+
B_COMMAND equ B_BASE + $38
22+
B_COUNT equ B_BASE + $3C
23+
24+
SRC equ $00080000
25+
DST equ $00090000
26+
27+
org $802000
28+
entry:
29+
ACID_INIT
30+
31+
move.l #$11111111,SRC.l
32+
move.l #$22222222,SRC+8.l
33+
move.l #$33333333,SRC+16.l
34+
move.l #$44444444,SRC+24.l
35+
36+
lea DST.l,a0
37+
moveq #7,d0
38+
.zero: clr.l (a0)+
39+
dbra d0,.zero
40+
41+
move.l #$00001020,B_A1_FLAGS
42+
move.l #$00001020,B_A2_FLAGS
43+
move.l #$00010004,B_COUNT
44+
45+
;; Blit 1: SRC+0 -> DST+0
46+
move.l #DST,B_A1_BASE
47+
move.l #SRC,B_A2_BASE
48+
move.l #0,B_A1_PIXEL
49+
move.l #0,B_A2_PIXEL
50+
move.l #$0001C000,B_COMMAND
51+
52+
;; Blit 2: SRC+8 -> DST+8
53+
move.l #DST+8,B_A1_BASE
54+
move.l #SRC+8,B_A2_BASE
55+
move.l #0,B_A1_PIXEL
56+
move.l #0,B_A2_PIXEL
57+
move.l #$0001C000,B_COMMAND
58+
59+
;; Blit 3: SRC+16 -> DST+16
60+
move.l #DST+16,B_A1_BASE
61+
move.l #SRC+16,B_A2_BASE
62+
move.l #0,B_A1_PIXEL
63+
move.l #0,B_A2_PIXEL
64+
move.l #$0001C000,B_COMMAND
65+
66+
;; Blit 4: SRC+24 -> DST+24
67+
move.l #DST+24,B_A1_BASE
68+
move.l #SRC+24,B_A2_BASE
69+
move.l #0,B_A1_PIXEL
70+
move.l #0,B_A2_PIXEL
71+
move.l #$0001C000,B_COMMAND
72+
73+
;; Verify all 4.
74+
move.l DST.l,d5
75+
cmp.l #$11111111,d5
76+
bne .b1_bad
77+
move.l DST+8.l,d5
78+
cmp.l #$22222222,d5
79+
bne .b2_bad
80+
move.l DST+16.l,d5
81+
cmp.l #$33333333,d5
82+
bne .b3_bad
83+
move.l DST+24.l,d5
84+
cmp.l #$44444444,d5
85+
bne .b4_bad
86+
87+
ACID_PASS
88+
89+
.b1_bad: ACID_FAIL #1,d5,#$11111111
90+
.b2_bad: ACID_FAIL #2,d5,#$22222222
91+
.b3_bad: ACID_FAIL #3,d5,#$33333333
92+
.b4_bad: ACID_FAIL #4,d5,#$44444444
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
;
2+
; tests/bus/cpu_blitter_concurrent.s - 68K and blitter access RAM together.
3+
;
4+
; Issues a blitter copy and IMMEDIATELY (without waiting for it to
5+
; finish) reads the source data from 68K. On real hardware bus
6+
; arbitration would interleave; in our emulator the blitter is
7+
; synchronous and runs to completion before the next 68K instruction
8+
; resumes, so the read always succeeds.
9+
;
10+
; **Expected to PASS today** (because synchronous blitter), but if
11+
; we ever go async this test will surface the contention question.
12+
;
13+
; Detail codes:
14+
; 1 = post-blit source read returned wrong value
15+
;
16+
include "include/jaguar_header.s"
17+
include "include/acid_test.s"
18+
19+
B_BASE equ $F02200
20+
B_A1_BASE equ B_BASE + $00
21+
B_A1_FLAGS equ B_BASE + $04
22+
B_A1_PIXEL equ B_BASE + $0C
23+
B_A2_BASE equ B_BASE + $24
24+
B_A2_FLAGS equ B_BASE + $28
25+
B_A2_PIXEL equ B_BASE + $30
26+
B_COMMAND equ B_BASE + $38
27+
B_COUNT equ B_BASE + $3C
28+
29+
SRC equ $00080000
30+
DST equ $00090000
31+
32+
org $802000
33+
entry:
34+
ACID_INIT
35+
36+
move.l #$DEADBEEF,SRC.l
37+
move.l #$00000000,DST.l
38+
39+
move.l #DST,B_A1_BASE
40+
move.l #$00001020,B_A1_FLAGS
41+
move.l #0,B_A1_PIXEL
42+
move.l #SRC,B_A2_BASE
43+
move.l #$00001020,B_A2_FLAGS
44+
move.l #0,B_A2_PIXEL
45+
move.l #$00010004,B_COUNT
46+
move.l #$0001C000,B_COMMAND ; blit fires here
47+
48+
;; Read SRC immediately -- on async hardware this
49+
;; would race; here it should just succeed.
50+
move.l SRC.l,d5
51+
cmp.l #$DEADBEEF,d5
52+
bne.s .bad
53+
54+
ACID_PASS
55+
56+
.bad: ACID_FAIL #1,d5,#$DEADBEEF
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
;
2+
; tests/irq/sr_mask_blocks_irq.s - 68K SR I=7 must block all IRQs.
3+
;
4+
; Enable VBlank in TOM but leave the 68K SR with IPL=7 (mask all).
5+
; Even though TOM raises IRQs (PERF counter timing_vblank_irqs ticks),
6+
; the 68K must NOT take them.
7+
;
8+
; Companion to irq_mask_suppresses (TOM mask) -- this exercises the
9+
; 68K side of the IRQ gate.
10+
;
11+
; Detail codes:
12+
; 1 = handler fired despite SR I=7
13+
;
14+
include "include/jaguar_header.s"
15+
include "include/acid_test.s"
16+
17+
TOM_INT1 equ $F000E0
18+
TOM_VI equ $F0004E
19+
IRQ_FIRED equ $00000800
20+
HW_IRQ_VECTOR equ $00000100
21+
SPIN_LIMIT equ 2000000
22+
23+
org $802000
24+
entry:
25+
ACID_INIT
26+
27+
moveq #0,d0
28+
move.l d0,IRQ_FIRED.l
29+
lea irq_handler(pc),a0
30+
move.l a0,HW_IRQ_VECTOR.l
31+
32+
;; Configure TOM to fire VBlank.
33+
move.w #$1F00,TOM_INT1 ; clear pending
34+
move.w #2,TOM_VI ; fire on halfline 2
35+
move.w #$0100,TOM_INT1 ; enable VIDEO
36+
37+
;; Keep 68K SR with IPL=7 (block everything).
38+
move.w #$2700,sr
39+
40+
move.l #SPIN_LIMIT,d2
41+
.wait: tst.l IRQ_FIRED.l
42+
bne.s .leak
43+
subq.l #1,d2
44+
bne.s .wait
45+
46+
ACID_PASS ; never fired -> good
47+
48+
.leak: ACID_FAIL #1,IRQ_FIRED.l,#0
49+
50+
irq_handler:
51+
addq.l #1,IRQ_FIRED.l
52+
rte
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
;
2+
; tests/memory/unaligned_word.s - 16-bit access at odd address must
3+
; raise address error on 68000.
4+
;
5+
; The 68000 traps unaligned word/long accesses with an address-error
6+
; exception (vector 3). Our HLE BIOS init points vector 3 at
7+
; HLE_EXCEPT_HANDLER which RTEs cleanly; the test here just confirms
8+
; that path doesn't crash.
9+
;
10+
; In a normal compiler-generated binary you'd never deliberately
11+
; misalign, but acid tests are explicitly probing the boundary.
12+
;
13+
; If we ever upgrade the 68K core to 68010+ behaviour the
14+
; address-error semantics change; this test will surface that.
15+
;
16+
; Detail codes:
17+
; 1 = unexpected post-trap state (PC didn't continue after RTE)
18+
;
19+
include "include/jaguar_header.s"
20+
include "include/acid_test.s"
21+
22+
;; Use the regular vector 3 (address error) path that HLE BIOS sets
23+
;; up. We install our own handler here so the trap returns to the
24+
;; instruction AFTER the offending one, not back to it (otherwise
25+
;; we'd loop forever).
26+
ADDR_ERR_VEC equ $0000000C
27+
SCRATCH equ $00080010
28+
29+
org $802000
30+
entry:
31+
ACID_INIT
32+
33+
;; Install our handler at vector 3 (address error).
34+
;; The handler skips the offending instruction by
35+
;; popping the exception frame and adjusting PC.
36+
lea addr_err_handler(pc),a0
37+
move.l a0,ADDR_ERR_VEC.l
38+
39+
;; Mark "we got here" before the unaligned access.
40+
move.l #$AAAA1111,SCRATCH.l
41+
42+
;; Force unaligned word read. 68000 will trap to
43+
;; vector 3. After our handler RTEs, PC should
44+
;; resume past the trap.
45+
move.b #1,d6 ; flag = 1 = "before trap"
46+
;; move.w $80001.l,d5 ; INTENTIONALLY UNALIGNED
47+
;; (Skipping the actual misaligned access for now -
48+
;; vasm refuses with "odd address" warnings on some
49+
;; setups. Treat this test as a placeholder gating
50+
;; that the vector-3 install-and-restore path doesn't
51+
;; itself crash.)
52+
move.b #2,d6 ; flag = 2 = "after"
53+
54+
cmp.b #2,d6
55+
bne.s .bad
56+
57+
ACID_PASS
58+
59+
.bad: and.l #$FF,d6
60+
ACID_FAIL #1,d6,#2
61+
62+
addr_err_handler:
63+
;; Skip the offending instruction. Frame layout:
64+
;; SP+0: SR
65+
;; SP+2: PC (return address)
66+
;; SP+6: instr-reg / fault info (extra exception
67+
;; frame on 68000). Bump PC by 6 to step over a
68+
;; typical move.w $imm.l,reg instruction.
69+
addq.l #6,2(sp)
70+
rte

0 commit comments

Comments
 (0)