mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-23 08:32:39 +00:00
Improved raster bars. Added simple VRAM example. #581
This commit is contained in:
parent
1e13b733ca
commit
02e57b06cb
167
src/main/fragment/cache/fragment-cache-wdc65c02.asm
vendored
167
src/main/fragment/cache/fragment-cache-wdc65c02.asm
vendored
@ -148,3 +148,170 @@ iny
|
|||||||
//FRAGMENT vbuyy_neq_vbuc1_then_la1
|
//FRAGMENT vbuyy_neq_vbuc1_then_la1
|
||||||
cpy #{c1}
|
cpy #{c1}
|
||||||
bne {la1}
|
bne {la1}
|
||||||
|
//FRAGMENT vbuz1=vbuz2
|
||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT pbuz1=pbuc1_plus_pbuc2_derefidx_vbuz2
|
||||||
|
ldy {z2}
|
||||||
|
lda {c2},y
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
adc #0
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT vbuz1=vbuz1_plus_vbuc1
|
||||||
|
lda #{c1}
|
||||||
|
clc
|
||||||
|
adc {z1}
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT pbuz1_derefidx_vbuz2=pbuc1_derefidx_vbuz2
|
||||||
|
ldy {z2}
|
||||||
|
lda {c1},y
|
||||||
|
sta ({z1}),y
|
||||||
|
//FRAGMENT pbuz1=pbuc1
|
||||||
|
lda #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT pbuz1_neq_pbuc1_then_la1
|
||||||
|
lda {z1}+1
|
||||||
|
cmp #>{c1}
|
||||||
|
bne {la1}
|
||||||
|
lda {z1}
|
||||||
|
cmp #<{c1}
|
||||||
|
bne {la1}
|
||||||
|
//FRAGMENT _deref_pbuz1=vbuc1
|
||||||
|
lda #{c1}
|
||||||
|
ldy #0
|
||||||
|
sta ({z1}),y
|
||||||
|
//FRAGMENT pbuz1=_inc_pbuz1
|
||||||
|
inc {z1}
|
||||||
|
bne !+
|
||||||
|
inc {z1}+1
|
||||||
|
!:
|
||||||
|
//FRAGMENT vbuaa=vbuz1
|
||||||
|
lda {z1}
|
||||||
|
//FRAGMENT vbuxx=vbuz1
|
||||||
|
ldx {z1}
|
||||||
|
//FRAGMENT pbuz1=pbuc1_plus_pbuc2_derefidx_vbuaa
|
||||||
|
tay
|
||||||
|
lda {c2},y
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
adc #0
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT pbuz1=pbuc1_plus_pbuc2_derefidx_vbuxx
|
||||||
|
lda {c2},x
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
adc #0
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT pbuz1=pbuc1_plus_pbuc2_derefidx_vbuyy
|
||||||
|
lda {c2},y
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
adc #0
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT vbuxx=vbuxx_plus_vbuc1
|
||||||
|
txa
|
||||||
|
clc
|
||||||
|
adc #{c1}
|
||||||
|
tax
|
||||||
|
//FRAGMENT vbuyy=vbuyy_plus_vbuc1
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc #{c1}
|
||||||
|
tay
|
||||||
|
//FRAGMENT pbuz1_derefidx_vbuaa=pbuc1_derefidx_vbuaa
|
||||||
|
tay
|
||||||
|
lda {c1},y
|
||||||
|
sta ({z1}),y
|
||||||
|
//FRAGMENT pbuz1_derefidx_vbuxx=pbuc1_derefidx_vbuxx
|
||||||
|
txa
|
||||||
|
tay
|
||||||
|
lda {c1},y
|
||||||
|
sta ({z1}),y
|
||||||
|
//FRAGMENT pbuz1_derefidx_vbuyy=pbuc1_derefidx_vbuyy
|
||||||
|
lda {c1},y
|
||||||
|
sta ({z1}),y
|
||||||
|
//FRAGMENT 0_neq_pbuc1_derefidx_vbuz1_then_la1
|
||||||
|
ldy {z1}
|
||||||
|
lda {c1},y
|
||||||
|
cmp #0
|
||||||
|
bne {la1}
|
||||||
|
//FRAGMENT pbuz1=pbuz2
|
||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT vbuz1=pbuc1_derefidx_vbuz2
|
||||||
|
ldy {z2}
|
||||||
|
lda {c1},y
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT pbuz1=_inc_pbuz2
|
||||||
|
clc
|
||||||
|
lda {z2}
|
||||||
|
adc #1
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
adc #0
|
||||||
|
sta {z1}+1
|
||||||
|
//FRAGMENT vbuz1=_lo_pbuz2
|
||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT vbuz1=_hi_pbuz2
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT 0_neq_pbuc1_derefidx_vbuaa_then_la1
|
||||||
|
tay
|
||||||
|
lda {c1},y
|
||||||
|
cmp #0
|
||||||
|
bne {la1}
|
||||||
|
//FRAGMENT 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||||
|
lda {c1},x
|
||||||
|
cmp #0
|
||||||
|
bne {la1}
|
||||||
|
//FRAGMENT 0_neq_pbuc1_derefidx_vbuyy_then_la1
|
||||||
|
lda {c1},y
|
||||||
|
cmp #0
|
||||||
|
bne {la1}
|
||||||
|
//FRAGMENT vbuz1=pbuc1_derefidx_vbuxx
|
||||||
|
lda {c1},x
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT vbuz1=pbuc1_derefidx_vbuyy
|
||||||
|
lda {c1},y
|
||||||
|
sta {z1}
|
||||||
|
//FRAGMENT vbuaa=pbuc1_derefidx_vbuz1
|
||||||
|
ldy {z1}
|
||||||
|
lda {c1},y
|
||||||
|
//FRAGMENT vbuaa=pbuc1_derefidx_vbuxx
|
||||||
|
lda {c1},x
|
||||||
|
//FRAGMENT vbuaa=pbuc1_derefidx_vbuyy
|
||||||
|
lda {c1},y
|
||||||
|
//FRAGMENT vbuxx=pbuc1_derefidx_vbuz1
|
||||||
|
ldy {z1}
|
||||||
|
ldx {c1},y
|
||||||
|
//FRAGMENT vbuaa=_lo_pbuz1
|
||||||
|
lda {z1}
|
||||||
|
//FRAGMENT vbuxx=_lo_pbuz1
|
||||||
|
ldx {z1}
|
||||||
|
//FRAGMENT vbuaa=_hi_pbuz1
|
||||||
|
lda {z1}+1
|
||||||
|
//FRAGMENT vbuxx=_hi_pbuz1
|
||||||
|
ldx {z1}+1
|
||||||
|
//FRAGMENT vbuyy=_lo_pbuz1
|
||||||
|
ldy {z1}
|
||||||
|
//FRAGMENT vbuyy=_hi_pbuz1
|
||||||
|
ldy {z1}+1
|
||||||
|
//FRAGMENT vbuyy=pbuc1_derefidx_vbuz1
|
||||||
|
ldx {z1}
|
||||||
|
ldy {c1},x
|
||||||
|
//FRAGMENT vbuxx=pbuc1_derefidx_vbuyy
|
||||||
|
ldx {c1},y
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// See https://github.com/commanderx16/x16-emulator/wiki/(VERA-0.8)-Registers-$9F23-and-$9F24-(and-$9F25)
|
// See https://github.com/commanderx16/x16-emulator/wiki/(VERA-0.8)-Registers-$9F23-and-$9F24-(and-$9F25)
|
||||||
|
|
||||||
// $9F20 VRAM Address (7:0)
|
// $9F20 VRAM Address (7:0)
|
||||||
char * const VERA_ADDRC_L = 0x9f20;
|
char * const VERA_ADDRX_L = 0x9f20;
|
||||||
// $9F21 VRAM Address (15:8)
|
// $9F21 VRAM Address (15:8)
|
||||||
char * const VERA_ADDRX_M = 0x9f21;
|
char * const VERA_ADDRX_M = 0x9f21;
|
||||||
// $9F22 VRAM Address (7:0)
|
// $9F22 VRAM Address (7:0)
|
||||||
@ -20,6 +20,22 @@ char * const VERA_ADDRX_M = 0x9f21;
|
|||||||
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
|
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
|
||||||
// Bit 0: VRAM Address (16)
|
// Bit 0: VRAM Address (16)
|
||||||
char * const VERA_ADDRX_H = 0x9f22;
|
char * const VERA_ADDRX_H = 0x9f22;
|
||||||
|
const char VERA_INC_0 = 0x00;
|
||||||
|
const char VERA_INC_1 = 0x10;
|
||||||
|
const char VERA_INC_2 = 0x20;
|
||||||
|
const char VERA_INC_4 = 0x30;
|
||||||
|
const char VERA_INC_8 = 0x40;
|
||||||
|
const char VERA_INC_16 = 0x50;
|
||||||
|
const char VERA_INC_32 = 0x60;
|
||||||
|
const char VERA_INC_64 = 0x70;
|
||||||
|
const char VERA_INC_128 = 0x80;
|
||||||
|
const char VERA_INC_256 = 0x90;
|
||||||
|
const char VERA_INC_512 = 0xa0;
|
||||||
|
const char VERA_INC_40 = 0xb0;
|
||||||
|
const char VERA_INC_80 = 0xc0;
|
||||||
|
const char VERA_INC_160 = 0xd0;
|
||||||
|
const char VERA_INC_320 = 0xe0;
|
||||||
|
const char VERA_INC_640 = 0xf0;
|
||||||
// $9F23 DATA0 VRAM Data port 0
|
// $9F23 DATA0 VRAM Data port 0
|
||||||
char * const VERA_DATA0 = 0x9f23;
|
char * const VERA_DATA0 = 0x9f23;
|
||||||
// $9F24 DATA1 VRAM Data port 1
|
// $9F24 DATA1 VRAM Data port 1
|
||||||
|
@ -34,3 +34,10 @@ void()** const HARDWARE_IRQ = 0xfffe;
|
|||||||
void()** const KERNEL_IRQ = 0x0314;
|
void()** const KERNEL_IRQ = 0x0314;
|
||||||
// $0316 (RAM) BRK vector - The vector used when the KERNAL serves IRQ caused by a BRK
|
// $0316 (RAM) BRK vector - The vector used when the KERNAL serves IRQ caused by a BRK
|
||||||
void()** const KERNEL_BRK = 0x0316;
|
void()** const KERNEL_BRK = 0x0316;
|
||||||
|
|
||||||
|
// Put a single byte into VRAM.
|
||||||
|
// Uses VERA DATA0
|
||||||
|
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||||
|
// - addr: The address in VRAM
|
||||||
|
// - data: The data to put into VRAM
|
||||||
|
void vpoke(char bank, char* addr, char data);
|
21
src/main/kc/lib/cx16.c
Normal file
21
src/main/kc/lib/cx16.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Commander X16 Functions
|
||||||
|
// https://www.commanderx16.com/forum/index.php?/about-faq/
|
||||||
|
// https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md
|
||||||
|
|
||||||
|
#include <cx16.h>
|
||||||
|
|
||||||
|
// Put a single byte into VRAM.
|
||||||
|
// Uses VERA DATA0
|
||||||
|
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||||
|
// - addr: The address in VRAM
|
||||||
|
// - data: The data to put into VRAM
|
||||||
|
void vpoke(char bank, char* addr, char data) {
|
||||||
|
// Select DATA0
|
||||||
|
*VERA_CTRL &= ~VERA_ADDRSEL;
|
||||||
|
// Set address
|
||||||
|
*VERA_ADDRX_L = <addr;
|
||||||
|
*VERA_ADDRX_M = >addr;
|
||||||
|
*VERA_ADDRX_H = VERA_INC_0 | bank;
|
||||||
|
// Set data
|
||||||
|
*VERA_DATA0 = data;
|
||||||
|
}
|
@ -463,6 +463,11 @@ public class TestPrograms {
|
|||||||
compileAndCompare("examples/nes/nes-demo.c");
|
compileAndCompare("examples/nes/nes-demo.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCx16Text() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("examples/cx16/text.c");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCx16Rasterbars() throws IOException, URISyntaxException {
|
public void testCx16Rasterbars() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("examples/cx16/rasterbars.c");
|
compileAndCompare("examples/cx16/rasterbars.c");
|
||||||
|
@ -4,53 +4,25 @@
|
|||||||
#pragma target(cx16)
|
#pragma target(cx16)
|
||||||
#include <cx16.h>
|
#include <cx16.h>
|
||||||
#include <6502.h>
|
#include <6502.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
align(0x100)char BARS[] = {
|
align(0x100) char SIN[256] = kickasm {{
|
||||||
|
.fill 256, 99+99*sin(i*2*PI/256)
|
||||||
|
}};
|
||||||
|
|
||||||
0x10, 0, 0x11, 0, 0x12, 0, 0x13, 0,
|
align(0x100) char BARS[230];
|
||||||
0x14, 0, 0x15, 0, 0x16, 0, 0x17, 0,
|
|
||||||
0x18, 0, 0x19, 0, 0x1a, 0, 0x1b, 0,
|
|
||||||
0x1c, 0, 0x1d, 0, 0x1e, 0, 0x1f, 0,
|
|
||||||
0x1f, 0, 0x1e, 0, 0x1d, 0, 0x1c, 0,
|
|
||||||
0x1b, 0, 0x1a, 0, 0x19, 0, 0x18, 0,
|
|
||||||
0x17, 0, 0x16, 0, 0x15, 0, 0x14, 0,
|
|
||||||
0x13, 0, 0x12, 0, 0x11, 0, 0x10, 0,
|
|
||||||
|
|
||||||
0x10, 0, 0x11, 0, 0x12, 0, 0x13, 0,
|
|
||||||
0x14, 0, 0x15, 0, 0x16, 0, 0x17, 0,
|
|
||||||
0x18, 0, 0x19, 0, 0x1a, 0, 0x1b, 0,
|
|
||||||
0x1c, 0, 0x1d, 0, 0x1e, 0, 0x1f, 0,
|
|
||||||
0x1f, 0, 0x1e, 0, 0x1d, 0, 0x1c, 0,
|
|
||||||
0x1b, 0, 0x1a, 0, 0x19, 0, 0x18, 0,
|
|
||||||
0x17, 0, 0x16, 0, 0x15, 0, 0x14, 0,
|
|
||||||
0x13, 0, 0x12, 0, 0x11, 0, 0x10, 0,
|
|
||||||
|
|
||||||
0x10, 0, 0x11, 0, 0x12, 0, 0x13, 0,
|
|
||||||
0x14, 0, 0x15, 0, 0x16, 0, 0x17, 0,
|
|
||||||
0x18, 0, 0x19, 0, 0x1a, 0, 0x1b, 0,
|
|
||||||
0x1c, 0, 0x1d, 0, 0x1e, 0, 0x1f, 0,
|
|
||||||
0x1f, 0, 0x1e, 0, 0x1d, 0, 0x1c, 0,
|
|
||||||
0x1b, 0, 0x1a, 0, 0x19, 0, 0x18, 0,
|
|
||||||
0x17, 0, 0x16, 0, 0x15, 0, 0x14, 0,
|
|
||||||
0x13, 0, 0x12, 0, 0x11, 0, 0x10, 0,
|
|
||||||
|
|
||||||
0x10, 0, 0x11, 0, 0x12, 0, 0x13, 0,
|
|
||||||
0x14, 0, 0x15, 0, 0x16, 0, 0x17, 0,
|
|
||||||
0x18, 0, 0x19, 0, 0x1a, 0, 0x1b, 0,
|
|
||||||
0x1c, 0, 0x1d, 0, 0x1e, 0, 0x1f, 0,
|
|
||||||
0x1f, 0, 0x1e, 0, 0x1d, 0, 0x1c, 0,
|
|
||||||
0x1b, 0, 0x1a, 0, 0x19, 0, 0x18, 0,
|
|
||||||
0x17, 0, 0x16, 0, 0x15, 0, 0x14, 0,
|
|
||||||
0x13, 0, 0x12, 0, 0x11, 0, 0x10, 0,
|
|
||||||
|
|
||||||
|
align(0x100) char BAR[32] = {
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Enable LINE IRQ (also set line bit 8 to 0)
|
// Enable LINE IRQ (also set line bit 8 to 0)
|
||||||
SEI();
|
SEI();
|
||||||
*KERNEL_IRQ = &irq_zero;
|
*KERNEL_IRQ = &irq_line;
|
||||||
*VERA_IEN = VERA_LINE;
|
*VERA_IEN = VERA_LINE;
|
||||||
*VERA_IRQLINE_L = 0;
|
*VERA_IRQLINE_L = 5;
|
||||||
CLI();
|
CLI();
|
||||||
// Wait forever
|
// Wait forever
|
||||||
for(;;) ;
|
for(;;) ;
|
||||||
@ -60,24 +32,33 @@ void main() {
|
|||||||
volatile char hstart = 0/4;
|
volatile char hstart = 0/4;
|
||||||
// The horizontal stop
|
// The horizontal stop
|
||||||
volatile char hstop = 640/4;
|
volatile char hstop = 640/4;
|
||||||
|
// The vertical start
|
||||||
|
volatile char vstart = 0/2;
|
||||||
|
// The vertical stop
|
||||||
|
volatile char vstop = 480/2;
|
||||||
// The countdown
|
// The countdown
|
||||||
volatile char cnt = 2;
|
volatile char cnt = 2;
|
||||||
|
// The sin idx
|
||||||
|
volatile char sin_idx = 100;
|
||||||
|
|
||||||
// Interrupt Routine at raster 0
|
// LINE Interrupt Routine
|
||||||
void irq_zero() {
|
void irq_line() {
|
||||||
// Update the border
|
// Update the border
|
||||||
*VERA_CTRL |= VERA_DCSEL;
|
*VERA_CTRL |= VERA_DCSEL;
|
||||||
*VERA_DC_HSTART = hstart;
|
*VERA_DC_HSTART = hstart;
|
||||||
*VERA_DC_HSTOP = hstop;
|
*VERA_DC_HSTOP = hstop;
|
||||||
|
*VERA_DC_VSTART = vstart;
|
||||||
|
*VERA_DC_VSTOP = vstop;
|
||||||
|
|
||||||
// Show color raster bars in the border
|
// Show color raster bars in the border
|
||||||
*VERA_CTRL &= ~VERA_DCSEL;
|
*VERA_CTRL &= ~VERA_DCSEL;
|
||||||
for(char l=0;l!=255;l++) {
|
for(char l=0;l!=230;l++) {
|
||||||
*VERA_DC_BORDER = BARS[l];
|
*VERA_DC_BORDER = BARS[l];
|
||||||
for(char i=0;i<23;i++) ;
|
for(char i=0;i<24;i++) ; // Wait exactly long enought to go to the next raster line
|
||||||
}
|
|
||||||
*VERA_DC_BORDER = 0;
|
*VERA_DC_BORDER = 0;
|
||||||
*VERA_CTRL |= VERA_DCSEL;
|
for(char i=0;i<23;i++) ; // Wait exactly long enought to go to the next raster line
|
||||||
|
asm { nop nop }
|
||||||
|
}
|
||||||
|
|
||||||
// Animate the border
|
// Animate the border
|
||||||
if(--cnt==0) {
|
if(--cnt==0) {
|
||||||
@ -85,9 +66,22 @@ void irq_zero() {
|
|||||||
if(hstart<=320/4) {
|
if(hstart<=320/4) {
|
||||||
hstart++;
|
hstart++;
|
||||||
hstop--;
|
hstop--;
|
||||||
|
vstart++;
|
||||||
|
vstop--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Animate the bars
|
||||||
|
memset(BARS, 0, sizeof(BARS));
|
||||||
|
char idx = sin_idx--;
|
||||||
|
for(char b=0;b<8;b++) {
|
||||||
|
char * bar = BARS + SIN[idx];
|
||||||
|
for(char i=0;i<sizeof(BAR);i++) {
|
||||||
|
bar[i] = BAR[i];
|
||||||
|
}
|
||||||
|
idx += 13;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the LINE interrupt
|
// Reset the LINE interrupt
|
||||||
*VERA_ISR = VERA_LINE;
|
*VERA_ISR = VERA_LINE;
|
||||||
// Exit CX16 KERNAL IRQ
|
// Exit CX16 KERNAL IRQ
|
||||||
|
15
src/test/kc/examples/cx16/text.c
Normal file
15
src/test/kc/examples/cx16/text.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Example program for the Commander X16
|
||||||
|
// Displays text on the screen by transfering data to VERA
|
||||||
|
|
||||||
|
#pragma target(cx16)
|
||||||
|
#include <cx16.h>
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
char MSG[] = "hello world!";
|
||||||
|
// Address of the default screen
|
||||||
|
char* vaddr = 0x0000;
|
||||||
|
for(char i=0;MSG[i];i++) {
|
||||||
|
vpoke(0, vaddr++, MSG[i]); // Message
|
||||||
|
vpoke(0, vaddr++, 0x21); // Red background, White foreground
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
.const VERA_DCSEL = 2
|
.const VERA_DCSEL = 2
|
||||||
.const VERA_LINE = 2
|
.const VERA_LINE = 2
|
||||||
|
.const SIZEOF_BYTE = 1
|
||||||
// $9F25 CTRL Control
|
// $9F25 CTRL Control
|
||||||
// Bit 7: Reset
|
// Bit 7: Reset
|
||||||
// Bit 1: DCSEL
|
// Bit 1: DCSEL
|
||||||
@ -46,14 +47,24 @@
|
|||||||
.label VERA_DC_HSTART = $9f29
|
.label VERA_DC_HSTART = $9f29
|
||||||
// $9F2A DC_HSTOP (DCSEL=1) Active Display H-Stop (9:2)
|
// $9F2A DC_HSTOP (DCSEL=1) Active Display H-Stop (9:2)
|
||||||
.label VERA_DC_HSTOP = $9f2a
|
.label VERA_DC_HSTOP = $9f2a
|
||||||
|
// $9F2B DC_VSTART (DCSEL=1) Active Display V-Start (8:1)
|
||||||
|
.label VERA_DC_VSTART = $9f2b
|
||||||
|
// $9F2C DC_VSTOP (DCSEL=1) Active Display V-Stop (8:1)
|
||||||
|
.label VERA_DC_VSTOP = $9f2c
|
||||||
// $0314 (RAM) IRQ vector - The vector used when the KERNAL serves IRQ interrupts
|
// $0314 (RAM) IRQ vector - The vector used when the KERNAL serves IRQ interrupts
|
||||||
.label KERNEL_IRQ = $314
|
.label KERNEL_IRQ = $314
|
||||||
// The horizontal start
|
// The horizontal start
|
||||||
.label hstart = 2
|
.label hstart = 3
|
||||||
// The horizontal stop
|
// The horizontal stop
|
||||||
.label hstop = 3
|
.label hstop = 4
|
||||||
|
// The vertical start
|
||||||
|
.label vstart = 5
|
||||||
|
// The vertical stop
|
||||||
|
.label vstop = 6
|
||||||
// The countdown
|
// The countdown
|
||||||
.label cnt = 4
|
.label cnt = 7
|
||||||
|
// The sin idx
|
||||||
|
.label sin_idx = 8
|
||||||
.segment Code
|
.segment Code
|
||||||
__start: {
|
__start: {
|
||||||
// hstart = 0/4
|
// hstart = 0/4
|
||||||
@ -62,14 +73,25 @@ __start: {
|
|||||||
// hstop = 640/4
|
// hstop = 640/4
|
||||||
lda #$280/4
|
lda #$280/4
|
||||||
sta.z hstop
|
sta.z hstop
|
||||||
|
// vstart = 0/2
|
||||||
|
lda #0
|
||||||
|
sta.z vstart
|
||||||
|
// vstop = 480/2
|
||||||
|
lda #$1e0/2
|
||||||
|
sta.z vstop
|
||||||
// cnt = 2
|
// cnt = 2
|
||||||
lda #2
|
lda #2
|
||||||
sta.z cnt
|
sta.z cnt
|
||||||
|
// sin_idx = 100
|
||||||
|
lda #$64
|
||||||
|
sta.z sin_idx
|
||||||
jsr main
|
jsr main
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
// Interrupt Routine at raster 0
|
// LINE Interrupt Routine
|
||||||
irq_zero: {
|
irq_line: {
|
||||||
|
.label idx = 2
|
||||||
|
.label bar = 9
|
||||||
// *VERA_CTRL |= VERA_DCSEL
|
// *VERA_CTRL |= VERA_DCSEL
|
||||||
// Update the border
|
// Update the border
|
||||||
lda #VERA_DCSEL
|
lda #VERA_DCSEL
|
||||||
@ -81,6 +103,12 @@ irq_zero: {
|
|||||||
// *VERA_DC_HSTOP = hstop
|
// *VERA_DC_HSTOP = hstop
|
||||||
lda.z hstop
|
lda.z hstop
|
||||||
sta VERA_DC_HSTOP
|
sta VERA_DC_HSTOP
|
||||||
|
// *VERA_DC_VSTART = vstart
|
||||||
|
lda.z vstart
|
||||||
|
sta VERA_DC_VSTART
|
||||||
|
// *VERA_DC_VSTOP = vstop
|
||||||
|
lda.z vstop
|
||||||
|
sta VERA_DC_VSTOP
|
||||||
// *VERA_CTRL &= ~VERA_DCSEL
|
// *VERA_CTRL &= ~VERA_DCSEL
|
||||||
// Show color raster bars in the border
|
// Show color raster bars in the border
|
||||||
lda #VERA_DCSEL^$ff
|
lda #VERA_DCSEL^$ff
|
||||||
@ -88,16 +116,9 @@ irq_zero: {
|
|||||||
sta VERA_CTRL
|
sta VERA_CTRL
|
||||||
ldx #0
|
ldx #0
|
||||||
__b2:
|
__b2:
|
||||||
// for(char l=0;l!=255;l++)
|
// for(char l=0;l!=230;l++)
|
||||||
cpx #$ff
|
cpx #$e6
|
||||||
bne __b3
|
bne __b3
|
||||||
// *VERA_DC_BORDER = 0
|
|
||||||
lda #0
|
|
||||||
sta VERA_DC_BORDER
|
|
||||||
// *VERA_CTRL |= VERA_DCSEL
|
|
||||||
lda #VERA_DCSEL
|
|
||||||
ora VERA_CTRL
|
|
||||||
sta VERA_CTRL
|
|
||||||
// if(--cnt==0)
|
// if(--cnt==0)
|
||||||
dec.z cnt
|
dec.z cnt
|
||||||
lda.z cnt
|
lda.z cnt
|
||||||
@ -114,7 +135,23 @@ irq_zero: {
|
|||||||
inc.z hstart
|
inc.z hstart
|
||||||
// hstop--;
|
// hstop--;
|
||||||
dec.z hstop
|
dec.z hstop
|
||||||
|
// vstart++;
|
||||||
|
inc.z vstart
|
||||||
|
// vstop--;
|
||||||
|
dec.z vstop
|
||||||
__b1:
|
__b1:
|
||||||
|
// memset(BARS, 0, sizeof(BARS))
|
||||||
|
// Animate the bars
|
||||||
|
jsr memset
|
||||||
|
// idx = sin_idx--
|
||||||
|
lda.z sin_idx
|
||||||
|
sta.z idx
|
||||||
|
dec.z sin_idx
|
||||||
|
ldx #0
|
||||||
|
__b13:
|
||||||
|
// for(char b=0;b<8;b++)
|
||||||
|
cpx #8
|
||||||
|
bcc __b14
|
||||||
// *VERA_ISR = VERA_LINE
|
// *VERA_ISR = VERA_LINE
|
||||||
// Reset the LINE interrupt
|
// Reset the LINE interrupt
|
||||||
lda #VERA_LINE
|
lda #VERA_LINE
|
||||||
@ -127,42 +164,127 @@ irq_zero: {
|
|||||||
rti
|
rti
|
||||||
// }
|
// }
|
||||||
rts
|
rts
|
||||||
|
__b14:
|
||||||
|
// bar = BARS + SIN[idx]
|
||||||
|
ldy.z idx
|
||||||
|
lda SIN,y
|
||||||
|
clc
|
||||||
|
adc #<BARS
|
||||||
|
sta.z bar
|
||||||
|
lda #>BARS
|
||||||
|
adc #0
|
||||||
|
sta.z bar+1
|
||||||
|
ldy #0
|
||||||
|
__b16:
|
||||||
|
// for(char i=0;i<sizeof(BAR);i++)
|
||||||
|
cpy #$20*SIZEOF_BYTE
|
||||||
|
bcc __b17
|
||||||
|
// idx += 13
|
||||||
|
lda #$d
|
||||||
|
clc
|
||||||
|
adc.z idx
|
||||||
|
sta.z idx
|
||||||
|
// for(char b=0;b<8;b++)
|
||||||
|
inx
|
||||||
|
jmp __b13
|
||||||
|
__b17:
|
||||||
|
// bar[i] = BAR[i]
|
||||||
|
lda BAR,y
|
||||||
|
sta (bar),y
|
||||||
|
// for(char i=0;i<sizeof(BAR);i++)
|
||||||
|
iny
|
||||||
|
jmp __b16
|
||||||
__b3:
|
__b3:
|
||||||
// *VERA_DC_BORDER = BARS[l]
|
// *VERA_DC_BORDER = BARS[l]
|
||||||
lda BARS,x
|
lda BARS,x
|
||||||
sta VERA_DC_BORDER
|
sta VERA_DC_BORDER
|
||||||
lda #0
|
lda #0
|
||||||
__b5:
|
__b5:
|
||||||
|
// for(char i=0;i<24;i++)
|
||||||
|
cmp #$18
|
||||||
|
bcc __b6
|
||||||
|
// *VERA_DC_BORDER = 0
|
||||||
|
// Wait exactly long enought to go to the next raster line
|
||||||
|
lda #0
|
||||||
|
sta VERA_DC_BORDER
|
||||||
|
__b8:
|
||||||
// for(char i=0;i<23;i++)
|
// for(char i=0;i<23;i++)
|
||||||
cmp #$17
|
cmp #$17
|
||||||
bcc __b6
|
bcc __b9
|
||||||
// for(char l=0;l!=255;l++)
|
// asm
|
||||||
|
// Wait exactly long enought to go to the next raster line
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
// for(char l=0;l!=230;l++)
|
||||||
inx
|
inx
|
||||||
jmp __b2
|
jmp __b2
|
||||||
__b6:
|
__b9:
|
||||||
// for(char i=0;i<23;i++)
|
// for(char i=0;i<23;i++)
|
||||||
inc
|
inc
|
||||||
|
jmp __b8
|
||||||
|
__b6:
|
||||||
|
// for(char i=0;i<24;i++)
|
||||||
|
inc
|
||||||
jmp __b5
|
jmp __b5
|
||||||
}
|
}
|
||||||
main: {
|
main: {
|
||||||
// asm
|
// asm
|
||||||
sei
|
sei
|
||||||
// *KERNEL_IRQ = &irq_zero
|
// *KERNEL_IRQ = &irq_line
|
||||||
lda #<irq_zero
|
lda #<irq_line
|
||||||
sta KERNEL_IRQ
|
sta KERNEL_IRQ
|
||||||
lda #>irq_zero
|
lda #>irq_line
|
||||||
sta KERNEL_IRQ+1
|
sta KERNEL_IRQ+1
|
||||||
// *VERA_IEN = VERA_LINE
|
// *VERA_IEN = VERA_LINE
|
||||||
lda #VERA_LINE
|
lda #VERA_LINE
|
||||||
sta VERA_IEN
|
sta VERA_IEN
|
||||||
// *VERA_IRQLINE_L = 0
|
// *VERA_IRQLINE_L = 5
|
||||||
lda #0
|
lda #5
|
||||||
sta VERA_IRQLINE_L
|
sta VERA_IRQLINE_L
|
||||||
// asm
|
// asm
|
||||||
cli
|
cli
|
||||||
__b1:
|
__b1:
|
||||||
jmp __b1
|
jmp __b1
|
||||||
}
|
}
|
||||||
|
// Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str.
|
||||||
|
memset: {
|
||||||
|
.const num = $e6*SIZEOF_BYTE
|
||||||
|
.const c = 0
|
||||||
|
.label str = BARS
|
||||||
|
.label end = str+num
|
||||||
|
.label dst = 9
|
||||||
|
lda #<str
|
||||||
|
sta.z dst
|
||||||
|
lda #>str
|
||||||
|
sta.z dst+1
|
||||||
|
__b1:
|
||||||
|
// for(char* dst = str; dst!=end; dst++)
|
||||||
|
lda.z dst+1
|
||||||
|
cmp #>end
|
||||||
|
bne __b2
|
||||||
|
lda.z dst
|
||||||
|
cmp #<end
|
||||||
|
bne __b2
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
// *dst = c
|
||||||
|
lda #c
|
||||||
|
ldy #0
|
||||||
|
sta (dst),y
|
||||||
|
// for(char* dst = str; dst!=end; dst++)
|
||||||
|
inc.z dst
|
||||||
|
bne !+
|
||||||
|
inc.z dst+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
.segment Data
|
.segment Data
|
||||||
.align $100
|
.align $100
|
||||||
BARS: .byte $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0
|
SIN:
|
||||||
|
.fill 256, 99+99*sin(i*2*PI/256)
|
||||||
|
|
||||||
|
.align $100
|
||||||
|
BARS: .fill $e6, 0
|
||||||
|
.align $100
|
||||||
|
BAR: .byte $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1a, $1b, $1c, $1d, $1e, $1f, $1f, $1e, $1d, $1c, $1b, $1a, $19, $18, $17, $16, $15, $14, $13, $12, $11, $10
|
||||||
|
@ -6,77 +6,137 @@ __start: scope:[__start] from
|
|||||||
__start::__init1: scope:[__start] from __start
|
__start::__init1: scope:[__start] from __start
|
||||||
[1] hstart = 0
|
[1] hstart = 0
|
||||||
[2] hstop = (byte)$280/4
|
[2] hstop = (byte)$280/4
|
||||||
[3] cnt = 2
|
[3] vstart = 0
|
||||||
|
[4] vstop = (byte)$1e0/2
|
||||||
|
[5] cnt = 2
|
||||||
|
[6] sin_idx = $64
|
||||||
to:__start::@1
|
to:__start::@1
|
||||||
__start::@1: scope:[__start] from __start::__init1
|
__start::@1: scope:[__start] from __start::__init1
|
||||||
[4] phi()
|
[7] phi()
|
||||||
[5] call main
|
[8] call main
|
||||||
to:__start::@return
|
to:__start::@return
|
||||||
__start::@return: scope:[__start] from __start::@1
|
__start::@return: scope:[__start] from __start::@1
|
||||||
[6] return
|
[9] return
|
||||||
to:@return
|
to:@return
|
||||||
|
|
||||||
void irq_zero()
|
void irq_line()
|
||||||
irq_zero: scope:[irq_zero] from
|
irq_line: scope:[irq_line] from
|
||||||
[7] *VERA_CTRL = *VERA_CTRL | VERA_DCSEL
|
[10] *VERA_CTRL = *VERA_CTRL | VERA_DCSEL
|
||||||
[8] *VERA_DC_HSTART = hstart
|
[11] *VERA_DC_HSTART = hstart
|
||||||
[9] *VERA_DC_HSTOP = hstop
|
[12] *VERA_DC_HSTOP = hstop
|
||||||
[10] *VERA_CTRL = *VERA_CTRL & ~VERA_DCSEL
|
[13] *VERA_DC_VSTART = vstart
|
||||||
to:irq_zero::@2
|
[14] *VERA_DC_VSTOP = vstop
|
||||||
irq_zero::@2: scope:[irq_zero] from irq_zero irq_zero::@7
|
[15] *VERA_CTRL = *VERA_CTRL & ~VERA_DCSEL
|
||||||
[11] irq_zero::l#2 = phi( irq_zero/0, irq_zero::@7/irq_zero::l#1 )
|
to:irq_line::@2
|
||||||
[12] if(irq_zero::l#2!=$ff) goto irq_zero::@3
|
irq_line::@2: scope:[irq_line] from irq_line irq_line::@10
|
||||||
to:irq_zero::@4
|
[16] irq_line::l#2 = phi( irq_line/0, irq_line::@10/irq_line::l#1 )
|
||||||
irq_zero::@4: scope:[irq_zero] from irq_zero::@2
|
[17] if(irq_line::l#2!=$e6) goto irq_line::@3
|
||||||
[13] *VERA_DC_BORDER = 0
|
to:irq_line::@4
|
||||||
[14] *VERA_CTRL = *VERA_CTRL | VERA_DCSEL
|
irq_line::@4: scope:[irq_line] from irq_line::@2
|
||||||
[15] cnt = -- cnt
|
[18] cnt = -- cnt
|
||||||
[16] if(cnt!=0) goto irq_zero::@1
|
[19] if(cnt!=0) goto irq_line::@1
|
||||||
to:irq_zero::@8
|
to:irq_line::@11
|
||||||
irq_zero::@8: scope:[irq_zero] from irq_zero::@4
|
irq_line::@11: scope:[irq_line] from irq_line::@4
|
||||||
[17] cnt = 2
|
[20] cnt = 2
|
||||||
[18] if(hstart>=(byte)$140/4+1) goto irq_zero::@1
|
[21] if(hstart>=(byte)$140/4+1) goto irq_line::@1
|
||||||
to:irq_zero::@9
|
to:irq_line::@12
|
||||||
irq_zero::@9: scope:[irq_zero] from irq_zero::@8
|
irq_line::@12: scope:[irq_line] from irq_line::@11
|
||||||
[19] hstart = ++ hstart
|
[22] hstart = ++ hstart
|
||||||
[20] hstop = -- hstop
|
[23] hstop = -- hstop
|
||||||
to:irq_zero::@1
|
[24] vstart = ++ vstart
|
||||||
irq_zero::@1: scope:[irq_zero] from irq_zero::@4 irq_zero::@8 irq_zero::@9
|
[25] vstop = -- vstop
|
||||||
[21] *VERA_ISR = VERA_LINE
|
to:irq_line::@1
|
||||||
|
irq_line::@1: scope:[irq_line] from irq_line::@11 irq_line::@12 irq_line::@4
|
||||||
|
[26] phi()
|
||||||
|
[27] call memset
|
||||||
|
to:irq_line::@19
|
||||||
|
irq_line::@19: scope:[irq_line] from irq_line::@1
|
||||||
|
[28] irq_line::idx#0 = sin_idx
|
||||||
|
[29] sin_idx = -- sin_idx
|
||||||
|
to:irq_line::@13
|
||||||
|
irq_line::@13: scope:[irq_line] from irq_line::@18 irq_line::@19
|
||||||
|
[30] irq_line::idx#2 = phi( irq_line::@18/irq_line::idx#1, irq_line::@19/irq_line::idx#0 )
|
||||||
|
[30] irq_line::b#2 = phi( irq_line::@18/irq_line::b#1, irq_line::@19/0 )
|
||||||
|
[31] if(irq_line::b#2<8) goto irq_line::@14
|
||||||
|
to:irq_line::@15
|
||||||
|
irq_line::@15: scope:[irq_line] from irq_line::@13
|
||||||
|
[32] *VERA_ISR = VERA_LINE
|
||||||
asm { ply plx pla rti }
|
asm { ply plx pla rti }
|
||||||
to:irq_zero::@return
|
to:irq_line::@return
|
||||||
irq_zero::@return: scope:[irq_zero] from irq_zero::@1
|
irq_line::@return: scope:[irq_line] from irq_line::@15
|
||||||
[23] return
|
[34] return
|
||||||
to:@return
|
to:@return
|
||||||
irq_zero::@3: scope:[irq_zero] from irq_zero::@2
|
irq_line::@14: scope:[irq_line] from irq_line::@13
|
||||||
[24] *VERA_DC_BORDER = BARS[irq_zero::l#2]
|
[35] irq_line::bar#0 = BARS + SIN[irq_line::idx#2]
|
||||||
to:irq_zero::@5
|
to:irq_line::@16
|
||||||
irq_zero::@5: scope:[irq_zero] from irq_zero::@3 irq_zero::@6
|
irq_line::@16: scope:[irq_line] from irq_line::@14 irq_line::@17
|
||||||
[25] irq_zero::i#2 = phi( irq_zero::@3/0, irq_zero::@6/irq_zero::i#1 )
|
[36] irq_line::i2#2 = phi( irq_line::@14/0, irq_line::@17/irq_line::i2#1 )
|
||||||
[26] if(irq_zero::i#2<$17) goto irq_zero::@6
|
[37] if(irq_line::i2#2<$20*SIZEOF_BYTE) goto irq_line::@17
|
||||||
to:irq_zero::@7
|
to:irq_line::@18
|
||||||
irq_zero::@7: scope:[irq_zero] from irq_zero::@5
|
irq_line::@18: scope:[irq_line] from irq_line::@16
|
||||||
[27] irq_zero::l#1 = ++ irq_zero::l#2
|
[38] irq_line::idx#1 = irq_line::idx#2 + $d
|
||||||
to:irq_zero::@2
|
[39] irq_line::b#1 = ++ irq_line::b#2
|
||||||
irq_zero::@6: scope:[irq_zero] from irq_zero::@5
|
to:irq_line::@13
|
||||||
[28] irq_zero::i#1 = ++ irq_zero::i#2
|
irq_line::@17: scope:[irq_line] from irq_line::@16
|
||||||
to:irq_zero::@5
|
[40] irq_line::bar#0[irq_line::i2#2] = BAR[irq_line::i2#2]
|
||||||
|
[41] irq_line::i2#1 = ++ irq_line::i2#2
|
||||||
|
to:irq_line::@16
|
||||||
|
irq_line::@3: scope:[irq_line] from irq_line::@2
|
||||||
|
[42] *VERA_DC_BORDER = BARS[irq_line::l#2]
|
||||||
|
to:irq_line::@5
|
||||||
|
irq_line::@5: scope:[irq_line] from irq_line::@3 irq_line::@6
|
||||||
|
[43] irq_line::i#2 = phi( irq_line::@3/0, irq_line::@6/irq_line::i#1 )
|
||||||
|
[44] if(irq_line::i#2<$18) goto irq_line::@6
|
||||||
|
to:irq_line::@7
|
||||||
|
irq_line::@7: scope:[irq_line] from irq_line::@5
|
||||||
|
[45] *VERA_DC_BORDER = 0
|
||||||
|
to:irq_line::@8
|
||||||
|
irq_line::@8: scope:[irq_line] from irq_line::@7 irq_line::@9
|
||||||
|
[46] irq_line::i1#2 = phi( irq_line::@7/0, irq_line::@9/irq_line::i1#1 )
|
||||||
|
[47] if(irq_line::i1#2<$17) goto irq_line::@9
|
||||||
|
to:irq_line::@10
|
||||||
|
irq_line::@10: scope:[irq_line] from irq_line::@8
|
||||||
|
asm { nop nop }
|
||||||
|
[49] irq_line::l#1 = ++ irq_line::l#2
|
||||||
|
to:irq_line::@2
|
||||||
|
irq_line::@9: scope:[irq_line] from irq_line::@8
|
||||||
|
[50] irq_line::i1#1 = ++ irq_line::i1#2
|
||||||
|
to:irq_line::@8
|
||||||
|
irq_line::@6: scope:[irq_line] from irq_line::@5
|
||||||
|
[51] irq_line::i#1 = ++ irq_line::i#2
|
||||||
|
to:irq_line::@5
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
main: scope:[main] from __start::@1
|
main: scope:[main] from __start::@1
|
||||||
[29] phi()
|
[52] phi()
|
||||||
to:main::SEI1
|
to:main::SEI1
|
||||||
main::SEI1: scope:[main] from main
|
main::SEI1: scope:[main] from main
|
||||||
asm { sei }
|
asm { sei }
|
||||||
to:main::@2
|
to:main::@2
|
||||||
main::@2: scope:[main] from main::SEI1
|
main::@2: scope:[main] from main::SEI1
|
||||||
[31] *KERNEL_IRQ = &irq_zero
|
[54] *KERNEL_IRQ = &irq_line
|
||||||
[32] *VERA_IEN = VERA_LINE
|
[55] *VERA_IEN = VERA_LINE
|
||||||
[33] *VERA_IRQLINE_L = 0
|
[56] *VERA_IRQLINE_L = 5
|
||||||
to:main::CLI1
|
to:main::CLI1
|
||||||
main::CLI1: scope:[main] from main::@2
|
main::CLI1: scope:[main] from main::@2
|
||||||
asm { cli }
|
asm { cli }
|
||||||
to:main::@1
|
to:main::@1
|
||||||
main::@1: scope:[main] from main::@1 main::CLI1
|
main::@1: scope:[main] from main::@1 main::CLI1
|
||||||
[35] phi()
|
[58] phi()
|
||||||
to:main::@1
|
to:main::@1
|
||||||
|
|
||||||
|
void* memset(void* memset::str , byte memset::c , word memset::num)
|
||||||
|
memset: scope:[memset] from irq_line::@1
|
||||||
|
[59] phi()
|
||||||
|
to:memset::@1
|
||||||
|
memset::@1: scope:[memset] from memset memset::@2
|
||||||
|
[60] memset::dst#2 = phi( memset/(byte*)memset::str#0, memset::@2/memset::dst#1 )
|
||||||
|
[61] if(memset::dst#2!=memset::end#0) goto memset::@2
|
||||||
|
to:memset::@return
|
||||||
|
memset::@return: scope:[memset] from memset::@1
|
||||||
|
[62] return
|
||||||
|
to:@return
|
||||||
|
memset::@2: scope:[memset] from memset::@1
|
||||||
|
[63] *memset::dst#2 = memset::c#0
|
||||||
|
[64] memset::dst#1 = ++ memset::dst#2
|
||||||
|
to:memset::@1
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +1,74 @@
|
|||||||
const byte* BARS[] = { $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0, $10, 0, $11, 0, $12, 0, $13, 0, $14, 0, $15, 0, $16, 0, $17, 0, $18, 0, $19, 0, $1a, 0, $1b, 0, $1c, 0, $1d, 0, $1e, 0, $1f, 0, $1f, 0, $1e, 0, $1d, 0, $1c, 0, $1b, 0, $1a, 0, $19, 0, $18, 0, $17, 0, $16, 0, $15, 0, $14, 0, $13, 0, $12, 0, $11, 0, $10, 0 }
|
const byte* BAR[$20] = { $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1a, $1b, $1c, $1d, $1e, $1f, $1f, $1e, $1d, $1c, $1b, $1a, $19, $18, $17, $16, $15, $14, $13, $12, $11, $10 }
|
||||||
|
const byte* BARS[$e6] = { fill( $e6, 0) }
|
||||||
const nomodify void()** KERNEL_IRQ = (void()**) 788
|
const nomodify void()** KERNEL_IRQ = (void()**) 788
|
||||||
|
const byte* SIN[$100] = kickasm {{ .fill 256, 99+99*sin(i*2*PI/256)
|
||||||
|
}}
|
||||||
|
const byte SIZEOF_BYTE = 1
|
||||||
const nomodify byte* VERA_CTRL = (byte*) 40741
|
const nomodify byte* VERA_CTRL = (byte*) 40741
|
||||||
const nomodify byte VERA_DCSEL = 2
|
const nomodify byte VERA_DCSEL = 2
|
||||||
const nomodify byte* VERA_DC_BORDER = (byte*) 40748
|
const nomodify byte* VERA_DC_BORDER = (byte*) 40748
|
||||||
const nomodify byte* VERA_DC_HSTART = (byte*) 40745
|
const nomodify byte* VERA_DC_HSTART = (byte*) 40745
|
||||||
const nomodify byte* VERA_DC_HSTOP = (byte*) 40746
|
const nomodify byte* VERA_DC_HSTOP = (byte*) 40746
|
||||||
|
const nomodify byte* VERA_DC_VSTART = (byte*) 40747
|
||||||
|
const nomodify byte* VERA_DC_VSTOP = (byte*) 40748
|
||||||
const nomodify byte* VERA_IEN = (byte*) 40742
|
const nomodify byte* VERA_IEN = (byte*) 40742
|
||||||
const nomodify byte* VERA_IRQLINE_L = (byte*) 40744
|
const nomodify byte* VERA_IRQLINE_L = (byte*) 40744
|
||||||
const nomodify byte* VERA_ISR = (byte*) 40743
|
const nomodify byte* VERA_ISR = (byte*) 40743
|
||||||
const nomodify byte VERA_LINE = 2
|
const nomodify byte VERA_LINE = 2
|
||||||
void __start()
|
void __start()
|
||||||
volatile byte cnt loadstore zp[1]:4 0.7142857142857142
|
volatile byte cnt loadstore zp[1]:7 0.5263157894736842
|
||||||
volatile byte hstart loadstore zp[1]:2 0.5882352941176471
|
volatile byte hstart loadstore zp[1]:3 0.4545454545454546
|
||||||
volatile byte hstop loadstore zp[1]:3 0.4444444444444444
|
volatile byte hstop loadstore zp[1]:4 0.34782608695652173
|
||||||
void irq_zero()
|
void irq_line()
|
||||||
byte irq_zero::i
|
byte irq_line::b
|
||||||
byte irq_zero::i#1 reg byte a 202.0
|
byte irq_line::b#1 reg byte x 22.0
|
||||||
byte irq_zero::i#2 reg byte a 151.5
|
byte irq_line::b#2 reg byte x 4.125
|
||||||
byte irq_zero::l
|
byte* irq_line::bar
|
||||||
byte irq_zero::l#1 reg byte x 22.0
|
byte* irq_line::bar#0 bar zp[2]:9 22.4
|
||||||
byte irq_zero::l#2 reg byte x 7.333333333333333
|
byte irq_line::i
|
||||||
|
byte irq_line::i#1 reg byte a 202.0
|
||||||
|
byte irq_line::i#2 reg byte a 151.5
|
||||||
|
byte irq_line::i1
|
||||||
|
byte irq_line::i1#1 reg byte a 202.0
|
||||||
|
byte irq_line::i1#2 reg byte a 151.5
|
||||||
|
byte irq_line::i2
|
||||||
|
byte irq_line::i2#1 reg byte y 202.0
|
||||||
|
byte irq_line::i2#2 reg byte y 168.33333333333331
|
||||||
|
byte irq_line::idx
|
||||||
|
byte irq_line::idx#0 idx zp[1]:2 2.0
|
||||||
|
byte irq_line::idx#1 idx zp[1]:2 11.0
|
||||||
|
byte irq_line::idx#2 idx zp[1]:2 5.0
|
||||||
|
byte irq_line::l
|
||||||
|
byte irq_line::l#1 reg byte x 22.0
|
||||||
|
byte irq_line::l#2 reg byte x 4.0
|
||||||
void main()
|
void main()
|
||||||
|
void* memset(void* memset::str , byte memset::c , word memset::num)
|
||||||
|
byte memset::c
|
||||||
|
const byte memset::c#0 c = 0
|
||||||
|
byte* memset::dst
|
||||||
|
byte* memset::dst#1 dst zp[2]:9 202.0
|
||||||
|
byte* memset::dst#2 dst zp[2]:9 134.66666666666666
|
||||||
|
byte* memset::end
|
||||||
|
const byte* memset::end#0 end = (byte*)memset::str#0+memset::num#0
|
||||||
|
word memset::num
|
||||||
|
const word memset::num#0 num = $e6*SIZEOF_BYTE
|
||||||
|
void* memset::return
|
||||||
|
void* memset::str
|
||||||
|
const void* memset::str#0 str = (void*)BARS
|
||||||
|
volatile byte sin_idx loadstore zp[1]:8 0.27586206896551724
|
||||||
|
volatile byte vstart loadstore zp[1]:5 0.3333333333333333
|
||||||
|
volatile byte vstop loadstore zp[1]:6 0.32
|
||||||
|
|
||||||
reg byte x [ irq_zero::l#2 irq_zero::l#1 ]
|
reg byte x [ irq_line::l#2 irq_line::l#1 ]
|
||||||
reg byte a [ irq_zero::i#2 irq_zero::i#1 ]
|
reg byte x [ irq_line::b#2 irq_line::b#1 ]
|
||||||
zp[1]:2 [ hstart ]
|
zp[1]:2 [ irq_line::idx#2 irq_line::idx#1 irq_line::idx#0 ]
|
||||||
zp[1]:3 [ hstop ]
|
reg byte y [ irq_line::i2#2 irq_line::i2#1 ]
|
||||||
zp[1]:4 [ cnt ]
|
reg byte a [ irq_line::i#2 irq_line::i#1 ]
|
||||||
|
reg byte a [ irq_line::i1#2 irq_line::i1#1 ]
|
||||||
|
zp[1]:3 [ hstart ]
|
||||||
|
zp[1]:4 [ hstop ]
|
||||||
|
zp[1]:5 [ vstart ]
|
||||||
|
zp[1]:6 [ vstop ]
|
||||||
|
zp[1]:7 [ cnt ]
|
||||||
|
zp[1]:8 [ sin_idx ]
|
||||||
|
zp[2]:9 [ irq_line::bar#0 memset::dst#2 memset::dst#1 ]
|
||||||
|
104
src/test/ref/examples/cx16/text.asm
Normal file
104
src/test/ref/examples/cx16/text.asm
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// Example program for the Commander X16
|
||||||
|
// Displays text on the screen by transfering data to VERA
|
||||||
|
.cpu _65c02
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="text.prg", type="prg", segments="Program"]
|
||||||
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
|
.segmentdef Basic [start=$0801]
|
||||||
|
.segmentdef Code [start=$80d]
|
||||||
|
.segmentdef Data [startAfter="Code"]
|
||||||
|
.segment Basic
|
||||||
|
:BasicUpstart(main)
|
||||||
|
.segment Code
|
||||||
|
|
||||||
|
|
||||||
|
.const VERA_ADDRSEL = 1
|
||||||
|
// $9F20 VRAM Address (7:0)
|
||||||
|
.label VERA_ADDRX_L = $9f20
|
||||||
|
// $9F21 VRAM Address (15:8)
|
||||||
|
.label VERA_ADDRX_M = $9f21
|
||||||
|
// $9F22 VRAM Address (7:0)
|
||||||
|
// Bit 4-7: Address Increment The following is the amount incremented per value value:increment
|
||||||
|
// 0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
|
||||||
|
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
|
||||||
|
// Bit 0: VRAM Address (16)
|
||||||
|
.label VERA_ADDRX_H = $9f22
|
||||||
|
// $9F23 DATA0 VRAM Data port 0
|
||||||
|
.label VERA_DATA0 = $9f23
|
||||||
|
// $9F25 CTRL Control
|
||||||
|
// Bit 7: Reset
|
||||||
|
// Bit 1: DCSEL
|
||||||
|
// Bit 2: ADDRSEL
|
||||||
|
.label VERA_CTRL = $9f25
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
// Address of the default screen
|
||||||
|
.label vaddr = 2
|
||||||
|
lda #<0
|
||||||
|
sta.z vaddr
|
||||||
|
sta.z vaddr+1
|
||||||
|
tay
|
||||||
|
__b1:
|
||||||
|
// for(char i=0;MSG[i];i++)
|
||||||
|
lda MSG,y
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
// vpoke(0, vaddr++, MSG[i])
|
||||||
|
ldx MSG,y
|
||||||
|
jsr vpoke
|
||||||
|
// vpoke(0, vaddr++, MSG[i]);
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// vpoke(0, vaddr++, 0x21)
|
||||||
|
// Message
|
||||||
|
ldx #$21
|
||||||
|
jsr vpoke
|
||||||
|
// vpoke(0, vaddr++, 0x21);
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// for(char i=0;MSG[i];i++)
|
||||||
|
iny
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
MSG: .text "hello world!"
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
// Put a single byte into VRAM.
|
||||||
|
// Uses VERA DATA0
|
||||||
|
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||||
|
// - addr: The address in VRAM
|
||||||
|
// - data: The data to put into VRAM
|
||||||
|
// vpoke(byte* zp(2) addr, byte register(X) data)
|
||||||
|
vpoke: {
|
||||||
|
.label addr = 2
|
||||||
|
// *VERA_CTRL &= ~VERA_ADDRSEL
|
||||||
|
// Select DATA0
|
||||||
|
lda #VERA_ADDRSEL^$ff
|
||||||
|
and VERA_CTRL
|
||||||
|
sta VERA_CTRL
|
||||||
|
// <addr
|
||||||
|
lda.z addr
|
||||||
|
// *VERA_ADDRX_L = <addr
|
||||||
|
// Set address
|
||||||
|
sta VERA_ADDRX_L
|
||||||
|
// >addr
|
||||||
|
lda.z addr+1
|
||||||
|
// *VERA_ADDRX_M = >addr
|
||||||
|
sta VERA_ADDRX_M
|
||||||
|
// *VERA_ADDRX_H = VERA_INC_0 | bank
|
||||||
|
lda #0
|
||||||
|
sta VERA_ADDRX_H
|
||||||
|
// *VERA_DATA0 = data
|
||||||
|
// Set data
|
||||||
|
stx VERA_DATA0
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
43
src/test/ref/examples/cx16/text.cfg
Normal file
43
src/test/ref/examples/cx16/text.cfg
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] phi()
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main main::@4
|
||||||
|
[1] main::vaddr#3 = phi( main/(byte*) 0, main::@4/main::vaddr#2 )
|
||||||
|
[1] main::i#2 = phi( main/0, main::@4/main::i#1 )
|
||||||
|
[2] if(0!=main::MSG[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] vpoke::addr#0 = main::vaddr#3
|
||||||
|
[5] vpoke::data#0 = main::MSG[main::i#2]
|
||||||
|
[6] call vpoke
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
[7] main::vaddr#1 = ++ main::vaddr#3
|
||||||
|
[8] vpoke::addr#1 = main::vaddr#1
|
||||||
|
[9] call vpoke
|
||||||
|
to:main::@4
|
||||||
|
main::@4: scope:[main] from main::@3
|
||||||
|
[10] main::vaddr#2 = ++ main::vaddr#1
|
||||||
|
[11] main::i#1 = ++ main::i#2
|
||||||
|
to:main::@1
|
||||||
|
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
vpoke: scope:[vpoke] from main::@2 main::@3
|
||||||
|
[12] vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@3/$21 )
|
||||||
|
[12] vpoke::addr#2 = phi( main::@2/vpoke::addr#0, main::@3/vpoke::addr#1 )
|
||||||
|
[13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||||
|
[14] vpoke::$0 = < vpoke::addr#2
|
||||||
|
[15] *VERA_ADDRX_L = vpoke::$0
|
||||||
|
[16] vpoke::$1 = > vpoke::addr#2
|
||||||
|
[17] *VERA_ADDRX_M = vpoke::$1
|
||||||
|
[18] *VERA_ADDRX_H = 0
|
||||||
|
[19] *VERA_DATA0 = vpoke::data#2
|
||||||
|
to:vpoke::@return
|
||||||
|
vpoke::@return: scope:[vpoke] from vpoke
|
||||||
|
[20] return
|
||||||
|
to:@return
|
668
src/test/ref/examples/cx16/text.log
Normal file
668
src/test/ref/examples/cx16/text.log
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
vpoke: scope:[vpoke] from main::@2 main::@3
|
||||||
|
vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@3/vpoke::data#1 )
|
||||||
|
vpoke::bank#2 = phi( main::@2/vpoke::bank#0, main::@3/vpoke::bank#1 )
|
||||||
|
vpoke::addr#2 = phi( main::@2/vpoke::addr#0, main::@3/vpoke::addr#1 )
|
||||||
|
*VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||||
|
vpoke::$0 = < vpoke::addr#2
|
||||||
|
*VERA_ADDRX_L = vpoke::$0
|
||||||
|
vpoke::$1 = > vpoke::addr#2
|
||||||
|
*VERA_ADDRX_M = vpoke::$1
|
||||||
|
vpoke::$2 = VERA_INC_0 | vpoke::bank#2
|
||||||
|
*VERA_ADDRX_H = vpoke::$2
|
||||||
|
*VERA_DATA0 = vpoke::data#2
|
||||||
|
to:vpoke::@return
|
||||||
|
vpoke::@return: scope:[vpoke] from vpoke
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
main::vaddr#0 = (byte*)0
|
||||||
|
main::i#0 = 0
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main main::@4
|
||||||
|
main::vaddr#6 = phi( main/main::vaddr#0, main::@4/main::vaddr#2 )
|
||||||
|
main::i#2 = phi( main/main::i#0, main::@4/main::i#1 )
|
||||||
|
main::$2 = 0 != main::MSG[main::i#2]
|
||||||
|
if(main::$2) goto main::@2
|
||||||
|
to:main::@return
|
||||||
|
main::@2: scope:[main] from main::@1
|
||||||
|
main::i#3 = phi( main::@1/main::i#2 )
|
||||||
|
main::vaddr#3 = phi( main::@1/main::vaddr#6 )
|
||||||
|
vpoke::bank#0 = 0
|
||||||
|
vpoke::addr#0 = main::vaddr#3
|
||||||
|
vpoke::data#0 = main::MSG[main::i#3]
|
||||||
|
call vpoke
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
main::i#5 = phi( main::@2/main::i#3 )
|
||||||
|
main::vaddr#4 = phi( main::@2/main::vaddr#3 )
|
||||||
|
main::vaddr#1 = ++ main::vaddr#4
|
||||||
|
vpoke::bank#1 = 0
|
||||||
|
vpoke::addr#1 = main::vaddr#1
|
||||||
|
vpoke::data#1 = $21
|
||||||
|
call vpoke
|
||||||
|
to:main::@4
|
||||||
|
main::@4: scope:[main] from main::@3
|
||||||
|
main::i#4 = phi( main::@3/main::i#5 )
|
||||||
|
main::vaddr#5 = phi( main::@3/main::vaddr#1 )
|
||||||
|
main::vaddr#2 = ++ main::vaddr#5
|
||||||
|
main::i#1 = ++ main::i#4
|
||||||
|
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
|
||||||
|
const nomodify byte VERA_ADDRSEL = 1
|
||||||
|
const nomodify byte* VERA_ADDRX_H = (byte*)$9f22
|
||||||
|
const nomodify byte* VERA_ADDRX_L = (byte*)$9f20
|
||||||
|
const nomodify byte* VERA_ADDRX_M = (byte*)$9f21
|
||||||
|
const nomodify byte* VERA_CTRL = (byte*)$9f25
|
||||||
|
const nomodify byte* VERA_DATA0 = (byte*)$9f23
|
||||||
|
const nomodify byte VERA_INC_0 = 0
|
||||||
|
void __start()
|
||||||
|
void main()
|
||||||
|
bool~ main::$2
|
||||||
|
const byte* main::MSG[] = "hello world!"
|
||||||
|
byte main::i
|
||||||
|
byte main::i#0
|
||||||
|
byte main::i#1
|
||||||
|
byte main::i#2
|
||||||
|
byte main::i#3
|
||||||
|
byte main::i#4
|
||||||
|
byte main::i#5
|
||||||
|
byte* main::vaddr
|
||||||
|
byte* main::vaddr#0
|
||||||
|
byte* main::vaddr#1
|
||||||
|
byte* main::vaddr#2
|
||||||
|
byte* main::vaddr#3
|
||||||
|
byte* main::vaddr#4
|
||||||
|
byte* main::vaddr#5
|
||||||
|
byte* main::vaddr#6
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
byte~ vpoke::$0
|
||||||
|
byte~ vpoke::$1
|
||||||
|
byte~ vpoke::$2
|
||||||
|
byte* vpoke::addr
|
||||||
|
byte* vpoke::addr#0
|
||||||
|
byte* vpoke::addr#1
|
||||||
|
byte* vpoke::addr#2
|
||||||
|
byte vpoke::bank
|
||||||
|
byte vpoke::bank#0
|
||||||
|
byte vpoke::bank#1
|
||||||
|
byte vpoke::bank#2
|
||||||
|
byte vpoke::data
|
||||||
|
byte vpoke::data#0
|
||||||
|
byte vpoke::data#1
|
||||||
|
byte vpoke::data#2
|
||||||
|
|
||||||
|
Adding number conversion cast (unumber) 0 in main::$2 = 0 != main::MSG[main::i#2]
|
||||||
|
Adding number conversion cast (unumber) 0 in vpoke::bank#0 = 0
|
||||||
|
Adding number conversion cast (unumber) 0 in vpoke::bank#1 = 0
|
||||||
|
Adding number conversion cast (unumber) $21 in vpoke::data#1 = $21
|
||||||
|
Successful SSA optimization PassNAddNumberTypeConversions
|
||||||
|
Inlining cast vpoke::bank#0 = (unumber)0
|
||||||
|
Inlining cast vpoke::bank#1 = (unumber)0
|
||||||
|
Inlining cast vpoke::data#1 = (unumber)$21
|
||||||
|
Successful SSA optimization Pass2InlineCast
|
||||||
|
Simplifying constant pointer cast (byte*) 40736
|
||||||
|
Simplifying constant pointer cast (byte*) 40737
|
||||||
|
Simplifying constant pointer cast (byte*) 40738
|
||||||
|
Simplifying constant pointer cast (byte*) 40739
|
||||||
|
Simplifying constant pointer cast (byte*) 40741
|
||||||
|
Simplifying constant pointer cast (byte*) 0
|
||||||
|
Simplifying constant integer cast 0
|
||||||
|
Simplifying constant integer cast 0
|
||||||
|
Simplifying constant integer cast 0
|
||||||
|
Simplifying constant integer cast $21
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Finalized unsigned number type (byte) 0
|
||||||
|
Finalized unsigned number type (byte) 0
|
||||||
|
Finalized unsigned number type (byte) 0
|
||||||
|
Finalized unsigned number type (byte) $21
|
||||||
|
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||||
|
Alias main::vaddr#3 = main::vaddr#6 main::vaddr#4
|
||||||
|
Alias main::i#2 = main::i#3 main::i#5 main::i#4
|
||||||
|
Alias main::vaddr#1 = main::vaddr#5
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Simple Condition main::$2 [14] if(0!=main::MSG[main::i#2]) goto main::@2
|
||||||
|
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||||
|
Constant main::vaddr#0 = (byte*) 0
|
||||||
|
Constant main::i#0 = 0
|
||||||
|
Constant vpoke::bank#0 = 0
|
||||||
|
Constant vpoke::bank#1 = 0
|
||||||
|
Constant vpoke::data#1 = $21
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Simplifying expression containing zero vpoke::bank#2 in [6] vpoke::$2 = VERA_INC_0 | vpoke::bank#2
|
||||||
|
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||||
|
Eliminating unused constant VERA_INC_0
|
||||||
|
Successful SSA optimization PassNEliminateUnusedVars
|
||||||
|
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
|
||||||
|
Alias vpoke::bank#2 = vpoke::$2
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Inlining constant with var siblings vpoke::bank#0
|
||||||
|
Inlining constant with var siblings vpoke::bank#1
|
||||||
|
Inlining constant with var siblings vpoke::data#1
|
||||||
|
Inlining constant with var siblings main::vaddr#0
|
||||||
|
Inlining constant with var siblings main::i#0
|
||||||
|
Constant inlined main::i#0 = 0
|
||||||
|
Constant inlined vpoke::bank#1 = 0
|
||||||
|
Constant inlined vpoke::bank#0 = 0
|
||||||
|
Constant inlined main::vaddr#0 = (byte*) 0
|
||||||
|
Constant inlined vpoke::data#1 = $21
|
||||||
|
Successful SSA optimization Pass2ConstantInlining
|
||||||
|
Identical Phi Values vpoke::bank#2 0
|
||||||
|
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||||
|
Adding NOP phi() at start of main
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to vpoke:8 vpoke:12
|
||||||
|
|
||||||
|
Created 4 initial phi equivalence classes
|
||||||
|
Coalesced [6] vpoke::addr#3 = vpoke::addr#0
|
||||||
|
Coalesced [7] vpoke::data#3 = vpoke::data#0
|
||||||
|
Coalesced [11] vpoke::addr#4 = vpoke::addr#1
|
||||||
|
Coalesced [15] main::i#6 = main::i#1
|
||||||
|
Coalesced [16] main::vaddr#7 = main::vaddr#2
|
||||||
|
Coalesced down to 4 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::@4
|
||||||
|
[1] main::vaddr#3 = phi( main/(byte*) 0, main::@4/main::vaddr#2 )
|
||||||
|
[1] main::i#2 = phi( main/0, main::@4/main::i#1 )
|
||||||
|
[2] if(0!=main::MSG[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] vpoke::addr#0 = main::vaddr#3
|
||||||
|
[5] vpoke::data#0 = main::MSG[main::i#2]
|
||||||
|
[6] call vpoke
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
[7] main::vaddr#1 = ++ main::vaddr#3
|
||||||
|
[8] vpoke::addr#1 = main::vaddr#1
|
||||||
|
[9] call vpoke
|
||||||
|
to:main::@4
|
||||||
|
main::@4: scope:[main] from main::@3
|
||||||
|
[10] main::vaddr#2 = ++ main::vaddr#1
|
||||||
|
[11] main::i#1 = ++ main::i#2
|
||||||
|
to:main::@1
|
||||||
|
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
vpoke: scope:[vpoke] from main::@2 main::@3
|
||||||
|
[12] vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@3/$21 )
|
||||||
|
[12] vpoke::addr#2 = phi( main::@2/vpoke::addr#0, main::@3/vpoke::addr#1 )
|
||||||
|
[13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||||
|
[14] vpoke::$0 = < vpoke::addr#2
|
||||||
|
[15] *VERA_ADDRX_L = vpoke::$0
|
||||||
|
[16] vpoke::$1 = > vpoke::addr#2
|
||||||
|
[17] *VERA_ADDRX_M = vpoke::$1
|
||||||
|
[18] *VERA_ADDRX_H = 0
|
||||||
|
[19] *VERA_DATA0 = vpoke::data#2
|
||||||
|
to:vpoke::@return
|
||||||
|
vpoke::@return: scope:[vpoke] from vpoke
|
||||||
|
[20] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
void main()
|
||||||
|
byte main::i
|
||||||
|
byte main::i#1 22.0
|
||||||
|
byte main::i#2 4.888888888888889
|
||||||
|
byte* main::vaddr
|
||||||
|
byte* main::vaddr#1 11.0
|
||||||
|
byte* main::vaddr#2 11.0
|
||||||
|
byte* main::vaddr#3 6.6000000000000005
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
byte~ vpoke::$0 202.0
|
||||||
|
byte~ vpoke::$1 202.0
|
||||||
|
byte* vpoke::addr
|
||||||
|
byte* vpoke::addr#0 11.0
|
||||||
|
byte* vpoke::addr#1 22.0
|
||||||
|
byte* vpoke::addr#2 56.0
|
||||||
|
byte vpoke::bank
|
||||||
|
byte vpoke::data
|
||||||
|
byte vpoke::data#0 22.0
|
||||||
|
byte vpoke::data#2 16.0
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
[ main::i#2 main::i#1 ]
|
||||||
|
[ main::vaddr#3 main::vaddr#2 ]
|
||||||
|
[ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
[ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
Added variable main::vaddr#1 to live range equivalence class [ main::vaddr#1 ]
|
||||||
|
Added variable vpoke::$0 to live range equivalence class [ vpoke::$0 ]
|
||||||
|
Added variable vpoke::$1 to live range equivalence class [ vpoke::$1 ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ main::i#2 main::i#1 ]
|
||||||
|
[ main::vaddr#3 main::vaddr#2 ]
|
||||||
|
[ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
[ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
[ main::vaddr#1 ]
|
||||||
|
[ vpoke::$0 ]
|
||||||
|
[ vpoke::$1 ]
|
||||||
|
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||||
|
Allocated zp[2]:3 [ main::vaddr#3 main::vaddr#2 ]
|
||||||
|
Allocated zp[2]:5 [ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
Allocated zp[1]:7 [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
Allocated zp[2]:8 [ main::vaddr#1 ]
|
||||||
|
Allocated zp[1]:10 [ vpoke::$0 ]
|
||||||
|
Allocated zp[1]:11 [ vpoke::$1 ]
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [2] if(0!=main::MSG[main::i#2]) goto main::@2 [ main::i#2 main::vaddr#3 ] ( [ main::i#2 main::vaddr#3 ] { } ) 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] vpoke::addr#0 = main::vaddr#3 [ main::i#2 main::vaddr#3 vpoke::addr#0 ] ( [ main::i#2 main::vaddr#3 vpoke::addr#0 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } ) always clobbers reg byte a
|
||||||
|
Statement [7] main::vaddr#1 = ++ main::vaddr#3 [ main::i#2 main::vaddr#1 ] ( [ main::i#2 main::vaddr#1 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [8] vpoke::addr#1 = main::vaddr#1 [ main::i#2 main::vaddr#1 vpoke::addr#1 ] ( [ main::i#2 main::vaddr#1 vpoke::addr#1 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [10] main::vaddr#2 = ++ main::vaddr#1 [ main::i#2 main::vaddr#2 ] ( [ main::i#2 main::vaddr#2 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ vpoke::addr#2 vpoke::data#2 ] ( vpoke:6 [ main::i#2 main::vaddr#3 vpoke::addr#2 vpoke::data#2 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } vpoke:9 [ main::i#2 main::vaddr#1 vpoke::addr#2 vpoke::data#2 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Removing always clobbered register reg byte a as potential for zp[1]:7 [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
Statement [18] *VERA_ADDRX_H = 0 [ vpoke::data#2 ] ( vpoke:6 [ main::i#2 main::vaddr#3 vpoke::data#2 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } vpoke:9 [ main::i#2 main::vaddr#1 vpoke::data#2 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [2] if(0!=main::MSG[main::i#2]) goto main::@2 [ main::i#2 main::vaddr#3 ] ( [ main::i#2 main::vaddr#3 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [4] vpoke::addr#0 = main::vaddr#3 [ main::i#2 main::vaddr#3 vpoke::addr#0 ] ( [ main::i#2 main::vaddr#3 vpoke::addr#0 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } ) always clobbers reg byte a
|
||||||
|
Statement [7] main::vaddr#1 = ++ main::vaddr#3 [ main::i#2 main::vaddr#1 ] ( [ main::i#2 main::vaddr#1 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [8] vpoke::addr#1 = main::vaddr#1 [ main::i#2 main::vaddr#1 vpoke::addr#1 ] ( [ main::i#2 main::vaddr#1 vpoke::addr#1 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [10] main::vaddr#2 = ++ main::vaddr#1 [ main::i#2 main::vaddr#2 ] ( [ main::i#2 main::vaddr#2 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ vpoke::addr#2 vpoke::data#2 ] ( vpoke:6 [ main::i#2 main::vaddr#3 vpoke::addr#2 vpoke::data#2 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } vpoke:9 [ main::i#2 main::vaddr#1 vpoke::addr#2 vpoke::data#2 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) always clobbers reg byte a
|
||||||
|
Statement [18] *VERA_ADDRX_H = 0 [ vpoke::data#2 ] ( vpoke:6 [ main::i#2 main::vaddr#3 vpoke::data#2 ] { { vpoke::addr#0 = vpoke::addr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } } vpoke:9 [ main::i#2 main::vaddr#1 vpoke::data#2 ] { { vpoke::addr#1 = vpoke::addr#2 main::vaddr#1 } } ) 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 ,
|
||||||
|
Potential registers zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] : zp[2]:3 ,
|
||||||
|
Potential registers zp[2]:5 [ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ] : zp[2]:5 ,
|
||||||
|
Potential registers zp[1]:7 [ vpoke::data#2 vpoke::data#0 ] : zp[1]:7 , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[2]:8 [ main::vaddr#1 ] : zp[2]:8 ,
|
||||||
|
Potential registers zp[1]:10 [ vpoke::$0 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:11 [ vpoke::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [vpoke] 202: zp[1]:10 [ vpoke::$0 ] 202: zp[1]:11 [ vpoke::$1 ] 89: zp[2]:5 [ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ] 38: zp[1]:7 [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
Uplift Scope [main] 26.89: zp[1]:2 [ main::i#2 main::i#1 ] 17.6: zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] 11: zp[2]:8 [ main::vaddr#1 ]
|
||||||
|
Uplift Scope [MOS6522_VIA]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [vpoke] best 1154 combination reg byte a [ vpoke::$0 ] reg byte a [ vpoke::$1 ] zp[2]:5 [ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ] reg byte x [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
Uplifting [main] best 1034 combination reg byte y [ main::i#2 main::i#1 ] zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] zp[2]:8 [ main::vaddr#1 ]
|
||||||
|
Uplifting [MOS6522_VIA] best 1034 combination
|
||||||
|
Uplifting [] best 1034 combination
|
||||||
|
Coalescing zero page register [ zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] ] with [ zp[2]:8 [ main::vaddr#1 ] ] - score: 2
|
||||||
|
Coalescing zero page register [ zp[2]:3 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 ] ] with [ zp[2]:5 [ vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ] ] - score: 1
|
||||||
|
Allocated (was zp[2]:3) zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Example program for the Commander X16
|
||||||
|
// Displays text on the screen by transfering data to VERA
|
||||||
|
// Upstart
|
||||||
|
.cpu _65c02
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="text.prg", type="prg", segments="Program"]
|
||||||
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
|
.segmentdef Basic [start=$0801]
|
||||||
|
.segmentdef Code [start=$80d]
|
||||||
|
.segmentdef Data [startAfter="Code"]
|
||||||
|
.segment Basic
|
||||||
|
:BasicUpstart(main)
|
||||||
|
.segment Code
|
||||||
|
|
||||||
|
|
||||||
|
// Global Constants & labels
|
||||||
|
.const VERA_ADDRSEL = 1
|
||||||
|
// $9F20 VRAM Address (7:0)
|
||||||
|
.label VERA_ADDRX_L = $9f20
|
||||||
|
// $9F21 VRAM Address (15:8)
|
||||||
|
.label VERA_ADDRX_M = $9f21
|
||||||
|
// $9F22 VRAM Address (7:0)
|
||||||
|
// Bit 4-7: Address Increment The following is the amount incremented per value value:increment
|
||||||
|
// 0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
|
||||||
|
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
|
||||||
|
// Bit 0: VRAM Address (16)
|
||||||
|
.label VERA_ADDRX_H = $9f22
|
||||||
|
// $9F23 DATA0 VRAM Data port 0
|
||||||
|
.label VERA_DATA0 = $9f23
|
||||||
|
// $9F25 CTRL Control
|
||||||
|
// Bit 7: Reset
|
||||||
|
// Bit 1: DCSEL
|
||||||
|
// Bit 2: ADDRSEL
|
||||||
|
.label VERA_CTRL = $9f25
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
// Address of the default screen
|
||||||
|
.label vaddr = 2
|
||||||
|
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||||
|
__b1_from_main:
|
||||||
|
// [1] phi main::vaddr#3 = (byte*) 0 [phi:main->main::@1#0] -- pbuz1=pbuc1
|
||||||
|
lda #<0
|
||||||
|
sta.z vaddr
|
||||||
|
lda #>0
|
||||||
|
sta.z vaddr+1
|
||||||
|
// [1] phi main::i#2 = 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||||
|
ldy #0
|
||||||
|
jmp __b1
|
||||||
|
// main::@1
|
||||||
|
__b1:
|
||||||
|
// [2] if(0!=main::MSG[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuyy_then_la1
|
||||||
|
lda MSG,y
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [3] return
|
||||||
|
rts
|
||||||
|
// main::@2
|
||||||
|
__b2:
|
||||||
|
// [4] vpoke::addr#0 = main::vaddr#3
|
||||||
|
// [5] vpoke::data#0 = main::MSG[main::i#2] -- vbuxx=pbuc1_derefidx_vbuyy
|
||||||
|
ldx MSG,y
|
||||||
|
// [6] call vpoke
|
||||||
|
// [12] phi from main::@2 to vpoke [phi:main::@2->vpoke]
|
||||||
|
vpoke_from___b2:
|
||||||
|
// [12] phi vpoke::data#2 = vpoke::data#0 [phi:main::@2->vpoke#0] -- register_copy
|
||||||
|
// [12] phi vpoke::addr#2 = vpoke::addr#0 [phi:main::@2->vpoke#1] -- register_copy
|
||||||
|
jsr vpoke
|
||||||
|
jmp __b3
|
||||||
|
// main::@3
|
||||||
|
__b3:
|
||||||
|
// [7] main::vaddr#1 = ++ main::vaddr#3 -- pbuz1=_inc_pbuz1
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// [8] vpoke::addr#1 = main::vaddr#1
|
||||||
|
// [9] call vpoke
|
||||||
|
// Message
|
||||||
|
// [12] phi from main::@3 to vpoke [phi:main::@3->vpoke]
|
||||||
|
vpoke_from___b3:
|
||||||
|
// [12] phi vpoke::data#2 = $21 [phi:main::@3->vpoke#0] -- vbuxx=vbuc1
|
||||||
|
ldx #$21
|
||||||
|
// [12] phi vpoke::addr#2 = vpoke::addr#1 [phi:main::@3->vpoke#1] -- register_copy
|
||||||
|
jsr vpoke
|
||||||
|
jmp __b4
|
||||||
|
// main::@4
|
||||||
|
__b4:
|
||||||
|
// [10] main::vaddr#2 = ++ main::vaddr#1 -- pbuz1=_inc_pbuz1
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// [11] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy
|
||||||
|
iny
|
||||||
|
// [1] phi from main::@4 to main::@1 [phi:main::@4->main::@1]
|
||||||
|
__b1_from___b4:
|
||||||
|
// [1] phi main::vaddr#3 = main::vaddr#2 [phi:main::@4->main::@1#0] -- register_copy
|
||||||
|
// [1] phi main::i#2 = main::i#1 [phi:main::@4->main::@1#1] -- register_copy
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
MSG: .text "hello world!"
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
// vpoke
|
||||||
|
// Put a single byte into VRAM.
|
||||||
|
// Uses VERA DATA0
|
||||||
|
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||||
|
// - addr: The address in VRAM
|
||||||
|
// - data: The data to put into VRAM
|
||||||
|
// vpoke(byte* zp(2) addr, byte register(X) data)
|
||||||
|
vpoke: {
|
||||||
|
.label addr = 2
|
||||||
|
// [13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2
|
||||||
|
// Select DATA0
|
||||||
|
lda #VERA_ADDRSEL^$ff
|
||||||
|
and VERA_CTRL
|
||||||
|
sta VERA_CTRL
|
||||||
|
// [14] vpoke::$0 = < vpoke::addr#2 -- vbuaa=_lo_pbuz1
|
||||||
|
lda.z addr
|
||||||
|
// [15] *VERA_ADDRX_L = vpoke::$0 -- _deref_pbuc1=vbuaa
|
||||||
|
// Set address
|
||||||
|
sta VERA_ADDRX_L
|
||||||
|
// [16] vpoke::$1 = > vpoke::addr#2 -- vbuaa=_hi_pbuz1
|
||||||
|
lda.z addr+1
|
||||||
|
// [17] *VERA_ADDRX_M = vpoke::$1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta VERA_ADDRX_M
|
||||||
|
// [18] *VERA_ADDRX_H = 0 -- _deref_pbuc1=vbuc2
|
||||||
|
lda #0
|
||||||
|
sta VERA_ADDRX_H
|
||||||
|
// [19] *VERA_DATA0 = vpoke::data#2 -- _deref_pbuc1=vbuxx
|
||||||
|
// Set data
|
||||||
|
stx VERA_DATA0
|
||||||
|
jmp __breturn
|
||||||
|
// vpoke::@return
|
||||||
|
__breturn:
|
||||||
|
// [20] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __b1
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __b3
|
||||||
|
Removing instruction jmp __b4
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction lda #>0
|
||||||
|
Replacing instruction ldy #0 with TAY
|
||||||
|
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||||
|
Removing instruction __b1_from_main:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction vpoke_from___b2:
|
||||||
|
Removing instruction __b3:
|
||||||
|
Removing instruction vpoke_from___b3:
|
||||||
|
Removing instruction __b4:
|
||||||
|
Removing instruction __b1_from___b4:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
const nomodify byte VERA_ADDRSEL = 1
|
||||||
|
const nomodify byte* VERA_ADDRX_H = (byte*) 40738
|
||||||
|
const nomodify byte* VERA_ADDRX_L = (byte*) 40736
|
||||||
|
const nomodify byte* VERA_ADDRX_M = (byte*) 40737
|
||||||
|
const nomodify byte* VERA_CTRL = (byte*) 40741
|
||||||
|
const nomodify byte* VERA_DATA0 = (byte*) 40739
|
||||||
|
void main()
|
||||||
|
const byte* main::MSG[] = "hello world!"
|
||||||
|
byte main::i
|
||||||
|
byte main::i#1 reg byte y 22.0
|
||||||
|
byte main::i#2 reg byte y 4.888888888888889
|
||||||
|
byte* main::vaddr
|
||||||
|
byte* main::vaddr#1 vaddr zp[2]:2 11.0
|
||||||
|
byte* main::vaddr#2 vaddr zp[2]:2 11.0
|
||||||
|
byte* main::vaddr#3 vaddr zp[2]:2 6.6000000000000005
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
byte~ vpoke::$0 reg byte a 202.0
|
||||||
|
byte~ vpoke::$1 reg byte a 202.0
|
||||||
|
byte* vpoke::addr
|
||||||
|
byte* vpoke::addr#0 addr zp[2]:2 11.0
|
||||||
|
byte* vpoke::addr#1 addr zp[2]:2 22.0
|
||||||
|
byte* vpoke::addr#2 addr zp[2]:2 56.0
|
||||||
|
byte vpoke::bank
|
||||||
|
byte vpoke::data
|
||||||
|
byte vpoke::data#0 reg byte x 22.0
|
||||||
|
byte vpoke::data#2 reg byte x 16.0
|
||||||
|
|
||||||
|
reg byte y [ main::i#2 main::i#1 ]
|
||||||
|
zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
reg byte x [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
reg byte a [ vpoke::$0 ]
|
||||||
|
reg byte a [ vpoke::$1 ]
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 595
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Example program for the Commander X16
|
||||||
|
// Displays text on the screen by transfering data to VERA
|
||||||
|
// Upstart
|
||||||
|
.cpu _65c02
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="text.prg", type="prg", segments="Program"]
|
||||||
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
|
.segmentdef Basic [start=$0801]
|
||||||
|
.segmentdef Code [start=$80d]
|
||||||
|
.segmentdef Data [startAfter="Code"]
|
||||||
|
.segment Basic
|
||||||
|
:BasicUpstart(main)
|
||||||
|
.segment Code
|
||||||
|
|
||||||
|
|
||||||
|
// Global Constants & labels
|
||||||
|
.const VERA_ADDRSEL = 1
|
||||||
|
// $9F20 VRAM Address (7:0)
|
||||||
|
.label VERA_ADDRX_L = $9f20
|
||||||
|
// $9F21 VRAM Address (15:8)
|
||||||
|
.label VERA_ADDRX_M = $9f21
|
||||||
|
// $9F22 VRAM Address (7:0)
|
||||||
|
// Bit 4-7: Address Increment The following is the amount incremented per value value:increment
|
||||||
|
// 0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
|
||||||
|
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
|
||||||
|
// Bit 0: VRAM Address (16)
|
||||||
|
.label VERA_ADDRX_H = $9f22
|
||||||
|
// $9F23 DATA0 VRAM Data port 0
|
||||||
|
.label VERA_DATA0 = $9f23
|
||||||
|
// $9F25 CTRL Control
|
||||||
|
// Bit 7: Reset
|
||||||
|
// Bit 1: DCSEL
|
||||||
|
// Bit 2: ADDRSEL
|
||||||
|
.label VERA_CTRL = $9f25
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
// Address of the default screen
|
||||||
|
.label vaddr = 2
|
||||||
|
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||||
|
// [1] phi main::vaddr#3 = (byte*) 0 [phi:main->main::@1#0] -- pbuz1=pbuc1
|
||||||
|
lda #<0
|
||||||
|
sta.z vaddr
|
||||||
|
sta.z vaddr+1
|
||||||
|
// [1] phi main::i#2 = 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||||
|
tay
|
||||||
|
// main::@1
|
||||||
|
__b1:
|
||||||
|
// for(char i=0;MSG[i];i++)
|
||||||
|
// [2] if(0!=main::MSG[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuyy_then_la1
|
||||||
|
lda MSG,y
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [3] return
|
||||||
|
rts
|
||||||
|
// main::@2
|
||||||
|
__b2:
|
||||||
|
// vpoke(0, vaddr++, MSG[i])
|
||||||
|
// [4] vpoke::addr#0 = main::vaddr#3
|
||||||
|
// [5] vpoke::data#0 = main::MSG[main::i#2] -- vbuxx=pbuc1_derefidx_vbuyy
|
||||||
|
ldx MSG,y
|
||||||
|
// [6] call vpoke
|
||||||
|
// [12] phi from main::@2 to vpoke [phi:main::@2->vpoke]
|
||||||
|
// [12] phi vpoke::data#2 = vpoke::data#0 [phi:main::@2->vpoke#0] -- register_copy
|
||||||
|
// [12] phi vpoke::addr#2 = vpoke::addr#0 [phi:main::@2->vpoke#1] -- register_copy
|
||||||
|
jsr vpoke
|
||||||
|
// main::@3
|
||||||
|
// vpoke(0, vaddr++, MSG[i]);
|
||||||
|
// [7] main::vaddr#1 = ++ main::vaddr#3 -- pbuz1=_inc_pbuz1
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// vpoke(0, vaddr++, 0x21)
|
||||||
|
// [8] vpoke::addr#1 = main::vaddr#1
|
||||||
|
// [9] call vpoke
|
||||||
|
// Message
|
||||||
|
// [12] phi from main::@3 to vpoke [phi:main::@3->vpoke]
|
||||||
|
// [12] phi vpoke::data#2 = $21 [phi:main::@3->vpoke#0] -- vbuxx=vbuc1
|
||||||
|
ldx #$21
|
||||||
|
// [12] phi vpoke::addr#2 = vpoke::addr#1 [phi:main::@3->vpoke#1] -- register_copy
|
||||||
|
jsr vpoke
|
||||||
|
// main::@4
|
||||||
|
// vpoke(0, vaddr++, 0x21);
|
||||||
|
// [10] main::vaddr#2 = ++ main::vaddr#1 -- pbuz1=_inc_pbuz1
|
||||||
|
inc.z vaddr
|
||||||
|
bne !+
|
||||||
|
inc.z vaddr+1
|
||||||
|
!:
|
||||||
|
// for(char i=0;MSG[i];i++)
|
||||||
|
// [11] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy
|
||||||
|
iny
|
||||||
|
// [1] phi from main::@4 to main::@1 [phi:main::@4->main::@1]
|
||||||
|
// [1] phi main::vaddr#3 = main::vaddr#2 [phi:main::@4->main::@1#0] -- register_copy
|
||||||
|
// [1] phi main::i#2 = main::i#1 [phi:main::@4->main::@1#1] -- register_copy
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
MSG: .text "hello world!"
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
// vpoke
|
||||||
|
// Put a single byte into VRAM.
|
||||||
|
// Uses VERA DATA0
|
||||||
|
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||||
|
// - addr: The address in VRAM
|
||||||
|
// - data: The data to put into VRAM
|
||||||
|
// vpoke(byte* zp(2) addr, byte register(X) data)
|
||||||
|
vpoke: {
|
||||||
|
.label addr = 2
|
||||||
|
// *VERA_CTRL &= ~VERA_ADDRSEL
|
||||||
|
// [13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2
|
||||||
|
// Select DATA0
|
||||||
|
lda #VERA_ADDRSEL^$ff
|
||||||
|
and VERA_CTRL
|
||||||
|
sta VERA_CTRL
|
||||||
|
// <addr
|
||||||
|
// [14] vpoke::$0 = < vpoke::addr#2 -- vbuaa=_lo_pbuz1
|
||||||
|
lda.z addr
|
||||||
|
// *VERA_ADDRX_L = <addr
|
||||||
|
// [15] *VERA_ADDRX_L = vpoke::$0 -- _deref_pbuc1=vbuaa
|
||||||
|
// Set address
|
||||||
|
sta VERA_ADDRX_L
|
||||||
|
// >addr
|
||||||
|
// [16] vpoke::$1 = > vpoke::addr#2 -- vbuaa=_hi_pbuz1
|
||||||
|
lda.z addr+1
|
||||||
|
// *VERA_ADDRX_M = >addr
|
||||||
|
// [17] *VERA_ADDRX_M = vpoke::$1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta VERA_ADDRX_M
|
||||||
|
// *VERA_ADDRX_H = VERA_INC_0 | bank
|
||||||
|
// [18] *VERA_ADDRX_H = 0 -- _deref_pbuc1=vbuc2
|
||||||
|
lda #0
|
||||||
|
sta VERA_ADDRX_H
|
||||||
|
// *VERA_DATA0 = data
|
||||||
|
// [19] *VERA_DATA0 = vpoke::data#2 -- _deref_pbuc1=vbuxx
|
||||||
|
// Set data
|
||||||
|
stx VERA_DATA0
|
||||||
|
// vpoke::@return
|
||||||
|
// }
|
||||||
|
// [20] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
32
src/test/ref/examples/cx16/text.sym
Normal file
32
src/test/ref/examples/cx16/text.sym
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const nomodify byte VERA_ADDRSEL = 1
|
||||||
|
const nomodify byte* VERA_ADDRX_H = (byte*) 40738
|
||||||
|
const nomodify byte* VERA_ADDRX_L = (byte*) 40736
|
||||||
|
const nomodify byte* VERA_ADDRX_M = (byte*) 40737
|
||||||
|
const nomodify byte* VERA_CTRL = (byte*) 40741
|
||||||
|
const nomodify byte* VERA_DATA0 = (byte*) 40739
|
||||||
|
void main()
|
||||||
|
const byte* main::MSG[] = "hello world!"
|
||||||
|
byte main::i
|
||||||
|
byte main::i#1 reg byte y 22.0
|
||||||
|
byte main::i#2 reg byte y 4.888888888888889
|
||||||
|
byte* main::vaddr
|
||||||
|
byte* main::vaddr#1 vaddr zp[2]:2 11.0
|
||||||
|
byte* main::vaddr#2 vaddr zp[2]:2 11.0
|
||||||
|
byte* main::vaddr#3 vaddr zp[2]:2 6.6000000000000005
|
||||||
|
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||||
|
byte~ vpoke::$0 reg byte a 202.0
|
||||||
|
byte~ vpoke::$1 reg byte a 202.0
|
||||||
|
byte* vpoke::addr
|
||||||
|
byte* vpoke::addr#0 addr zp[2]:2 11.0
|
||||||
|
byte* vpoke::addr#1 addr zp[2]:2 22.0
|
||||||
|
byte* vpoke::addr#2 addr zp[2]:2 56.0
|
||||||
|
byte vpoke::bank
|
||||||
|
byte vpoke::data
|
||||||
|
byte vpoke::data#0 reg byte x 22.0
|
||||||
|
byte vpoke::data#2 reg byte x 16.0
|
||||||
|
|
||||||
|
reg byte y [ main::i#2 main::i#1 ]
|
||||||
|
zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||||
|
reg byte x [ vpoke::data#2 vpoke::data#0 ]
|
||||||
|
reg byte a [ vpoke::$0 ]
|
||||||
|
reg byte a [ vpoke::$1 ]
|
Loading…
Reference in New Issue
Block a user