1
0
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:
jespergravgaard 2021-12-23 15:57:32 +01:00
parent 73395870db
commit 70190a9e8e
24 changed files with 824 additions and 14 deletions

View File

@ -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;

View File

@ -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]

View File

@ -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
}
}

View 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)

View 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
}
}

View 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)

View 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
}
}

View File

@ -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");

View 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;
}
}

View 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;
}
}

View File

@ -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]

View File

@ -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]

View 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

View 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

View 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

View 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 ]

View 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

View 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

View 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

View 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 ]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]