1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added malloc tests. Improved cast handing in ASM fragments. Optimized screen center distance calculation (implemented table-based sqr() and sqrt() using binary search).

This commit is contained in:
jespergravgaard 2019-06-23 23:44:55 +02:00
parent 306bbc381f
commit 20ec350ca5
37 changed files with 7218 additions and 103 deletions

View File

@ -0,0 +1,10 @@
ldy #1
lda ({z1}),y
cmp {z2}+1
bne !+
dey
lda ({z1}),y
cmp {z2}
beq {la1}
!:
bcc {la1}

View File

@ -0,0 +1,4 @@
lda #<{c1}
sta {z1}
lda #>{c1}
sta {z1}+1

View File

@ -0,0 +1,4 @@
lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1

View File

@ -1,3 +1,3 @@
eor #$ff
tax
axs #{c1}+1
axs #-{c1}-1

View File

@ -0,0 +1,9 @@
sec
ldy #0
lda ({z2}),y
sbc {z3}
sta {z1}
iny
lda ({z2}),y
sbc {z3}+1
sta {z1}+1

View File

@ -0,0 +1,9 @@
sec
lda {z2}
ldy #0
sbc ({z3}),y
sta {z1}
lda {z2}+1
iny
sbc ({z3}),y
sta {z1}+1

View File

@ -0,0 +1,4 @@
lda {z1}+1
bne {la1}
lda {z1}
bne {la1}

View File

@ -0,0 +1,5 @@
lda {z1}+1
bne {la1}
lda {z1}
bne {la1}
!:

View File

@ -7,7 +7,10 @@ import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.symbols.ConstantVar;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.*;
import dk.camelot64.kickc.model.values.*;
@ -223,13 +226,29 @@ public class AsmFragmentInstanceSpecFactory {
if(value instanceof CastValue) {
CastValue cast = (CastValue) value;
SymbolType toType = cast.getToType();
OperatorUnary castUnary = Operators.getCastUnary(toType);
RValue castValue = cast.getValue();
SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue);
if(castValueType.getSizeBytes() == toType.getSizeBytes()) {
return bind(castValue, toType);
if(castType != null) {
if(castType.getSizeBytes() == toType.getSizeBytes()) {
return bind(castValue, castType);
} else {
OperatorUnary castUnary = Operators.getCastUnary(castType);
return getOperatorFragmentName(castUnary) + bind(castValue, toType);
}
} else {
return bind(castValue, toType);
}
} else {
return getOperatorFragmentName(castUnary) + bind(castValue);
// Size of inner value and inner cast type mismatches - require explicit conversion
if(castType != null) {
OperatorUnary castUnaryInner = Operators.getCastUnary(toType);
OperatorUnary castUnaryOuter = Operators.getCastUnary(castType);
return getOperatorFragmentName(castUnaryOuter) + getOperatorFragmentName(castUnaryInner) + bind(castValue);
} else {
OperatorUnary castUnaryInner = Operators.getCastUnary(toType);
return getOperatorFragmentName(castUnaryInner) + bind(castValue);
}
}
} else if(value instanceof ConstantCastValue) {
ConstantCastValue castVal = (ConstantCastValue) value;

View File

@ -1298,7 +1298,12 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
} else {
simpleTypeName = "int";
}
return SymbolType.get(signedness + " " + simpleTypeName);
String fullName = signedness + " " + simpleTypeName;
SymbolType symbolType = SymbolType.get(fullName);
if(symbolType==null) {
throw new CompileError("Unknown type "+fullName, new StatementSource(ctx));
}
return symbolType;
}
@Override

View File

@ -35,6 +35,16 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testUnsignedVoidError() throws IOException, URISyntaxException {
assertError("unsigned-void-error", "Unknown type unsigned void");
}
@Test
public void testScreenCenterDistance() throws IOException, URISyntaxException {
compileAndCompare("screen-center-distance");
}
@Test
public void testFontHexShow() throws IOException, URISyntaxException {
compileAndCompare("font-hex-show");
@ -502,6 +512,16 @@ public class TestPrograms {
compileAndCompare("memory-heap");
}
@Test
public void testMalloc1() throws IOException, URISyntaxException {
compileAndCompare("malloc-1");
}
@Test
public void testMalloc0() throws IOException, URISyntaxException {
compileAndCompare("malloc-0");
}
@Test
public void testTernaryInference() throws IOException, URISyntaxException {
compileAndCompare("ternary-inference");

11
src/test/kc/malloc-0.kc Normal file
View File

@ -0,0 +1,11 @@
// Experiments with malloc() - a byte array
import "stdlib"
byte* BYTES = malloc(0x100);
void main() {
for( byte i: 0..255) {
BYTES[i] = i;
}
}

12
src/test/kc/malloc-1.kc Normal file
View File

@ -0,0 +1,12 @@
// Experiments with malloc() - a word array
import "stdlib"
word* WORDS = malloc(0x200);
void main() {
word* w = WORDS;
for( byte i: 0..255) {
*w++ = i;
}
}

View File

@ -3,8 +3,8 @@
import "stdlib"
void main() {
unsigned char* buf1 = (unsigned char*) malloc(100);
unsigned char* buf2 = (unsigned char*) malloc(100);
unsigned char* buf1 = malloc(100);
unsigned char* buf2 = malloc(100);
for(unsigned char i:0..99) {
buf1[i] = i;
buf2[i] = 255-i;

View File

@ -0,0 +1,86 @@
// Calculate the distance to the center of the screen - and show it using font-hex
import "stdlib"
import "c64"
import "font-hex"
#reserve(08)
const byte* CHARSET = 0x2000;
const byte* SCREEN = 0x2800;
void main() {
init_font_hex(CHARSET);
*D018 = toD018(SCREEN, CHARSET);
NUM_SQUARES = 0x30;
init_squares();
byte* screen = SCREEN;
for(byte y: 0..24) {
byte y2 = y*2;
byte yd = (y2>=24)?(y2-24):(24-y2);
word yds = sqr(yd);
for(byte x: 0..39) {
byte x2 = x*2;
byte xd = (x2>=39)?(x2-39):(39-x2);
word xds = sqr(xd);
word ds = xds+yds;
byte d = sqrt(ds);
*screen++ = d;
}
}
}
// The number of squares to pre-calculate. Limits what values sqr() can calculate and the result of sqrt()
byte NUM_SQUARES = 0xff;
// Squares for each byte value SQUARES[i] = i*i
// Initialized by init_squares()
word* SQUARES;
// Initialize squares table
// Uses iterative formula (x+1)^2 = x^2 + 2*x + 1
void init_squares() {
SQUARES = malloc(NUM_SQUARES*sizeof(word));
word* squares = SQUARES;
word sqr = 0;
for( byte i: 0..NUM_SQUARES-1) {
*squares++ = sqr;
sqr += i*2+1;
}
}
// Find the square of a byte value
// Uses a table of squares that must be initialized by calling init_squares()
word sqr(byte val) {
return SQUARES[val];
}
// Find the (integer) square root of a word value
// If the square is not an integer then it returns the largest integer N where N*N <= val
// Uses a table of squares that must be initialized by calling init_squares()
byte sqrt(word val) {
word* found = bsearch16u(val, SQUARES, NUM_SQUARES);
byte sqr1 = (byte)((byte*)found-(byte*)SQUARES)/2;
return sqr1;
}
// Searches an array of nitems unsigned words, the initial member of which is pointed to by base, for a member that matches the value key.
// - key - The value to look for
// - items - Pointer to the start of the array to search in
// - num - The number of items in the array
// Returns pointer to an entry in the array that matches the search key
word* bsearch16u(word key, word* items, byte num) {
while (num > 0) {
word* pivot = items + (num >> 1);
signed word result = (signed word)key-(signed word)*pivot;
if (result == 0)
return pivot;
if (result > 0) {
items = pivot+1;
num--;
}
num >>= 1;
}
// not found - return closest lower value
return *items<=key?items:items-1;
}

View File

@ -0,0 +1,11 @@
// Tests that unsigned void produces an error
void main() {
getNull();
}
unsigned void* getNull() {
return (byte*) 0;
}

View File

@ -264,13 +264,13 @@ mulf_init: {
tya
eor #$ff
tax
axs #1+1
axs #-1-1
lda val
sta mulf_sqr2,x
tya
eor #$ff
tax
axs #1+1
axs #-1-1
lda val
sta mulf_sqr2+$100,x
lda sqr

View File

@ -3003,7 +3003,7 @@ mulf_init: {
tya
eor #$ff
tax
axs #1+1
axs #-1-1
//SEG201 [96] *((const byte[$200]) mulf_sqr2#0 + (byte~) mulf_init::$8) ← (byte) mulf_init::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
lda val
sta mulf_sqr2,x
@ -3011,7 +3011,7 @@ mulf_init: {
tya
eor #$ff
tax
axs #1+1
axs #-1-1
//SEG203 [98] *((const byte[$200]) mulf_sqr2#0+(word) $100 + (byte~) mulf_init::$10) ← (byte) mulf_init::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
lda val
sta mulf_sqr2+$100,x
@ -3829,7 +3829,7 @@ mulf_init: {
tya
eor #$ff
tax
axs #1+1
axs #-1-1
//SEG201 [96] *((const byte[$200]) mulf_sqr2#0 + (byte~) mulf_init::$8) ← (byte) mulf_init::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
lda val
sta mulf_sqr2,x
@ -3837,7 +3837,7 @@ mulf_init: {
tya
eor #$ff
tax
axs #1+1
axs #-1-1
//SEG203 [98] *((const byte[$200]) mulf_sqr2#0+(word) $100 + (byte~) mulf_init::$10) ← (byte) mulf_init::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
lda val
sta mulf_sqr2+$100,x

View File

@ -2229,7 +2229,7 @@ anim: {
jmp mulf8s_prepare1
//SEG38 anim::mulf8s_prepare1
mulf8s_prepare1:
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuz1=pbsc1_derefidx_vbuz2
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuz1=pbuc1_derefidx_vbuz2
ldy angle
lda COS,y
sta mulf8u_prepare.a
@ -2280,7 +2280,7 @@ anim: {
jmp mulf8s_prepare2
//SEG56 anim::mulf8s_prepare2
mulf8s_prepare2:
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuz1=pbsc1_derefidx_vbuz2
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuz1=pbuc1_derefidx_vbuz2
ldy angle
lda SIN,y
sta mulf8u_prepare.a
@ -2866,14 +2866,12 @@ REGISTER UPLIFT POTENTIAL REGISTERS
Equivalence Class zp ZP_BYTE:42 [ anim::$22 ] has ALU potential.
Statement [12] if(*((const byte*) RASTER#0)!=(byte) $ff) goto anim::@2 [ anim::angle#6 ] ( main:3::anim:8 [ anim::angle#6 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ anim::angle#6 anim::angle#1 ]
Statement [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 mulf8u_prepare::a#3 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 mulf8u_prepare::a#3 ] ) always clobbers reg byte a
Statement [21] (signed word) anim::xr#0 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ anim::i#10 anim::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ anim::sprite_msb#10 anim::sprite_msb#5 anim::sprite_msb#2 anim::sprite_msb#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:24 [ anim::x#0 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:25 [ anim::y#0 ]
Statement [21] (signed word) anim::xr#0 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ) always clobbers reg byte a
Statement [24] (signed word) anim::yr#0 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 ] ) always clobbers reg byte a
Statement [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 mulf8u_prepare::a#4 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 mulf8u_prepare::a#4 ] ) always clobbers reg byte a
Statement [29] (signed word~) anim::$10 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::xr#0 anim::yr#0 anim::$10 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::xr#0 anim::yr#0 anim::$10 ] ) always clobbers reg byte a
Statement [30] (signed word) anim::xr#1 ← (signed word) anim::xr#0 - (signed word~) anim::$10 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::yr#0 anim::xr#1 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::yr#0 anim::xr#1 ] ) always clobbers reg byte a
Statement [33] (signed word~) anim::$12 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::yr#0 anim::xr#1 anim::$12 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::yr#0 anim::xr#1 anim::$12 ] ) always clobbers reg byte a
@ -2930,10 +2928,8 @@ Statement [110] if((byte*) mulf_init::sqr2_lo#1!=(const byte[$200]) mulf_sqr2_lo
Statement [111] *((const byte[$200]) mulf_sqr2_lo#0+(word) $1ff) ← *((const byte[$200]) mulf_sqr1_lo#0+(word) $100) [ ] ( main:3::init:6::mulf_init:77 [ ] ) always clobbers reg byte a
Statement [112] *((const byte[$200]) mulf_sqr2_hi#0+(word) $1ff) ← *((const byte[$200]) mulf_sqr1_hi#0+(word) $100) [ ] ( main:3::init:6::mulf_init:77 [ ] ) always clobbers reg byte a
Statement [12] if(*((const byte*) RASTER#0)!=(byte) $ff) goto anim::@2 [ anim::angle#6 ] ( main:3::anim:8 [ anim::angle#6 ] ) always clobbers reg byte a
Statement [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 mulf8u_prepare::a#3 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 mulf8u_prepare::a#3 ] ) always clobbers reg byte a
Statement [21] (signed word) anim::xr#0 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 ] ) always clobbers reg byte a
Statement [24] (signed word) anim::yr#0 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 ] ) always clobbers reg byte a
Statement [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 mulf8u_prepare::a#4 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::y#0 anim::xr#0 anim::yr#0 mulf8u_prepare::a#4 ] ) always clobbers reg byte a
Statement [29] (signed word~) anim::$10 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::xr#0 anim::yr#0 anim::$10 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::xr#0 anim::yr#0 anim::$10 ] ) always clobbers reg byte a
Statement [30] (signed word) anim::xr#1 ← (signed word) anim::xr#0 - (signed word~) anim::$10 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::yr#0 anim::xr#1 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::x#0 anim::yr#0 anim::xr#1 ] ) always clobbers reg byte a
Statement [33] (signed word~) anim::$12 ← (signed word)(word) mulf8s_prepared::m#4 << (byte) 1 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::yr#0 anim::xr#1 anim::$12 ] ( main:3::anim:8 [ anim::angle#6 anim::i#10 anim::sprite_msb#10 anim::yr#0 anim::xr#1 anim::$12 ] ) always clobbers reg byte a
@ -3204,7 +3200,7 @@ anim: {
jmp mulf8s_prepare1
//SEG38 anim::mulf8s_prepare1
mulf8s_prepare1:
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuaa=pbsc1_derefidx_vbuz1
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuaa=pbuc1_derefidx_vbuz1
ldy angle
lda COS,y
//SEG40 [18] call mulf8u_prepare
@ -3252,7 +3248,7 @@ anim: {
jmp mulf8s_prepare2
//SEG56 anim::mulf8s_prepare2
mulf8s_prepare2:
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuaa=pbsc1_derefidx_vbuz1
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuaa=pbuc1_derefidx_vbuz1
ldy angle
lda SIN,y
//SEG58 [26] call mulf8u_prepare
@ -4237,7 +4233,7 @@ anim: {
lda ys,y
sta y
//SEG38 anim::mulf8s_prepare1
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuaa=pbsc1_derefidx_vbuz1
//SEG39 [17] (byte~) mulf8u_prepare::a#3 ← (byte)(signed byte)*((const byte*) COS#0 + (byte) anim::angle#6) -- vbuaa=pbuc1_derefidx_vbuz1
ldy angle
lda COS,y
//SEG40 [18] call mulf8u_prepare
@ -4274,7 +4270,7 @@ anim: {
rol
sta yr+1
//SEG56 anim::mulf8s_prepare2
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuaa=pbsc1_derefidx_vbuz1
//SEG57 [25] (byte~) mulf8u_prepare::a#4 ← (byte)(signed byte)*((const byte*) SIN#0 + (byte) anim::angle#6) -- vbuaa=pbuc1_derefidx_vbuz1
ldy angle
lda SIN,y
//SEG58 [26] call mulf8u_prepare

25
src/test/ref/malloc-0.asm Normal file
View File

@ -0,0 +1,25 @@
// Experiments with malloc() - a byte array
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Start of the heap used by malloc()
.label HEAP_START = $c000
bbegin:
jsr malloc
jsr main
rts
main: {
ldx #0
b1:
txa
sta HEAP_START,x
inx
cpx #0
bne b1
rts
}
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
rts
}

31
src/test/ref/malloc-0.cfg Normal file
View File

@ -0,0 +1,31 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call malloc
to:@2
@2: scope:[] from @1
[3] phi()
[4] call main
to:@end
@end: scope:[] from @2
[5] phi()
main: scope:[main] from @2
[6] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[7] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
[8] *((const byte*) HEAP_START#0 + (byte) main::i#2) ← (byte) main::i#2
[9] (byte) main::i#1 ← ++ (byte) main::i#2
[10] if((byte) main::i#1!=(byte) 0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[11] return
to:@return
malloc: scope:[malloc] from @1
[12] phi()
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
[13] return
to:@return

516
src/test/ref/malloc-0.log Normal file
View File

@ -0,0 +1,516 @@
Adding pointer type conversion cast (byte*) HEAP_START in (byte*) HEAP_START ← (number) $c000
Identified constant variable (byte*) HEAP_START
Culled Empty Block (label) malloc::@1
Culled Empty Block (label) @1
Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*) HEAP_START#0 ← ((byte*)) (number) $c000
(byte*) heap_head#0 ← (byte*) HEAP_START#0
to:@2
malloc: scope:[malloc] from @2
(word) malloc::size#1 ← phi( @2/(word) malloc::size#0 )
(byte*) heap_head#4 ← phi( @2/(byte*) heap_head#7 )
(byte*) malloc::mem#0 ← (byte*) heap_head#4
(byte*) heap_head#1 ← (byte*) heap_head#4 + (word) malloc::size#1
(byte*) malloc::return#0 ← (byte*) malloc::mem#0
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
(byte*) heap_head#5 ← phi( malloc/(byte*) heap_head#1 )
(byte*) malloc::return#3 ← phi( malloc/(byte*) malloc::return#0 )
(byte*) malloc::return#1 ← (byte*) malloc::return#3
(byte*) heap_head#2 ← (byte*) heap_head#5
return
to:@return
@2: scope:[] from @begin
(byte*) heap_head#7 ← phi( @begin/(byte*) heap_head#0 )
(word) malloc::size#0 ← (number) $100
call malloc
(byte*) malloc::return#2 ← (byte*) malloc::return#1
to:@4
@4: scope:[] from @2
(byte*) heap_head#6 ← phi( @2/(byte*) heap_head#2 )
(byte*) malloc::return#4 ← phi( @2/(byte*) malloc::return#2 )
(byte*~) $0 ← (byte*) malloc::return#4
(byte*) heap_head#3 ← (byte*) heap_head#6
(byte*) BYTES#0 ← (byte*~) $0
to:@3
main: scope:[main] from @3
(byte*) BYTES#2 ← phi( @3/(byte*) BYTES#3 )
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(byte*) BYTES#1 ← phi( main/(byte*) BYTES#2 main::@1/(byte*) BYTES#1 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
*((byte*) BYTES#1 + (byte) main::i#2) ← (byte) main::i#2
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,$ff)
(bool~) main::$0 ← (byte) main::i#1 != rangelast(0,$ff)
if((bool~) main::$0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
@3: scope:[] from @4
(byte*) BYTES#3 ← phi( @4/(byte*) BYTES#0 )
call main
to:@5
@5: scope:[] from @3
to:@end
@end: scope:[] from @5
SYMBOL TABLE SSA
(byte*~) $0
(label) @2
(label) @3
(label) @4
(label) @5
(label) @begin
(label) @end
(byte*) BYTES
(byte*) BYTES#0
(byte*) BYTES#1
(byte*) BYTES#2
(byte*) BYTES#3
(byte*) HEAP_START
(byte*) HEAP_START#0
(byte*) heap_head
(byte*) heap_head#0
(byte*) heap_head#1
(byte*) heap_head#2
(byte*) heap_head#3
(byte*) heap_head#4
(byte*) heap_head#5
(byte*) heap_head#6
(byte*) heap_head#7
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::mem#0
(byte*) malloc::return
(byte*) malloc::return#0
(byte*) malloc::return#1
(byte*) malloc::return#2
(byte*) malloc::return#3
(byte*) malloc::return#4
(word) malloc::size
(word) malloc::size#0
(word) malloc::size#1
Adding number conversion cast (unumber) $100 in (word) malloc::size#0 ← (number) $100
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) HEAP_START#0 ← (byte*)(number) $c000
Inlining cast (word) malloc::size#0 ← (unumber)(number) $100
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 49152
Simplifying constant integer cast $100
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (word) $100
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte*) HEAP_START#0 = (byte*) heap_head#0 (byte*) heap_head#7
Alias (byte*) malloc::return#0 = (byte*) malloc::mem#0 (byte*) malloc::return#3 (byte*) malloc::return#1
Alias (byte*) heap_head#1 = (byte*) heap_head#5 (byte*) heap_head#2
Alias (byte*) malloc::return#2 = (byte*) malloc::return#4
Alias (byte*) heap_head#3 = (byte*) heap_head#6
Alias (byte*) BYTES#0 = (byte*~) $0 (byte*) BYTES#3
Successful SSA optimization Pass2AliasElimination
Self Phi Eliminated (byte*) BYTES#1
Successful SSA optimization Pass2SelfPhiElimination
Identical Phi Values (byte*) heap_head#4 (byte*) HEAP_START#0
Identical Phi Values (word) malloc::size#1 (word) malloc::size#0
Identical Phi Values (byte*) heap_head#3 (byte*) heap_head#1
Identical Phi Values (byte*) BYTES#2 (byte*) BYTES#0
Identical Phi Values (byte*) BYTES#1 (byte*) BYTES#2
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$0 [24] if((byte) main::i#1!=rangelast(0,$ff)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) HEAP_START#0 = (byte*) 49152
Constant (const word) malloc::size#0 = $100
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) malloc::return#0 = HEAP_START#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) malloc::return#2 = malloc::return#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) BYTES#0 = malloc::return#2
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [22] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [24] if(main::i#1!=rangelast(0,$ff)) goto main::@1 to (number) 0
Eliminating unused variable (byte*) heap_head#1 and assignment [0] (byte*) heap_head#1 ← (const byte*) HEAP_START#0 + (const word) malloc::size#0
Successful SSA optimization PassNEliminateUnusedVars
Eliminating unused constant (const word) malloc::size#0
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 0 in if((byte) main::i#1!=(number) 0) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Constant inlined malloc::return#2 = (const byte*) HEAP_START#0
Constant inlined BYTES#0 = (const byte*) HEAP_START#0
Constant inlined malloc::return#0 = (const byte*) HEAP_START#0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @4
Adding NOP phi() at start of @3
Adding NOP phi() at start of @5
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of malloc
CALL GRAPH
Calls in [] to malloc:2 main:5
Created 1 initial phi equivalence classes
Coalesced [14] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @4
Culled Empty Block (label) @5
Culled Empty Block (label) main::@3
Renumbering block @2 to @1
Renumbering block @3 to @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of malloc
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call malloc
to:@2
@2: scope:[] from @1
[3] phi()
[4] call main
to:@end
@end: scope:[] from @2
[5] phi()
main: scope:[main] from @2
[6] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[7] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
[8] *((const byte*) HEAP_START#0 + (byte) main::i#2) ← (byte) main::i#2
[9] (byte) main::i#1 ← ++ (byte) main::i#2
[10] if((byte) main::i#1!=(byte) 0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[11] return
to:@return
malloc: scope:[malloc] from @1
[12] phi()
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte*) BYTES
(byte*) HEAP_START
(byte*) heap_head
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 22.0
(byte*()) malloc((word) malloc::size)
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
INITIAL ASM
//SEG0 File Comments
// Experiments with malloc() - a byte array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call malloc
//SEG7 [12] phi from @1 to malloc [phi:@1->malloc]
malloc_from_b1:
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
jmp b2
//SEG9 @2
b2:
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG13 @end
bend:
//SEG14 main
main: {
.label i = 2
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG16 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta i
jmp b1
//SEG17 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG18 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG19 main::@1
b1:
//SEG20 [8] *((const byte*) HEAP_START#0 + (byte) main::i#2) ← (byte) main::i#2 -- pbuc1_derefidx_vbuz1=vbuz1
ldy i
tya
sta HEAP_START,y
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc i
//SEG22 [10] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuz1_neq_0_then_la1
lda i
cmp #0
bne b1_from_b1
jmp breturn
//SEG23 main::@return
breturn:
//SEG24 [11] return
rts
}
//SEG25 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
jmp breturn
//SEG26 malloc::@return
breturn:
//SEG27 [13] return
rts
}
//SEG28 File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 38.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplift Scope [malloc]
Uplift Scope []
Uplifting [main] best 308 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [malloc] best 308 combination
Uplifting [] best 308 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Experiments with malloc() - a byte array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call malloc
//SEG7 [12] phi from @1 to malloc [phi:@1->malloc]
malloc_from_b1:
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
jmp b2
//SEG9 @2
b2:
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG13 @end
bend:
//SEG14 main
main: {
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG16 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG17 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG18 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG19 main::@1
b1:
//SEG20 [8] *((const byte*) HEAP_START#0 + (byte) main::i#2) ← (byte) main::i#2 -- pbuc1_derefidx_vbuxx=vbuxx
txa
sta HEAP_START,x
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG22 [10] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuxx_neq_0_then_la1
cpx #0
bne b1_from_b1
jmp breturn
//SEG23 main::@return
breturn:
//SEG24 [11] return
rts
}
//SEG25 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
jmp breturn
//SEG26 malloc::@return
breturn:
//SEG27 [13] return
rts
}
//SEG28 File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b1 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction malloc_from_b1:
Removing instruction b2_from_b1:
Removing instruction main_from_b2:
Removing instruction bend_from_b2:
Removing instruction b1_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(byte*) BYTES
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(byte*) heap_head
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 22.0
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
reg byte x [ main::i#2 main::i#1 ]
FINAL ASSEMBLER
Score: 185
//SEG0 File Comments
// Experiments with malloc() - a byte array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call malloc
//SEG7 [12] phi from @1 to malloc [phi:@1->malloc]
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
//SEG9 @2
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
jsr main
rts
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
//SEG13 @end
//SEG14 main
main: {
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
//SEG16 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
//SEG17 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
//SEG18 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG19 main::@1
b1:
//SEG20 [8] *((const byte*) HEAP_START#0 + (byte) main::i#2) ← (byte) main::i#2 -- pbuc1_derefidx_vbuxx=vbuxx
txa
sta HEAP_START,x
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG22 [10] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuxx_neq_0_then_la1
cpx #0
bne b1
//SEG23 main::@return
//SEG24 [11] return
rts
}
//SEG25 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
//SEG26 malloc::@return
//SEG27 [13] return
rts
}
//SEG28 File Data

21
src/test/ref/malloc-0.sym Normal file
View File

@ -0,0 +1,21 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(byte*) BYTES
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(byte*) heap_head
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 22.0
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
reg byte x [ main::i#2 main::i#1 ]

42
src/test/ref/malloc-1.asm Normal file
View File

@ -0,0 +1,42 @@
// Experiments with malloc() - a word array
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
.const SIZEOF_WORD = 2
// Start of the heap used by malloc()
.label HEAP_START = $c000
bbegin:
jsr malloc
jsr main
rts
main: {
.label w = 2
lda #<HEAP_START
sta w
lda #>HEAP_START
sta w+1
ldx #0
b1:
txa
ldy #0
sta (w),y
tya
iny
sta (w),y
lda #SIZEOF_WORD
clc
adc w
sta w
bcc !+
inc w+1
!:
inx
cpx #0
bne b1
rts
}
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
rts
}

33
src/test/ref/malloc-1.cfg Normal file
View File

@ -0,0 +1,33 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call malloc
to:@2
@2: scope:[] from @1
[3] phi()
[4] call main
to:@end
@end: scope:[] from @2
[5] phi()
main: scope:[main] from @2
[6] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[7] (word*) main::w#2 ← phi( main/(const byte*) HEAP_START#0 main::@1/(word*) main::w#1 )
[7] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
[8] *((word*) main::w#2) ← (byte) main::i#2
[9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD
[10] (byte) main::i#1 ← ++ (byte) main::i#2
[11] if((byte) main::i#1!=(byte) 0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[12] return
to:@return
malloc: scope:[malloc] from @1
[13] phi()
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
[14] return
to:@return

605
src/test/ref/malloc-1.log Normal file
View File

@ -0,0 +1,605 @@
Adding pointer type conversion cast (byte*) HEAP_START in (byte*) HEAP_START ← (number) $c000
Fixing pointer increment (word*) main::w ← ++ (word*) main::w
Identified constant variable (byte*) HEAP_START
Culled Empty Block (label) malloc::@1
Culled Empty Block (label) @1
Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*) HEAP_START#0 ← ((byte*)) (number) $c000
(byte*) heap_head#0 ← (byte*) HEAP_START#0
to:@2
malloc: scope:[malloc] from @2
(word) malloc::size#1 ← phi( @2/(word) malloc::size#0 )
(byte*) heap_head#4 ← phi( @2/(byte*) heap_head#7 )
(byte*) malloc::mem#0 ← (byte*) heap_head#4
(byte*) heap_head#1 ← (byte*) heap_head#4 + (word) malloc::size#1
(byte*) malloc::return#0 ← (byte*) malloc::mem#0
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
(byte*) heap_head#5 ← phi( malloc/(byte*) heap_head#1 )
(byte*) malloc::return#3 ← phi( malloc/(byte*) malloc::return#0 )
(byte*) malloc::return#1 ← (byte*) malloc::return#3
(byte*) heap_head#2 ← (byte*) heap_head#5
return
to:@return
@2: scope:[] from @begin
(byte*) heap_head#7 ← phi( @begin/(byte*) heap_head#0 )
(word) malloc::size#0 ← (number) $200
call malloc
(byte*) malloc::return#2 ← (byte*) malloc::return#1
to:@4
@4: scope:[] from @2
(byte*) heap_head#6 ← phi( @2/(byte*) heap_head#2 )
(byte*) malloc::return#4 ← phi( @2/(byte*) malloc::return#2 )
(byte*~) $0 ← (byte*) malloc::return#4
(byte*) heap_head#3 ← (byte*) heap_head#6
(word*) WORDS#0 ← (byte*~) $0
to:@3
main: scope:[main] from @3
(word*) WORDS#1 ← phi( @3/(word*) WORDS#2 )
(word*) main::w#0 ← (word*) WORDS#1
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(word*) main::w#2 ← phi( main/(word*) main::w#0 main::@1/(word*) main::w#1 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
*((word*) main::w#2) ← (byte) main::i#2
(word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,$ff)
(bool~) main::$0 ← (byte) main::i#1 != rangelast(0,$ff)
if((bool~) main::$0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
@3: scope:[] from @4
(word*) WORDS#2 ← phi( @4/(word*) WORDS#0 )
call main
to:@5
@5: scope:[] from @3
to:@end
@end: scope:[] from @5
SYMBOL TABLE SSA
(byte*~) $0
(label) @2
(label) @3
(label) @4
(label) @5
(label) @begin
(label) @end
(byte*) HEAP_START
(byte*) HEAP_START#0
(const byte) SIZEOF_WORD = (byte) 2
(word*) WORDS
(word*) WORDS#0
(word*) WORDS#1
(word*) WORDS#2
(byte*) heap_head
(byte*) heap_head#0
(byte*) heap_head#1
(byte*) heap_head#2
(byte*) heap_head#3
(byte*) heap_head#4
(byte*) heap_head#5
(byte*) heap_head#6
(byte*) heap_head#7
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(word*) main::w
(word*) main::w#0
(word*) main::w#1
(word*) main::w#2
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::mem#0
(byte*) malloc::return
(byte*) malloc::return#0
(byte*) malloc::return#1
(byte*) malloc::return#2
(byte*) malloc::return#3
(byte*) malloc::return#4
(word) malloc::size
(word) malloc::size#0
(word) malloc::size#1
Adding number conversion cast (unumber) $200 in (word) malloc::size#0 ← (number) $200
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) HEAP_START#0 ← (byte*)(number) $c000
Inlining cast (word) malloc::size#0 ← (unumber)(number) $200
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 49152
Simplifying constant integer cast $200
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (word) $200
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte*) HEAP_START#0 = (byte*) heap_head#0 (byte*) heap_head#7
Alias (byte*) malloc::return#0 = (byte*) malloc::mem#0 (byte*) malloc::return#3 (byte*) malloc::return#1
Alias (byte*) heap_head#1 = (byte*) heap_head#5 (byte*) heap_head#2
Alias (byte*) malloc::return#2 = (byte*) malloc::return#4
Alias (byte*) heap_head#3 = (byte*) heap_head#6
Alias (word*) WORDS#0 = (byte*~) $0 (word*) WORDS#2
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte*) heap_head#4 (byte*) HEAP_START#0
Identical Phi Values (word) malloc::size#1 (word) malloc::size#0
Identical Phi Values (byte*) heap_head#3 (byte*) heap_head#1
Identical Phi Values (word*) WORDS#1 (word*) WORDS#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$0 [26] if((byte) main::i#1!=rangelast(0,$ff)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) HEAP_START#0 = (byte*) 49152
Constant (const word) malloc::size#0 = $200
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) malloc::return#0 = HEAP_START#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) malloc::return#2 = malloc::return#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const word*) WORDS#0 = malloc::return#2
Successful SSA optimization Pass2ConstantIdentification
Constant (const word*) main::w#0 = WORDS#0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [24] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [26] if(main::i#1!=rangelast(0,$ff)) goto main::@1 to (number) 0
Eliminating unused variable (byte*) heap_head#1 and assignment [0] (byte*) heap_head#1 ← (const byte*) HEAP_START#0 + (const word) malloc::size#0
Successful SSA optimization PassNEliminateUnusedVars
Eliminating unused constant (const word) malloc::size#0
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 0 in if((byte) main::i#1!=(number) 0) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const word*) main::w#0
Constant inlined main::i#0 = (byte) 0
Constant inlined malloc::return#2 = (const byte*) HEAP_START#0
Constant inlined malloc::return#0 = (const byte*) HEAP_START#0
Constant inlined main::w#0 = (const byte*) HEAP_START#0
Constant inlined WORDS#0 = (const byte*) HEAP_START#0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @4
Adding NOP phi() at start of @3
Adding NOP phi() at start of @5
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of malloc
CALL GRAPH
Calls in [] to malloc:2 main:5
Created 2 initial phi equivalence classes
Coalesced [15] main::i#3 ← main::i#1
Coalesced [16] main::w#3 ← main::w#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @4
Culled Empty Block (label) @5
Culled Empty Block (label) main::@3
Renumbering block @2 to @1
Renumbering block @3 to @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of malloc
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call malloc
to:@2
@2: scope:[] from @1
[3] phi()
[4] call main
to:@end
@end: scope:[] from @2
[5] phi()
main: scope:[main] from @2
[6] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[7] (word*) main::w#2 ← phi( main/(const byte*) HEAP_START#0 main::@1/(word*) main::w#1 )
[7] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
[8] *((word*) main::w#2) ← (byte) main::i#2
[9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD
[10] (byte) main::i#1 ← ++ (byte) main::i#2
[11] if((byte) main::i#1!=(byte) 0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[12] return
to:@return
malloc: scope:[malloc] from @1
[13] phi()
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte*) HEAP_START
(word*) WORDS
(byte*) heap_head
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 11.0
(word*) main::w
(word*) main::w#1 7.333333333333333
(word*) main::w#2 16.5
(byte*()) malloc((word) malloc::size)
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ main::w#2 main::w#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::w#2 main::w#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_WORD:3 [ main::w#2 main::w#1 ]
INITIAL ASM
//SEG0 File Comments
// Experiments with malloc() - a word array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call malloc
//SEG7 [13] phi from @1 to malloc [phi:@1->malloc]
malloc_from_b1:
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
jmp b2
//SEG9 @2
b2:
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG13 @end
bend:
//SEG14 main
main: {
.label w = 3
.label i = 2
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG16 [7] phi (word*) main::w#2 = (const byte*) HEAP_START#0 [phi:main->main::@1#0] -- pwuz1=pbuc1
lda #<HEAP_START
sta w
lda #>HEAP_START
sta w+1
//SEG17 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
lda #0
sta i
jmp b1
//SEG18 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG19 [7] phi (word*) main::w#2 = (word*) main::w#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG20 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy
jmp b1
//SEG21 main::@1
b1:
//SEG22 [8] *((word*) main::w#2) ← (byte) main::i#2 -- _deref_pwuz1=vbuz2
lda i
ldy #0
sta (w),y
tya
iny
sta (w),y
//SEG23 [9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc w
sta w
bcc !+
inc w+1
!:
//SEG24 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc i
//SEG25 [11] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuz1_neq_0_then_la1
lda i
cmp #0
bne b1_from_b1
jmp breturn
//SEG26 main::@return
breturn:
//SEG27 [12] return
rts
}
//SEG28 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
jmp breturn
//SEG29 malloc::@return
breturn:
//SEG30 [14] return
rts
}
//SEG31 File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [8] *((word*) main::w#2) ← (byte) main::i#2 [ main::i#2 main::w#2 ] ( main:4 [ main::i#2 main::w#2 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement [9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD [ main::i#2 main::w#1 ] ( main:4 [ main::i#2 main::w#1 ] ) always clobbers reg byte a
Statement [8] *((word*) main::w#2) ← (byte) main::i#2 [ main::i#2 main::w#2 ] ( main:4 [ main::i#2 main::w#2 ] ) always clobbers reg byte a reg byte y
Statement [9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD [ main::i#2 main::w#1 ] ( main:4 [ main::i#2 main::w#1 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x ,
Potential registers zp ZP_WORD:3 [ main::w#2 main::w#1 ] : zp ZP_WORD:3 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 23.83: zp ZP_WORD:3 [ main::w#2 main::w#1 ]
Uplift Scope [malloc]
Uplift Scope []
Uplifting [main] best 713 combination reg byte x [ main::i#2 main::i#1 ] zp ZP_WORD:3 [ main::w#2 main::w#1 ]
Uplifting [malloc] best 713 combination
Uplifting [] best 713 combination
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::w#2 main::w#1 ]
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Experiments with malloc() - a word array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call malloc
//SEG7 [13] phi from @1 to malloc [phi:@1->malloc]
malloc_from_b1:
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
jmp b2
//SEG9 @2
b2:
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG13 @end
bend:
//SEG14 main
main: {
.label w = 2
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG16 [7] phi (word*) main::w#2 = (const byte*) HEAP_START#0 [phi:main->main::@1#0] -- pwuz1=pbuc1
lda #<HEAP_START
sta w
lda #>HEAP_START
sta w+1
//SEG17 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG18 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG19 [7] phi (word*) main::w#2 = (word*) main::w#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG20 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy
jmp b1
//SEG21 main::@1
b1:
//SEG22 [8] *((word*) main::w#2) ← (byte) main::i#2 -- _deref_pwuz1=vbuxx
txa
ldy #0
sta (w),y
tya
iny
sta (w),y
//SEG23 [9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc w
sta w
bcc !+
inc w+1
!:
//SEG24 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG25 [11] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuxx_neq_0_then_la1
cpx #0
bne b1_from_b1
jmp breturn
//SEG26 main::@return
breturn:
//SEG27 [12] return
rts
}
//SEG28 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
jmp breturn
//SEG29 malloc::@return
breturn:
//SEG30 [14] return
rts
}
//SEG31 File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b1 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction malloc_from_b1:
Removing instruction b2_from_b1:
Removing instruction main_from_b2:
Removing instruction bend_from_b2:
Removing instruction b1_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2
(word*) WORDS
(byte*) heap_head
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 11.0
(word*) main::w
(word*) main::w#1 w zp ZP_WORD:2 7.333333333333333
(word*) main::w#2 w zp ZP_WORD:2 16.5
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
reg byte x [ main::i#2 main::i#1 ]
zp ZP_WORD:2 [ main::w#2 main::w#1 ]
FINAL ASSEMBLER
Score: 590
//SEG0 File Comments
// Experiments with malloc() - a word array
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
// Start of the heap used by malloc()
.label HEAP_START = $c000
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call malloc
//SEG7 [13] phi from @1 to malloc [phi:@1->malloc]
jsr malloc
//SEG8 [3] phi from @1 to @2 [phi:@1->@2]
//SEG9 @2
//SEG10 [4] call main
//SEG11 [6] phi from @2 to main [phi:@2->main]
jsr main
rts
//SEG12 [5] phi from @2 to @end [phi:@2->@end]
//SEG13 @end
//SEG14 main
main: {
.label w = 2
//SEG15 [7] phi from main to main::@1 [phi:main->main::@1]
//SEG16 [7] phi (word*) main::w#2 = (const byte*) HEAP_START#0 [phi:main->main::@1#0] -- pwuz1=pbuc1
lda #<HEAP_START
sta w
lda #>HEAP_START
sta w+1
//SEG17 [7] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
ldx #0
//SEG18 [7] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
//SEG19 [7] phi (word*) main::w#2 = (word*) main::w#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG20 [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy
//SEG21 main::@1
b1:
//SEG22 [8] *((word*) main::w#2) ← (byte) main::i#2 -- _deref_pwuz1=vbuxx
txa
ldy #0
sta (w),y
tya
iny
sta (w),y
//SEG23 [9] (word*) main::w#1 ← (word*) main::w#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc w
sta w
bcc !+
inc w+1
!:
//SEG24 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG25 [11] if((byte) main::i#1!=(byte) 0) goto main::@1 -- vbuxx_neq_0_then_la1
cpx #0
bne b1
//SEG26 main::@return
//SEG27 [12] return
rts
}
//SEG28 malloc
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
//SEG29 malloc::@return
//SEG30 [14] return
rts
}
//SEG31 File Data

26
src/test/ref/malloc-1.sym Normal file
View File

@ -0,0 +1,26 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2
(word*) WORDS
(byte*) heap_head
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 11.0
(word*) main::w
(word*) main::w#1 w zp ZP_WORD:2 7.333333333333333
(word*) main::w#2 w zp ZP_WORD:2 16.5
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
reg byte x [ main::i#2 main::i#1 ]
zp ZP_WORD:2 [ main::w#2 main::w#1 ]

View File

@ -23,8 +23,8 @@ main::@4: scope:[main] from main::@3
main::@1: scope:[main] from main::@1 main::@4
[11] (byte) main::i#2 ← phi( main::@1/(byte) main::i#1 main::@4/(byte) 0 )
[12] *((byte*) main::buf1#0 + (byte) main::i#2) ← (byte) main::i#2
[13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2
[14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$6
[13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2
[14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$4
[15] (byte) main::i#1 ← ++ (byte) main::i#2
[16] if((byte) main::i#1!=(byte) $64) goto main::@1
to:main::@2

View File

@ -1,4 +1,6 @@
Adding pointer type conversion cast (byte*) HEAP_START in (byte*) HEAP_START ← (number) $c000
Adding void pointer type conversion cast (void*) main::buf1 in (void~) main::$2 ← call free (byte*) main::buf1
Adding void pointer type conversion cast (void*) main::buf2 in (void~) main::$3 ← call free (byte*) main::buf2
Adding pointer type conversion cast (byte*) main::screen in (byte*) main::screen ← (number) $400
Identified constant variable (byte*) HEAP_START
Identified constant variable (byte*) main::screen
@ -41,8 +43,7 @@ main::@3: scope:[main] from main
(byte*) malloc::return#5 ← phi( main/(byte*) malloc::return#2 )
(byte*~) main::$0 ← (byte*) malloc::return#5
(byte*) heap_head#3 ← (byte*) heap_head#9
(byte*~) main::$1 ← ((byte*)) (byte*~) main::$0
(byte*) main::buf1#0 ← (byte*~) main::$1
(byte*) main::buf1#0 ← (byte*~) main::$0
(word) malloc::size#1 ← (number) $64
call malloc
(byte*) malloc::return#3 ← (byte*) malloc::return#1
@ -51,10 +52,9 @@ main::@4: scope:[main] from main::@3
(byte*) main::buf1#4 ← phi( main::@3/(byte*) main::buf1#0 )
(byte*) heap_head#10 ← phi( main::@3/(byte*) heap_head#2 )
(byte*) malloc::return#6 ← phi( main::@3/(byte*) malloc::return#3 )
(byte*~) main::$2 ← (byte*) malloc::return#6
(byte*~) main::$1 ← (byte*) malloc::return#6
(byte*) heap_head#4 ← (byte*) heap_head#10
(byte*~) main::$3 ← ((byte*)) (byte*~) main::$2
(byte*) main::buf2#0 ← (byte*~) main::$3
(byte*) main::buf2#0 ← (byte*~) main::$1
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main::@1 main::@4
@ -63,24 +63,24 @@ main::@1: scope:[main] from main::@1 main::@4
(byte*) main::buf1#1 ← phi( main::@1/(byte*) main::buf1#1 main::@4/(byte*) main::buf1#4 )
(byte) main::i#2 ← phi( main::@1/(byte) main::i#1 main::@4/(byte) main::i#0 )
*((byte*) main::buf1#1 + (byte) main::i#2) ← (byte) main::i#2
(number~) main::$6 ← (number) $ff - (byte) main::i#2
*((byte*) main::buf2#1 + (byte) main::i#2) ← (number~) main::$6
(number~) main::$4 ← (number) $ff - (byte) main::i#2
*((byte*) main::buf2#1 + (byte) main::i#2) ← (number~) main::$4
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,$63)
(bool~) main::$7 ← (byte) main::i#1 != rangelast(0,$63)
if((bool~) main::$7) goto main::@1
(bool~) main::$5 ← (byte) main::i#1 != rangelast(0,$63)
if((bool~) main::$5) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
(byte*) heap_head#17 ← phi( main::@1/(byte*) heap_head#18 )
(byte*) main::buf2#4 ← phi( main::@1/(byte*) main::buf2#1 )
(byte*) main::buf1#2 ← phi( main::@1/(byte*) main::buf1#1 )
(byte*) free::ptr#0 ← (byte*) main::buf1#2
(void*) free::ptr#0 ← (void*)(byte*) main::buf1#2
call free
to:main::@5
main::@5: scope:[main] from main::@2
(byte*) heap_head#16 ← phi( main::@2/(byte*) heap_head#17 )
(byte*) main::buf1#5 ← phi( main::@2/(byte*) main::buf1#2 )
(byte*) main::buf2#2 ← phi( main::@2/(byte*) main::buf2#4 )
(byte*) free::ptr#1 ← (byte*) main::buf2#2
(void*) free::ptr#1 ← (void*)(byte*) main::buf2#2
call free
to:main::@6
main::@6: scope:[main] from main::@5
@ -113,11 +113,11 @@ SYMBOL TABLE SSA
(label) @end
(byte*) HEAP_START
(byte*) HEAP_START#0
(void()) free((byte*) free::ptr)
(void()) free((void*) free::ptr)
(label) free::@return
(byte*) free::ptr
(byte*) free::ptr#0
(byte*) free::ptr#1
(void*) free::ptr
(void*) free::ptr#0
(void*) free::ptr#1
(byte*) heap_head
(byte*) heap_head#0
(byte*) heap_head#1
@ -141,10 +141,8 @@ SYMBOL TABLE SSA
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(number~) main::$6
(bool~) main::$7
(number~) main::$4
(bool~) main::$5
(label) main::@1
(label) main::@2
(label) main::@3
@ -190,23 +188,19 @@ SYMBOL TABLE SSA
Adding number conversion cast (unumber) $64 in (word) malloc::size#0 ← (number) $64
Adding number conversion cast (unumber) $64 in (word) malloc::size#1 ← (number) $64
Adding number conversion cast (unumber) $ff in (number~) main::$6 ← (number) $ff - (byte) main::i#2
Adding number conversion cast (unumber) main::$6 in (number~) main::$6 ← (unumber)(number) $ff - (byte) main::i#2
Adding number conversion cast (unumber) $ff in (number~) main::$4 ← (number) $ff - (byte) main::i#2
Adding number conversion cast (unumber) main::$4 in (number~) main::$4 ← (unumber)(number) $ff - (byte) main::i#2
Adding number conversion cast (unumber) 0 in *((byte*) main::screen#0 + (number) 0) ← *((byte*) main::buf1#3)
Adding number conversion cast (unumber) 1 in *((byte*) main::screen#0 + (number) 1) ← *((byte*) main::buf2#3)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) HEAP_START#0 ← (byte*)(number) $c000
Inlining cast (word) malloc::size#0 ← (unumber)(number) $64
Inlining cast (byte*~) main::$1 ← (byte*)(byte*~) main::$0
Inlining cast (word) malloc::size#1 ← (unumber)(number) $64
Inlining cast (byte*~) main::$3 ← (byte*)(byte*~) main::$2
Inlining cast (byte*) main::screen#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 49152
Simplifying constant integer cast $64
Simplifying constant integer cast (byte*~) main::$0
Simplifying constant integer cast $64
Simplifying constant integer cast (byte*~) main::$2
Simplifying constant integer cast $ff
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
@ -218,16 +212,16 @@ Finalized unsigned number type (byte) $ff
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$6 ← (byte) $ff - (byte) main::i#2
Inferred type updated to byte in (unumber~) main::$4 ← (byte) $ff - (byte) main::i#2
Alias (byte*) HEAP_START#0 = (byte*) heap_head#0 (byte*) heap_head#15
Alias (byte*) malloc::return#0 = (byte*) malloc::mem#0 (byte*) malloc::return#4 (byte*) malloc::return#1
Alias (byte*) heap_head#1 = (byte*) heap_head#8 (byte*) heap_head#2
Alias (byte*) malloc::return#2 = (byte*) malloc::return#5
Alias (byte*) heap_head#3 = (byte*) heap_head#9
Alias (byte*) main::buf1#0 = (byte*~) main::$1 (byte*~) main::$0 (byte*) main::buf1#4
Alias (byte*) main::buf1#0 = (byte*~) main::$0 (byte*) main::buf1#4
Alias (byte*) malloc::return#3 = (byte*) malloc::return#6
Alias (byte*) heap_head#10 = (byte*) heap_head#4
Alias (byte*) main::buf2#0 = (byte*~) main::$3 (byte*~) main::$2
Alias (byte*) main::buf2#0 = (byte*~) main::$1
Alias (byte*) main::buf1#1 = (byte*) main::buf1#2 (byte*) main::buf1#5 (byte*) main::buf1#3
Alias (byte*) main::buf2#1 = (byte*) main::buf2#4 (byte*) main::buf2#2 (byte*) main::buf2#3
Alias (byte*) heap_head#11 = (byte*) heap_head#17 (byte*) heap_head#18 (byte*) heap_head#16 (byte*) heap_head#14 (byte*) heap_head#5
@ -245,7 +239,7 @@ Identical Phi Values (byte*) main::buf2#1 (byte*) main::buf2#0
Identical Phi Values (byte*) heap_head#11 (byte*) heap_head#10
Identical Phi Values (byte*) heap_head#12 (byte*) heap_head#11
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$7 [35] if((byte) main::i#1!=rangelast(0,$63)) goto main::@1
Simple Condition (bool~) main::$5 [33] if((byte) main::i#1!=rangelast(0,$63)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) HEAP_START#0 = (byte*) 49152
Constant (const word) malloc::size#0 = $64
@ -253,12 +247,12 @@ Constant (const word) malloc::size#1 = $64
Constant (const byte) main::i#0 = 0
Constant (const byte*) main::screen#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [33] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [35] if(main::i#1!=rangelast(0,$63)) goto main::@1 to (number) $64
Simplifying expression containing zero main::screen#0 in [44] *((const byte*) main::screen#0 + (byte) 0) ← *((byte*) main::buf1#0)
Resolved ranged next value [31] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [33] if(main::i#1!=rangelast(0,$63)) goto main::@1 to (number) $64
Simplifying expression containing zero main::screen#0 in [42] *((const byte*) main::screen#0 + (byte) 0) ← *((byte*) main::buf1#0)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*) free::ptr#0 and assignment [17] (byte*) free::ptr#0 ← (byte*) main::buf1#0
Eliminating unused variable (byte*) free::ptr#1 and assignment [19] (byte*) free::ptr#1 ← (byte*) main::buf2#0
Eliminating unused variable (void*) free::ptr#0 and assignment [17] (void*) free::ptr#0 ← (void*)(byte*) main::buf1#0
Eliminating unused variable (void*) free::ptr#1 and assignment [19] (void*) free::ptr#1 ← (void*)(byte*) main::buf2#0
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) $64 in if((byte) main::i#1!=(number) $64) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
@ -331,8 +325,8 @@ main::@4: scope:[main] from main::@3
main::@1: scope:[main] from main::@1 main::@4
[11] (byte) main::i#2 ← phi( main::@1/(byte) main::i#1 main::@4/(byte) 0 )
[12] *((byte*) main::buf1#0 + (byte) main::i#2) ← (byte) main::i#2
[13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2
[14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$6
[13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2
[14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$4
[15] (byte) main::i#1 ← ++ (byte) main::i#2
[16] if((byte) main::i#1!=(byte) $64) goto main::@1
to:main::@2
@ -369,13 +363,13 @@ malloc::@return: scope:[malloc] from malloc
VARIABLE REGISTER WEIGHTS
(byte*) HEAP_START
(void()) free((byte*) free::ptr)
(byte*) free::ptr
(void()) free((void*) free::ptr)
(void*) free::ptr
(byte*) heap_head
(byte*) heap_head#1 0.8
(byte*) heap_head#7 3.0
(void()) main()
(byte~) main::$6 22.0
(byte~) main::$4 22.0
(byte*) main::buf1
(byte*) main::buf1#0 1.0714285714285714
(byte*) main::buf2
@ -399,7 +393,7 @@ Added variable malloc::return#2 to zero page equivalence class [ malloc::return#
Added variable main::buf1#0 to zero page equivalence class [ main::buf1#0 ]
Added variable malloc::return#3 to zero page equivalence class [ malloc::return#3 ]
Added variable main::buf2#0 to zero page equivalence class [ main::buf2#0 ]
Added variable main::$6 to zero page equivalence class [ main::$6 ]
Added variable main::$4 to zero page equivalence class [ main::$4 ]
Added variable malloc::return#0 to zero page equivalence class [ malloc::return#0 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
@ -408,7 +402,7 @@ Complete equivalence classes
[ main::buf1#0 ]
[ malloc::return#3 ]
[ main::buf2#0 ]
[ main::$6 ]
[ main::$4 ]
[ malloc::return#0 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_WORD:3 [ heap_head#7 heap_head#1 ]
@ -416,7 +410,7 @@ Allocated zp ZP_WORD:5 [ malloc::return#2 ]
Allocated zp ZP_WORD:7 [ main::buf1#0 ]
Allocated zp ZP_WORD:9 [ malloc::return#3 ]
Allocated zp ZP_WORD:11 [ main::buf2#0 ]
Allocated zp ZP_BYTE:13 [ main::$6 ]
Allocated zp ZP_BYTE:13 [ main::$4 ]
Allocated zp ZP_WORD:14 [ malloc::return#0 ]
INITIAL ASM
@ -449,7 +443,7 @@ bend:
//SEG10 main
main: {
.label screen = $400
.label _6 = $d
.label _4 = $d
.label buf1 = 7
.label buf2 = $b
.label i = 2
@ -509,13 +503,13 @@ main: {
lda i
tay
sta (buf1),y
//SEG29 [13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2 -- vbuz1=vbuc1_minus_vbuz2
//SEG29 [13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2 -- vbuz1=vbuc1_minus_vbuz2
lda #$ff
sec
sbc i
sta _6
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$6 -- pbuz1_derefidx_vbuz2=vbuz3
lda _6
sta _4
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$4 -- pbuz1_derefidx_vbuz2=vbuz3
lda _4
ldy i
sta (buf2),y
//SEG31 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
@ -602,7 +596,7 @@ Statement [6] (byte*) malloc::return#2 ← (byte*) malloc::return#0 [ malloc::re
Statement [7] (byte*) main::buf1#0 ← (byte*) malloc::return#2 [ main::buf1#0 heap_head#1 ] ( main:2 [ main::buf1#0 heap_head#1 ] ) always clobbers reg byte a
Statement [9] (byte*) malloc::return#3 ← (byte*) malloc::return#0 [ main::buf1#0 malloc::return#3 ] ( main:2 [ main::buf1#0 malloc::return#3 ] ) always clobbers reg byte a
Statement [10] (byte*) main::buf2#0 ← (byte*) malloc::return#3 [ main::buf1#0 main::buf2#0 ] ( main:2 [ main::buf1#0 main::buf2#0 ] ) always clobbers reg byte a
Statement [13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$6 ] ( main:2 [ main::buf1#0 main::buf2#0 main::i#2 main::$6 ] ) always clobbers reg byte a
Statement [13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] ( main:2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement [21] *((const byte*) main::screen#0) ← *((byte*) main::buf1#0) [ main::buf2#0 ] ( main:2 [ main::buf2#0 ] ) always clobbers reg byte a reg byte y
Statement [22] *((const byte*) main::screen#0+(byte) 1) ← *((byte*) main::buf2#0) [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
@ -613,7 +607,7 @@ Statement [7] (byte*) main::buf1#0 ← (byte*) malloc::return#2 [ main::buf1#0 h
Statement [9] (byte*) malloc::return#3 ← (byte*) malloc::return#0 [ main::buf1#0 malloc::return#3 ] ( main:2 [ main::buf1#0 malloc::return#3 ] ) always clobbers reg byte a
Statement [10] (byte*) main::buf2#0 ← (byte*) malloc::return#3 [ main::buf1#0 main::buf2#0 ] ( main:2 [ main::buf1#0 main::buf2#0 ] ) always clobbers reg byte a
Statement [12] *((byte*) main::buf1#0 + (byte) main::i#2) ← (byte) main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 ] ( main:2 [ main::buf1#0 main::buf2#0 main::i#2 ] ) always clobbers reg byte a
Statement [13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$6 ] ( main:2 [ main::buf1#0 main::buf2#0 main::i#2 main::$6 ] ) always clobbers reg byte a
Statement [13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] ( main:2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] ) always clobbers reg byte a
Statement [21] *((const byte*) main::screen#0) ← *((byte*) main::buf1#0) [ main::buf2#0 ] ( main:2 [ main::buf2#0 ] ) always clobbers reg byte a reg byte y
Statement [22] *((const byte*) main::screen#0+(byte) 1) ← *((byte*) main::buf2#0) [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
Statement [27] (byte*) malloc::return#0 ← (byte*) heap_head#7 [ malloc::return#0 heap_head#7 ] ( main:2::malloc:5 [ malloc::return#0 heap_head#7 ] main:2::malloc:8 [ main::buf1#0 malloc::return#0 heap_head#7 ] ) always clobbers reg byte a
@ -624,16 +618,16 @@ Potential registers zp ZP_WORD:5 [ malloc::return#2 ] : zp ZP_WORD:5 ,
Potential registers zp ZP_WORD:7 [ main::buf1#0 ] : zp ZP_WORD:7 ,
Potential registers zp ZP_WORD:9 [ malloc::return#3 ] : zp ZP_WORD:9 ,
Potential registers zp ZP_WORD:11 [ main::buf2#0 ] : zp ZP_WORD:11 ,
Potential registers zp ZP_BYTE:13 [ main::$6 ] : zp ZP_BYTE:13 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:13 [ main::$4 ] : zp ZP_BYTE:13 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_WORD:14 [ malloc::return#0 ] : zp ZP_WORD:14 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:13 [ main::$6 ] 1.25: zp ZP_WORD:11 [ main::buf2#0 ] 1.07: zp ZP_WORD:7 [ main::buf1#0 ]
Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:13 [ main::$4 ] 1.25: zp ZP_WORD:11 [ main::buf2#0 ] 1.07: zp ZP_WORD:7 [ main::buf1#0 ]
Uplift Scope [malloc] 4: zp ZP_WORD:5 [ malloc::return#2 ] 4: zp ZP_WORD:9 [ malloc::return#3 ] 1.2: zp ZP_WORD:14 [ malloc::return#0 ]
Uplift Scope [] 3.8: zp ZP_WORD:3 [ heap_head#7 heap_head#1 ]
Uplift Scope [free]
Uplifting [main] best 579 combination reg byte y [ main::i#2 main::i#1 ] reg byte a [ main::$6 ] zp ZP_WORD:11 [ main::buf2#0 ] zp ZP_WORD:7 [ main::buf1#0 ]
Uplifting [main] best 579 combination reg byte y [ main::i#2 main::i#1 ] reg byte a [ main::$4 ] zp ZP_WORD:11 [ main::buf2#0 ] zp ZP_WORD:7 [ main::buf1#0 ]
Uplifting [malloc] best 579 combination zp ZP_WORD:5 [ malloc::return#2 ] zp ZP_WORD:9 [ malloc::return#3 ] zp ZP_WORD:14 [ malloc::return#0 ]
Uplifting [] best 579 combination zp ZP_WORD:3 [ heap_head#7 heap_head#1 ]
Uplifting [free] best 579 combination
@ -718,12 +712,12 @@ main: {
//SEG28 [12] *((byte*) main::buf1#0 + (byte) main::i#2) ← (byte) main::i#2 -- pbuz1_derefidx_vbuyy=vbuyy
tya
sta (buf1),y
//SEG29 [13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2 -- vbuaa=vbuc1_minus_vbuyy
//SEG29 [13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2 -- vbuaa=vbuc1_minus_vbuyy
tya
eor #$ff
clc
adc #$ff+1
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$6 -- pbuz1_derefidx_vbuyy=vbuaa
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$4 -- pbuz1_derefidx_vbuyy=vbuaa
sta (buf2),y
//SEG31 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny
@ -855,14 +849,14 @@ FINAL SYMBOL TABLE
(label) @end
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(void()) free((byte*) free::ptr)
(void()) free((void*) free::ptr)
(label) free::@return
(byte*) free::ptr
(void*) free::ptr
(byte*) heap_head
(byte*) heap_head#1 heap_head zp ZP_WORD:2 0.8
(byte*) heap_head#7 heap_head zp ZP_WORD:2 3.0
(void()) main()
(byte~) main::$6 reg byte a 22.0
(byte~) main::$4 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@3
@ -892,7 +886,7 @@ reg byte y [ main::i#2 main::i#1 ]
zp ZP_WORD:2 [ heap_head#7 heap_head#1 ]
zp ZP_WORD:4 [ malloc::return#2 main::buf1#0 ]
zp ZP_WORD:6 [ malloc::return#3 main::buf2#0 malloc::return#0 ]
reg byte a [ main::$6 ]
reg byte a [ main::$4 ]
FINAL ASSEMBLER
@ -952,12 +946,12 @@ main: {
//SEG28 [12] *((byte*) main::buf1#0 + (byte) main::i#2) ← (byte) main::i#2 -- pbuz1_derefidx_vbuyy=vbuyy
tya
sta (buf1),y
//SEG29 [13] (byte~) main::$6 ← (byte) $ff - (byte) main::i#2 -- vbuaa=vbuc1_minus_vbuyy
//SEG29 [13] (byte~) main::$4 ← (byte) $ff - (byte) main::i#2 -- vbuaa=vbuc1_minus_vbuyy
tya
eor #$ff
clc
adc #$ff+1
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$6 -- pbuz1_derefidx_vbuyy=vbuaa
//SEG30 [14] *((byte*) main::buf2#0 + (byte) main::i#2) ← (byte~) main::$4 -- pbuz1_derefidx_vbuyy=vbuaa
sta (buf2),y
//SEG31 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny

View File

@ -3,14 +3,14 @@
(label) @end
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(void()) free((byte*) free::ptr)
(void()) free((void*) free::ptr)
(label) free::@return
(byte*) free::ptr
(void*) free::ptr
(byte*) heap_head
(byte*) heap_head#1 heap_head zp ZP_WORD:2 0.8
(byte*) heap_head#7 heap_head zp ZP_WORD:2 3.0
(void()) main()
(byte~) main::$6 reg byte a 22.0
(byte~) main::$4 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@3
@ -40,4 +40,4 @@ reg byte y [ main::i#2 main::i#1 ]
zp ZP_WORD:2 [ heap_head#7 heap_head#1 ]
zp ZP_WORD:4 [ malloc::return#2 main::buf1#0 ]
zp ZP_WORD:6 [ malloc::return#3 main::buf2#0 malloc::return#0 ]
reg byte a [ main::$6 ]
reg byte a [ main::$4 ]

View File

@ -0,0 +1,350 @@
// Calculate the distance to the center of the screen - and show it using font-hex
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_WORD = 2
// Start of the heap used by malloc()
.label HEAP_START = $c000
.label D018 = $d018
.label CHARSET = $2000
.label SCREEN = $2800
.const NUM_SQUARES = $30
main: {
.const toD0181_return = (>(SCREEN&$3fff)*4)|(>CHARSET)/4&$f
.label yds = $16
.label xds = $18
.label ds = $18
.label screen = 4
.label x = 3
.label y = 2
jsr init_font_hex
lda #toD0181_return
sta D018
jsr init_squares
lda #<SCREEN
sta screen
lda #>SCREEN
sta screen+1
lda #0
sta y
b1:
lda y
asl
cmp #$18
bcs b2
eor #$ff
clc
adc #$18+1
b4:
jsr sqr
lda sqr.return_2
sta sqr.return
lda sqr.return_2+1
sta sqr.return+1
lda #0
sta x
b5:
lda x
asl
cmp #$27
bcs b6
eor #$ff
clc
adc #$27+1
b8:
jsr sqr
lda ds
clc
adc yds
sta ds
lda ds+1
adc yds+1
sta ds+1
jsr sqrt
ldy #0
sta (screen),y
inc screen
bne !+
inc screen+1
!:
inc x
lda #$28
cmp x
bne b5
inc y
lda #$19
cmp y
bne b1
rts
b6:
sec
sbc #$27
jmp b8
b2:
sec
sbc #$18
jmp b4
}
// Find the (integer) square root of a word value
// If the square is not an integer then it returns the largest integer N where N*N <= val
// Uses a table of squares that must be initialized by calling init_squares()
// sqrt(word zeropage($18) val)
sqrt: {
.label _3 = 6
.label val = $18
.label found = 6
jsr bsearch16u
lda _3
sec
sbc #<HEAP_START
sta _3
lda _3+1
sbc #>HEAP_START
sta _3+1
lda _3
lsr
rts
}
// Searches an array of nitems unsigned words, the initial member of which is pointed to by base, for a member that matches the value key.
// - key - The value to look for
// - items - Pointer to the start of the array to search in
// - num - The number of items in the array
// Returns pointer to an entry in the array that matches the search key
// bsearch16u(word zeropage($18) key, word* zeropage(6) items, byte register(X) num)
bsearch16u: {
.label _2 = 6
.label key = $18
.label return = 6
.label pivot = $1a
.label result = $1c
.label items = 6
lda #<HEAP_START
sta items
lda #>HEAP_START
sta items+1
ldx #NUM_SQUARES
b3:
cpx #0
bne b4
ldy #1
lda (items),y
cmp key+1
bne !+
dey
lda (items),y
cmp key
beq b2
!:
bcc b2
lda _2
sec
sbc #<1*SIZEOF_WORD
sta _2
lda _2+1
sbc #>1*SIZEOF_WORD
sta _2+1
b2:
rts
b4:
txa
lsr
asl
clc
adc items
sta pivot
lda #0
adc items+1
sta pivot+1
sec
lda key
ldy #0
sbc (pivot),y
sta result
lda key+1
iny
sbc (pivot),y
sta result+1
bne b6
lda result
bne b6
lda pivot
sta return
lda pivot+1
sta return+1
rts
b6:
lda result+1
bmi b7
bne !+
lda result
beq b7
!:
lda #1*SIZEOF_WORD
clc
adc pivot
sta items
lda #0
adc pivot+1
sta items+1
dex
b7:
txa
lsr
tax
jmp b3
}
// Find the square of a byte value
// Uses a table of squares that must be initialized by calling init_squares()
// sqr(byte register(A) val)
sqr: {
.label return = $16
.label return_1 = $18
.label return_2 = $18
asl
tay
lda HEAP_START,y
sta return_2
lda #0
sta return_2+1
rts
}
// Initialize squares table
// Uses iterative formula (x+1)^2 = x^2 + 2*x + 1
init_squares: {
.label squares = $b
.label sqr = 9
jsr malloc
ldx #0
lda #<HEAP_START
sta squares
lda #>HEAP_START
sta squares+1
txa
sta sqr
sta sqr+1
b1:
ldy #0
lda sqr
sta (squares),y
iny
lda sqr+1
sta (squares),y
lda #SIZEOF_WORD
clc
adc squares
sta squares
bcc !+
inc squares+1
!:
txa
asl
clc
adc #1
clc
adc sqr
sta sqr
bcc !+
inc sqr+1
!:
inx
cpx #NUM_SQUARES-1+1
bne b1
rts
}
// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
malloc: {
rts
}
// Make charset from proto chars
// init_font_hex(byte* zeropage($10) charset)
init_font_hex: {
.label _0 = $1e
.label idx = $15
.label proto_lo = $12
.label charset = $10
.label c1 = $14
.label proto_hi = $d
.label c = $f
lda #0
sta c
lda #<FONT_HEX_PROTO
sta proto_hi
lda #>FONT_HEX_PROTO
sta proto_hi+1
lda #<CHARSET
sta charset
lda #>CHARSET
sta charset+1
b1:
lda #0
sta c1
lda #<FONT_HEX_PROTO
sta proto_lo
lda #>FONT_HEX_PROTO
sta proto_lo+1
b2:
lda #0
tay
sta (charset),y
lda #1
sta idx
ldx #0
b3:
txa
tay
lda (proto_hi),y
asl
asl
asl
asl
sta _0
txa
tay
lda (proto_lo),y
asl
ora _0
ldy idx
sta (charset),y
inc idx
inx
cpx #5
bne b3
lda #0
ldy idx
sta (charset),y
iny
sta (charset),y
lda #5
clc
adc proto_lo
sta proto_lo
bcc !+
inc proto_lo+1
!:
lda #8
clc
adc charset
sta charset
bcc !+
inc charset+1
!:
inc c1
lda #$10
cmp c1
bne b2
lda #5
clc
adc proto_hi
sta proto_hi
bcc !+
inc proto_hi+1
!:
inc c
lda #$10
cmp c
bne b1
rts
}
// Bit patterns for symbols 0-f (3x5 pixels) used in font hex
FONT_HEX_PROTO: .byte 2, 5, 5, 5, 2, 6, 2, 2, 2, 7, 6, 1, 2, 4, 7, 6, 1, 2, 1, 6, 5, 5, 7, 1, 1, 7, 4, 6, 1, 6, 3, 4, 6, 5, 2, 7, 1, 1, 1, 1, 2, 5, 2, 5, 2, 2, 5, 3, 1, 1, 2, 5, 7, 5, 5, 6, 5, 6, 5, 6, 2, 5, 4, 5, 2, 6, 5, 5, 5, 6, 7, 4, 6, 4, 7, 7, 4, 6, 4, 4

View File

@ -0,0 +1,212 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
[5] call init_font_hex
to:main::toD0181
main::toD0181: scope:[main] from main
[6] phi()
to:main::@10
main::@10: scope:[main] from main::toD0181
[7] *((const byte*) D018#0) ← (const byte) main::toD0181_return#0
[8] call init_squares
to:main::@1
main::@1: scope:[main] from main::@10 main::@9
[9] (byte*) main::screen#10 ← phi( main::@9/(byte*) main::screen#1 main::@10/(const byte*) SCREEN#0 )
[9] (byte) main::y#10 ← phi( main::@9/(byte) main::y#1 main::@10/(byte) 0 )
[10] (byte) main::y2#0 ← (byte) main::y#10 << (byte) 1
[11] if((byte) main::y2#0>=(byte) $18) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[12] (byte~) main::$6 ← (byte) $18 - (byte) main::y2#0
to:main::@4
main::@4: scope:[main] from main::@2 main::@3
[13] (byte) main::yd#0 ← phi( main::@2/(byte~) main::$8 main::@3/(byte~) main::$6 )
[14] (byte) sqr::val#0 ← (byte) main::yd#0
[15] call sqr
[16] (word) sqr::return#0 ← (word) sqr::return#2
to:main::@11
main::@11: scope:[main] from main::@4
[17] (word) main::yds#0 ← (word) sqr::return#0
to:main::@5
main::@5: scope:[main] from main::@11 main::@13
[18] (byte*) main::screen#2 ← phi( main::@11/(byte*) main::screen#10 main::@13/(byte*) main::screen#1 )
[18] (byte) main::x#2 ← phi( main::@11/(byte) 0 main::@13/(byte) main::x#1 )
[19] (byte) main::x2#0 ← (byte) main::x#2 << (byte) 1
[20] if((byte) main::x2#0>=(byte) $27) goto main::@6
to:main::@7
main::@7: scope:[main] from main::@5
[21] (byte~) main::$14 ← (byte) $27 - (byte) main::x2#0
to:main::@8
main::@8: scope:[main] from main::@6 main::@7
[22] (byte) main::xd#0 ← phi( main::@6/(byte~) main::$16 main::@7/(byte~) main::$14 )
[23] (byte) sqr::val#1 ← (byte) main::xd#0
[24] call sqr
[25] (word) sqr::return#1 ← (word) sqr::return#2
to:main::@12
main::@12: scope:[main] from main::@8
[26] (word) main::xds#0 ← (word) sqr::return#1
[27] (word) main::ds#0 ← (word) main::xds#0 + (word) main::yds#0
[28] (word) sqrt::val#0 ← (word) main::ds#0
[29] call sqrt
[30] (byte) sqrt::return#0 ← (byte) sqrt::return#1
to:main::@13
main::@13: scope:[main] from main::@12
[31] (byte) main::d#0 ← (byte) sqrt::return#0
[32] *((byte*) main::screen#2) ← (byte) main::d#0
[33] (byte*) main::screen#1 ← ++ (byte*) main::screen#2
[34] (byte) main::x#1 ← ++ (byte) main::x#2
[35] if((byte) main::x#1!=(byte) $28) goto main::@5
to:main::@9
main::@9: scope:[main] from main::@13
[36] (byte) main::y#1 ← ++ (byte) main::y#10
[37] if((byte) main::y#1!=(byte) $19) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@9
[38] return
to:@return
main::@6: scope:[main] from main::@5
[39] (byte~) main::$16 ← (byte) main::x2#0 - (byte) $27
to:main::@8
main::@2: scope:[main] from main::@1
[40] (byte~) main::$8 ← (byte) main::y2#0 - (byte) $18
to:main::@4
sqrt: scope:[sqrt] from main::@12
[41] (word) bsearch16u::key#0 ← (word) sqrt::val#0
[42] call bsearch16u
[43] (word*) bsearch16u::return#0 ← (word*) bsearch16u::return#2
to:sqrt::@1
sqrt::@1: scope:[sqrt] from sqrt
[44] (word*) sqrt::found#0 ← (word*) bsearch16u::return#0
[45] (word~) sqrt::$3 ← (byte*)(word*) sqrt::found#0 - (const byte*) HEAP_START#0
[46] (byte~) sqrt::$4 ← (byte)(word~) sqrt::$3
[47] (byte) sqrt::return#1 ← (byte~) sqrt::$4 >> (byte) 1
to:sqrt::@return
sqrt::@return: scope:[sqrt] from sqrt::@1
[48] return
to:@return
bsearch16u: scope:[bsearch16u] from sqrt
[49] phi()
to:bsearch16u::@3
bsearch16u::@3: scope:[bsearch16u] from bsearch16u bsearch16u::@7
[50] (word*) bsearch16u::items#2 ← phi( bsearch16u/(const byte*) HEAP_START#0 bsearch16u::@7/(word*) bsearch16u::items#8 )
[50] (byte) bsearch16u::num#3 ← phi( bsearch16u/(const byte) NUM_SQUARES#0 bsearch16u::@7/(byte) bsearch16u::num#1 )
[51] if((byte) bsearch16u::num#3>(byte) 0) goto bsearch16u::@4
to:bsearch16u::@5
bsearch16u::@5: scope:[bsearch16u] from bsearch16u::@3
[52] if(*((word*) bsearch16u::items#2)<=(word) bsearch16u::key#0) goto bsearch16u::@2
to:bsearch16u::@1
bsearch16u::@1: scope:[bsearch16u] from bsearch16u::@5
[53] (word*~) bsearch16u::$2 ← (word*) bsearch16u::items#2 - (byte) 1*(const byte) SIZEOF_WORD
to:bsearch16u::@2
bsearch16u::@2: scope:[bsearch16u] from bsearch16u::@1 bsearch16u::@5
[54] (word*) bsearch16u::return#3 ← phi( bsearch16u::@5/(word*) bsearch16u::items#2 bsearch16u::@1/(word*~) bsearch16u::$2 )
to:bsearch16u::@return
bsearch16u::@return: scope:[bsearch16u] from bsearch16u::@2 bsearch16u::@8
[55] (word*) bsearch16u::return#2 ← phi( bsearch16u::@8/(word*~) bsearch16u::return#6 bsearch16u::@2/(word*) bsearch16u::return#3 )
[56] return
to:@return
bsearch16u::@4: scope:[bsearch16u] from bsearch16u::@3
[57] (byte~) bsearch16u::$6 ← (byte) bsearch16u::num#3 >> (byte) 1
[58] (byte~) bsearch16u::$16 ← (byte~) bsearch16u::$6 << (byte) 1
[59] (word*) bsearch16u::pivot#0 ← (word*) bsearch16u::items#2 + (byte~) bsearch16u::$16
[60] (signed word) bsearch16u::result#0 ← (signed word)(word) bsearch16u::key#0 - (signed word)*((word*) bsearch16u::pivot#0)
[61] if((signed word) bsearch16u::result#0!=(signed byte) 0) goto bsearch16u::@6
to:bsearch16u::@8
bsearch16u::@8: scope:[bsearch16u] from bsearch16u::@4
[62] (word*~) bsearch16u::return#6 ← (word*) bsearch16u::pivot#0
to:bsearch16u::@return
bsearch16u::@6: scope:[bsearch16u] from bsearch16u::@4
[63] if((signed word) bsearch16u::result#0<=(signed byte) 0) goto bsearch16u::@7
to:bsearch16u::@9
bsearch16u::@9: scope:[bsearch16u] from bsearch16u::@6
[64] (word*) bsearch16u::items#1 ← (word*) bsearch16u::pivot#0 + (byte) 1*(const byte) SIZEOF_WORD
[65] (byte) bsearch16u::num#2 ← -- (byte) bsearch16u::num#3
to:bsearch16u::@7
bsearch16u::@7: scope:[bsearch16u] from bsearch16u::@6 bsearch16u::@9
[66] (word*) bsearch16u::items#8 ← phi( bsearch16u::@9/(word*) bsearch16u::items#1 bsearch16u::@6/(word*) bsearch16u::items#2 )
[66] (byte) bsearch16u::num#5 ← phi( bsearch16u::@9/(byte) bsearch16u::num#2 bsearch16u::@6/(byte) bsearch16u::num#3 )
[67] (byte) bsearch16u::num#1 ← (byte) bsearch16u::num#5 >> (byte) 1
to:bsearch16u::@3
sqr: scope:[sqr] from main::@4 main::@8
[68] (byte) sqr::val#2 ← phi( main::@4/(byte) sqr::val#0 main::@8/(byte) sqr::val#1 )
[69] (byte~) sqr::$0 ← (byte) sqr::val#2 << (byte) 1
[70] (word) sqr::return#2 ← *((const byte*) HEAP_START#0 + (byte~) sqr::$0)
to:sqr::@return
sqr::@return: scope:[sqr] from sqr
[71] return
to:@return
init_squares: scope:[init_squares] from main::@10
[72] phi()
[73] call malloc
to:init_squares::@1
init_squares::@1: scope:[init_squares] from init_squares init_squares::@1
[74] (byte) init_squares::i#2 ← phi( init_squares::@1/(byte) init_squares::i#1 init_squares/(byte) 0 )
[74] (word*) init_squares::squares#2 ← phi( init_squares::@1/(word*) init_squares::squares#1 init_squares/(const byte*) HEAP_START#0 )
[74] (word) init_squares::sqr#2 ← phi( init_squares::@1/(word) init_squares::sqr#1 init_squares/(byte) 0 )
[75] *((word*) init_squares::squares#2) ← (word) init_squares::sqr#2
[76] (word*) init_squares::squares#1 ← (word*) init_squares::squares#2 + (const byte) SIZEOF_WORD
[77] (byte~) init_squares::$3 ← (byte) init_squares::i#2 << (byte) 1
[78] (byte~) init_squares::$4 ← (byte~) init_squares::$3 + (byte) 1
[79] (word) init_squares::sqr#1 ← (word) init_squares::sqr#2 + (byte~) init_squares::$4
[80] (byte) init_squares::i#1 ← ++ (byte) init_squares::i#2
[81] if((byte) init_squares::i#1!=(const byte) NUM_SQUARES#0-(byte) 1+(byte) 1) goto init_squares::@1
to:init_squares::@return
init_squares::@return: scope:[init_squares] from init_squares::@1
[82] return
to:@return
malloc: scope:[malloc] from init_squares
[83] phi()
to:malloc::@return
malloc::@return: scope:[malloc] from malloc
[84] return
to:@return
init_font_hex: scope:[init_font_hex] from main
[85] phi()
to:init_font_hex::@1
init_font_hex::@1: scope:[init_font_hex] from init_font_hex init_font_hex::@5
[86] (byte) init_font_hex::c#6 ← phi( init_font_hex/(byte) 0 init_font_hex::@5/(byte) init_font_hex::c#1 )
[86] (byte*) init_font_hex::proto_hi#6 ← phi( init_font_hex/(const byte[]) FONT_HEX_PROTO#0 init_font_hex::@5/(byte*) init_font_hex::proto_hi#1 )
[86] (byte*) init_font_hex::charset#5 ← phi( init_font_hex/(const byte*) CHARSET#0 init_font_hex::@5/(byte*) init_font_hex::charset#0 )
to:init_font_hex::@2
init_font_hex::@2: scope:[init_font_hex] from init_font_hex::@1 init_font_hex::@4
[87] (byte) init_font_hex::c1#4 ← phi( init_font_hex::@1/(byte) 0 init_font_hex::@4/(byte) init_font_hex::c1#1 )
[87] (byte*) init_font_hex::proto_lo#4 ← phi( init_font_hex::@1/(const byte[]) FONT_HEX_PROTO#0 init_font_hex::@4/(byte*) init_font_hex::proto_lo#1 )
[87] (byte*) init_font_hex::charset#2 ← phi( init_font_hex::@1/(byte*) init_font_hex::charset#5 init_font_hex::@4/(byte*) init_font_hex::charset#0 )
[88] *((byte*) init_font_hex::charset#2) ← (byte) 0
to:init_font_hex::@3
init_font_hex::@3: scope:[init_font_hex] from init_font_hex::@2 init_font_hex::@3
[89] (byte) init_font_hex::idx#5 ← phi( init_font_hex::@2/(byte) 1 init_font_hex::@3/(byte) init_font_hex::idx#2 )
[89] (byte) init_font_hex::i#2 ← phi( init_font_hex::@2/(byte) 0 init_font_hex::@3/(byte) init_font_hex::i#1 )
[90] (byte~) init_font_hex::$0 ← *((byte*) init_font_hex::proto_hi#6 + (byte) init_font_hex::i#2) << (byte) 4
[91] (byte~) init_font_hex::$1 ← *((byte*) init_font_hex::proto_lo#4 + (byte) init_font_hex::i#2) << (byte) 1
[92] (byte~) init_font_hex::$2 ← (byte~) init_font_hex::$0 | (byte~) init_font_hex::$1
[93] *((byte*) init_font_hex::charset#2 + (byte) init_font_hex::idx#5) ← (byte~) init_font_hex::$2
[94] (byte) init_font_hex::idx#2 ← ++ (byte) init_font_hex::idx#5
[95] (byte) init_font_hex::i#1 ← ++ (byte) init_font_hex::i#2
[96] if((byte) init_font_hex::i#1!=(byte) 5) goto init_font_hex::@3
to:init_font_hex::@4
init_font_hex::@4: scope:[init_font_hex] from init_font_hex::@3
[97] *((byte*) init_font_hex::charset#2 + (byte) init_font_hex::idx#2) ← (byte) 0
[98] (byte) init_font_hex::idx#3 ← ++ (byte) init_font_hex::idx#2
[99] *((byte*) init_font_hex::charset#2 + (byte) init_font_hex::idx#3) ← (byte) 0
[100] (byte*) init_font_hex::proto_lo#1 ← (byte*) init_font_hex::proto_lo#4 + (byte) 5
[101] (byte*) init_font_hex::charset#0 ← (byte*) init_font_hex::charset#2 + (byte) 8
[102] (byte) init_font_hex::c1#1 ← ++ (byte) init_font_hex::c1#4
[103] if((byte) init_font_hex::c1#1!=(byte) $10) goto init_font_hex::@2
to:init_font_hex::@5
init_font_hex::@5: scope:[init_font_hex] from init_font_hex::@4
[104] (byte*) init_font_hex::proto_hi#1 ← (byte*) init_font_hex::proto_hi#6 + (byte) 5
[105] (byte) init_font_hex::c#1 ← ++ (byte) init_font_hex::c#6
[106] if((byte) init_font_hex::c#1!=(byte) $10) goto init_font_hex::@1
to:init_font_hex::@return
init_font_hex::@return: scope:[init_font_hex] from init_font_hex::@5
[107] return
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
(label) @1
(label) @begin
(label) @end
(byte*) CHARSET
(const byte*) CHARSET#0 CHARSET = (byte*) 8192
(byte*) D018
(const byte*) D018#0 D018 = (byte*) 53272
(byte[]) FONT_HEX_PROTO
(const byte[]) FONT_HEX_PROTO#0 FONT_HEX_PROTO = { (byte) 2, (byte) 5, (byte) 5, (byte) 5, (byte) 2, (byte) 6, (byte) 2, (byte) 2, (byte) 2, (byte) 7, (byte) 6, (byte) 1, (byte) 2, (byte) 4, (byte) 7, (byte) 6, (byte) 1, (byte) 2, (byte) 1, (byte) 6, (byte) 5, (byte) 5, (byte) 7, (byte) 1, (byte) 1, (byte) 7, (byte) 4, (byte) 6, (byte) 1, (byte) 6, (byte) 3, (byte) 4, (byte) 6, (byte) 5, (byte) 2, (byte) 7, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 2, (byte) 5, (byte) 2, (byte) 5, (byte) 2, (byte) 2, (byte) 5, (byte) 3, (byte) 1, (byte) 1, (byte) 2, (byte) 5, (byte) 7, (byte) 5, (byte) 5, (byte) 6, (byte) 5, (byte) 6, (byte) 5, (byte) 6, (byte) 2, (byte) 5, (byte) 4, (byte) 5, (byte) 2, (byte) 6, (byte) 5, (byte) 5, (byte) 5, (byte) 6, (byte) 7, (byte) 4, (byte) 6, (byte) 4, (byte) 7, (byte) 7, (byte) 4, (byte) 6, (byte) 4, (byte) 4 }
(byte*) HEAP_START
(const byte*) HEAP_START#0 HEAP_START = (byte*) 49152
(byte) NUM_SQUARES
(const byte) NUM_SQUARES#0 NUM_SQUARES = (byte) $30
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 10240
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2
(word*) SQUARES
(word*()) bsearch16u((word) bsearch16u::key , (word*) bsearch16u::items , (byte) bsearch16u::num)
(byte~) bsearch16u::$16 reg byte a 2002.0
(word*~) bsearch16u::$2 $2 zp ZP_WORD:6 4.0
(byte~) bsearch16u::$6 reg byte a 2002.0
(label) bsearch16u::@1
(label) bsearch16u::@2
(label) bsearch16u::@3
(label) bsearch16u::@4
(label) bsearch16u::@5
(label) bsearch16u::@6
(label) bsearch16u::@7
(label) bsearch16u::@8
(label) bsearch16u::@9
(label) bsearch16u::@return
(word*) bsearch16u::items
(word*) bsearch16u::items#1 items zp ZP_WORD:6 1001.0
(word*) bsearch16u::items#2 items zp ZP_WORD:6 334.33333333333337
(word*) bsearch16u::items#8 items zp ZP_WORD:6 1501.5
(word) bsearch16u::key
(word) bsearch16u::key#0 key zp ZP_WORD:24 0.2857142857142857
(byte) bsearch16u::num
(byte) bsearch16u::num#1 reg byte x 2002.0
(byte) bsearch16u::num#2 reg byte x 2002.0
(byte) bsearch16u::num#3 reg byte x 556.1111111111111
(byte) bsearch16u::num#5 reg byte x 3003.0
(word*) bsearch16u::pivot
(word*) bsearch16u::pivot#0 pivot zp ZP_WORD:26 501.0
(signed word) bsearch16u::result
(signed word) bsearch16u::result#0 result zp ZP_WORD:28 1501.5
(word*) bsearch16u::return
(word*) bsearch16u::return#0 return zp ZP_WORD:6 4.0
(word*) bsearch16u::return#2 return zp ZP_WORD:6 2.0
(word*) bsearch16u::return#3 return zp ZP_WORD:6 6.0
(word*~) bsearch16u::return#6 return zp ZP_WORD:6 4.0
(byte*) heap_head
(void()) init_font_hex((byte*) init_font_hex::charset)
(byte~) init_font_hex::$0 $0 zp ZP_BYTE:30 1001.0
(byte~) init_font_hex::$1 reg byte a 2002.0
(byte~) init_font_hex::$2 reg byte a 2002.0
(label) init_font_hex::@1
(label) init_font_hex::@2
(label) init_font_hex::@3
(label) init_font_hex::@4
(label) init_font_hex::@5
(label) init_font_hex::@return
(byte) init_font_hex::c
(byte) init_font_hex::c#1 c zp ZP_BYTE:15 16.5
(byte) init_font_hex::c#6 c zp ZP_BYTE:15 1.1578947368421053
(byte) init_font_hex::c1
(byte) init_font_hex::c1#1 c1 zp ZP_BYTE:20 151.5
(byte) init_font_hex::c1#4 c1 zp ZP_BYTE:20 13.466666666666667
(byte*) init_font_hex::charset
(byte*) init_font_hex::charset#0 charset zp ZP_WORD:16 35.5
(byte*) init_font_hex::charset#2 charset zp ZP_WORD:16 108.35714285714285
(byte*) init_font_hex::charset#5 charset zp ZP_WORD:16 22.0
(byte) init_font_hex::i
(byte) init_font_hex::i#1 reg byte x 1501.5
(byte) init_font_hex::i#2 reg byte x 667.3333333333334
(byte) init_font_hex::idx
(byte) init_font_hex::idx#2 idx zp ZP_BYTE:21 551.0
(byte) init_font_hex::idx#3 reg byte y 202.0
(byte) init_font_hex::idx#5 idx zp ZP_BYTE:21 600.5999999999999
(byte*) init_font_hex::proto_hi
(byte*) init_font_hex::proto_hi#1 proto_hi zp ZP_WORD:13 7.333333333333333
(byte*) init_font_hex::proto_hi#6 proto_hi zp ZP_WORD:13 56.83333333333334
(byte*) init_font_hex::proto_lo
(byte*) init_font_hex::proto_lo#1 proto_lo zp ZP_WORD:18 50.5
(byte*) init_font_hex::proto_lo#4 proto_lo zp ZP_WORD:18 92.53846153846155
(void()) init_squares()
(byte~) init_squares::$3 reg byte a 22.0
(byte~) init_squares::$4 reg byte a 22.0
(label) init_squares::@1
(label) init_squares::@return
(byte) init_squares::i
(byte) init_squares::i#1 reg byte x 16.5
(byte) init_squares::i#2 reg byte x 5.5
(word) init_squares::sqr
(word) init_squares::sqr#1 sqr zp ZP_WORD:9 7.333333333333333
(word) init_squares::sqr#2 sqr zp ZP_WORD:9 6.6000000000000005
(word*) init_squares::squares
(word*) init_squares::squares#1 squares zp ZP_WORD:11 3.6666666666666665
(word*) init_squares::squares#2 squares zp ZP_WORD:11 16.5
(void()) main()
(byte~) main::$14 reg byte a 202.0
(byte~) main::$16 reg byte a 202.0
(byte~) main::$6 reg byte a 22.0
(byte~) main::$8 reg byte a 22.0
(label) main::@1
(label) main::@10
(label) main::@11
(label) main::@12
(label) main::@13
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@8
(label) main::@9
(label) main::@return
(byte) main::d
(byte) main::d#0 reg byte a 202.0
(word) main::ds
(word) main::ds#0 ds zp ZP_WORD:24 202.0
(byte*) main::screen
(byte*) main::screen#1 screen zp ZP_WORD:4 42.599999999999994
(byte*) main::screen#10 screen zp ZP_WORD:4 2.2
(byte*) main::screen#2 screen zp ZP_WORD:4 19.625
(label) main::toD0181
(word~) main::toD0181_$0
(number~) main::toD0181_$1
(number~) main::toD0181_$2
(number~) main::toD0181_$3
(word~) main::toD0181_$4
(byte~) main::toD0181_$5
(number~) main::toD0181_$6
(number~) main::toD0181_$7
(number~) main::toD0181_$8
(byte*) main::toD0181_gfx
(byte) main::toD0181_return
(const byte) main::toD0181_return#0 toD0181_return = >(word)(const byte*) SCREEN#0&(word) $3fff*(byte) 4|>(word)(const byte*) CHARSET#0/(byte) 4&(byte) $f
(byte*) main::toD0181_screen
(byte) main::x
(byte) main::x#1 x zp ZP_BYTE:3 151.5
(byte) main::x#2 x zp ZP_BYTE:3 17.823529411764707
(byte) main::x2
(byte) main::x2#0 reg byte a 202.0
(byte) main::xd
(byte) main::xd#0 reg byte a 303.0
(word) main::xds
(word) main::xds#0 xds zp ZP_WORD:24 202.0
(byte) main::y
(byte) main::y#1 y zp ZP_BYTE:2 16.5
(byte) main::y#10 y zp ZP_BYTE:2 1.1379310344827585
(byte) main::y2
(byte) main::y2#0 reg byte a 22.0
(byte) main::yd
(byte) main::yd#0 reg byte a 33.0
(word) main::yds
(word) main::yds#0 yds zp ZP_WORD:22 5.6
(byte*()) malloc((word) malloc::size)
(label) malloc::@return
(byte*) malloc::mem
(byte*) malloc::return
(word) malloc::size
(word()) sqr((byte) sqr::val)
(byte~) sqr::$0 reg byte a 4.0
(label) sqr::@return
(word) sqr::return
(word) sqr::return#0 return zp ZP_WORD:22 22.0
(word) sqr::return#1 return#1 zp ZP_WORD:24 202.0
(word) sqr::return#2 return#2 zp ZP_WORD:24 28.5
(byte) sqr::val
(byte) sqr::val#0 reg byte a 22.0
(byte) sqr::val#1 reg byte a 202.0
(byte) sqr::val#2 reg byte a 114.0
(byte()) sqrt((word) sqrt::val)
(word~) sqrt::$3 $3 zp ZP_WORD:6 2.0
(byte~) sqrt::$4 reg byte a 4.0
(label) sqrt::@1
(label) sqrt::@return
(word*) sqrt::found
(word*) sqrt::found#0 found zp ZP_WORD:6 2.0
(byte) sqrt::return
(byte) sqrt::return#0 reg byte a 202.0
(byte) sqrt::return#1 reg byte a 34.33333333333333
(byte) sqrt::sqr1
(word) sqrt::val
(word) sqrt::val#0 val zp ZP_WORD:24 103.0
zp ZP_BYTE:2 [ main::y#10 main::y#1 ]
reg byte a [ main::yd#0 main::$8 main::$6 ]
zp ZP_BYTE:3 [ main::x#2 main::x#1 ]
zp ZP_WORD:4 [ main::screen#2 main::screen#10 main::screen#1 ]
reg byte a [ main::xd#0 main::$16 main::$14 ]
zp ZP_WORD:6 [ bsearch16u::return#2 bsearch16u::return#6 bsearch16u::return#3 bsearch16u::items#2 bsearch16u::items#8 bsearch16u::$2 bsearch16u::items#1 bsearch16u::return#0 sqrt::found#0 sqrt::$3 ]
reg byte x [ bsearch16u::num#5 bsearch16u::num#2 bsearch16u::num#3 bsearch16u::num#1 ]
reg byte a [ sqr::val#2 sqr::val#0 sqr::val#1 ]
zp ZP_WORD:9 [ init_squares::sqr#2 init_squares::sqr#1 ]
zp ZP_WORD:11 [ init_squares::squares#2 init_squares::squares#1 ]
reg byte x [ init_squares::i#2 init_squares::i#1 ]
zp ZP_WORD:13 [ init_font_hex::proto_hi#6 init_font_hex::proto_hi#1 ]
zp ZP_BYTE:15 [ init_font_hex::c#6 init_font_hex::c#1 ]
zp ZP_WORD:16 [ init_font_hex::charset#2 init_font_hex::charset#5 init_font_hex::charset#0 ]
zp ZP_WORD:18 [ init_font_hex::proto_lo#4 init_font_hex::proto_lo#1 ]
zp ZP_BYTE:20 [ init_font_hex::c1#4 init_font_hex::c1#1 ]
reg byte x [ init_font_hex::i#2 init_font_hex::i#1 ]
zp ZP_BYTE:21 [ init_font_hex::idx#5 init_font_hex::idx#2 ]
reg byte a [ main::y2#0 ]
zp ZP_WORD:22 [ sqr::return#0 main::yds#0 ]
reg byte a [ main::x2#0 ]
zp ZP_WORD:24 [ sqr::return#1 main::xds#0 sqr::return#2 main::ds#0 sqrt::val#0 bsearch16u::key#0 ]
reg byte a [ sqrt::return#0 ]
reg byte a [ main::d#0 ]
reg byte a [ sqrt::$4 ]
reg byte a [ sqrt::return#1 ]
reg byte a [ bsearch16u::$6 ]
reg byte a [ bsearch16u::$16 ]
zp ZP_WORD:26 [ bsearch16u::pivot#0 ]
zp ZP_WORD:28 [ bsearch16u::result#0 ]
reg byte a [ sqr::$0 ]
reg byte a [ init_squares::$3 ]
reg byte a [ init_squares::$4 ]
zp ZP_BYTE:30 [ init_font_hex::$0 ]
reg byte a [ init_font_hex::$1 ]
reg byte a [ init_font_hex::$2 ]
reg byte y [ init_font_hex::idx#3 ]

View File

@ -5843,7 +5843,7 @@ printEntry: {
jmp b1
//SEG200 printEntry::@1
b1:
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pptz2
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pwuz2
ldy #0
lda (entry),y
sta print_word.w
@ -5895,7 +5895,7 @@ printEntry: {
jmp b2
//SEG219 printEntry::@2
b2:
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pptz2_derefidx_vbuc1
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #2
lda (entry),y
sta print_word.w
@ -5999,7 +5999,7 @@ printEntry: {
jmp b4
//SEG257 printEntry::@4
b4:
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pptz2_derefidx_vbuc1
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #6
lda (entry),y
sta print_word.w
@ -7918,7 +7918,7 @@ printEntry: {
jmp b1
//SEG200 printEntry::@1
b1:
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pptz2
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pwuz2
ldy #0
lda (entry),y
sta print_word.w
@ -7970,7 +7970,7 @@ printEntry: {
jmp b2
//SEG219 printEntry::@2
b2:
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pptz2_derefidx_vbuc1
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #2
lda (entry),y
sta print_word.w
@ -8074,7 +8074,7 @@ printEntry: {
jmp b4
//SEG257 printEntry::@4
b4:
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pptz2_derefidx_vbuc1
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #6
lda (entry),y
sta print_word.w
@ -10389,7 +10389,7 @@ printEntry: {
//SEG198 [96] phi from printEntry to printEntry::entryBufDisk1 [phi:printEntry->printEntry::entryBufDisk1]
//SEG199 printEntry::entryBufDisk1
//SEG200 printEntry::@1
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pptz2
//SEG201 [97] (word~) print_word::w#7 ← (word)*((byte**)(byte*) printEntry::entry#10) -- vwuz1=_deref_pwuz2
ldy #0
lda (entry),y
sta print_word.w
@ -10429,7 +10429,7 @@ printEntry: {
//SEG217 [103] phi from printEntry::@15 to printEntry::entryBufEdit1 [phi:printEntry::@15->printEntry::entryBufEdit1]
//SEG218 printEntry::entryBufEdit1
//SEG219 printEntry::@2
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pptz2_derefidx_vbuc1
//SEG220 [104] (word~) print_word::w#8 ← (word)*((byte**)(byte*) printEntry::entry#10 + (byte) 2) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #2
lda (entry),y
sta print_word.w
@ -10509,7 +10509,7 @@ printEntry: {
//SEG255 [117] phi from printEntry::@19 to printEntry::entryTsOrder1 [phi:printEntry::@19->printEntry::entryTsOrder1]
//SEG256 printEntry::entryTsOrder1
//SEG257 printEntry::@4
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pptz2_derefidx_vbuc1
//SEG258 [118] (word~) print_word::w#10 ← (word)*((word**)(byte*) printEntry::entry#10 + (byte) 6) -- vwuz1=pwuz2_derefidx_vbuc1
ldy #6
lda (entry),y
sta print_word.w

View File

@ -9,7 +9,7 @@ main: {
tya
eor #$ff
tax
axs #$ff+1
axs #-$ff-1
lda #0
sta table,x
iny

View File

@ -257,7 +257,7 @@ main: {
tya
eor #$ff
tax
axs #$ff+1
axs #-$ff-1
//SEG17 [7] *((const byte[$100]) table#0 + (byte~) main::$0) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2
lda #0
sta table,x
@ -349,7 +349,7 @@ main: {
tya
eor #$ff
tax
axs #$ff+1
axs #-$ff-1
//SEG17 [7] *((const byte[$100]) table#0 + (byte~) main::$0) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2
lda #0
sta table,x