diff --git a/src/main/kc/include/atari-xl.h b/src/main/kc/include/atari-xl.h index 352cf18fe..29bf0e6b3 100644 --- a/src/main/kc/include/atari-xl.h +++ b/src/main/kc/include/atari-xl.h @@ -6,10 +6,10 @@ #include // Atari GTIA write registers -struct ATARI_GTIA_WRITE * const TIA = 0xd000; +struct ATARI_GTIA_WRITE * const GTIA = 0xd000; // Atari GTIA read registers -struct ATARI_GTIA_READ * const TIA_READ = 0xd000; +struct ATARI_GTIA_READ * const GTIA_READ = 0xd000; // Atari POKEY write registers struct ATARI_POKEY_WRITE * const POKEY = 0xd200; diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 10ee4932e..a5fc6a61c 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -202,6 +202,11 @@ public class TestPrograms { compileAndCompare("examples/mega65/hello-mega65.c"); } + @Test + public void testAtariXlRasterbars() throws IOException, URISyntaxException { + compileAndCompare("examples/atarixl/rasterbars.c"); + } + @Test public void testAtariXlHello() throws IOException, URISyntaxException { compileAndCompare("examples/atarixl/helloxl.c"); diff --git a/src/test/kc/.vscode/tasks.json b/src/test/kc/.vscode/tasks.json index ab9551c74..7674bf64e 100644 --- a/src/test/kc/.vscode/tasks.json +++ b/src/test/kc/.vscode/tasks.json @@ -110,6 +110,7 @@ "command": "~/c64/kickc_local/bin/kickc.sh", "args": [ "-vasmout", + "-Oloophead" "-Sc", "-odir", "~/c64/tmp/", diff --git a/src/test/kc/examples/atarixl/rasterbars.c b/src/test/kc/examples/atarixl/rasterbars.c new file mode 100644 index 000000000..f3ce2ca34 --- /dev/null +++ b/src/test/kc/examples/atarixl/rasterbars.c @@ -0,0 +1,47 @@ +// Raster Bars for Atari XL / XE + +#pragma target(atarixl) +#pragma emulator("65XEDebugger") +#include + +void main() { + // Disable IRQ + asm { sei } + // Enable DMA, Narrow Playfield - ANTIC Direct Memory Access Control + ANTIC->DMACTL = 0x21; + // Set ANTIC Display List Pointer + ANTIC->DLIST = DISPLAY_LIST; + // Set colors + GTIA->COLPF0 = 0x28; + GTIA->COLPF1 = 0x48; + GTIA->COLPF2 = 0x80; + GTIA->COLPF3 = 0xc8; + + // Loop forever - Display raster bars + char col = 0; + for(;;) { + while(ANTIC->VCOUNT!=40) ; + char c = col++; + for( char l=0;l<100;l++) { + ANTIC->WSYNC = c; + GTIA->COLBK = c; + c++; + } + GTIA->COLBK = 0; + }; +} + +// Message to show +char TEXT[] = "HELLO atari 8BIT" + "Demonstrates ANTIC display list!" + ; + +// ANTIC Display List Program +// https://en.wikipedia.org/wiki/ANTIC +char DISPLAY_LIST[] = { + BLANK8, BLANK8, BLANK8, // 3* 8 blank lines + LMS|MODE7, TEXT, // Load memory address and set to charmode 7 (16/20/24 chars wide, 16 lines per char) + BLANK4, // 4 blank lines + MODE2, // Charmode 2 (32/40/48 chars wide, 8 lines per char) + JVB, DISPLAY_LIST // Wait for VBLANK and jump +}; diff --git a/src/test/ref/examples/atarixl/rasterbars.asm b/src/test/ref/examples/atarixl/rasterbars.asm new file mode 100644 index 000000000..edd5e5ba8 --- /dev/null +++ b/src/test/ref/examples/atarixl/rasterbars.asm @@ -0,0 +1,117 @@ +// Raster Bars for Atari XL / XE + // Atari XL/XE XEX file minimal file +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="rasterbars.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // 2: High Resolution Text Mode. 8 scanlines per char, 32/40/48 chars wide. bit 7 controls inversion or blinking, based on modes in CHACTL. + .const MODE2 = 2 + // 7: Single color text in five colors. 16 scanlines per char, 16/20/24 chars wide. the upper two bits are used to select the foreground color used by 1 bits, with 00-11 producing PF0-PF3. + .const MODE7 = 7 + // Load memory scan counter (LMS operation) - Load memory scan counter with new 16-bit address. Can be combined with mode instructions by OR. + .const LMS = $40 + // Jump and wait for Vertical Blank - suspends the display list until vertical blank and then jumps. This is usually used to terminate the display list and restart it for the next frame. + .const JVB = $41 + // Blank 4 lines + .const BLANK4 = $30 + // Blank 8 lines + .const BLANK8 = $70 + .const OFFSET_STRUCT_ATARI_ANTIC_DLIST = 2 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = $16 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = $17 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = $18 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = $19 + .const OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = $b + .const OFFSET_STRUCT_ATARI_ANTIC_WSYNC = $a + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = $1a + // Atari GTIA write registers + .label GTIA = $d000 + // Atari ANTIC registers + .label ANTIC = $d400 +.segment Code +main: { + // asm + // Disable IRQ + sei + // ANTIC->DMACTL = 0x21 + // Enable DMA, Narrow Playfield - ANTIC Direct Memory Access Control + lda #$21 + sta ANTIC + // ANTIC->DLIST = DISPLAY_LIST + // Set ANTIC Display List Pointer + lda #DISPLAY_LIST + sta ANTIC+OFFSET_STRUCT_ATARI_ANTIC_DLIST+1 + // GTIA->COLPF0 = 0x28 + // Set colors + lda #$28 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 + // GTIA->COLPF1 = 0x48 + lda #$48 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 + // GTIA->COLPF2 = 0x80 + lda #$80 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 + // GTIA->COLPF3 = 0xc8 + lda #$c8 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 + ldy #0 + __b1: + // while(ANTIC->VCOUNT!=40) + lda #$28 + cmp ANTIC+OFFSET_STRUCT_ATARI_ANTIC_VCOUNT + bne __b1 + // c = col++ + tya + tax + inx + lda #0 + __b3: + // for( char l=0;l<100;l++) + cmp #$64 + bcc __b4 + // GTIA->COLBK = 0 + lda #0 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + txa + tay + jmp __b1 + __b4: + // ANTIC->WSYNC = c + sty ANTIC+OFFSET_STRUCT_ATARI_ANTIC_WSYNC + // GTIA->COLBK = c + sty GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // c++; + iny + // for( char l=0;l<100;l++) + clc + adc #1 + jmp __b3 +} +.segment Data + // Message to show +.encoding "ascii" + TEXT: .text @"\$28\$25\$2c\$2c\$2f\$00atari\$00\$18\$22\$29\$34\$24emonstrates\$00\$21\$2e\$34\$29\$23\$00display\$00list\$01" + .byte 0 + // ANTIC Display List Program + // https://en.wikipedia.org/wiki/ANTIC + DISPLAY_LIST: .byte BLANK8, BLANK8, BLANK8, LMS|MODE7, TEXT, BLANK4, MODE2, JVB, DISPLAY_LIST diff --git a/src/test/ref/examples/atarixl/rasterbars.cfg b/src/test/ref/examples/atarixl/rasterbars.cfg new file mode 100644 index 000000000..0a296ca35 --- /dev/null +++ b/src/test/ref/examples/atarixl/rasterbars.cfg @@ -0,0 +1,33 @@ + +(void()) main() +main: scope:[main] from + asm { sei } + [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 + [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST + [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 + [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 + [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 + [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 + to:main::@1 +main::@1: scope:[main] from main main::@1 main::@5 + [7] (byte) main::col#2 ← phi( main/(byte) 0 main::@1/(byte) main::col#2 main::@5/(byte) main::col#8 ) + [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) main::col#1 ← ++ (byte) main::col#2 + to:main::@3 +main::@3: scope:[main] from main::@2 main::@4 + [10] (byte) main::c#2 ← phi( main::@2/(byte) main::col#2 main::@4/(byte) main::c#1 ) + [10] (byte) main::l#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::l#1 ) + [11] if((byte) main::l#2<(byte) $64) goto main::@4 + to:main::@5 +main::@5: scope:[main] from main::@3 + [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 + [13] (byte) main::col#8 ← (byte) main::col#1 + to:main::@1 +main::@4: scope:[main] from main::@3 + [14] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 + [15] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 + [16] (byte) main::c#1 ← ++ (byte) main::c#2 + [17] (byte) main::l#1 ← ++ (byte) main::l#2 + to:main::@3 diff --git a/src/test/ref/examples/atarixl/rasterbars.log b/src/test/ref/examples/atarixl/rasterbars.log new file mode 100644 index 000000000..94dc53374 --- /dev/null +++ b/src/test/ref/examples/atarixl/rasterbars.log @@ -0,0 +1,1138 @@ +Resolved forward reference DISPLAY_LIST to (const byte*) DISPLAY_LIST +Fixing struct type size struct ATARI_GTIA_READ to 32 +Fixing struct type size struct ATARI_POKEY_READ to 16 +Fixing struct type SIZE_OF struct ATARI_GTIA_READ to 32 +Fixing struct type SIZE_OF struct ATARI_POKEY_READ to 16 +Fixing struct type SIZE_OF struct ATARI_GTIA_READ to 32 +Fixing struct type SIZE_OF struct ATARI_POKEY_READ to 16 +Inlined call call __init + +CONTROL FLOW GRAPH SSA + +(void()) main() +main: scope:[main] from __start::@1 + asm { sei } + *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL) ← (number) $21 + *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (number) $28 + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (number) $48 + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (number) $80 + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (number) $c8 + (byte) main::col#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 main::@5 + (byte) main::col#3 ← phi( main/(byte) main::col#0 main::@1/(byte) main::col#3 main::@5/(byte) main::col#4 ) + (bool~) main::$0 ← *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT) != (number) $28 + if((bool~) main::$0) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) main::col#2 ← phi( main::@1/(byte) main::col#3 ) + (byte) main::c#0 ← (byte) main::col#2 + (byte) main::col#1 ← ++ (byte) main::col#2 + (byte) main::l#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@2 main::@4 + (byte) main::col#5 ← phi( main::@2/(byte) main::col#1 main::@4/(byte) main::col#6 ) + (byte) main::c#3 ← phi( main::@2/(byte) main::c#0 main::@4/(byte) main::c#1 ) + (byte) main::l#2 ← phi( main::@2/(byte) main::l#0 main::@4/(byte) main::l#1 ) + (bool~) main::$1 ← (byte) main::l#2 < (number) $64 + if((bool~) main::$1) goto main::@4 + to:main::@5 +main::@4: scope:[main] from main::@3 + (byte) main::col#6 ← phi( main::@3/(byte) main::col#5 ) + (byte) main::l#3 ← phi( main::@3/(byte) main::l#2 ) + (byte) main::c#2 ← phi( main::@3/(byte) main::c#3 ) + *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 + (byte) main::c#1 ← ++ (byte) main::c#2 + (byte) main::l#1 ← ++ (byte) main::l#3 + to:main::@3 +main::@5: scope:[main] from main::@3 + (byte) main::col#4 ← phi( main::@3/(byte) main::col#5 ) + *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (number) 0 + to:main::@1 +main::@return: scope:[main] from + return + to:@return + +(void()) __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + call main + to:__start::@2 +__start::@2: scope:[__start] from __start::@1 + to:__start::@return +__start::@return: scope:[__start] from __start::@2 + return + to:@return + +SYMBOL TABLE SSA +(const nomodify struct ATARI_ANTIC*) ANTIC = (struct ATARI_ANTIC*)(number) $d400 +(byte) ATARI_ANTIC::CHACTL +(byte) ATARI_ANTIC::CHBASE +(byte*) ATARI_ANTIC::DLIST +(byte) ATARI_ANTIC::DMACTL +(byte) ATARI_ANTIC::HSCROL +(byte) ATARI_ANTIC::NMIEN +(byte) ATARI_ANTIC::NMIST +(byte) ATARI_ANTIC::PENH +(byte) ATARI_ANTIC::PENV +(byte) ATARI_ANTIC::PMBASE +(byte) ATARI_ANTIC::UNUSED1 +(byte) ATARI_ANTIC::UNUSED2 +(byte) ATARI_ANTIC::VCOUNT +(byte) ATARI_ANTIC::VSCROL +(byte) ATARI_ANTIC::WSYNC +(byte) ATARI_GTIA_READ::CONSOL +(byte) ATARI_GTIA_READ::M0PF +(byte) ATARI_GTIA_READ::M0PL +(byte) ATARI_GTIA_READ::M1PF +(byte) ATARI_GTIA_READ::M1PL +(byte) ATARI_GTIA_READ::M2PF +(byte) ATARI_GTIA_READ::M2PL +(byte) ATARI_GTIA_READ::M3PF +(byte) ATARI_GTIA_READ::M3PL +(byte) ATARI_GTIA_READ::P0PF +(byte) ATARI_GTIA_READ::P0PL +(byte) ATARI_GTIA_READ::P1PF +(byte) ATARI_GTIA_READ::P1PL +(byte) ATARI_GTIA_READ::P2PF +(byte) ATARI_GTIA_READ::P2PL +(byte) ATARI_GTIA_READ::P3PF +(byte) ATARI_GTIA_READ::P3PL +(byte) ATARI_GTIA_READ::PAL +(byte) ATARI_GTIA_READ::TRIG0 +(byte) ATARI_GTIA_READ::TRIG1 +(byte) ATARI_GTIA_READ::TRIG2 +(byte) ATARI_GTIA_READ::TRIG3 +(const byte*) ATARI_GTIA_READ::UNUSED[(number) $a] = { fill( $a, 0) } +(byte) ATARI_GTIA_WRITE::COLBK +(byte) ATARI_GTIA_WRITE::COLPF0 +(byte) ATARI_GTIA_WRITE::COLPF1 +(byte) ATARI_GTIA_WRITE::COLPF2 +(byte) ATARI_GTIA_WRITE::COLPF3 +(byte) ATARI_GTIA_WRITE::COLPM0 +(byte) ATARI_GTIA_WRITE::COLPM1 +(byte) ATARI_GTIA_WRITE::COLPM2 +(byte) ATARI_GTIA_WRITE::COLPM3 +(byte) ATARI_GTIA_WRITE::CONSPK +(byte) ATARI_GTIA_WRITE::GRACTL +(byte) ATARI_GTIA_WRITE::GRAFM +(byte) ATARI_GTIA_WRITE::GRAFP0 +(byte) ATARI_GTIA_WRITE::GRAFP1 +(byte) ATARI_GTIA_WRITE::GRAFP2 +(byte) ATARI_GTIA_WRITE::GRAFP3 +(byte) ATARI_GTIA_WRITE::HITCLR +(byte) ATARI_GTIA_WRITE::HPOSM0 +(byte) ATARI_GTIA_WRITE::HPOSM1 +(byte) ATARI_GTIA_WRITE::HPOSM2 +(byte) ATARI_GTIA_WRITE::HPOSM3 +(byte) ATARI_GTIA_WRITE::HPOSP0 +(byte) ATARI_GTIA_WRITE::HPOSP1 +(byte) ATARI_GTIA_WRITE::HPOSP2 +(byte) ATARI_GTIA_WRITE::HPOSP3 +(byte) ATARI_GTIA_WRITE::PRIOR +(byte) ATARI_GTIA_WRITE::SIZEM +(byte) ATARI_GTIA_WRITE::SIZEP0 +(byte) ATARI_GTIA_WRITE::SIZEP1 +(byte) ATARI_GTIA_WRITE::SIZEP2 +(byte) ATARI_GTIA_WRITE::SIZEP3 +(byte) ATARI_GTIA_WRITE::VDELAY +(byte) ATARI_POKEY_READ::ALLPOT +(byte) ATARI_POKEY_READ::IRQST +(byte) ATARI_POKEY_READ::KBCODE +(byte) ATARI_POKEY_READ::POT0 +(byte) ATARI_POKEY_READ::POT1 +(byte) ATARI_POKEY_READ::POT2 +(byte) ATARI_POKEY_READ::POT3 +(byte) ATARI_POKEY_READ::POT4 +(byte) ATARI_POKEY_READ::POT5 +(byte) ATARI_POKEY_READ::POT6 +(byte) ATARI_POKEY_READ::POT7 +(byte) ATARI_POKEY_READ::RANDOM +(byte) ATARI_POKEY_READ::SERIN +(byte) ATARI_POKEY_READ::SKSTAT +(const byte*) ATARI_POKEY_READ::UNUSED[(number) 2] = { fill( 2, 0) } +(byte) ATARI_POKEY_WRITE::AUDC1 +(byte) ATARI_POKEY_WRITE::AUDC2 +(byte) ATARI_POKEY_WRITE::AUDC3 +(byte) ATARI_POKEY_WRITE::AUDC4 +(byte) ATARI_POKEY_WRITE::AUDCTL +(byte) ATARI_POKEY_WRITE::AUDF1 +(byte) ATARI_POKEY_WRITE::AUDF2 +(byte) ATARI_POKEY_WRITE::AUDF3 +(byte) ATARI_POKEY_WRITE::AUDF4 +(byte) ATARI_POKEY_WRITE::IRQEN +(byte) ATARI_POKEY_WRITE::POTGO +(byte) ATARI_POKEY_WRITE::SEROUT +(byte) ATARI_POKEY_WRITE::SKCTL +(byte) ATARI_POKEY_WRITE::SKREST +(byte) ATARI_POKEY_WRITE::STIMER +(byte) ATARI_POKEY_WRITE::UNUSED +(const nomodify byte) BLANK4 = (byte) $30 +(const nomodify byte) BLANK8 = (byte) $70 +(const byte*) DISPLAY_LIST[] = { (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) LMS|(const nomodify byte) MODE7, <(const byte*) TEXT, >(const byte*) TEXT, (const nomodify byte) BLANK4, (const nomodify byte) MODE2, (const nomodify byte) JVB, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } +(const nomodify struct ATARI_GTIA_WRITE*) GTIA = (struct ATARI_GTIA_WRITE*)(number) $d000 +(const nomodify byte) JVB = (byte) $41 +(const nomodify byte) LMS = (byte) $40 +(const nomodify byte) MODE2 = (byte) 2 +(const nomodify byte) MODE7 = (byte) 7 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST = (byte) 2 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL = (byte) 0 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = (byte) $b +(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC = (byte) $a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = (byte) $1a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = (byte) $16 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = (byte) $17 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = (byte) $18 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = (byte) $19 +(const byte*) TEXT[] = (byte*) "HELLO atari 8BITDemonstrates ANTIC display list!"sa +(void()) __start() +(label) __start::@1 +(label) __start::@2 +(label) __start::@return +(label) __start::__init1 +(void()) main() +(bool~) main::$0 +(bool~) main::$1 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@return +(byte) main::c +(byte) main::c#0 +(byte) main::c#1 +(byte) main::c#2 +(byte) main::c#3 +(byte) main::col +(byte) main::col#0 +(byte) main::col#1 +(byte) main::col#2 +(byte) main::col#3 +(byte) main::col#4 +(byte) main::col#5 +(byte) main::col#6 +(byte) main::l +(byte) main::l#0 +(byte) main::l#1 +(byte) main::l#2 +(byte) main::l#3 + +Adding number conversion cast (unumber) $21 in *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL) ← (number) $21 +Adding number conversion cast (unumber) $28 in *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (number) $28 +Adding number conversion cast (unumber) $48 in *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (number) $48 +Adding number conversion cast (unumber) $80 in *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (number) $80 +Adding number conversion cast (unumber) $c8 in *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (number) $c8 +Adding number conversion cast (unumber) $28 in (bool~) main::$0 ← *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT) != (number) $28 +Adding number conversion cast (unumber) $64 in (bool~) main::$1 ← (byte) main::l#2 < (number) $64 +Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (number) 0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL) ← (unumber)(number) $21 +Inlining cast *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (unumber)(number) $28 +Inlining cast *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (unumber)(number) $48 +Inlining cast *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (unumber)(number) $80 +Inlining cast *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (unumber)(number) $c8 +Inlining cast *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (unumber)(number) 0 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (struct ATARI_GTIA_WRITE*) 53248 +Simplifying constant pointer cast (struct ATARI_ANTIC*) 54272 +Simplifying constant integer cast $21 +Simplifying constant integer cast $28 +Simplifying constant integer cast $48 +Simplifying constant integer cast $80 +Simplifying constant integer cast $c8 +Simplifying constant integer cast $28 +Simplifying constant integer cast $64 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) $21 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) $48 +Finalized unsigned number type (byte) $80 +Finalized unsigned number type (byte) $c8 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) $64 +Finalized unsigned number type (byte) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias main::col#2 = main::col#3 main::c#0 +Alias main::c#2 = main::c#3 +Alias main::l#2 = main::l#3 +Alias main::col#4 = main::col#6 main::col#5 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (byte) main::col#4 (byte) main::col#1 +Successful SSA optimization Pass2IdenticalPhiElimination +Simple Condition (bool~) main::$0 [10] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 +Simple Condition (bool~) main::$1 [15] if((byte) main::l#2<(byte) $64) goto main::@4 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) main::col#0 = 0 +Constant (const byte) main::l#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero (byte*)ANTIC in [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL) ← (byte) $21 +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) OFFSET_STRUCT_ATARI_ANTIC_DMACTL +Successful SSA optimization PassNEliminateUnusedVars +Removing unused block main::@return +Successful SSA optimization Pass2EliminateUnusedBlocks +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::__init1 +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@2 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Inlining constant with var siblings (const byte) main::col#0 +Inlining constant with var siblings (const byte) main::l#0 +Constant inlined main::col#0 = (byte) 0 +Constant inlined main::l#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@6(between main::@1 and main::@1) +CALL GRAPH + +Created 3 initial phi equivalence classes +Coalesced [10] main::c#4 ← main::col#2 +Not coalescing [14] main::col#8 ← main::col#1 +Coalesced [19] main::l#4 ← main::l#1 +Coalesced [20] main::c#5 ← main::c#1 +Coalesced (already) [21] main::col#7 ← main::col#2 +Coalesced down to 3 phi equivalence classes +Culled Empty Block (label) main::@6 + +FINAL CONTROL FLOW GRAPH + +(void()) main() +main: scope:[main] from + asm { sei } + [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 + [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST + [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 + [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 + [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 + [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 + to:main::@1 +main::@1: scope:[main] from main main::@1 main::@5 + [7] (byte) main::col#2 ← phi( main/(byte) 0 main::@1/(byte) main::col#2 main::@5/(byte) main::col#8 ) + [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) main::col#1 ← ++ (byte) main::col#2 + to:main::@3 +main::@3: scope:[main] from main::@2 main::@4 + [10] (byte) main::c#2 ← phi( main::@2/(byte) main::col#2 main::@4/(byte) main::c#1 ) + [10] (byte) main::l#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::l#1 ) + [11] if((byte) main::l#2<(byte) $64) goto main::@4 + to:main::@5 +main::@5: scope:[main] from main::@3 + [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 + [13] (byte) main::col#8 ← (byte) main::col#1 + to:main::@1 +main::@4: scope:[main] from main::@3 + [14] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 + [15] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 + [16] (byte) main::c#1 ← ++ (byte) main::c#2 + [17] (byte) main::l#1 ← ++ (byte) main::l#2 + to:main::@3 + + +VARIABLE REGISTER WEIGHTS +(byte) ATARI_ANTIC::CHACTL +(byte) ATARI_ANTIC::CHBASE +(byte*) ATARI_ANTIC::DLIST +(byte) ATARI_ANTIC::DMACTL +(byte) ATARI_ANTIC::HSCROL +(byte) ATARI_ANTIC::NMIEN +(byte) ATARI_ANTIC::NMIST +(byte) ATARI_ANTIC::PENH +(byte) ATARI_ANTIC::PENV +(byte) ATARI_ANTIC::PMBASE +(byte) ATARI_ANTIC::UNUSED1 +(byte) ATARI_ANTIC::UNUSED2 +(byte) ATARI_ANTIC::VCOUNT +(byte) ATARI_ANTIC::VSCROL +(byte) ATARI_ANTIC::WSYNC +(byte) ATARI_GTIA_READ::CONSOL +(byte) ATARI_GTIA_READ::M0PF +(byte) ATARI_GTIA_READ::M0PL +(byte) ATARI_GTIA_READ::M1PF +(byte) ATARI_GTIA_READ::M1PL +(byte) ATARI_GTIA_READ::M2PF +(byte) ATARI_GTIA_READ::M2PL +(byte) ATARI_GTIA_READ::M3PF +(byte) ATARI_GTIA_READ::M3PL +(byte) ATARI_GTIA_READ::P0PF +(byte) ATARI_GTIA_READ::P0PL +(byte) ATARI_GTIA_READ::P1PF +(byte) ATARI_GTIA_READ::P1PL +(byte) ATARI_GTIA_READ::P2PF +(byte) ATARI_GTIA_READ::P2PL +(byte) ATARI_GTIA_READ::P3PF +(byte) ATARI_GTIA_READ::P3PL +(byte) ATARI_GTIA_READ::PAL +(byte) ATARI_GTIA_READ::TRIG0 +(byte) ATARI_GTIA_READ::TRIG1 +(byte) ATARI_GTIA_READ::TRIG2 +(byte) ATARI_GTIA_READ::TRIG3 +(byte) ATARI_GTIA_WRITE::COLBK +(byte) ATARI_GTIA_WRITE::COLPF0 +(byte) ATARI_GTIA_WRITE::COLPF1 +(byte) ATARI_GTIA_WRITE::COLPF2 +(byte) ATARI_GTIA_WRITE::COLPF3 +(byte) ATARI_GTIA_WRITE::COLPM0 +(byte) ATARI_GTIA_WRITE::COLPM1 +(byte) ATARI_GTIA_WRITE::COLPM2 +(byte) ATARI_GTIA_WRITE::COLPM3 +(byte) ATARI_GTIA_WRITE::CONSPK +(byte) ATARI_GTIA_WRITE::GRACTL +(byte) ATARI_GTIA_WRITE::GRAFM +(byte) ATARI_GTIA_WRITE::GRAFP0 +(byte) ATARI_GTIA_WRITE::GRAFP1 +(byte) ATARI_GTIA_WRITE::GRAFP2 +(byte) ATARI_GTIA_WRITE::GRAFP3 +(byte) ATARI_GTIA_WRITE::HITCLR +(byte) ATARI_GTIA_WRITE::HPOSM0 +(byte) ATARI_GTIA_WRITE::HPOSM1 +(byte) ATARI_GTIA_WRITE::HPOSM2 +(byte) ATARI_GTIA_WRITE::HPOSM3 +(byte) ATARI_GTIA_WRITE::HPOSP0 +(byte) ATARI_GTIA_WRITE::HPOSP1 +(byte) ATARI_GTIA_WRITE::HPOSP2 +(byte) ATARI_GTIA_WRITE::HPOSP3 +(byte) ATARI_GTIA_WRITE::PRIOR +(byte) ATARI_GTIA_WRITE::SIZEM +(byte) ATARI_GTIA_WRITE::SIZEP0 +(byte) ATARI_GTIA_WRITE::SIZEP1 +(byte) ATARI_GTIA_WRITE::SIZEP2 +(byte) ATARI_GTIA_WRITE::SIZEP3 +(byte) ATARI_GTIA_WRITE::VDELAY +(byte) ATARI_POKEY_READ::ALLPOT +(byte) ATARI_POKEY_READ::IRQST +(byte) ATARI_POKEY_READ::KBCODE +(byte) ATARI_POKEY_READ::POT0 +(byte) ATARI_POKEY_READ::POT1 +(byte) ATARI_POKEY_READ::POT2 +(byte) ATARI_POKEY_READ::POT3 +(byte) ATARI_POKEY_READ::POT4 +(byte) ATARI_POKEY_READ::POT5 +(byte) ATARI_POKEY_READ::POT6 +(byte) ATARI_POKEY_READ::POT7 +(byte) ATARI_POKEY_READ::RANDOM +(byte) ATARI_POKEY_READ::SERIN +(byte) ATARI_POKEY_READ::SKSTAT +(byte) ATARI_POKEY_WRITE::AUDC1 +(byte) ATARI_POKEY_WRITE::AUDC2 +(byte) ATARI_POKEY_WRITE::AUDC3 +(byte) ATARI_POKEY_WRITE::AUDC4 +(byte) ATARI_POKEY_WRITE::AUDCTL +(byte) ATARI_POKEY_WRITE::AUDF1 +(byte) ATARI_POKEY_WRITE::AUDF2 +(byte) ATARI_POKEY_WRITE::AUDF3 +(byte) ATARI_POKEY_WRITE::AUDF4 +(byte) ATARI_POKEY_WRITE::IRQEN +(byte) ATARI_POKEY_WRITE::POTGO +(byte) ATARI_POKEY_WRITE::SEROUT +(byte) ATARI_POKEY_WRITE::SKCTL +(byte) ATARI_POKEY_WRITE::SKREST +(byte) ATARI_POKEY_WRITE::STIMER +(byte) ATARI_POKEY_WRITE::UNUSED +(void()) main() +(byte) main::c +(byte) main::c#1 101.0 +(byte) main::c#2 103.75 +(byte) main::col +(byte) main::col#1 2.75 +(byte) main::col#2 78.33333333333334 +(byte) main::col#8 22.0 +(byte) main::l +(byte) main::l#1 202.0 +(byte) main::l#2 60.599999999999994 + +Initial phi equivalence classes +[ main::l#2 main::l#1 ] +[ main::c#2 main::col#2 main::col#8 main::c#1 ] +Added variable main::col#1 to live range equivalence class [ main::col#1 ] +Complete equivalence classes +[ main::l#2 main::l#1 ] +[ main::c#2 main::col#2 main::col#8 main::c#1 ] +[ main::col#1 ] +Allocated zp[1]:2 [ main::l#2 main::l#1 ] +Allocated zp[1]:3 [ main::c#2 main::col#2 main::col#8 main::c#1 ] +Allocated zp[1]:4 [ main::col#1 ] + +INITIAL ASM +Target platform is atarixl / MOS6502X + // File Comments +// Raster Bars for Atari XL / XE + // Upstart + // Atari XL/XE XEX file minimal file +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="rasterbars.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // Global Constants & labels + // 2: High Resolution Text Mode. 8 scanlines per char, 32/40/48 chars wide. bit 7 controls inversion or blinking, based on modes in CHACTL. + .const MODE2 = 2 + // 7: Single color text in five colors. 16 scanlines per char, 16/20/24 chars wide. the upper two bits are used to select the foreground color used by 1 bits, with 00-11 producing PF0-PF3. + .const MODE7 = 7 + // Load memory scan counter (LMS operation) - Load memory scan counter with new 16-bit address. Can be combined with mode instructions by OR. + .const LMS = $40 + // Jump and wait for Vertical Blank - suspends the display list until vertical blank and then jumps. This is usually used to terminate the display list and restart it for the next frame. + .const JVB = $41 + // Blank 4 lines + .const BLANK4 = $30 + // Blank 8 lines + .const BLANK8 = $70 + .const OFFSET_STRUCT_ATARI_ANTIC_DLIST = 2 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = $16 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = $17 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = $18 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = $19 + .const OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = $b + .const OFFSET_STRUCT_ATARI_ANTIC_WSYNC = $a + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = $1a + // Atari GTIA write registers + .label GTIA = $d000 + // Atari ANTIC registers + .label ANTIC = $d400 +.segment Code + // main +main: { + // Loop forever - Display raster bars + .label col = 4 + .label c = 3 + .label l = 2 + // Loop forever - Display raster bars + .label col_1 = 3 + // asm { sei } + // Disable IRQ + sei + // [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 -- _deref_pbuc1=vbuc2 + // Enable DMA, Narrow Playfield - ANTIC Direct Memory Access Control + lda #$21 + sta ANTIC + // [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2 + // Set ANTIC Display List Pointer + lda #DISPLAY_LIST + sta ANTIC+OFFSET_STRUCT_ATARI_ANTIC_DLIST+1 + // [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 -- _deref_pbuc1=vbuc2 + // Set colors + lda #$28 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 + // [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 -- _deref_pbuc1=vbuc2 + lda #$48 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 + // [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 + // [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 -- _deref_pbuc1=vbuc2 + lda #$c8 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 + // [7] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [7] phi (byte) main::col#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z col_1 + jmp __b1 + // [7] phi from main::@1 main::@5 to main::@1 [phi:main::@1/main::@5->main::@1] + __b1_from___b1: + __b1_from___b5: + // [7] phi (byte) main::col#2 = (byte) main::col#2 [phi:main::@1/main::@5->main::@1#0] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 -- _deref_pbuc1_neq_vbuc2_then_la1 + lda #$28 + cmp ANTIC+OFFSET_STRUCT_ATARI_ANTIC_VCOUNT + bne __b1_from___b1 + jmp __b2 + // main::@2 + __b2: + // [9] (byte) main::col#1 ← ++ (byte) main::col#2 -- vbuz1=_inc_vbuz2 + ldy.z col_1 + iny + sty.z col + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + __b3_from___b2: + // [10] phi (byte) main::c#2 = (byte) main::col#2 [phi:main::@2->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuz1=vbuc1 + lda #0 + sta.z l + jmp __b3 + // main::@3 + __b3: + // [11] if((byte) main::l#2<(byte) $64) goto main::@4 -- vbuz1_lt_vbuc1_then_la1 + lda.z l + cmp #$64 + bcc __b4 + jmp __b5 + // main::@5 + __b5: + // [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // [13] (byte) main::col#8 ← (byte) main::col#1 -- vbuz1=vbuz2 + lda.z col + sta.z col_1 + jmp __b1_from___b5 + // main::@4 + __b4: + // [14] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 -- _deref_pbuc1=vbuz1 + lda.z c + sta ANTIC+OFFSET_STRUCT_ATARI_ANTIC_WSYNC + // [15] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuz1 + lda.z c + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // [16] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuz1=_inc_vbuz1 + inc.z c + // [17] (byte) main::l#1 ← ++ (byte) main::l#2 -- vbuz1=_inc_vbuz1 + inc.z l + // [10] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + __b3_from___b4: + // [10] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@4->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) main::l#1 [phi:main::@4->main::@3#1] -- register_copy + jmp __b3 +} + // File Data +.segment Data + // Message to show +.encoding "ascii" + TEXT: .text @"\$28\$25\$2c\$2c\$2f\$00atari\$00\$18\$22\$29\$34\$24emonstrates\$00\$21\$2e\$34\$29\$23\$00display\$00list\$01" + .byte 0 + // ANTIC Display List Program + // https://en.wikipedia.org/wiki/ANTIC + DISPLAY_LIST: .byte BLANK8, BLANK8, BLANK8, LMS|MODE7, TEXT, BLANK4, MODE2, JVB, DISPLAY_LIST + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST [ ] ( [ ] { } ) always clobbers reg byte a +Statement [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 [ main::col#2 ] ( [ main::col#2 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::c#2 main::col#2 main::col#8 main::c#1 ] +Statement [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 [ main::col#1 ] ( [ main::col#1 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::col#1 ] +Statement [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST [ ] ( [ ] { } ) always clobbers reg byte a +Statement [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 [ main::col#2 ] ( [ main::col#2 ] { } ) always clobbers reg byte a +Statement [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 [ main::col#1 ] ( [ main::col#1 ] { } ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::l#2 main::l#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::c#2 main::col#2 main::col#8 main::c#1 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ main::col#1 ] : zp[1]:4 , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 305.08: zp[1]:3 [ main::c#2 main::col#2 main::col#8 main::c#1 ] 262.6: zp[1]:2 [ main::l#2 main::l#1 ] 2.75: zp[1]:4 [ main::col#1 ] +Uplift Scope [ATARI_ANTIC] +Uplift Scope [ATARI_GTIA_READ] +Uplift Scope [ATARI_GTIA_WRITE] +Uplift Scope [ATARI_POKEY_READ] +Uplift Scope [ATARI_POKEY_WRITE] +Uplift Scope [] + +Uplifting [main] best 5134 combination reg byte y [ main::c#2 main::col#2 main::col#8 main::c#1 ] reg byte a [ main::l#2 main::l#1 ] reg byte x [ main::col#1 ] +Uplifting [ATARI_ANTIC] best 5134 combination +Uplifting [ATARI_GTIA_READ] best 5134 combination +Uplifting [ATARI_GTIA_WRITE] best 5134 combination +Uplifting [ATARI_POKEY_READ] best 5134 combination +Uplifting [ATARI_POKEY_WRITE] best 5134 combination +Uplifting [] best 5134 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Raster Bars for Atari XL / XE + // Upstart + // Atari XL/XE XEX file minimal file +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="rasterbars.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // Global Constants & labels + // 2: High Resolution Text Mode. 8 scanlines per char, 32/40/48 chars wide. bit 7 controls inversion or blinking, based on modes in CHACTL. + .const MODE2 = 2 + // 7: Single color text in five colors. 16 scanlines per char, 16/20/24 chars wide. the upper two bits are used to select the foreground color used by 1 bits, with 00-11 producing PF0-PF3. + .const MODE7 = 7 + // Load memory scan counter (LMS operation) - Load memory scan counter with new 16-bit address. Can be combined with mode instructions by OR. + .const LMS = $40 + // Jump and wait for Vertical Blank - suspends the display list until vertical blank and then jumps. This is usually used to terminate the display list and restart it for the next frame. + .const JVB = $41 + // Blank 4 lines + .const BLANK4 = $30 + // Blank 8 lines + .const BLANK8 = $70 + .const OFFSET_STRUCT_ATARI_ANTIC_DLIST = 2 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = $16 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = $17 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = $18 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = $19 + .const OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = $b + .const OFFSET_STRUCT_ATARI_ANTIC_WSYNC = $a + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = $1a + // Atari GTIA write registers + .label GTIA = $d000 + // Atari ANTIC registers + .label ANTIC = $d400 +.segment Code + // main +main: { + // asm { sei } + // Disable IRQ + sei + // [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 -- _deref_pbuc1=vbuc2 + // Enable DMA, Narrow Playfield - ANTIC Direct Memory Access Control + lda #$21 + sta ANTIC + // [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2 + // Set ANTIC Display List Pointer + lda #DISPLAY_LIST + sta ANTIC+OFFSET_STRUCT_ATARI_ANTIC_DLIST+1 + // [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 -- _deref_pbuc1=vbuc2 + // Set colors + lda #$28 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 + // [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 -- _deref_pbuc1=vbuc2 + lda #$48 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 + // [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 + // [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 -- _deref_pbuc1=vbuc2 + lda #$c8 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 + // [7] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [7] phi (byte) main::col#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + jmp __b1 + // [7] phi from main::@1 main::@5 to main::@1 [phi:main::@1/main::@5->main::@1] + __b1_from___b1: + __b1_from___b5: + // [7] phi (byte) main::col#2 = (byte) main::col#2 [phi:main::@1/main::@5->main::@1#0] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 -- _deref_pbuc1_neq_vbuc2_then_la1 + lda #$28 + cmp ANTIC+OFFSET_STRUCT_ATARI_ANTIC_VCOUNT + bne __b1_from___b1 + jmp __b2 + // main::@2 + __b2: + // [9] (byte) main::col#1 ← ++ (byte) main::col#2 -- vbuxx=_inc_vbuyy + tya + tax + inx + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + __b3_from___b2: + // [10] phi (byte) main::c#2 = (byte) main::col#2 [phi:main::@2->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuaa=vbuc1 + lda #0 + jmp __b3 + // main::@3 + __b3: + // [11] if((byte) main::l#2<(byte) $64) goto main::@4 -- vbuaa_lt_vbuc1_then_la1 + cmp #$64 + bcc __b4 + jmp __b5 + // main::@5 + __b5: + // [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // [13] (byte) main::col#8 ← (byte) main::col#1 -- vbuyy=vbuxx + txa + tay + jmp __b1_from___b5 + // main::@4 + __b4: + // [14] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 -- _deref_pbuc1=vbuyy + sty ANTIC+OFFSET_STRUCT_ATARI_ANTIC_WSYNC + // [15] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuyy + sty GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // [16] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuyy=_inc_vbuyy + iny + // [17] (byte) main::l#1 ← ++ (byte) main::l#2 -- vbuaa=_inc_vbuaa + clc + adc #1 + // [10] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + __b3_from___b4: + // [10] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@4->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) main::l#1 [phi:main::@4->main::@3#1] -- register_copy + jmp __b3 +} + // File Data +.segment Data + // Message to show +.encoding "ascii" + TEXT: .text @"\$28\$25\$2c\$2c\$2f\$00atari\$00\$18\$22\$29\$34\$24emonstrates\$00\$21\$2e\$34\$29\$23\$00display\$00list\$01" + .byte 0 + // ANTIC Display List Program + // https://en.wikipedia.org/wiki/ANTIC + DISPLAY_LIST: .byte BLANK8, BLANK8, BLANK8, LMS|MODE7, TEXT, BLANK4, MODE2, JVB, DISPLAY_LIST + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __b5 +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __b1_from___b1 with __b1 +Replacing label __b1_from___b5 with __b1 +Removing instruction __b1_from___b1: +Removing instruction __b1_from___b5: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b1_from_main: +Removing instruction __b2: +Removing instruction __b3_from___b2: +Removing instruction __b5: +Removing instruction __b3_from___b4: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +(const nomodify struct ATARI_ANTIC*) ANTIC = (struct ATARI_ANTIC*) 54272 +(byte) ATARI_ANTIC::CHACTL +(byte) ATARI_ANTIC::CHBASE +(byte*) ATARI_ANTIC::DLIST +(byte) ATARI_ANTIC::DMACTL +(byte) ATARI_ANTIC::HSCROL +(byte) ATARI_ANTIC::NMIEN +(byte) ATARI_ANTIC::NMIST +(byte) ATARI_ANTIC::PENH +(byte) ATARI_ANTIC::PENV +(byte) ATARI_ANTIC::PMBASE +(byte) ATARI_ANTIC::UNUSED1 +(byte) ATARI_ANTIC::UNUSED2 +(byte) ATARI_ANTIC::VCOUNT +(byte) ATARI_ANTIC::VSCROL +(byte) ATARI_ANTIC::WSYNC +(byte) ATARI_GTIA_READ::CONSOL +(byte) ATARI_GTIA_READ::M0PF +(byte) ATARI_GTIA_READ::M0PL +(byte) ATARI_GTIA_READ::M1PF +(byte) ATARI_GTIA_READ::M1PL +(byte) ATARI_GTIA_READ::M2PF +(byte) ATARI_GTIA_READ::M2PL +(byte) ATARI_GTIA_READ::M3PF +(byte) ATARI_GTIA_READ::M3PL +(byte) ATARI_GTIA_READ::P0PF +(byte) ATARI_GTIA_READ::P0PL +(byte) ATARI_GTIA_READ::P1PF +(byte) ATARI_GTIA_READ::P1PL +(byte) ATARI_GTIA_READ::P2PF +(byte) ATARI_GTIA_READ::P2PL +(byte) ATARI_GTIA_READ::P3PF +(byte) ATARI_GTIA_READ::P3PL +(byte) ATARI_GTIA_READ::PAL +(byte) ATARI_GTIA_READ::TRIG0 +(byte) ATARI_GTIA_READ::TRIG1 +(byte) ATARI_GTIA_READ::TRIG2 +(byte) ATARI_GTIA_READ::TRIG3 +(const byte*) ATARI_GTIA_READ::UNUSED[(number) $a] = { fill( $a, 0) } +(byte) ATARI_GTIA_WRITE::COLBK +(byte) ATARI_GTIA_WRITE::COLPF0 +(byte) ATARI_GTIA_WRITE::COLPF1 +(byte) ATARI_GTIA_WRITE::COLPF2 +(byte) ATARI_GTIA_WRITE::COLPF3 +(byte) ATARI_GTIA_WRITE::COLPM0 +(byte) ATARI_GTIA_WRITE::COLPM1 +(byte) ATARI_GTIA_WRITE::COLPM2 +(byte) ATARI_GTIA_WRITE::COLPM3 +(byte) ATARI_GTIA_WRITE::CONSPK +(byte) ATARI_GTIA_WRITE::GRACTL +(byte) ATARI_GTIA_WRITE::GRAFM +(byte) ATARI_GTIA_WRITE::GRAFP0 +(byte) ATARI_GTIA_WRITE::GRAFP1 +(byte) ATARI_GTIA_WRITE::GRAFP2 +(byte) ATARI_GTIA_WRITE::GRAFP3 +(byte) ATARI_GTIA_WRITE::HITCLR +(byte) ATARI_GTIA_WRITE::HPOSM0 +(byte) ATARI_GTIA_WRITE::HPOSM1 +(byte) ATARI_GTIA_WRITE::HPOSM2 +(byte) ATARI_GTIA_WRITE::HPOSM3 +(byte) ATARI_GTIA_WRITE::HPOSP0 +(byte) ATARI_GTIA_WRITE::HPOSP1 +(byte) ATARI_GTIA_WRITE::HPOSP2 +(byte) ATARI_GTIA_WRITE::HPOSP3 +(byte) ATARI_GTIA_WRITE::PRIOR +(byte) ATARI_GTIA_WRITE::SIZEM +(byte) ATARI_GTIA_WRITE::SIZEP0 +(byte) ATARI_GTIA_WRITE::SIZEP1 +(byte) ATARI_GTIA_WRITE::SIZEP2 +(byte) ATARI_GTIA_WRITE::SIZEP3 +(byte) ATARI_GTIA_WRITE::VDELAY +(byte) ATARI_POKEY_READ::ALLPOT +(byte) ATARI_POKEY_READ::IRQST +(byte) ATARI_POKEY_READ::KBCODE +(byte) ATARI_POKEY_READ::POT0 +(byte) ATARI_POKEY_READ::POT1 +(byte) ATARI_POKEY_READ::POT2 +(byte) ATARI_POKEY_READ::POT3 +(byte) ATARI_POKEY_READ::POT4 +(byte) ATARI_POKEY_READ::POT5 +(byte) ATARI_POKEY_READ::POT6 +(byte) ATARI_POKEY_READ::POT7 +(byte) ATARI_POKEY_READ::RANDOM +(byte) ATARI_POKEY_READ::SERIN +(byte) ATARI_POKEY_READ::SKSTAT +(const byte*) ATARI_POKEY_READ::UNUSED[(number) 2] = { fill( 2, 0) } +(byte) ATARI_POKEY_WRITE::AUDC1 +(byte) ATARI_POKEY_WRITE::AUDC2 +(byte) ATARI_POKEY_WRITE::AUDC3 +(byte) ATARI_POKEY_WRITE::AUDC4 +(byte) ATARI_POKEY_WRITE::AUDCTL +(byte) ATARI_POKEY_WRITE::AUDF1 +(byte) ATARI_POKEY_WRITE::AUDF2 +(byte) ATARI_POKEY_WRITE::AUDF3 +(byte) ATARI_POKEY_WRITE::AUDF4 +(byte) ATARI_POKEY_WRITE::IRQEN +(byte) ATARI_POKEY_WRITE::POTGO +(byte) ATARI_POKEY_WRITE::SEROUT +(byte) ATARI_POKEY_WRITE::SKCTL +(byte) ATARI_POKEY_WRITE::SKREST +(byte) ATARI_POKEY_WRITE::STIMER +(byte) ATARI_POKEY_WRITE::UNUSED +(const nomodify byte) BLANK4 = (byte) $30 +(const nomodify byte) BLANK8 = (byte) $70 +(const byte*) DISPLAY_LIST[] = { (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) LMS|(const nomodify byte) MODE7, <(const byte*) TEXT, >(const byte*) TEXT, (const nomodify byte) BLANK4, (const nomodify byte) MODE2, (const nomodify byte) JVB, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } +(const nomodify struct ATARI_GTIA_WRITE*) GTIA = (struct ATARI_GTIA_WRITE*) 53248 +(const nomodify byte) JVB = (byte) $41 +(const nomodify byte) LMS = (byte) $40 +(const nomodify byte) MODE2 = (byte) 2 +(const nomodify byte) MODE7 = (byte) 7 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST = (byte) 2 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = (byte) $b +(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC = (byte) $a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = (byte) $1a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = (byte) $16 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = (byte) $17 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = (byte) $18 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = (byte) $19 +(const byte*) TEXT[] = (byte*) "HELLO atari 8BITDemonstrates ANTIC display list!"sa +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(byte) main::c +(byte) main::c#1 reg byte y 101.0 +(byte) main::c#2 reg byte y 103.75 +(byte) main::col +(byte) main::col#1 reg byte x 2.75 +(byte) main::col#2 reg byte y 78.33333333333334 +(byte) main::col#8 reg byte y 22.0 +(byte) main::l +(byte) main::l#1 reg byte a 202.0 +(byte) main::l#2 reg byte a 60.599999999999994 + +reg byte a [ main::l#2 main::l#1 ] +reg byte y [ main::c#2 main::col#2 main::col#8 main::c#1 ] +reg byte x [ main::col#1 ] + + +FINAL ASSEMBLER +Score: 3634 + + // File Comments +// Raster Bars for Atari XL / XE + // Upstart + // Atari XL/XE XEX file minimal file +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="rasterbars.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // Global Constants & labels + // 2: High Resolution Text Mode. 8 scanlines per char, 32/40/48 chars wide. bit 7 controls inversion or blinking, based on modes in CHACTL. + .const MODE2 = 2 + // 7: Single color text in five colors. 16 scanlines per char, 16/20/24 chars wide. the upper two bits are used to select the foreground color used by 1 bits, with 00-11 producing PF0-PF3. + .const MODE7 = 7 + // Load memory scan counter (LMS operation) - Load memory scan counter with new 16-bit address. Can be combined with mode instructions by OR. + .const LMS = $40 + // Jump and wait for Vertical Blank - suspends the display list until vertical blank and then jumps. This is usually used to terminate the display list and restart it for the next frame. + .const JVB = $41 + // Blank 4 lines + .const BLANK4 = $30 + // Blank 8 lines + .const BLANK8 = $70 + .const OFFSET_STRUCT_ATARI_ANTIC_DLIST = 2 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = $16 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = $17 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = $18 + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = $19 + .const OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = $b + .const OFFSET_STRUCT_ATARI_ANTIC_WSYNC = $a + .const OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = $1a + // Atari GTIA write registers + .label GTIA = $d000 + // Atari ANTIC registers + .label ANTIC = $d400 +.segment Code + // main +main: { + // asm + // asm { sei } + // Disable IRQ + sei + // ANTIC->DMACTL = 0x21 + // [1] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC) ← (byte) $21 -- _deref_pbuc1=vbuc2 + // Enable DMA, Narrow Playfield - ANTIC Direct Memory Access Control + lda #$21 + sta ANTIC + // ANTIC->DLIST = DISPLAY_LIST + // [2] *((byte**)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2 + // Set ANTIC Display List Pointer + lda #DISPLAY_LIST + sta ANTIC+OFFSET_STRUCT_ATARI_ANTIC_DLIST+1 + // GTIA->COLPF0 = 0x28 + // [3] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0) ← (byte) $28 -- _deref_pbuc1=vbuc2 + // Set colors + lda #$28 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 + // GTIA->COLPF1 = 0x48 + // [4] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1) ← (byte) $48 -- _deref_pbuc1=vbuc2 + lda #$48 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 + // GTIA->COLPF2 = 0x80 + // [5] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 + // GTIA->COLPF3 = 0xc8 + // [6] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3) ← (byte) $c8 -- _deref_pbuc1=vbuc2 + lda #$c8 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 + // [7] phi from main to main::@1 [phi:main->main::@1] + // [7] phi (byte) main::col#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + // [7] phi from main::@1 main::@5 to main::@1 [phi:main::@1/main::@5->main::@1] + // [7] phi (byte) main::col#2 = (byte) main::col#2 [phi:main::@1/main::@5->main::@1#0] -- register_copy + // main::@1 + __b1: + // while(ANTIC->VCOUNT!=40) + // [8] if(*((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT)!=(byte) $28) goto main::@1 -- _deref_pbuc1_neq_vbuc2_then_la1 + lda #$28 + cmp ANTIC+OFFSET_STRUCT_ATARI_ANTIC_VCOUNT + bne __b1 + // main::@2 + // c = col++ + // [9] (byte) main::col#1 ← ++ (byte) main::col#2 -- vbuxx=_inc_vbuyy + tya + tax + inx + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + // [10] phi (byte) main::c#2 = (byte) main::col#2 [phi:main::@2->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuaa=vbuc1 + lda #0 + // main::@3 + __b3: + // for( char l=0;l<100;l++) + // [11] if((byte) main::l#2<(byte) $64) goto main::@4 -- vbuaa_lt_vbuc1_then_la1 + cmp #$64 + bcc __b4 + // main::@5 + // GTIA->COLBK = 0 + // [12] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // [13] (byte) main::col#8 ← (byte) main::col#1 -- vbuyy=vbuxx + txa + tay + jmp __b1 + // main::@4 + __b4: + // ANTIC->WSYNC = c + // [14] *((byte*)(const nomodify struct ATARI_ANTIC*) ANTIC+(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC) ← (byte) main::c#2 -- _deref_pbuc1=vbuyy + sty ANTIC+OFFSET_STRUCT_ATARI_ANTIC_WSYNC + // GTIA->COLBK = c + // [15] *((byte*)(const nomodify struct ATARI_GTIA_WRITE*) GTIA+(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuyy + sty GTIA+OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK + // c++; + // [16] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuyy=_inc_vbuyy + iny + // for( char l=0;l<100;l++) + // [17] (byte) main::l#1 ← ++ (byte) main::l#2 -- vbuaa=_inc_vbuaa + clc + adc #1 + // [10] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + // [10] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@4->main::@3#0] -- register_copy + // [10] phi (byte) main::l#2 = (byte) main::l#1 [phi:main::@4->main::@3#1] -- register_copy + jmp __b3 +} + // File Data +.segment Data + // Message to show +.encoding "ascii" + TEXT: .text @"\$28\$25\$2c\$2c\$2f\$00atari\$00\$18\$22\$29\$34\$24emonstrates\$00\$21\$2e\$34\$29\$23\$00display\$00list\$01" + .byte 0 + // ANTIC Display List Program + // https://en.wikipedia.org/wiki/ANTIC + DISPLAY_LIST: .byte BLANK8, BLANK8, BLANK8, LMS|MODE7, TEXT, BLANK4, MODE2, JVB, DISPLAY_LIST + diff --git a/src/test/ref/examples/atarixl/rasterbars.sym b/src/test/ref/examples/atarixl/rasterbars.sym new file mode 100644 index 000000000..645e4d1b2 --- /dev/null +++ b/src/test/ref/examples/atarixl/rasterbars.sym @@ -0,0 +1,139 @@ +(const nomodify struct ATARI_ANTIC*) ANTIC = (struct ATARI_ANTIC*) 54272 +(byte) ATARI_ANTIC::CHACTL +(byte) ATARI_ANTIC::CHBASE +(byte*) ATARI_ANTIC::DLIST +(byte) ATARI_ANTIC::DMACTL +(byte) ATARI_ANTIC::HSCROL +(byte) ATARI_ANTIC::NMIEN +(byte) ATARI_ANTIC::NMIST +(byte) ATARI_ANTIC::PENH +(byte) ATARI_ANTIC::PENV +(byte) ATARI_ANTIC::PMBASE +(byte) ATARI_ANTIC::UNUSED1 +(byte) ATARI_ANTIC::UNUSED2 +(byte) ATARI_ANTIC::VCOUNT +(byte) ATARI_ANTIC::VSCROL +(byte) ATARI_ANTIC::WSYNC +(byte) ATARI_GTIA_READ::CONSOL +(byte) ATARI_GTIA_READ::M0PF +(byte) ATARI_GTIA_READ::M0PL +(byte) ATARI_GTIA_READ::M1PF +(byte) ATARI_GTIA_READ::M1PL +(byte) ATARI_GTIA_READ::M2PF +(byte) ATARI_GTIA_READ::M2PL +(byte) ATARI_GTIA_READ::M3PF +(byte) ATARI_GTIA_READ::M3PL +(byte) ATARI_GTIA_READ::P0PF +(byte) ATARI_GTIA_READ::P0PL +(byte) ATARI_GTIA_READ::P1PF +(byte) ATARI_GTIA_READ::P1PL +(byte) ATARI_GTIA_READ::P2PF +(byte) ATARI_GTIA_READ::P2PL +(byte) ATARI_GTIA_READ::P3PF +(byte) ATARI_GTIA_READ::P3PL +(byte) ATARI_GTIA_READ::PAL +(byte) ATARI_GTIA_READ::TRIG0 +(byte) ATARI_GTIA_READ::TRIG1 +(byte) ATARI_GTIA_READ::TRIG2 +(byte) ATARI_GTIA_READ::TRIG3 +(const byte*) ATARI_GTIA_READ::UNUSED[(number) $a] = { fill( $a, 0) } +(byte) ATARI_GTIA_WRITE::COLBK +(byte) ATARI_GTIA_WRITE::COLPF0 +(byte) ATARI_GTIA_WRITE::COLPF1 +(byte) ATARI_GTIA_WRITE::COLPF2 +(byte) ATARI_GTIA_WRITE::COLPF3 +(byte) ATARI_GTIA_WRITE::COLPM0 +(byte) ATARI_GTIA_WRITE::COLPM1 +(byte) ATARI_GTIA_WRITE::COLPM2 +(byte) ATARI_GTIA_WRITE::COLPM3 +(byte) ATARI_GTIA_WRITE::CONSPK +(byte) ATARI_GTIA_WRITE::GRACTL +(byte) ATARI_GTIA_WRITE::GRAFM +(byte) ATARI_GTIA_WRITE::GRAFP0 +(byte) ATARI_GTIA_WRITE::GRAFP1 +(byte) ATARI_GTIA_WRITE::GRAFP2 +(byte) ATARI_GTIA_WRITE::GRAFP3 +(byte) ATARI_GTIA_WRITE::HITCLR +(byte) ATARI_GTIA_WRITE::HPOSM0 +(byte) ATARI_GTIA_WRITE::HPOSM1 +(byte) ATARI_GTIA_WRITE::HPOSM2 +(byte) ATARI_GTIA_WRITE::HPOSM3 +(byte) ATARI_GTIA_WRITE::HPOSP0 +(byte) ATARI_GTIA_WRITE::HPOSP1 +(byte) ATARI_GTIA_WRITE::HPOSP2 +(byte) ATARI_GTIA_WRITE::HPOSP3 +(byte) ATARI_GTIA_WRITE::PRIOR +(byte) ATARI_GTIA_WRITE::SIZEM +(byte) ATARI_GTIA_WRITE::SIZEP0 +(byte) ATARI_GTIA_WRITE::SIZEP1 +(byte) ATARI_GTIA_WRITE::SIZEP2 +(byte) ATARI_GTIA_WRITE::SIZEP3 +(byte) ATARI_GTIA_WRITE::VDELAY +(byte) ATARI_POKEY_READ::ALLPOT +(byte) ATARI_POKEY_READ::IRQST +(byte) ATARI_POKEY_READ::KBCODE +(byte) ATARI_POKEY_READ::POT0 +(byte) ATARI_POKEY_READ::POT1 +(byte) ATARI_POKEY_READ::POT2 +(byte) ATARI_POKEY_READ::POT3 +(byte) ATARI_POKEY_READ::POT4 +(byte) ATARI_POKEY_READ::POT5 +(byte) ATARI_POKEY_READ::POT6 +(byte) ATARI_POKEY_READ::POT7 +(byte) ATARI_POKEY_READ::RANDOM +(byte) ATARI_POKEY_READ::SERIN +(byte) ATARI_POKEY_READ::SKSTAT +(const byte*) ATARI_POKEY_READ::UNUSED[(number) 2] = { fill( 2, 0) } +(byte) ATARI_POKEY_WRITE::AUDC1 +(byte) ATARI_POKEY_WRITE::AUDC2 +(byte) ATARI_POKEY_WRITE::AUDC3 +(byte) ATARI_POKEY_WRITE::AUDC4 +(byte) ATARI_POKEY_WRITE::AUDCTL +(byte) ATARI_POKEY_WRITE::AUDF1 +(byte) ATARI_POKEY_WRITE::AUDF2 +(byte) ATARI_POKEY_WRITE::AUDF3 +(byte) ATARI_POKEY_WRITE::AUDF4 +(byte) ATARI_POKEY_WRITE::IRQEN +(byte) ATARI_POKEY_WRITE::POTGO +(byte) ATARI_POKEY_WRITE::SEROUT +(byte) ATARI_POKEY_WRITE::SKCTL +(byte) ATARI_POKEY_WRITE::SKREST +(byte) ATARI_POKEY_WRITE::STIMER +(byte) ATARI_POKEY_WRITE::UNUSED +(const nomodify byte) BLANK4 = (byte) $30 +(const nomodify byte) BLANK8 = (byte) $70 +(const byte*) DISPLAY_LIST[] = { (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) BLANK8, (const nomodify byte) LMS|(const nomodify byte) MODE7, <(const byte*) TEXT, >(const byte*) TEXT, (const nomodify byte) BLANK4, (const nomodify byte) MODE2, (const nomodify byte) JVB, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } +(const nomodify struct ATARI_GTIA_WRITE*) GTIA = (struct ATARI_GTIA_WRITE*) 53248 +(const nomodify byte) JVB = (byte) $41 +(const nomodify byte) LMS = (byte) $40 +(const nomodify byte) MODE2 = (byte) 2 +(const nomodify byte) MODE7 = (byte) 7 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_DLIST = (byte) 2 +(const byte) OFFSET_STRUCT_ATARI_ANTIC_VCOUNT = (byte) $b +(const byte) OFFSET_STRUCT_ATARI_ANTIC_WSYNC = (byte) $a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLBK = (byte) $1a +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF0 = (byte) $16 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF1 = (byte) $17 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF2 = (byte) $18 +(const byte) OFFSET_STRUCT_ATARI_GTIA_WRITE_COLPF3 = (byte) $19 +(const byte*) TEXT[] = (byte*) "HELLO atari 8BITDemonstrates ANTIC display list!"sa +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(byte) main::c +(byte) main::c#1 reg byte y 101.0 +(byte) main::c#2 reg byte y 103.75 +(byte) main::col +(byte) main::col#1 reg byte x 2.75 +(byte) main::col#2 reg byte y 78.33333333333334 +(byte) main::col#8 reg byte y 22.0 +(byte) main::l +(byte) main::l#1 reg byte a 202.0 +(byte) main::l#2 reg byte a 60.599999999999994 + +reg byte a [ main::l#2 main::l#1 ] +reg byte y [ main::c#2 main::col#2 main::col#8 main::c#1 ] +reg byte x [ main::col#1 ]