mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-24 04:31:02 +00:00
Added Atari XL/XE platform target generating a simple XEX-file. Closes #499
This commit is contained in:
parent
a7359f8395
commit
392ab7e442
@ -766,12 +766,6 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
// Rewrite (Z1),x to save Y to $FF and reload it into YY
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuxx=(.*)", twoZM1, "stx $ff" , "vb$1aa=$2", "ldz $ff\nsta ({z1}),z", mapZM1));
|
||||
|
||||
// TODO: Rewrite (Z1),y assignment to use A
|
||||
//synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuyy=(.*)", twoZM1+"|"+rvalYy, null , "vb$1aa=$2", "sta ({z1}),y", null, "yy"));
|
||||
//if(targetCpu.getCpu65xx().hasRegisterZ())
|
||||
// Rewrite (Z1),z assignment to use A
|
||||
// synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuzz=(.*)", twoZM1+"|"+rvalZz, null , "vb$1aa=$2", "sta ({z1}),z", null, "zz"));
|
||||
|
||||
// Rewrite (Z1),a to use TAY prefix
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuaa=(.*)", twoZM1+"|"+rvalYy, "tay" , "vb$1aa=$2", "sta ({z1}),y", mapZM1, "yy"));
|
||||
if(targetCpu.getCpu65xx().hasRegisterZ())
|
||||
|
22
src/main/kc/target/atarixl.ld
Normal file
22
src/main/kc/target/atarixl.ld
Normal file
@ -0,0 +1,22 @@
|
||||
// Atari XL/XE XEX file minimal file
|
||||
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
.file [name="%O", type="bin", segments="XexFile"]
|
||||
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
|
||||
.segmentdef ProgramStart [start=$2000]
|
||||
.segmentdef Code [startAfter="ProgramStart"]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef ProgramEnd [startAfter="Data"]
|
||||
.segment ProgramStart
|
||||
ProgramStart:
|
||||
.segment ProgramEnd
|
||||
ProgramEnd:
|
||||
.segmentdef XexFile
|
||||
.segment XexFile
|
||||
// Binary File Header
|
||||
.byte $ff, $ff
|
||||
// Program segment [start address, end address, data]
|
||||
.word ProgramStart, ProgramEnd
|
||||
.segmentout [ segments="Program" ]
|
||||
// RunAd - Run Address Segment [start address, end address, data]
|
||||
.word $02e0, $02e1
|
||||
.word %E
|
9
src/main/kc/target/atarixl.tgt
Normal file
9
src/main/kc/target/atarixl.tgt
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extension": "xex",
|
||||
"link": "atarixl.ld",
|
||||
"cpu": "MOS6502X",
|
||||
"emulator": "65XEDebugger",
|
||||
"defines": {
|
||||
"__ATARIXL__": 1
|
||||
}
|
||||
}
|
@ -192,6 +192,11 @@ public class TestPrograms {
|
||||
compileAndCompare("examples/nes-demo/nes-demo.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtariXlHello() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/atarixl/helloxl.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtari2600Sprites() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/atari2600/atari2600-sprites.c");
|
||||
|
64
src/test/kc/examples/atarixl/helloxl.c
Normal file
64
src/test/kc/examples/atarixl/helloxl.c
Normal file
@ -0,0 +1,64 @@
|
||||
// Hello World for Atari XL / XE
|
||||
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
|
||||
// Display Lists atariarchives.org/mapping/appendix8.php
|
||||
|
||||
#pragma target(atarixl)
|
||||
|
||||
// Direct Memory Access Control
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// - - - - - - 0 0 No playfield
|
||||
// - - - - - - 0 1 Narrow playfield (128 color clocks 32 characters)
|
||||
// - - - - - - 1 0 Standard playfield (160 color clocks 40 characters) (default)
|
||||
// - - - - - - 1 1 Wide playfield (192 color clocks 48 characters)
|
||||
// - - - - - 1 - - Enable missle DMA
|
||||
// - - - - 1 - - - Enable player DMA
|
||||
// - - - 1 - - - - One line player resolution
|
||||
// - - - 0 - - - - Two-line player resolution (default)
|
||||
// - - 1 - - - - - Enable DMA for fetching the display list instructions (default)
|
||||
// SHADOW: SDMCTL $022F
|
||||
char * const ANTIC_DMACTL = 0xd400;
|
||||
|
||||
// OS Shadow ANTIC Direct Memory Access Control
|
||||
char * const SDMCTL = 0x022f;
|
||||
|
||||
// Character Control
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// - - - - - - - 1 Video Blank. Inverse video characters display as blanks spaces.
|
||||
// - - - - - - 1 - Video Inverse. Inverse video characters appear as inverse video. (default)
|
||||
// - - - - - 1 - - Video Reflect. All characters are displayed vertically mirrored.
|
||||
// SHADOW: CHART $02F3
|
||||
char * const ANTIC_CHACTL = 0xd401;
|
||||
|
||||
// OS Shadow ANTIC Character Control
|
||||
char * const CHART = 0x02f3;
|
||||
|
||||
// Display List Pointer
|
||||
// ANTIC begins executing the Display List pointed to by the 16-bit address in registers DLISTL/DLISTH
|
||||
// SHADOW: SDLSTL/SDLSTH $0230/$0231
|
||||
char ** const ANTIC_DLIST = 0xd402;
|
||||
|
||||
// OS Shadow ANTIC Display List Pointer
|
||||
char ** const SDLST = 0x0230;
|
||||
|
||||
void main() {
|
||||
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
|
||||
*SDMCTL = 0x21;
|
||||
// Set Shadow ANTIC Display List Pointer
|
||||
*SDLST = DISPLAY_LIST;
|
||||
// Loop forever
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
// Message to show
|
||||
// Encoding: atari_internal
|
||||
char TEXT[] = {'h'|0x20,'e'|0x20,'l'|0x20,'l'|0x20,'o'|0x20,0x0,'x'|0x60,'t'|0x60,0x0,'w'|0x20,'o'|0x20,'r'|0x20,'l'|0x20,'d'|0x20,0x41,0x0,0x0,0x0,0x0};
|
||||
|
||||
// ANTIC Display List Program
|
||||
// https://en.wikipedia.org/wiki/ANTIC
|
||||
char DISPLAY_LIST[] = {
|
||||
0x70, 0x70, 0x70, // 3* BLK 8 (0x70) 8 blank lines
|
||||
0x47, <TEXT, >TEXT, // LMS 7, TEXT (0x47) Load memory address and set to charmode 7 (16/20/24 chars wide, 16 lines per char)
|
||||
0x41, <DISPLAY_LIST, >DISPLAY_LIST // JVB DISPLAY_LIST (0x41) jump and wait for VBLANK
|
||||
};
|
||||
|
53
src/test/ref/examples/atarixl/helloxl.asm
Normal file
53
src/test/ref/examples/atarixl/helloxl.asm
Normal file
@ -0,0 +1,53 @@
|
||||
// Hello World for Atari XL / XE
|
||||
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
|
||||
// Display Lists atariarchives.org/mapping/appendix8.php
|
||||
// Atari XL/XE minimal XEX file
|
||||
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
.file [name="helloxl.xex", type="bin", segments="XexFile"]
|
||||
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
|
||||
.segmentdef ProgramStart [start=$2000]
|
||||
.segmentdef Code [startAfter="ProgramStart"]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef ProgramEnd [startAfter="Data"]
|
||||
.segment ProgramStart
|
||||
ProgramStart:
|
||||
.segment ProgramEnd
|
||||
ProgramEnd:
|
||||
.segmentdef XexFile
|
||||
.segment XexFile
|
||||
// Binary File Header
|
||||
.byte $ff, $ff
|
||||
// Program segment [start address, end address, data]
|
||||
.word ProgramStart, ProgramEnd
|
||||
.segmentout [ segments="Program" ]
|
||||
// RunAd - Run Address Segment [start address, end address, data]
|
||||
.word $02e0, $02e1
|
||||
.word main
|
||||
// OS Shadow ANTIC Direct Memory Access Control
|
||||
.label SDMCTL = $22f
|
||||
// OS Shadow ANTIC Display List Pointer
|
||||
.label SDLST = $230
|
||||
.segment Code
|
||||
main: {
|
||||
// *SDMCTL = 0x21
|
||||
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
|
||||
lda #$21
|
||||
sta SDMCTL
|
||||
// *SDLST = DISPLAY_LIST
|
||||
// Set Shadow ANTIC Display List Pointer
|
||||
lda #<DISPLAY_LIST
|
||||
sta SDLST
|
||||
lda #>DISPLAY_LIST
|
||||
sta SDLST+1
|
||||
__b1:
|
||||
// Loop forever
|
||||
jmp __b1
|
||||
}
|
||||
.segment Data
|
||||
// Message to show
|
||||
// Encoding: atari_internal
|
||||
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
|
||||
// ANTIC Display List Program
|
||||
// https://en.wikipedia.org/wiki/ANTIC
|
||||
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
|
9
src/test/ref/examples/atarixl/helloxl.cfg
Normal file
9
src/test/ref/examples/atarixl/helloxl.cfg
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
[0] *((const nomodify byte*) SDMCTL) ← (byte) $21
|
||||
[1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[2] phi()
|
||||
to:main::@1
|
363
src/test/ref/examples/atarixl/helloxl.log
Normal file
363
src/test/ref/examples/atarixl/helloxl.log
Normal file
@ -0,0 +1,363 @@
|
||||
Resolved forward reference DISPLAY_LIST to (const byte*) DISPLAY_LIST
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from __start
|
||||
*((const nomodify byte*) SDMCTL) ← (number) $21
|
||||
*((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(bool~) main::$0 ← (number) 0 != (number) 1
|
||||
if((bool~) main::$0) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
(void()) __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
|
||||
(const nomodify byte**) SDLST = (byte**)(number) $230
|
||||
(const nomodify byte*) SDMCTL = (byte*)(number) $22f
|
||||
(const byte*) TEXT[] = { (byte)(byte) 'h'|(number) $20, (byte)(byte) 'e'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte) 0, (byte)(byte) 'x'|(number) $60, (byte)(byte) 't'|(number) $60, (byte) 0, (byte)(byte) 'w'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte)(byte) 'r'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'd'|(number) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
|
||||
(void()) __start()
|
||||
(label) __start::@1
|
||||
(label) __start::@return
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $60 in
|
||||
Adding number conversion cast (unumber) $60 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $20 in
|
||||
Adding number conversion cast (unumber) $21 in *((const nomodify byte*) SDMCTL) ← (number) $21
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((const nomodify byte*) SDMCTL) ← (unumber)(number) $21
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 559
|
||||
Simplifying constant pointer cast (byte**) 560
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $60
|
||||
Simplifying constant integer cast $60
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $20
|
||||
Simplifying constant integer cast $21
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $60
|
||||
Finalized unsigned number type (byte) $60
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $20
|
||||
Finalized unsigned number type (byte) $21
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Simple Condition (bool~) main::$0 [3] if((number) 0!=(number) 1) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
if() condition always true - replacing block destination [3] if((number) 0!=(number) 1) goto main::@1
|
||||
Successful SSA optimization Pass2ConstantIfs
|
||||
Removing unused block main::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Removing unused procedure __start
|
||||
Removing unused procedure block __start
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@return
|
||||
Successful SSA optimization PassNEliminateEmptyStart
|
||||
Simplifying constant integer cast (byte) 'h'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'e'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'l'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'l'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'o'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'x'|(byte) $60
|
||||
Simplifying constant integer cast (byte) 't'|(byte) $60
|
||||
Simplifying constant integer cast (byte) 'w'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'o'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'r'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'l'|(byte) $20
|
||||
Simplifying constant integer cast (byte) 'd'|(byte) $20
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Adding NOP phi() at start of main::@1
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Adding NOP phi() at start of main::@1
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
[0] *((const nomodify byte*) SDMCTL) ← (byte) $21
|
||||
[1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[2] phi()
|
||||
to:main::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is atarixl / MOS6502X
|
||||
// File Comments
|
||||
// Hello World for Atari XL / XE
|
||||
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
|
||||
// Display Lists atariarchives.org/mapping/appendix8.php
|
||||
// Upstart
|
||||
// Atari XL/XE minimal XEX file
|
||||
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
.file [name="helloxl.xex", type="bin", segments="XexFile"]
|
||||
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
|
||||
.segmentdef ProgramStart [start=$2000]
|
||||
.segmentdef Code [startAfter="ProgramStart"]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef ProgramEnd [startAfter="Data"]
|
||||
.segment ProgramStart
|
||||
ProgramStart:
|
||||
.segment ProgramEnd
|
||||
ProgramEnd:
|
||||
.segmentdef XexFile
|
||||
.segment XexFile
|
||||
// Binary File Header
|
||||
.byte $ff, $ff
|
||||
// Program segment [start address, end address, data]
|
||||
.word ProgramStart, ProgramEnd
|
||||
.segmentout [ segments="Program" ]
|
||||
// RunAd - Run Address Segment [start address, end address, data]
|
||||
.word $02e0, $02e1
|
||||
.word main
|
||||
// Global Constants & labels
|
||||
// OS Shadow ANTIC Direct Memory Access Control
|
||||
.label SDMCTL = $22f
|
||||
// OS Shadow ANTIC Display List Pointer
|
||||
.label SDLST = $230
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
|
||||
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
|
||||
lda #$21
|
||||
sta SDMCTL
|
||||
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
|
||||
// Set Shadow ANTIC Display List Pointer
|
||||
lda #<DISPLAY_LIST
|
||||
sta SDLST
|
||||
lda #>DISPLAY_LIST
|
||||
sta SDLST+1
|
||||
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
|
||||
__b1_from_main:
|
||||
__b1_from___b1:
|
||||
jmp __b1
|
||||
// Loop forever
|
||||
// main::@1
|
||||
__b1:
|
||||
jmp __b1_from___b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
// Message to show
|
||||
// Encoding: atari_internal
|
||||
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
|
||||
// ANTIC Display List Program
|
||||
// https://en.wikipedia.org/wiki/ANTIC
|
||||
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 78 combination
|
||||
Uplifting [] best 78 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Hello World for Atari XL / XE
|
||||
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
|
||||
// Display Lists atariarchives.org/mapping/appendix8.php
|
||||
// Upstart
|
||||
// Atari XL/XE minimal XEX file
|
||||
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
.file [name="helloxl.xex", type="bin", segments="XexFile"]
|
||||
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
|
||||
.segmentdef ProgramStart [start=$2000]
|
||||
.segmentdef Code [startAfter="ProgramStart"]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef ProgramEnd [startAfter="Data"]
|
||||
.segment ProgramStart
|
||||
ProgramStart:
|
||||
.segment ProgramEnd
|
||||
ProgramEnd:
|
||||
.segmentdef XexFile
|
||||
.segment XexFile
|
||||
// Binary File Header
|
||||
.byte $ff, $ff
|
||||
// Program segment [start address, end address, data]
|
||||
.word ProgramStart, ProgramEnd
|
||||
.segmentout [ segments="Program" ]
|
||||
// RunAd - Run Address Segment [start address, end address, data]
|
||||
.word $02e0, $02e1
|
||||
.word main
|
||||
// Global Constants & labels
|
||||
// OS Shadow ANTIC Direct Memory Access Control
|
||||
.label SDMCTL = $22f
|
||||
// OS Shadow ANTIC Display List Pointer
|
||||
.label SDLST = $230
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
|
||||
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
|
||||
lda #$21
|
||||
sta SDMCTL
|
||||
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
|
||||
// Set Shadow ANTIC Display List Pointer
|
||||
lda #<DISPLAY_LIST
|
||||
sta SDLST
|
||||
lda #>DISPLAY_LIST
|
||||
sta SDLST+1
|
||||
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
|
||||
__b1_from_main:
|
||||
__b1_from___b1:
|
||||
jmp __b1
|
||||
// Loop forever
|
||||
// main::@1
|
||||
__b1:
|
||||
jmp __b1_from___b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
// Message to show
|
||||
// Encoding: atari_internal
|
||||
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
|
||||
// ANTIC Display List Program
|
||||
// https://en.wikipedia.org/wiki/ANTIC
|
||||
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Relabelling long label __b1_from___b1 to __b1
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
|
||||
(const nomodify byte**) SDLST = (byte**) 560
|
||||
(const nomodify byte*) SDMCTL = (byte*) 559
|
||||
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 48
|
||||
|
||||
// File Comments
|
||||
// Hello World for Atari XL / XE
|
||||
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
|
||||
// Display Lists atariarchives.org/mapping/appendix8.php
|
||||
// Upstart
|
||||
// Atari XL/XE minimal XEX file
|
||||
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
|
||||
.file [name="helloxl.xex", type="bin", segments="XexFile"]
|
||||
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
|
||||
.segmentdef ProgramStart [start=$2000]
|
||||
.segmentdef Code [startAfter="ProgramStart"]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef ProgramEnd [startAfter="Data"]
|
||||
.segment ProgramStart
|
||||
ProgramStart:
|
||||
.segment ProgramEnd
|
||||
ProgramEnd:
|
||||
.segmentdef XexFile
|
||||
.segment XexFile
|
||||
// Binary File Header
|
||||
.byte $ff, $ff
|
||||
// Program segment [start address, end address, data]
|
||||
.word ProgramStart, ProgramEnd
|
||||
.segmentout [ segments="Program" ]
|
||||
// RunAd - Run Address Segment [start address, end address, data]
|
||||
.word $02e0, $02e1
|
||||
.word main
|
||||
// Global Constants & labels
|
||||
// OS Shadow ANTIC Direct Memory Access Control
|
||||
.label SDMCTL = $22f
|
||||
// OS Shadow ANTIC Display List Pointer
|
||||
.label SDLST = $230
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// *SDMCTL = 0x21
|
||||
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
|
||||
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
|
||||
lda #$21
|
||||
sta SDMCTL
|
||||
// *SDLST = DISPLAY_LIST
|
||||
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
|
||||
// Set Shadow ANTIC Display List Pointer
|
||||
lda #<DISPLAY_LIST
|
||||
sta SDLST
|
||||
lda #>DISPLAY_LIST
|
||||
sta SDLST+1
|
||||
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
|
||||
__b1:
|
||||
// Loop forever
|
||||
// main::@1
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
// Message to show
|
||||
// Encoding: atari_internal
|
||||
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
|
||||
// ANTIC Display List Program
|
||||
// https://en.wikipedia.org/wiki/ANTIC
|
||||
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
|
||||
|
7
src/test/ref/examples/atarixl/helloxl.sym
Normal file
7
src/test/ref/examples/atarixl/helloxl.sym
Normal file
@ -0,0 +1,7 @@
|
||||
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
|
||||
(const nomodify byte**) SDLST = (byte**) 560
|
||||
(const nomodify byte*) SDMCTL = (byte*) 559
|
||||
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
|
Loading…
Reference in New Issue
Block a user