mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-25 20:32:25 +00:00
Added support for VIC20 targets with +3k and +8k memory expansion. Closes #728
This commit is contained in:
parent
73395870db
commit
70190a9e8e
@ -10,12 +10,22 @@
|
||||
#error "Target platform must be VIC20"
|
||||
#endif
|
||||
|
||||
#ifdef __VIC20_8K__
|
||||
/// Default address of screen color matrix
|
||||
char * const DEFAULT_COLORRAM = (char*)0x9400;
|
||||
/// Default address of screen character matrix
|
||||
char * const DEFAULT_SCREEN = (char*)0x1000;
|
||||
#else
|
||||
/// Default address of screen color matrix
|
||||
char * const DEFAULT_COLORRAM = (char*)0x9600;
|
||||
/// Address of screen color matrix if bit 7 of $9002 is 1
|
||||
char * const ALTERNATIVE_COLORRAM = (char*)0x9400;
|
||||
/// Default address of screen character matrix
|
||||
char * const DEFAULT_SCREEN = (char*)0x1e00;
|
||||
#endif
|
||||
|
||||
/// Address of screen color matrix if bit 7 of $9002 is 0
|
||||
char * const PRIMARY_COLORRAM = (char*)0x9400;
|
||||
/// Address of screen color matrix if bit 7 of $9002 is 1
|
||||
char * const SECONDARY_COLORRAM = (char*)0x9600;
|
||||
|
||||
/// The address of the CHARGEN character set
|
||||
char * const CHARGEN = (char*)0x8000;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="%O", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"description": "Commodore VIC 20 executable PRG file",
|
||||
"description": "Commodore VIC 20 unexpanded executable PRG file",
|
||||
"extension": "prg",
|
||||
"link": "vic20.ld",
|
||||
"start_address": "0x100d",
|
||||
@ -8,6 +8,7 @@
|
||||
"zp_reserve": [ "0xfc..0xff" ],
|
||||
"emulator": "xvic",
|
||||
"defines": {
|
||||
"__VIC20__": 1
|
||||
"__VIC20__": 1,
|
||||
"__VIC20_0K_": 1
|
||||
}
|
||||
}
|
8
src/main/kc/target/vic20_3k.ld
Normal file
8
src/main/kc/target/vic20_3k.ld
Normal file
@ -0,0 +1,8 @@
|
||||
// Commodore VIC 20 +3k expanded executable PRG file
|
||||
.file [name="%O", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0401]
|
||||
.segmentdef Code [start=%P]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(%E)
|
14
src/main/kc/target/vic20_3k.tgt
Normal file
14
src/main/kc/target/vic20_3k.tgt
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"description": "Commodore VIC 20 +3k expanded executable PRG file",
|
||||
"extension": "prg",
|
||||
"link": "vic20_3k.ld",
|
||||
"start_address": "0x040d",
|
||||
"cpu": "MOS6502X",
|
||||
"interrupt": "rom_min_vic20",
|
||||
"zp_reserve": [ "0xfc..0xff" ],
|
||||
"emulator": "xvic -memory 3k",
|
||||
"defines": {
|
||||
"__VIC20__": 1,
|
||||
"__VIC20_3K__": 1
|
||||
}
|
||||
}
|
8
src/main/kc/target/vic20_8k.ld
Normal file
8
src/main/kc/target/vic20_8k.ld
Normal file
@ -0,0 +1,8 @@
|
||||
// Commodore VIC 20 +8k expanded executable PRG file
|
||||
.file [name="%O", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1201]
|
||||
.segmentdef Code [start=%P]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(%E)
|
13
src/main/kc/target/vic20_8k.tgt
Normal file
13
src/main/kc/target/vic20_8k.tgt
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"description": "Commodore VIC 20 +8k expanded executable PRG file",
|
||||
"extension": "prg",
|
||||
"link": "vic20_8k.ld",
|
||||
"start_address": "0x120d",
|
||||
"cpu": "MOS6502X",
|
||||
"interrupt": "rom_min_vic20",
|
||||
"emulator": "xvic -memory 8k",
|
||||
"defines": {
|
||||
"__VIC20__": 1,
|
||||
"__VIC20_8K__": 1
|
||||
}
|
||||
}
|
@ -810,6 +810,16 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("vic20-simple.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVic20_3kSimple() throws IOException {
|
||||
compileAndCompare("vic20-3k-simple.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVic20_8kSimple() throws IOException {
|
||||
compileAndCompare("vic20-8k-simple.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlus4KeyboardTest() throws IOException {
|
||||
compileAndCompare("plus4-keyboard-test.c");
|
||||
|
12
src/test/kc/vic20-3k-simple.c
Normal file
12
src/test/kc/vic20-3k-simple.c
Normal file
@ -0,0 +1,12 @@
|
||||
// Trivial VIC 20 program
|
||||
#pragma target(vic20_3k)
|
||||
#include <vic20.h>
|
||||
|
||||
char MESSAGE[] = "hello world!";
|
||||
|
||||
void main() {
|
||||
for(char i=0; MESSAGE[i]; i++) {
|
||||
DEFAULT_SCREEN[i] = MESSAGE[i];
|
||||
DEFAULT_COLORRAM[i] = RED;
|
||||
}
|
||||
}
|
12
src/test/kc/vic20-8k-simple.c
Normal file
12
src/test/kc/vic20-8k-simple.c
Normal file
@ -0,0 +1,12 @@
|
||||
// Trivial VIC 20 program
|
||||
#pragma target(vic20_8k)
|
||||
#include <vic20.h>
|
||||
|
||||
char MESSAGE[] = "hello world!";
|
||||
|
||||
void main() {
|
||||
for(char i=0; MESSAGE[i]; i++) {
|
||||
DEFAULT_SCREEN[i] = MESSAGE[i];
|
||||
DEFAULT_COLORRAM[i] = RED;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// Test #pragma without parenthesis
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="pragma-noparenthesis.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
@ -132,7 +132,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test #pragma without parenthesis
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="pragma-noparenthesis.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
@ -220,7 +220,7 @@ Score: 42
|
||||
// File Comments
|
||||
// Test #pragma without parenthesis
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="pragma-noparenthesis.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
48
src/test/ref/vic20-3k-simple.asm
Normal file
48
src/test/ref/vic20-3k-simple.asm
Normal file
@ -0,0 +1,48 @@
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Commodore VIC 20 +3k expanded executable PRG file
|
||||
.file [name="vic20-3k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0401]
|
||||
.segmentdef Code [start=$40d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9600
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1e00
|
||||
.segment Code
|
||||
main: {
|
||||
ldx #0
|
||||
__b1:
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// DEFAULT_SCREEN[i] = MESSAGE[i]
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// DEFAULT_COLORRAM[i] = RED
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
inx
|
||||
jmp __b1
|
||||
}
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
17
src/test/ref/vic20-3k-simple.cfg
Normal file
17
src/test/ref/vic20-3k-simple.cfg
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
|
||||
[2] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2]
|
||||
[5] DEFAULT_COLORRAM[main::i#2] = RED
|
||||
[6] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
286
src/test/ref/vic20-3k-simple.log
Normal file
286
src/test/ref/vic20-3k-simple.log
Normal file
@ -0,0 +1,286 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::i#0 = 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
main::i#2 = phi( main/main::i#0, main::@2/main::i#1 )
|
||||
main::$0 = 0 != MESSAGE[main::i#2]
|
||||
if(main::$0) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
main::i#3 = phi( main::@1/main::i#2 )
|
||||
DEFAULT_SCREEN[main::i#3] = MESSAGE[main::i#3]
|
||||
DEFAULT_COLORRAM[main::i#3] = RED
|
||||
main::i#1 = ++ main::i#3
|
||||
to:main::@1
|
||||
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
|
||||
__constant char * const DEFAULT_COLORRAM = (char *)$9600
|
||||
__constant char * const DEFAULT_SCREEN = (char *)$1e00
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void __start()
|
||||
void main()
|
||||
bool main::$0
|
||||
char main::i
|
||||
char main::i#0
|
||||
char main::i#1
|
||||
char main::i#2
|
||||
char main::i#3
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::$0 = 0 != MESSAGE[main::i#2]
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (char *) 38400
|
||||
Simplifying constant pointer cast (char *) 7680
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (char) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias main::i#2 = main::i#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition main::$0 [3] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
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
|
||||
Inlining constant with var siblings main::i#0
|
||||
Constant inlined main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [7] main::i#4 = main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
|
||||
[2] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2]
|
||||
[5] DEFAULT_COLORRAM[main::i#2] = RED
|
||||
[6] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // 22.0
|
||||
char main::i#2 // 16.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [2] if(0!=MESSAGE[main::i#2]) goto main::@2 [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Statement [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [5] DEFAULT_COLORRAM[main::i#2] = RED [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [2] if(0!=MESSAGE[main::i#2]) goto main::@2 [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [5] DEFAULT_COLORRAM[main::i#2] = RED [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 38.5: zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope [MOS6561_VIC]
|
||||
Uplift Scope [MOS6522_VIA]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 391 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [MOS6561_VIC] best 391 combination
|
||||
Uplifting [MOS6522_VIA] best 391 combination
|
||||
Uplifting [] best 391 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 +3k expanded executable PRG file
|
||||
.file [name="vic20-3k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0401]
|
||||
.segmentdef Code [start=$40d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9600
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1e00
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] if(0!=MESSAGE[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// [5] DEFAULT_COLORRAM[main::i#2] = RED -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
__b1_from___b2:
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __b1_from___b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
__constant char * const DEFAULT_COLORRAM = (char *) 38400
|
||||
__constant char * const DEFAULT_SCREEN = (char *) 7680
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // reg byte x 22.0
|
||||
char main::i#2 // reg byte x 16.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 331
|
||||
|
||||
// File Comments
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 +3k expanded executable PRG file
|
||||
.file [name="vic20-3k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0401]
|
||||
.segmentdef Code [start=$40d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9600
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1e00
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// main::@1
|
||||
__b1:
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
// [2] if(0!=MESSAGE[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
// main::@return
|
||||
// }
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// DEFAULT_SCREEN[i] = MESSAGE[i]
|
||||
// [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// DEFAULT_COLORRAM[i] = RED
|
||||
// [5] DEFAULT_COLORRAM[main::i#2] = RED -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
||||
|
10
src/test/ref/vic20-3k-simple.sym
Normal file
10
src/test/ref/vic20-3k-simple.sym
Normal file
@ -0,0 +1,10 @@
|
||||
__constant char * const DEFAULT_COLORRAM = (char *) 38400
|
||||
__constant char * const DEFAULT_SCREEN = (char *) 7680
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // reg byte x 22.0
|
||||
char main::i#2 // reg byte x 16.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
48
src/test/ref/vic20-8k-simple.asm
Normal file
48
src/test/ref/vic20-8k-simple.asm
Normal file
@ -0,0 +1,48 @@
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Commodore VIC 20 +8k expanded executable PRG file
|
||||
.file [name="vic20-8k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1201]
|
||||
.segmentdef Code [start=$120d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9400
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1000
|
||||
.segment Code
|
||||
main: {
|
||||
ldx #0
|
||||
__b1:
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// DEFAULT_SCREEN[i] = MESSAGE[i]
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// DEFAULT_COLORRAM[i] = RED
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
inx
|
||||
jmp __b1
|
||||
}
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
17
src/test/ref/vic20-8k-simple.cfg
Normal file
17
src/test/ref/vic20-8k-simple.cfg
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
|
||||
[2] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2]
|
||||
[5] DEFAULT_COLORRAM[main::i#2] = RED
|
||||
[6] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
286
src/test/ref/vic20-8k-simple.log
Normal file
286
src/test/ref/vic20-8k-simple.log
Normal file
@ -0,0 +1,286 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::i#0 = 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
main::i#2 = phi( main/main::i#0, main::@2/main::i#1 )
|
||||
main::$0 = 0 != MESSAGE[main::i#2]
|
||||
if(main::$0) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
main::i#3 = phi( main::@1/main::i#2 )
|
||||
DEFAULT_SCREEN[main::i#3] = MESSAGE[main::i#3]
|
||||
DEFAULT_COLORRAM[main::i#3] = RED
|
||||
main::i#1 = ++ main::i#3
|
||||
to:main::@1
|
||||
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
|
||||
__constant char * const DEFAULT_COLORRAM = (char *)$9400
|
||||
__constant char * const DEFAULT_SCREEN = (char *)$1000
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void __start()
|
||||
void main()
|
||||
bool main::$0
|
||||
char main::i
|
||||
char main::i#0
|
||||
char main::i#1
|
||||
char main::i#2
|
||||
char main::i#3
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::$0 = 0 != MESSAGE[main::i#2]
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (char *) 37888
|
||||
Simplifying constant pointer cast (char *) 4096
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (char) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias main::i#2 = main::i#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition main::$0 [3] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
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
|
||||
Inlining constant with var siblings main::i#0
|
||||
Constant inlined main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [7] main::i#4 = main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
|
||||
[2] if(0!=MESSAGE[main::i#2]) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2]
|
||||
[5] DEFAULT_COLORRAM[main::i#2] = RED
|
||||
[6] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // 22.0
|
||||
char main::i#2 // 16.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [2] if(0!=MESSAGE[main::i#2]) goto main::@2 [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Statement [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [5] DEFAULT_COLORRAM[main::i#2] = RED [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [2] if(0!=MESSAGE[main::i#2]) goto main::@2 [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [5] DEFAULT_COLORRAM[main::i#2] = RED [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 38.5: zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope [MOS6561_VIC]
|
||||
Uplift Scope [MOS6522_VIA]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 391 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [MOS6561_VIC] best 391 combination
|
||||
Uplifting [MOS6522_VIA] best 391 combination
|
||||
Uplifting [] best 391 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 +8k expanded executable PRG file
|
||||
.file [name="vic20-8k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1201]
|
||||
.segmentdef Code [start=$120d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9400
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1000
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] if(0!=MESSAGE[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// [5] DEFAULT_COLORRAM[main::i#2] = RED -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
__b1_from___b2:
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __b1_from___b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
__constant char * const DEFAULT_COLORRAM = (char *) 37888
|
||||
__constant char * const DEFAULT_SCREEN = (char *) 4096
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // reg byte x 22.0
|
||||
char main::i#2 // reg byte x 16.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 331
|
||||
|
||||
// File Comments
|
||||
// Trivial VIC 20 program
|
||||
/// @file
|
||||
/// Commodore VIC 20 registers and memory layout
|
||||
///
|
||||
/// http://sleepingelephant.com/denial/wiki/index.php?title=Memory_Map
|
||||
/// http://www.zimmers.net/anonftp/pub/cbm/vic20/manuals/VIC-20_Programmers_Reference_Guide_1st_Edition_6th_Printing.pdf
|
||||
/// @file
|
||||
/// MOS 6560/6561 VIDEO INTERFACE CHIP
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 +8k expanded executable PRG file
|
||||
.file [name="vic20-8k-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1201]
|
||||
.segmentdef Code [start=$120d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const RED = 2
|
||||
/// Default address of screen color matrix
|
||||
.label DEFAULT_COLORRAM = $9400
|
||||
/// Default address of screen character matrix
|
||||
.label DEFAULT_SCREEN = $1000
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// main::@1
|
||||
__b1:
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
// [2] if(0!=MESSAGE[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||
lda MESSAGE,x
|
||||
cmp #0
|
||||
bne __b2
|
||||
// main::@return
|
||||
// }
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// DEFAULT_SCREEN[i] = MESSAGE[i]
|
||||
// [4] DEFAULT_SCREEN[main::i#2] = MESSAGE[main::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx
|
||||
lda MESSAGE,x
|
||||
sta DEFAULT_SCREEN,x
|
||||
// DEFAULT_COLORRAM[i] = RED
|
||||
// [5] DEFAULT_COLORRAM[main::i#2] = RED -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #RED
|
||||
sta DEFAULT_COLORRAM,x
|
||||
// for(char i=0; MESSAGE[i]; i++)
|
||||
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
MESSAGE: .text "hello world!"
|
||||
.byte 0
|
||||
|
10
src/test/ref/vic20-8k-simple.sym
Normal file
10
src/test/ref/vic20-8k-simple.sym
Normal file
@ -0,0 +1,10 @@
|
||||
__constant char * const DEFAULT_COLORRAM = (char *) 37888
|
||||
__constant char * const DEFAULT_SCREEN = (char *) 4096
|
||||
__constant char MESSAGE[] = "hello world!"
|
||||
__constant const char RED = 2
|
||||
void main()
|
||||
char main::i
|
||||
char main::i#1 // reg byte x 22.0
|
||||
char main::i#2 // reg byte x 16.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
@ -9,7 +9,7 @@
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-raster.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
@ -99,7 +99,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-raster.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
@ -155,7 +155,7 @@ Score: 112
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-raster.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
@ -9,7 +9,7 @@
|
||||
///
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
@ -140,7 +140,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
@ -231,7 +231,7 @@ Score: 331
|
||||
/// Used in VIC 20
|
||||
/// http://archive.6502.org/datasheets/mos_6560_6561_vic.pdf
|
||||
// Upstart
|
||||
// Commodore VIC 20 executable PRG file
|
||||
// Commodore VIC 20 unexpanded executable PRG file
|
||||
.file [name="vic20-simple.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$1001]
|
||||
|
Loading…
Reference in New Issue
Block a user