mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-19 08:31:01 +00:00
Added support for array initialization using inline kickasm
This commit is contained in:
parent
44c5aa1313
commit
c4bcbddcd4
66
src/main/java/dk/camelot64/kickc/asm/AsmDataKickAsm.java
Normal file
66
src/main/java/dk/camelot64/kickc/asm/AsmDataKickAsm.java
Normal file
@ -0,0 +1,66 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
/** A labelled data array initialized by kickasm code. */
|
||||
public class AsmDataKickAsm implements AsmLine {
|
||||
|
||||
private String label;
|
||||
|
||||
private int bytes;
|
||||
|
||||
private String kickAsmCode;
|
||||
|
||||
private int index;
|
||||
|
||||
public AsmDataKickAsm(String label, int bytes, String kickAsmCode) {
|
||||
this.label = label;
|
||||
this.bytes = bytes;
|
||||
this.kickAsmCode = kickAsmCode;
|
||||
}
|
||||
|
||||
public String getKickAsmCode() {
|
||||
return kickAsmCode;
|
||||
}
|
||||
|
||||
public void setKickAsmCode(String kickAsmCode) {
|
||||
this.kickAsmCode = kickAsmCode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLineBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLineCycles() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
StringBuilder asm = new StringBuilder();
|
||||
asm.append(label + ":\n");
|
||||
asm.append(kickAsmCode);
|
||||
return asm.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of source lines in the inline assembler code (for line indexing)
|
||||
*
|
||||
* @return The number of source lines
|
||||
*/
|
||||
public long getLineCount() {
|
||||
return kickAsmCode.chars().filter(x -> x == '\n').count() + 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
}
|
@ -144,6 +144,16 @@ public class AsmProgram {
|
||||
addLine(new AsmInlineKickAsm(kickAsmCode, bytes, cycles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data array initialized with inline kick assembler code
|
||||
* @param label Name of the data
|
||||
* @param bytes The number of bytes (from array definition)
|
||||
* @param kickAsmCode Kick Assembler code to initialize the data
|
||||
*/
|
||||
public void addDataKickAsm(String label, int bytes, String kickAsmCode) {
|
||||
addLine(new AsmDataKickAsm(label, bytes, kickAsmCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes the segment occupies in memory.
|
||||
* Calculated by adding up the bytes of each ASM segment in the program.
|
||||
|
@ -231,6 +231,7 @@ public class ProgramValueIterator {
|
||||
value instanceof ConstantLiteral ||
|
||||
value instanceof ConstantRef ||
|
||||
value instanceof StructZero ||
|
||||
value instanceof ConstantArrayKickAsm ||
|
||||
value instanceof LabelRef
|
||||
) {
|
||||
// No sub values
|
||||
|
@ -18,7 +18,7 @@ public class StatementKickAsm extends StatementBase {
|
||||
/** The absolute address to generate the kick-assembler code at. If null it is generated inline. */
|
||||
private RValue location;
|
||||
|
||||
/** The number of bytes generated by the kick-assembler code. */
|
||||
/** The number of bytes generated by the kick-assembler code. */
|
||||
private RValue bytes;
|
||||
|
||||
/** The number of cycles used by the generated kick-assembler code. */
|
||||
|
@ -56,6 +56,8 @@ public class SymbolTypeInference {
|
||||
}
|
||||
} else if(rValue instanceof ConstantArrayList) {
|
||||
return new SymbolTypeArray(((ConstantArrayList) rValue).getElementType());
|
||||
} else if(rValue instanceof ConstantArrayKickAsm) {
|
||||
return new SymbolTypeArray(((ConstantArrayKickAsm) rValue).getElementType());
|
||||
} else if(rValue instanceof ArrayFilled) {
|
||||
return new SymbolTypeArray(((ArrayFilled) rValue).getElementType(), ((ArrayFilled) rValue).getSize());
|
||||
} else if(rValue instanceof ConstantArrayFilled) {
|
||||
|
@ -0,0 +1,12 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
|
||||
/**
|
||||
* An array initialized with constant values.
|
||||
*/
|
||||
public interface ConstantArray extends ConstantValue {
|
||||
|
||||
SymbolType getElementType();
|
||||
|
||||
}
|
@ -8,7 +8,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
/**
|
||||
* An zero-filled constant array. The array is allocated in the code memory (as a .fill() ).
|
||||
*/
|
||||
public class ConstantArrayFilled implements ConstantValue {
|
||||
public class ConstantArrayFilled implements ConstantArray {
|
||||
|
||||
private ConstantValue size;
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An array initialized using inline kick-assembler. The array is allocated in the code memory (eg. as a set of .byte's ).
|
||||
*/
|
||||
public class ConstantArrayKickAsm implements ConstantArray {
|
||||
|
||||
/** Type of the array elements. */
|
||||
private SymbolType elementType;
|
||||
|
||||
/** KickAssembler code generating the data. */
|
||||
private String kickAsmCode;
|
||||
|
||||
public ConstantArrayKickAsm(SymbolType elementType, String kickAsmCode) {
|
||||
this.elementType = elementType;
|
||||
this.kickAsmCode = kickAsmCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getType(ProgramScope scope) {
|
||||
return new SymbolTypeArray(elementType);
|
||||
}
|
||||
|
||||
public SymbolType getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
public String getKickAsmCode() {
|
||||
return kickAsmCode;
|
||||
}
|
||||
|
||||
public void setKickAsmCode(String kickAsmCode) {
|
||||
this.kickAsmCode = kickAsmCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantLiteral calculateLiteral(ProgramScope scope) {
|
||||
throw new ConstantNotLiteral("Cannot calculate literal array");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Program program) {
|
||||
StringBuilder txt = new StringBuilder();
|
||||
txt.append("kickasm {{ ");
|
||||
txt.append(kickAsmCode);
|
||||
txt.append(" }}");
|
||||
return txt.toString();
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ import java.util.List;
|
||||
/**
|
||||
* An array of constants. The array is allocated in the code memory (eg. as a set of .byte's ).
|
||||
*/
|
||||
public class ConstantArrayList implements ConstantValue {
|
||||
public class ConstantArrayList implements ConstantArray {
|
||||
|
||||
private List<ConstantValue> list;
|
||||
|
||||
|
@ -51,7 +51,7 @@ declVariableList
|
||||
|
||||
declVariableInit
|
||||
: NAME ('=' expr)? #declVariableInitExpr
|
||||
| NAME ('=' declKasm)? #declVariableInitKasm
|
||||
| NAME '=' declKasm #declVariableInitKasm
|
||||
;
|
||||
|
||||
declFunction
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -247,6 +247,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
}
|
||||
sequence.addStatement(statementKickAsm);
|
||||
return statementKickAsm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -523,7 +524,37 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitDeclVariableInitKasm(KickCParser.DeclVariableInitKasmContext ctx) {
|
||||
throw new InternalError("Not implemented");
|
||||
String varName = ctx.NAME().getText();
|
||||
VariableUnversioned lValue = visitDeclVariableInit(varName, ctx);
|
||||
SymbolType type = this.declVarType;
|
||||
List<Comment> comments = this.declVarComments;
|
||||
if(!(type instanceof SymbolTypeArray)) {
|
||||
throw new CompileError("KickAsm initializers only supported for arrays " + type.getTypeName(), new StatementSource(ctx));
|
||||
}
|
||||
// Add KickAsm statement
|
||||
StatementKickAsm kasm = (StatementKickAsm) this.visit(ctx.declKasm());
|
||||
if(kasm.getUses().size()>0) {
|
||||
throw new CompileError("KickAsm initializers does not support 'uses' directive.", new StatementSource(ctx));
|
||||
}
|
||||
if(kasm.getLocation()!=null) {
|
||||
throw new CompileError("KickAsm initializers does not support 'location' directive.", new StatementSource(ctx));
|
||||
}
|
||||
if(kasm.getCycles()!=null) {
|
||||
throw new CompileError("KickAsm initializers does not support 'cycles' directive.", new StatementSource(ctx));
|
||||
}
|
||||
if(kasm.getBytes()!=null) {
|
||||
throw new CompileError("KickAsm initializers does not support 'bytes' directive.", new StatementSource(ctx));
|
||||
}
|
||||
if(kasm.getDeclaredClobber()!=null) {
|
||||
throw new CompileError("KickAsm initializers does not support 'clobbers' directive.", new StatementSource(ctx));
|
||||
}
|
||||
ConstantArrayKickAsm constantArrayKickAsm = new ConstantArrayKickAsm(((SymbolTypeArray) type).getElementType(), kasm.getKickAsmCode());
|
||||
// Remove the KickAsm statement
|
||||
sequence.getStatements().remove(sequence.getStatements().size()-1);
|
||||
// Add an initializer statement instead
|
||||
Statement stmt = new StatementAssignment(lValue.getRef(), constantArrayKickAsm, new StatementSource(ctx), ensureUnusedComments(comments));
|
||||
sequence.addStatement(stmt);
|
||||
return null;
|
||||
}
|
||||
|
||||
private VariableUnversioned visitDeclVariableInit(String varName, KickCParser.DeclVariableInitContext ctx) {
|
||||
|
@ -93,7 +93,7 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
Collection<ConstantVar> allConstants = getProgram().getScope().getAllConstants(true);
|
||||
for(ConstantVar constant : allConstants) {
|
||||
if(constant.getRef().isIntermediate()) {
|
||||
if(!(constant.getType().equals(SymbolType.STRING)) && !(constant.getValue() instanceof ConstantArrayList) && !(constant.getValue() instanceof ConstantArrayFilled)) {
|
||||
if(!(constant.getType().equals(SymbolType.STRING)) && !(constant.getValue() instanceof ConstantArray)) {
|
||||
unnamed.put(constant.getRef(), constant.getValue());
|
||||
}
|
||||
}
|
||||
@ -150,7 +150,7 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
break;
|
||||
} else if(symbol instanceof ConstantVar) {
|
||||
ConstantValue otherValue = ((ConstantVar) symbol).getValue();
|
||||
if(!otherValue.equals(value) && !(value instanceof ConstantString) && !(value instanceof ConstantArrayList) && !(value instanceof ConstantArrayFilled) && !(otherValue instanceof ConstantRef)) {
|
||||
if(!otherValue.equals(value) && !(value instanceof ConstantString) && !(value instanceof ConstantArray) && !(otherValue instanceof ConstantRef)) {
|
||||
aliases.put(constant.getRef(), value);
|
||||
getLog().append("Inlining constant with different constant siblings " + constant);
|
||||
break;
|
||||
|
@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.fragment.*;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
@ -300,9 +301,7 @@ public class Pass4CodeGeneration {
|
||||
|
||||
private boolean hasData(ConstantVar constantVar) {
|
||||
ConstantValue constantValue = constantVar.getValue();
|
||||
if(constantValue instanceof ConstantArrayList) {
|
||||
return true;
|
||||
} else if(constantValue instanceof ConstantArrayFilled) {
|
||||
if(constantValue instanceof ConstantArray) {
|
||||
return true;
|
||||
} else {
|
||||
try {
|
||||
@ -471,8 +470,24 @@ public class Pass4CodeGeneration {
|
||||
asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0");
|
||||
added.add(asmName);
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled constant array element type " + constantArrayFilled.toString(program));
|
||||
throw new InternalError("Unhandled constant array element type " + constantArrayFilled.toString(program));
|
||||
}
|
||||
} else if(constantVar.getValue() instanceof ConstantArrayKickAsm) {
|
||||
ConstantArrayKickAsm kickAsm = (ConstantArrayKickAsm) constantVar.getValue();
|
||||
SymbolType type = constantVar.getType();
|
||||
// default - larger then 256
|
||||
int bytes = 1023;
|
||||
if(type instanceof SymbolTypeArray) {
|
||||
SymbolType elementType = ((SymbolTypeArray) type).getElementType();
|
||||
RValue size = ((SymbolTypeArray) type).getSize();
|
||||
if(size instanceof ConstantValue) {
|
||||
ConstantLiteral sizeLiteral = ((ConstantValue) size).calculateLiteral(getScope());
|
||||
if(sizeLiteral instanceof ConstantInteger) {
|
||||
bytes = (int)sizeLiteral.getValue() * elementType.getSizeBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
asm.addDataKickAsm(asmName.replace("#", "_").replace("$", "_"), bytes, kickAsm.getKickAsmCode());
|
||||
} else {
|
||||
try {
|
||||
ConstantLiteral literal = constantVar.getValue().calculateLiteral(getScope());
|
||||
|
@ -34,7 +34,7 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
currentLabel = ((AsmLabel) line).getLabel();
|
||||
} else if(line instanceof AsmComment || line instanceof AsmConstant || line instanceof AsmLabelDecl) {
|
||||
// ignore
|
||||
} else if(line instanceof AsmBasicUpstart || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString || line instanceof AsmDataAlignment || line instanceof AsmSetPc || line instanceof AsmInlineKickAsm|| line instanceof AsmSetEncoding) {
|
||||
} else if(line instanceof AsmBasicUpstart || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString || line instanceof AsmDataAlignment || line instanceof AsmSetPc || line instanceof AsmInlineKickAsm|| line instanceof AsmSetEncoding|| line instanceof AsmDataKickAsm) {
|
||||
currentLabel = null;
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
if(currentLabel != null) {
|
||||
|
@ -1,9 +1,6 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmComment;
|
||||
import dk.camelot64.kickc.asm.AsmInlineKickAsm;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmSegment;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
|
||||
/**
|
||||
@ -26,6 +23,10 @@ public class Pass5ReindexAsmLines extends Pass5AsmOptimization {
|
||||
asmLine.setIndex(nextIndex);
|
||||
AsmInlineKickAsm inlineKickAsm = (AsmInlineKickAsm) asmLine;
|
||||
nextIndex += inlineKickAsm.getLineCount();
|
||||
} else if(asmLine instanceof AsmDataKickAsm) {
|
||||
asmLine.setIndex(nextIndex);
|
||||
AsmDataKickAsm inlineKickAsm = (AsmDataKickAsm) asmLine;
|
||||
nextIndex += inlineKickAsm.getLineCount();
|
||||
} else {
|
||||
asmLine.setIndex(nextIndex++);
|
||||
}
|
||||
|
@ -35,6 +35,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArraysInitKasm0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("arrays-init-kasm-0", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScreenCenterAngle() throws IOException, URISyntaxException {
|
||||
compileAndCompare("screen-center-angle");
|
||||
|
13
src/test/kc/arrays-init-kasm-0.kc
Normal file
13
src/test/kc/arrays-init-kasm-0.kc
Normal file
@ -0,0 +1,13 @@
|
||||
// Test initializing array using KickAssembler
|
||||
|
||||
// Sinus table
|
||||
byte[] SINTAB = kickasm {{
|
||||
.fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
}};
|
||||
|
||||
byte* SCREEN = 0x400;
|
||||
|
||||
void main() {
|
||||
SCREEN[0] = SINTAB[0];
|
||||
|
||||
}
|
14
src/test/ref/arrays-init-kasm-0.asm
Normal file
14
src/test/ref/arrays-init-kasm-0.asm
Normal file
@ -0,0 +1,14 @@
|
||||
// Test initializing array using KickAssembler
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
lda SINTAB
|
||||
sta SCREEN
|
||||
rts
|
||||
}
|
||||
// Sinus table
|
||||
SINTAB:
|
||||
.fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
|
15
src/test/ref/arrays-init-kasm-0.cfg
Normal file
15
src/test/ref/arrays-init-kasm-0.cfg
Normal file
@ -0,0 +1,15 @@
|
||||
@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] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[5] return
|
||||
to:@return
|
247
src/test/ref/arrays-init-kasm-0.log
Normal file
247
src/test/ref/arrays-init-kasm-0.log
Normal file
@ -0,0 +1,247 @@
|
||||
Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (number) $400
|
||||
Identified constant variable (byte*) SCREEN
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte[]) SINTAB#0 ← kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
}}
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
*((byte*) SCREEN#0 + (number) 0) ← *((byte[]) SINTAB#0 + (number) 0)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(byte[]) SINTAB
|
||||
(byte[]) SINTAB#0
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((byte*) SCREEN#0 + (number) 0) ← *((byte[]) SINTAB#0 + (number) 0)
|
||||
Adding number conversion cast (unumber) 0 in *((byte*) SCREEN#0 + (number) 0) ← *((byte[]) SINTAB#0 + (unumber)(number) 0)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant (const byte[]) SINTAB#0 = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
}}
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero SINTAB#0 in [2] *((const byte*) SCREEN#0 + (byte) 0) ← *((const byte[]) SINTAB#0 + (byte) 0)
|
||||
Simplifying expression containing zero SCREEN#0 in [2] *((const byte*) SCREEN#0 + (byte) 0) ← *((const byte[]) SINTAB#0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
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
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@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] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[5] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) SCREEN
|
||||
(byte[]) SINTAB
|
||||
(void()) main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Test initializing array using KickAssembler
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
//SEG10 [4] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SINTAB
|
||||
sta SCREEN
|
||||
jmp breturn
|
||||
//SEG11 main::@return
|
||||
breturn:
|
||||
//SEG12 [5] return
|
||||
rts
|
||||
}
|
||||
//SEG13 File Data
|
||||
// Sinus table
|
||||
SINTAB:
|
||||
.fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 29 combination
|
||||
Uplifting [] best 29 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Test initializing array using KickAssembler
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
//SEG10 [4] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SINTAB
|
||||
sta SCREEN
|
||||
jmp breturn
|
||||
//SEG11 main::@return
|
||||
breturn:
|
||||
//SEG12 [5] return
|
||||
rts
|
||||
}
|
||||
//SEG13 File Data
|
||||
// Sinus table
|
||||
SINTAB:
|
||||
.fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte[]) SINTAB
|
||||
(const byte[]) SINTAB#0 SINTAB = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
}}
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 14
|
||||
|
||||
//SEG0 File Comments
|
||||
// Test initializing array using KickAssembler
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
//SEG5 @1
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG8 @end
|
||||
//SEG9 main
|
||||
main: {
|
||||
//SEG10 [4] *((const byte*) SCREEN#0) ← *((const byte[]) SINTAB#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SINTAB
|
||||
sta SCREEN
|
||||
//SEG11 main::@return
|
||||
//SEG12 [5] return
|
||||
rts
|
||||
}
|
||||
//SEG13 File Data
|
||||
// Sinus table
|
||||
SINTAB:
|
||||
.fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
|
||||
|
11
src/test/ref/arrays-init-kasm-0.sym
Normal file
11
src/test/ref/arrays-init-kasm-0.sym
Normal file
@ -0,0 +1,11 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte[]) SINTAB
|
||||
(const byte[]) SINTAB#0 SINTAB = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256)
|
||||
}}
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
Loading…
x
Reference in New Issue
Block a user