From 2cec5191e151fdc3b2202c902b408a149773b873 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 9 Aug 2020 22:34:40 +0200 Subject: [PATCH] Working on MEGA65 platform target. #507 --- src/main/kc/include/mega65.h | 95 ++++ src/main/kc/lib/conio-mega65.c | 51 +++ src/main/kc/lib/conio.c | 2 + src/main/kc/lib/mega65.c | 27 ++ .../dk/camelot64/kickc/test/TestPrograms.java | 5 + .../examples/mega65/32bit-addressing-mega65.c | 31 ++ src/test/kc/examples/mega65/hello-mega65.c | 3 +- .../mega65/32bit-addressing-mega65.asm | 66 +++ .../mega65/32bit-addressing-mega65.cfg | 26 ++ .../mega65/32bit-addressing-mega65.log | 421 ++++++++++++++++++ .../mega65/32bit-addressing-mega65.sym | 9 + src/test/ref/examples/mega65/hello-mega65.asm | 2 +- src/test/ref/examples/mega65/hello-mega65.log | 6 +- 13 files changed, 738 insertions(+), 6 deletions(-) create mode 100644 src/main/kc/include/mega65.h create mode 100644 src/main/kc/lib/conio-mega65.c create mode 100644 src/main/kc/lib/mega65.c create mode 100644 src/test/kc/examples/mega65/32bit-addressing-mega65.c create mode 100644 src/test/ref/examples/mega65/32bit-addressing-mega65.asm create mode 100644 src/test/ref/examples/mega65/32bit-addressing-mega65.cfg create mode 100644 src/test/ref/examples/mega65/32bit-addressing-mega65.log create mode 100644 src/test/ref/examples/mega65/32bit-addressing-mega65.sym diff --git a/src/main/kc/include/mega65.h b/src/main/kc/include/mega65.h new file mode 100644 index 000000000..86f5e6dd7 --- /dev/null +++ b/src/main/kc/include/mega65.h @@ -0,0 +1,95 @@ +// MEGA65 Registers and Constants +#ifndef __MEGA65__ +#error "Target platform must be MEGA64" +#endif +#include +#include +#include + +// I/O Personality selection +volatile char * const IO_KEY = 0xd02f; +// C65 Banking Register +volatile char * const IO_BANK = 0xd030; +// Map 2nd KB of colour RAM $DC00-$DFFF (hiding CIA's) +const char CRAM2K = 0b00000001; + +// Processor port data direction register +char* const PROCPORT_DDR = 0x00; +// Mask for PROCESSOR_PORT_DDR which allows only memory configuration to be written +const char PROCPORT_DDR_MEMORY_MASK = 0b00000111; +// Processor Port Register controlling RAM/ROM configuration and the datasette +char* const PROCPORT = 0x01; +// RAM in all three areas 0xA000, 0xD000, 0xE000 +const char PROCPORT_RAM_ALL = 0b00000000; +// RAM in 0xA000, 0xE000 I/O in 0xD000 +const char PROCPORT_RAM_IO = 0b00000101; +// RAM in 0xA000, 0xE000 CHAR ROM in 0xD000 +const char PROCPORT_RAM_CHARROM = 0b00000001; +// RAM in 0xA000, I/O in 0xD000, KERNEL in 0xE000 +const char PROCPORT_KERNEL_IO = 0b00000110; +// BASIC in 0xA000, I/O in 0xD000, KERNEL in 0xE000 +const char PROCPORT_BASIC_KERNEL_IO = 0b00000111; + +// The address of the CHARGEN character set +char* const CHARGEN = 0xd000; +// The SID MOS 6581/8580 +struct MOS6581_SID * const SID = 0xd400; +// The VIC-II MOS 6567/6569 +struct MOS6569_VICII* const VICII = 0xd000; +// Color Ram +char * const COLORRAM = 0xd800; + +// Default address of screen character matrix +char * const DEFAULT_SCREEN = 0x0800; + +// The CIA#1: keyboard matrix, joystick #1/#2 +struct MOS6526_CIA * const CIA1 = 0xdc00; +// The CIA#2: Serial bus, RS-232, VIC memory bank +struct MOS6526_CIA * const CIA2 = 0xdd00; +// CIA#1 Interrupt for reading in ASM +char * const CIA1_INTERRUPT = 0xdc0d; +// CIA#2 timer A&B as one single 32-bit value +unsigned long* const CIA2_TIMER_AB = 0xdd04; +// CIA#2 Interrupt for reading in ASM +char * const CIA2_INTERRUPT = 0xdd0d; + +// The vector used when the KERNAL serves IRQ interrupts +void()** const KERNEL_IRQ = 0x0314; +// The vector used when the KERNAL serves NMI interrupts +void()** const KERNEL_NMI = 0x0318; +// The vector used when the HARDWARE serves IRQ interrupts +void()** const HARDWARE_IRQ = 0xfffe; + +// The colors of the C64 +const char BLACK = 0x0; +const char WHITE = 0x1; +const char RED = 0x2; +const char CYAN = 0x3; +const char PURPLE = 0x4; +const char GREEN = 0x5; +const char BLUE = 0x6; +const char YELLOW = 0x7; +const char ORANGE = 0x8; +const char BROWN = 0x9; +const char PINK = 0xa; +const char DARK_GREY= 0xb; +const char GREY = 0xc; +const char LIGHT_GREEN = 0xd; +const char LIGHT_BLUE = 0xe; +const char LIGHT_GREY = 0xf; + +// Get the value to store into D018 to display a specific screen and charset/bitmap +// Optimized for ASM from (char)((((unsigned int)screen&0x3fff)/0x40)|(((unsigned int)charset&0x3fff)/0x400)); +char toD018(char* screen, char* gfx); + +// Get the value to store into DD00 (CIA 2 port A) to choose a specific VIC bank +// Optimized for ASM from %00000011 ^ (char)((unsigned int)gfx/0x4000) +char toDd00(char* gfx); + +// Get the sprite pointer for a sprite. +// The sprite pointer is the index of the sprite within the graphics bank and equal to the sprite (char)(sprite_addr/64) +// The sprite pointers are stored SCREEN+0x3f8+sprite_id to set the pointer of each sprite +char toSpritePtr(char* sprite); + +// Select a specific VIC graphics bank by setting the CIA 2 port A (0xdd00) as needed +void vicSelectGfxBank(char* gfx); \ No newline at end of file diff --git a/src/main/kc/lib/conio-mega65.c b/src/main/kc/lib/conio-mega65.c new file mode 100644 index 000000000..ac15ad317 --- /dev/null +++ b/src/main/kc/lib/conio-mega65.c @@ -0,0 +1,51 @@ +// MEGA65 conio.h implementation +#include +#include + +// The screen width +#define CONIO_WIDTH 80 +// The screen height +#define CONIO_HEIGHT 25 +// The text screen address +char * const CONIO_SCREEN_TEXT = DEFAULT_SCREEN; +// The color screen address +char * const CONIO_SCREEN_COLORS = COLORRAM; +// The default text color +const char CONIO_TEXTCOLOR_DEFAULT = LIGHT_BLUE; + +// Use the shared CMB flat memory implementation +#include "conio-cbm-shared.c" + +// Return true if there's a key waiting, return false if not +unsigned char kbhit (void) { + // CIA#1 Port A: keyboard matrix columns and joystick #2 + char* const CIA1_PORT_A = 0xdc00; + // CIA#1 Port B: keyboard matrix rows and joystick #1. + char* const CIA1_PORT_B = 0xdc01; + // Map CIA I/O + *IO_BANK &= ~CRAM2K; + // Read keyboard + *CIA1_PORT_A = 0; + unsigned char hit = ~*CIA1_PORT_B; + // Map 2K Color RAM + *IO_BANK |= CRAM2K; + return hit; +} + +// Set the color for the background. The old color setting is returned. +unsigned char bgcolor(unsigned char color) { + // The background color register address + char * const CONIO_BGCOLOR = 0xd021; + char old = *CONIO_BGCOLOR; + *CONIO_BGCOLOR = color; + return old; +} + +// Set the color for the border. The old color setting is returned. +unsigned char bordercolor(unsigned char color) { + // The border color register address + char * const CONIO_BORDERCOLOR = 0xd020; + char old = *CONIO_BORDERCOLOR; + *CONIO_BORDERCOLOR = color; + return old; +} diff --git a/src/main/kc/lib/conio.c b/src/main/kc/lib/conio.c index 44d2858ed..d151c7a5f 100644 --- a/src/main/kc/lib/conio.c +++ b/src/main/kc/lib/conio.c @@ -11,6 +11,8 @@ #include "conio-plus4.c" #elif defined(__VIC20__) #include "conio-vic20.c" +#elif defined(__MEGA65__) +#include "conio-mega65.c" #elif defined(__NES__) #include "conio-nes.c" #else diff --git a/src/main/kc/lib/mega65.c b/src/main/kc/lib/mega65.c new file mode 100644 index 000000000..95e92342a --- /dev/null +++ b/src/main/kc/lib/mega65.c @@ -0,0 +1,27 @@ +// Commodore 64 Registers and Constants +#include + +// Get the value to store into D018 to display a specific screen and charset/bitmap +// Optimized for ASM from (char)((((unsigned int)screen&$3fff)/$40)|(((unsigned int)charset&$3fff)/$400)); +inline char toD018(char* screen, char* gfx) { + return (>((((unsigned int)screen&$3fff)*4)))|(((>((unsigned int)gfx))/4)&$f); +} + +// Get the value to store into DD00 (CIA 2 port A) to choose a specific VIC bank +// Optimized for ASM from %00000011 ^ (char)((unsigned int)gfx/$4000) +inline char toDd00(char* gfx) { + return %00000011 ^ (>((unsigned int)gfx))/$40; +} + +// Get the sprite pointer for a sprite. +// The sprite pointer is the index of the sprite within the graphics bank and equal to the sprite (char)(sprite_addr/64) +// The sprite pointers are stored SCREEN+$3f8+sprite_id to set the pointer of each sprite +inline char toSpritePtr(char* sprite) { + return (char)(((unsigned int)sprite)/$40); +} + +// Select a specific VIC graphics bank by setting the CIA 2 port A ($dd00) as needed +inline void vicSelectGfxBank(char* gfx) { + CIA2->PORT_A_DDR = %00000011; + CIA2->PORT_A = toDd00(gfx); +} \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 861c6a101..10ee4932e 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -192,6 +192,11 @@ public class TestPrograms { compileAndCompare("examples/nes-demo/nes-demo.c"); } + @Test + public void testMega65Addressing32bit() throws IOException, URISyntaxException { + compileAndCompare("examples/mega65/32bit-addressing-mega65.c"); + } + @Test public void testMega65Hello() throws IOException, URISyntaxException { compileAndCompare("examples/mega65/hello-mega65.c"); diff --git a/src/test/kc/examples/mega65/32bit-addressing-mega65.c b/src/test/kc/examples/mega65/32bit-addressing-mega65.c new file mode 100644 index 000000000..f3f851a93 --- /dev/null +++ b/src/test/kc/examples/mega65/32bit-addressing-mega65.c @@ -0,0 +1,31 @@ +// 32-bit addressing using the new addressing mode +#pragma target(mega65) + +// Absolute 32-bit address to use for storing/loading data +volatile __zp unsigned long ADDR32; + +void main() { + // Modify Color Ram using 32-bit addressing + ADDR32 = 0xff80000; + asm { + ldz #0 + !: + tza + sta ((ADDR32)),z + inz + cpz #80 + bne !- + } + + // Modify Screen using 32-bit addressing + ADDR32 = 0x00000800; + asm { + lda #'*' + ldz #79 + !: + sta ((ADDR32)),z + dez + bpl !- + } + +} \ No newline at end of file diff --git a/src/test/kc/examples/mega65/hello-mega65.c b/src/test/kc/examples/mega65/hello-mega65.c index abbda3c4d..09f3b1a95 100644 --- a/src/test/kc/examples/mega65/hello-mega65.c +++ b/src/test/kc/examples/mega65/hello-mega65.c @@ -1,5 +1,4 @@ -// Hello World for MEGA 65 - +// Hello World for MEGA 65 - putting chars directly to the screen #pragma target(mega65) char * SCREEN = 0x0800; diff --git a/src/test/ref/examples/mega65/32bit-addressing-mega65.asm b/src/test/ref/examples/mega65/32bit-addressing-mega65.asm new file mode 100644 index 000000000..09aec8756 --- /dev/null +++ b/src/test/ref/examples/mega65/32bit-addressing-mega65.asm @@ -0,0 +1,66 @@ +// 32-bit addressing using the new addressing mode +.cpu _45gs02 + .file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"] +.segmentdef Program [segments="Basic, Code, Data"] +.segmentdef Basic [start=$2001] +.segmentdef Code [start=$2017] +.segmentdef Data [startAfter="Code"] +.segment Basic +.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0 +.byte $15, $20, $14, $00, $9e, $20 // 20 SYS +.text toIntString(__start) // NNNN +.byte $00, $00, $00 // + // Absolute 32-bit address to use for storing/loading data + .label ADDR32 = 2 +.segment Code +__start: { + // ADDR32 + lda #<0 + sta.z ADDR32 + sta.z ADDR32+1 + lda #<0>>$10 + sta.z ADDR32+2 + lda #>0>>$10 + sta.z ADDR32+3 + jsr main + rts +} +main: { + // ADDR32 = 0xff80000 + // Modify Color Ram using 32-bit addressing + lda #<$ff80000 + sta.z ADDR32 + lda #>$ff80000 + sta.z ADDR32+1 + lda #<$ff80000>>$10 + sta.z ADDR32+2 + lda #>$ff80000>>$10 + sta.z ADDR32+3 + // asm + ldz #0 + !: + tza + sta.z ((ADDR32)),z + inz + cpz #$50 + bne !- + // ADDR32 = 0x00000800 + // Modify Screen using 32-bit addressing + lda #<$800 + sta.z ADDR32 + lda #>$800 + sta.z ADDR32+1 + lda #<$800>>$10 + sta.z ADDR32+2 + lda #>$800>>$10 + sta.z ADDR32+3 + // asm + lda #'*' + ldz #$4f + !: + sta.z ((ADDR32)),z + dez + bpl !- + // } + rts +} diff --git a/src/test/ref/examples/mega65/32bit-addressing-mega65.cfg b/src/test/ref/examples/mega65/32bit-addressing-mega65.cfg new file mode 100644 index 000000000..bdb81ad8a --- /dev/null +++ b/src/test/ref/examples/mega65/32bit-addressing-mega65.cfg @@ -0,0 +1,26 @@ + +(void()) __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] (volatile dword) ADDR32 ← (dword) 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] call main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +(void()) main() +main: scope:[main] from __start::@1 + [5] (volatile dword) ADDR32 ← (dword) $ff80000 + asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + [7] (volatile dword) ADDR32 ← (word) $800 + asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + to:main::@return +main::@return: scope:[main] from main + [9] return + to:@return diff --git a/src/test/ref/examples/mega65/32bit-addressing-mega65.log b/src/test/ref/examples/mega65/32bit-addressing-mega65.log new file mode 100644 index 000000000..30861c723 --- /dev/null +++ b/src/test/ref/examples/mega65/32bit-addressing-mega65.log @@ -0,0 +1,421 @@ +Inlined call call __init + +CONTROL FLOW GRAPH SSA + +(void()) main() +main: scope:[main] from __start::@1 + (volatile dword) ADDR32 ← (number) $ff80000 + asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + (volatile dword) ADDR32 ← (number) $800 + asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + to:main::@return +main::@return: scope:[main] from main + return + to:@return + +(void()) __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + (volatile dword) ADDR32 ← (dword) 0 + 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 +(volatile dword) ADDR32 loadstore +(void()) __start() +(label) __start::@1 +(label) __start::@2 +(label) __start::@return +(label) __start::__init1 +(void()) main() +(label) main::@return + +Adding number conversion cast (unumber) $ff80000 in (volatile dword) ADDR32 ← (number) $ff80000 +Adding number conversion cast (unumber) $800 in (volatile dword) ADDR32 ← (number) $800 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (volatile dword) ADDR32 ← (unumber)(number) $ff80000 +Inlining cast (volatile dword) ADDR32 ← (unumber)(number) $800 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast $ff80000 +Simplifying constant integer cast $800 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (dword) $ff80000 +Finalized unsigned number type (word) $800 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of __start::@2 +CALL GRAPH +Calls in [__start] to main:3 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) __start::@2 +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 + +FINAL CONTROL FLOW GRAPH + +(void()) __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] (volatile dword) ADDR32 ← (dword) 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] call main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +(void()) main() +main: scope:[main] from __start::@1 + [5] (volatile dword) ADDR32 ← (dword) $ff80000 + asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + [7] (volatile dword) ADDR32 ← (word) $800 + asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + to:main::@return +main::@return: scope:[main] from main + [9] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(volatile dword) ADDR32 loadstore 12.0 +(void()) __start() +(void()) main() + +Initial phi equivalence classes +Added variable ADDR32 to live range equivalence class [ ADDR32 ] +Complete equivalence classes +[ ADDR32 ] +Allocated zp[4]:2 [ ADDR32 ] + +INITIAL ASM +Target platform is mega65 / MEGA45GS02 + // File Comments +// 32-bit addressing using the new addressing mode + // Upstart +.cpu _45gs02 + .file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"] +.segmentdef Program [segments="Basic, Code, Data"] +.segmentdef Basic [start=$2001] +.segmentdef Code [start=$2017] +.segmentdef Data [startAfter="Code"] +.segment Basic +.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0 +.byte $15, $20, $14, $00, $9e, $20 // 20 SYS +.text toIntString(__start) // NNNN +.byte $00, $00, $00 // + // Global Constants & labels + // Absolute 32-bit address to use for storing/loading data + .label ADDR32 = 2 +.segment Code + // __start +__start: { + jmp __init1 + // __start::__init1 + __init1: + // [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1 + lda #<0 + sta.z ADDR32 + lda #>0 + sta.z ADDR32+1 + lda #<0>>$10 + sta.z ADDR32+2 + lda #>0>>$10 + sta.z ADDR32+3 + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + __b1_from___init1: + jmp __b1 + // __start::@1 + __b1: + // [3] call main + jsr main + jmp __breturn + // __start::@return + __breturn: + // [4] return + rts +} + // main +main: { + // [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1 + // Modify Color Ram using 32-bit addressing + lda #<$ff80000 + sta.z ADDR32 + lda #>$ff80000 + sta.z ADDR32+1 + lda #<$ff80000>>$10 + sta.z ADDR32+2 + lda #>$ff80000>>$10 + sta.z ADDR32+3 + // asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + ldz #0 + !: + tza + sta.z ((ADDR32)),z + inz + cpz #$50 + bne !- + // [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1 + // Modify Screen using 32-bit addressing + lda #<$800 + sta.z ADDR32 + lda #>$800 + sta.z ADDR32+1 + lda #<$800>>$10 + sta.z ADDR32+2 + lda #>$800>>$10 + sta.z ADDR32+3 + // asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + lda #'*' + ldz #$4f + !: + sta.z ((ADDR32)),z + dez + bpl !- + jmp __breturn + // main::@return + __breturn: + // [9] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] (volatile dword) ADDR32 ← (dword) 0 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [5] (volatile dword) ADDR32 ← (dword) $ff80000 [ ADDR32 ] ( main:3 [ ADDR32 ] { } ) always clobbers reg byte a +Statement asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } always clobbers reg byte a reg byte z +Statement [7] (volatile dword) ADDR32 ← (word) $800 [ ADDR32 ] ( main:3 [ ADDR32 ] { } ) always clobbers reg byte a +Statement asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } always clobbers reg byte a reg byte z +Potential registers zp[4]:2 [ ADDR32 ] : zp[4]:2 , + +REGISTER UPLIFT SCOPES +Uplift Scope [] 12: zp[4]:2 [ ADDR32 ] +Uplift Scope [main] +Uplift Scope [__start] + +Uplifting [] best 148 combination zp[4]:2 [ ADDR32 ] +Uplifting [main] best 148 combination +Uplifting [__start] best 148 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// 32-bit addressing using the new addressing mode + // Upstart +.cpu _45gs02 + .file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"] +.segmentdef Program [segments="Basic, Code, Data"] +.segmentdef Basic [start=$2001] +.segmentdef Code [start=$2017] +.segmentdef Data [startAfter="Code"] +.segment Basic +.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0 +.byte $15, $20, $14, $00, $9e, $20 // 20 SYS +.text toIntString(__start) // NNNN +.byte $00, $00, $00 // + // Global Constants & labels + // Absolute 32-bit address to use for storing/loading data + .label ADDR32 = 2 +.segment Code + // __start +__start: { + jmp __init1 + // __start::__init1 + __init1: + // [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1 + lda #<0 + sta.z ADDR32 + lda #>0 + sta.z ADDR32+1 + lda #<0>>$10 + sta.z ADDR32+2 + lda #>0>>$10 + sta.z ADDR32+3 + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + __b1_from___init1: + jmp __b1 + // __start::@1 + __b1: + // [3] call main + jsr main + jmp __breturn + // __start::@return + __breturn: + // [4] return + rts +} + // main +main: { + // [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1 + // Modify Color Ram using 32-bit addressing + lda #<$ff80000 + sta.z ADDR32 + lda #>$ff80000 + sta.z ADDR32+1 + lda #<$ff80000>>$10 + sta.z ADDR32+2 + lda #>$ff80000>>$10 + sta.z ADDR32+3 + // asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + ldz #0 + !: + tza + sta.z ((ADDR32)),z + inz + cpz #$50 + bne !- + // [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1 + // Modify Screen using 32-bit addressing + lda #<$800 + sta.z ADDR32 + lda #>$800 + sta.z ADDR32+1 + lda #<$800>>$10 + sta.z ADDR32+2 + lda #>$800>>$10 + sta.z ADDR32+3 + // asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + lda #'*' + ldz #$4f + !: + sta.z ((ADDR32)),z + dez + bpl !- + jmp __breturn + // main::@return + __breturn: + // [9] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __init1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #>0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Removing instruction __b1_from___init1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __init1: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(volatile dword) ADDR32 loadstore zp[4]:2 12.0 +(void()) __start() +(label) __start::@1 +(label) __start::@return +(label) __start::__init1 +(void()) main() +(label) main::@return + +zp[4]:2 [ ADDR32 ] + + +FINAL ASSEMBLER +Score: 107 + + // File Comments +// 32-bit addressing using the new addressing mode + // Upstart +.cpu _45gs02 + .file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"] +.segmentdef Program [segments="Basic, Code, Data"] +.segmentdef Basic [start=$2001] +.segmentdef Code [start=$2017] +.segmentdef Data [startAfter="Code"] +.segment Basic +.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0 +.byte $15, $20, $14, $00, $9e, $20 // 20 SYS +.text toIntString(__start) // NNNN +.byte $00, $00, $00 // + // Global Constants & labels + // Absolute 32-bit address to use for storing/loading data + .label ADDR32 = 2 +.segment Code + // __start +__start: { + // __start::__init1 + // ADDR32 + // [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1 + lda #<0 + sta.z ADDR32 + sta.z ADDR32+1 + lda #<0>>$10 + sta.z ADDR32+2 + lda #>0>>$10 + sta.z ADDR32+3 + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + // __start::@1 + // [3] call main + jsr main + // __start::@return + // [4] return + rts +} + // main +main: { + // ADDR32 = 0xff80000 + // [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1 + // Modify Color Ram using 32-bit addressing + lda #<$ff80000 + sta.z ADDR32 + lda #>$ff80000 + sta.z ADDR32+1 + lda #<$ff80000>>$10 + sta.z ADDR32+2 + lda #>$ff80000>>$10 + sta.z ADDR32+3 + // asm + // asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } + ldz #0 + !: + tza + sta.z ((ADDR32)),z + inz + cpz #$50 + bne !- + // ADDR32 = 0x00000800 + // [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1 + // Modify Screen using 32-bit addressing + lda #<$800 + sta.z ADDR32 + lda #>$800 + sta.z ADDR32+1 + lda #<$800>>$10 + sta.z ADDR32+2 + lda #>$800>>$10 + sta.z ADDR32+3 + // asm + // asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } + lda #'*' + ldz #$4f + !: + sta.z ((ADDR32)),z + dez + bpl !- + // main::@return + // } + // [9] return + rts +} + // File Data + diff --git a/src/test/ref/examples/mega65/32bit-addressing-mega65.sym b/src/test/ref/examples/mega65/32bit-addressing-mega65.sym new file mode 100644 index 000000000..3a127b12a --- /dev/null +++ b/src/test/ref/examples/mega65/32bit-addressing-mega65.sym @@ -0,0 +1,9 @@ +(volatile dword) ADDR32 loadstore zp[4]:2 12.0 +(void()) __start() +(label) __start::@1 +(label) __start::@return +(label) __start::__init1 +(void()) main() +(label) main::@return + +zp[4]:2 [ ADDR32 ] diff --git a/src/test/ref/examples/mega65/hello-mega65.asm b/src/test/ref/examples/mega65/hello-mega65.asm index 77d2ee721..ffc7029da 100644 --- a/src/test/ref/examples/mega65/hello-mega65.asm +++ b/src/test/ref/examples/mega65/hello-mega65.asm @@ -1,4 +1,4 @@ -// Hello World for MEGA 65 +// Hello World for MEGA 65 - putting chars directly to the screen .cpu _45gs02 .file [name="hello-mega65.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] diff --git a/src/test/ref/examples/mega65/hello-mega65.log b/src/test/ref/examples/mega65/hello-mega65.log index 3d1102e08..9a29c5d30 100644 --- a/src/test/ref/examples/mega65/hello-mega65.log +++ b/src/test/ref/examples/mega65/hello-mega65.log @@ -122,7 +122,7 @@ Allocated zp[1]:2 [ main::i#2 main::i#1 ] INITIAL ASM Target platform is mega65 / MEGA45GS02 // File Comments -// Hello World for MEGA 65 +// Hello World for MEGA 65 - putting chars directly to the screen // Upstart .cpu _45gs02 .file [name="hello-mega65.prg", type="prg", segments="Program"] @@ -201,7 +201,7 @@ Uplifting [] best 391 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments -// Hello World for MEGA 65 +// Hello World for MEGA 65 - putting chars directly to the screen // Upstart .cpu _45gs02 .file [name="hello-mega65.prg", type="prg", segments="Program"] @@ -284,7 +284,7 @@ FINAL ASSEMBLER Score: 331 // File Comments -// Hello World for MEGA 65 +// Hello World for MEGA 65 - putting chars directly to the screen // Upstart .cpu _45gs02 .file [name="hello-mega65.prg", type="prg", segments="Program"]