1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-22 16:33:48 +00:00

Upgraded ANTLR. Improved clobber handling in inline kickasm.

This commit is contained in:
jespergravgaard 2021-10-19 10:10:47 +02:00
parent ae21d82383
commit f962948ef8
25 changed files with 533 additions and 176 deletions

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4:4.9">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4:4.9.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9.2/antlr4-4.9.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9.2/antlr4-4.9.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9.2/antlr4-4.9.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4-runtime:4.9">
<library name="Maven: org.antlr:antlr4-runtime:4.9.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9.2/antlr4-runtime-4.9.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9.2/antlr4-runtime-4.9.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9.2/antlr4-runtime-4.9.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -11,12 +11,12 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr4:4.9" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr4:4.9.2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr-runtime:3.5.2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:ST4:4.3" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.abego.treelayout:org.abego.treelayout.core:1.0.3" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.ibm.icu:icu4j:61.1" level="project" />
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.9" level="project" />
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.9.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.6.2" level="project" />

View File

@ -27,13 +27,13 @@
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.9</version>
<version>4.9.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.9</version>
<version>4.9.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT vbuzz=vbuc1
ldz #{c1}
//FRAGMENT vbuzz_lt_vbuc1_then_la1

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT _deref_pbuc1=vbuc2
ldz #{c2}
stz {c1}
@ -1652,110 +1652,11 @@ tza
sta {c1}
lda #0
sta {c1}+1
//FRAGMENT _deref_pbuc1=_inc__deref_pbuc1
inc {c1}
//FRAGMENT vwuz1=vbuc1
lda #<{c1}
sta {z1}
lda #>{c1}
sta {z1}+1
//FRAGMENT _deref_pbuc1_eq_vbuz1_then_la1
lda {c1}
cmp {z1}
beq {la1}
//FRAGMENT _deref_pbuc1=_dec__deref_pbuc1
dec {c1}
//FRAGMENT pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
ldx {z1}
inc {c1},x
//FRAGMENT vbuz1=_byte0_vwuz2
lda {z2}
sta {z1}
//FRAGMENT vbuz1=_byte1_vwuz2
lda {z2}+1
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuz3
lda {z2}
ora {z3}
sta {z1}
//FRAGMENT _deref_pbuc1_eq_vbuaa_then_la1
cmp {c1}
beq {la1}
//FRAGMENT pbuc1_derefidx_vbuaa=_inc_pbuc1_derefidx_vbuaa
tax
inc {c1},x
//FRAGMENT pbuc1_derefidx_vbuxx=_inc_pbuc1_derefidx_vbuxx
inc {c1},x
//FRAGMENT vbuaa=_byte1_vwuz1
lda {z1}+1
//FRAGMENT vbuxx=_byte1_vwuz1
ldx {z1}+1
//FRAGMENT vbuz1=vbuxx_bor_vbuz2
txa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuyy_bor_vbuz2
tya
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuzz_bor_vbuz2
tza
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuaa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuxx_bor_vbuaa
stx $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuyy_bor_vbuaa
sty $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuzz_bor_vbuaa
tay
tza
sty $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuxx
txa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuxx_bor_vbuxx
stx {z1}
//FRAGMENT vbuyy=_byte1_vwuz1
ldy {z1}+1
//FRAGMENT vbuzz=_byte1_vwuz1
lda {z1}+1
taz
//FRAGMENT vbuz1=vbuz2_bor_vbuyy
tya
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuzz
tza
ora {z2}
sta {z1}
//FRAGMENT pbuc1_derefidx_vbuyy=_inc_pbuc1_derefidx_vbuyy
lda {c1},y
inc
sta {c1},y
//FRAGMENT pbuc1_derefidx_vbuzz=_inc_pbuc1_derefidx_vbuzz
tza
tax
inc {c1},x
//FRAGMENT _deref_pbuc1_eq_vbuxx_then_la1
cpx {c1}
beq {la1}
//FRAGMENT _deref_pbuc1_eq_vbuyy_then_la1
tya
cmp {c1}
beq {la1}
//FRAGMENT _deref_pbuc1_eq_vbuzz_then_la1
cpz {c1}
beq {la1}
//FRAGMENT vduz1=vduc1
lda #<{c1}
sta {z1}
@ -1809,6 +1710,16 @@ lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
//FRAGMENT vbuz1=_byte0_vwuz2
lda {z2}
sta {z1}
//FRAGMENT vbuz1=_byte1_vwuz2
lda {z2}+1
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuz3
lda {z2}
ora {z3}
sta {z1}
//FRAGMENT vduz1=vduz2_ror_4
lda {z2}+3
lsr
@ -2396,10 +2307,62 @@ dey
bne !-
!e:
taz
//FRAGMENT vbuaa=_byte1_vwuz1
lda {z1}+1
//FRAGMENT vbuxx=_byte1_vwuz1
ldx {z1}+1
//FRAGMENT vbuz1=vbuxx_bor_vbuz2
txa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuyy_bor_vbuz2
tya
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuzz_bor_vbuz2
tza
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuaa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuxx_bor_vbuaa
stx $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuyy_bor_vbuaa
sty $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuzz_bor_vbuaa
tay
tza
sty $ff
ora $ff
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuxx
txa
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuxx_bor_vbuxx
stx {z1}
//FRAGMENT vbuaa=_byte1_vduz1
lda {z1}+1
//FRAGMENT vbuxx=_byte1_vduz1
ldx {z1}+1
//FRAGMENT vbuz1=vbuz2_bor_vbuyy
tya
ora {z2}
sta {z1}
//FRAGMENT vbuz1=vbuz2_bor_vbuzz
tza
ora {z2}
sta {z1}
//FRAGMENT vbuyy=_byte1_vwuz1
ldy {z1}+1
//FRAGMENT vbuzz=_byte1_vwuz1
lda {z1}+1
taz
//FRAGMENT vbuyy=_byte1_vduz1
ldy {z1}+1
//FRAGMENT vbuzz=_byte1_vduz1

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT vbuz1=vbuc1
lda #{c1}
sta {z1}

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT vbuz1=vbuc1
lda #{c1}
sta {z1}

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT _deref_pbuc1=_inc__deref_pbuc1
inc {c1}
//FRAGMENT isr_hardware_all_entry

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
//FRAGMENT vbuz1=_deref_pbuc1
lda {c1}
sta {z1}

View File

@ -1,5 +1,7 @@
package dk.camelot64.kickc.asm;
import dk.camelot64.cpufamily6502.CpuClobber;
/**
* Inlined KickAssembler code.
* If no cycles/byte size is specified it defaults to 256/256.
@ -12,7 +14,9 @@ public class AsmInlineKickAsm extends AsmLine {
private double cycles;
public AsmInlineKickAsm(String kickAsmCode, Long bytes, Long cycles) {
private CpuClobber clobber;
public AsmInlineKickAsm(String kickAsmCode, Long bytes, Long cycles, CpuClobber clobber) {
this.kickAsmCode = kickAsmCode;
if(bytes != null) {
this.bytes = bytes.intValue();
@ -24,16 +28,21 @@ public class AsmInlineKickAsm extends AsmLine {
} else {
this.cycles = 256;
}
if(clobber==null) {
this.clobber = CpuClobber.CLOBBER_ALL;
} else {
this.clobber = clobber;
}
}
public CpuClobber getClobber() {
return clobber;
}
public String getKickAsmCode() {
return kickAsmCode;
}
public void setKickAsmCode(String kickAsmCode) {
this.kickAsmCode = kickAsmCode;
}
/**
* Get the number of source lines in the inline assembler code (for line indexing)
*

View File

@ -213,8 +213,8 @@ public class AsmProgram {
*
* @param kickAsmCode The kickassembler code
*/
public void addInlinedKickAsm(String kickAsmCode, Long bytes, Long cycles) {
addLine(new AsmInlineKickAsm(kickAsmCode, bytes, cycles));
public void addInlinedKickAsm(String kickAsmCode, Long bytes, Long cycles, CpuClobber cpuClobber) {
addLine(new AsmInlineKickAsm(kickAsmCode, bytes, cycles, cpuClobber));
}
/**

View File

@ -83,6 +83,10 @@ public class AsmProgramStaticRegisterValues {
current = new AsmRegisterValues();
} else if(line instanceof AsmScopeEnd) {
current = new AsmRegisterValues();
} else if(line instanceof AsmInlineKickAsm) {
current = new AsmRegisterValues(current);
final CpuClobber cpuClobber = ((AsmInlineKickAsm) line).getClobber();
handleClobber(current, cpuClobber);
} else if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
values.put(instruction, current);
@ -92,34 +96,7 @@ public class AsmProgramStaticRegisterValues {
if(instruction.getCpuOpcode().getMnemonic().equals("jsr")) {
cpuClobber = CpuClobber.CLOBBER_ALL;
}
if(cpuClobber.isRegisterA()) {
current.setA(null);
current.setaMem(null);
}
if(cpuClobber.isRegisterX()) {
current.setX(null);
current.setxMem(null);
}
if(cpuClobber.isRegisterY()) {
current.setY(null);
current.setyMem(null);
}
if(cpuClobber.isRegisterZ()) {
current.setZ(null);
current.setzMem(null);
}
if(cpuClobber.isFlagC()) {
current.setFlagC(null);
}
if(cpuClobber.isFlagN()) {
current.setFlagN(null);
}
if(cpuClobber.isFlagV()) {
current.setFlagV(null);
}
if(cpuClobber.isFlagZ()) {
current.setFlagZ(null);
}
handleClobber(current, cpuClobber);
String mnemnonic = cpuOpcode.getMnemonic();
CpuAddressingMode addressingMode = cpuOpcode.getAddressingMode();
if((mnemnonic.equals("inc") || mnemnonic.equals("dec") || mnemnonic.equals("ror") || mnemnonic.equals("rol") || mnemnonic.equals("lsr") || mnemnonic.equals("asl")) && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
@ -245,6 +222,37 @@ public class AsmProgramStaticRegisterValues {
return current;
}
private void handleClobber(AsmRegisterValues current, CpuClobber cpuClobber) {
if(cpuClobber.isRegisterA()) {
current.setA(null);
current.setaMem(null);
}
if(cpuClobber.isRegisterX()) {
current.setX(null);
current.setxMem(null);
}
if(cpuClobber.isRegisterY()) {
current.setY(null);
current.setyMem(null);
}
if(cpuClobber.isRegisterZ()) {
current.setZ(null);
current.setzMem(null);
}
if(cpuClobber.isFlagC()) {
current.setFlagC(null);
}
if(cpuClobber.isFlagN()) {
current.setFlagN(null);
}
if(cpuClobber.isFlagV()) {
current.setFlagV(null);
}
if(cpuClobber.isFlagZ()) {
current.setFlagZ(null);
}
}
/**
* Known values of registers/flags at an instruction. null where value is unknown.
*/

View File

@ -98,7 +98,7 @@ public class Pass4CodeGeneration {
Number startAddress = program.getTargetPlatform().getStartAddress();
if(startAddress != null)
linkScriptBody = linkScriptBody.replace("%P", AsmFormat.getAsmNumber(startAddress));
asm.addLine(new AsmInlineKickAsm(linkScriptBody, 0L, 0L));
asm.addLine(new AsmInlineKickAsm(linkScriptBody, 0L, 0L, CpuClobber.CLOBBER_ALL));
// Generate global ZP labels
asm.startChunk(currentScope, null, "Global Constants & labels");
@ -815,7 +815,7 @@ public class Pass4CodeGeneration {
if(statementSource != null)
stmtFormat = statementSource.format();
program.getLog().append("Warning! Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature() + "\n" + stmtFormat);
asm.addLine(new AsmInlineKickAsm(".assert \"Missing ASM fragment " + e.getFragmentSignature() + "\", 0, 1", 0L, 0L));
asm.addLine(new AsmInlineKickAsm(".assert \"Missing ASM fragment " + e.getFragmentSignature() + "\", 0, 1", 0L, 0L, CpuClobber.CLOBBER_NONE));
} else {
throw new CompileError("Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature(), statementSource);
}
@ -1061,7 +1061,7 @@ public class Pass4CodeGeneration {
ConstantLiteral kasmCyclesLiteral = kasmCycles.calculateLiteral(getScope());
asmCycles = ((ConstantInteger) kasmCyclesLiteral).getInteger();
}
asm.addInlinedKickAsm(statementKasm.getKickAsmCode(), asmBytes, asmCycles);
asm.addInlinedKickAsm(statementKasm.getKickAsmCode(), asmBytes, asmCycles, statementKasm.getDeclaredClobber());
}
/**

View File

@ -3598,6 +3598,11 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("inline-kasm-clobber.c");
}
@Test
public void testInlineKickAsmClobberMem() throws IOException {
compileAndCompare("inline-kasm-clobbermem.c");
}
@Test
public void testInlineAsmClobberNone() throws IOException {

View File

@ -0,0 +1,16 @@
// Demonstrate problem with inline kasm clobbering memory
// And the ASM peephole optimizer not realizing this
void main() {
__ma char tile = 0;
char * const SCREEN = (char*)0x0400;
for(char i=0;i<10;i++) {
kickasm(uses tile, clobbers "A") {{
lda #4
sta tile
lda #2
sta $02
}}
SCREEN[i] = tile;
}
}

View File

@ -332,9 +332,9 @@ memoryRemap: {
}
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)

View File

@ -1484,9 +1484,9 @@ memoryRemap: {
// memcpy_dma4
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)
@ -2185,9 +2185,9 @@ memoryRemap: {
// memcpy_dma4
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)

View File

@ -100,9 +100,9 @@ memoryRemap: {
}
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)

View File

@ -627,9 +627,9 @@ memoryRemap: {
// memcpy_dma4
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)
@ -890,9 +890,9 @@ memoryRemap: {
// memcpy_dma4
// Copy a memory block anywhere in first 4MB memory space using MEGA65 DMagic DMA
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// - dest_bank The 64KB bank for the destination (0-63)
// - dest_bank The 64KB bank for the destination (0-127)
// - dest The destination address (within the MB and bank)
// - src_bank The 64KB bank for the source (0-63)
// - src_bank The 64KB bank for the source (0-127)
// - src The source address (within the MB and bank)
// - num The number of bytes to copy
// void memcpy_dma4(char dest_bank, void *dest, char src_bank, void *src, unsigned int num)

View File

@ -0,0 +1,38 @@
// Demonstrate problem with inline kasm clobbering memory
// And the ASM peephole optimizer not realizing this
// Commodore 64 PRG executable file
.file [name="inline-kasm-clobbermem.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.segment Code
main: {
.label SCREEN = $400
.label tile = 2
// __ma char tile = 0
lda #0
sta.z tile
tax
__b1:
// for(char i=0;i<10;i++)
cpx #$a
bcc __b2
// }
rts
__b2:
// kickasm
lda #4
sta tile
lda #2
sta $02
// SCREEN[i] = tile
lda.z tile
sta SCREEN,x
// for(char i=0;i<10;i++)
inx
jmp __b1
}

View File

@ -0,0 +1,21 @@
void main()
main: scope:[main] from
[0] main::tile = 0
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
[2] if(main::i#2<$a) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}}
[5] main::SCREEN[main::i#2] = main::tile
[6] main::i#1 = ++ main::i#2
to:main::@1

View File

@ -0,0 +1,288 @@
Setting inferred volatile on symbol affected by address-of: main::tile in kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}}
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
main::tile = 0
main::i#0 = 0
to:main::@1
main::@1: scope:[main] from main main::@2
main::i#2 = phi( main/main::i#0, main::@2/main::i#1 )
main::$0 = main::i#2 < $a
if(main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
main::i#3 = phi( main::@1/main::i#2 )
kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}}
main::SCREEN[main::i#3] = main::tile
main::i#1 = ++ main::i#3
to:main::@1
main::@return: scope:[main] from main::@1
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
void __start()
void main()
bool main::$0
__constant char * const main::SCREEN = (char *)$400
char main::i
char main::i#0
char main::i#1
char main::i#2
char main::i#3
__loadstore volatile char main::tile
Adding number conversion cast (unumber) $a in main::$0 = main::i#2 < $a
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast $a
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $a
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias main::i#2 = main::i#3
Successful SSA optimization Pass2AliasElimination
Simple Condition main::$0 [4] if(main::i#2<$a) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Inlining constant with var siblings main::i#0
Constant inlined main::i#0 = 0
Successful SSA optimization Pass2ConstantInlining
CALL GRAPH
Created 1 initial phi equivalence classes
Coalesced [7] main::i#4 = main::i#1
Coalesced down to 1 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] main::tile = 0
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::i#2 = phi( main/0, main::@2/main::i#1 )
[2] if(main::i#2<$a) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}}
[5] main::SCREEN[main::i#2] = main::tile
[6] main::i#1 = ++ main::i#2
to:main::@1
VARIABLE REGISTER WEIGHTS
void main()
char main::i
char main::i#1 // 22.0
char main::i#2 // 11.0
__loadstore volatile char main::tile // 2.1666666666666665
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Added variable main::tile to live range equivalence class [ main::tile ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::tile ]
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
Allocated zp[1]:3 [ main::tile ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] main::tile = 0 [ main::tile ] ( [ main::tile ] { } ) always clobbers reg byte a
Statement kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}} always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [5] main::SCREEN[main::i#2] = main::tile [ main::tile main::i#2 ] ( [ main::tile main::i#2 ] { } ) always clobbers reg byte a
Statement [0] main::tile = 0 [ main::tile ] ( [ main::tile ] { } ) always clobbers reg byte a
Statement kickasm( uses main::tile) {{ lda #4
sta tile
lda #2
sta $02
}} always clobbers reg byte a
Statement [5] main::SCREEN[main::i#2] = main::tile [ main::tile main::i#2 ] ( [ main::tile main::i#2 ] { } ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ main::tile ] : zp[1]:3 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp[1]:2 [ main::i#2 main::i#1 ] 2.17: zp[1]:3 [ main::tile ]
Uplift Scope []
Uplifting [main] best 2826 combination reg byte x [ main::i#2 main::i#1 ] zp[1]:3 [ main::tile ]
Uplifting [] best 2826 combination
Attempting to uplift remaining variables inzp[1]:3 [ main::tile ]
Uplifting [main] best 2826 combination zp[1]:3 [ main::tile ]
Allocated (was zp[1]:3) zp[1]:2 [ main::tile ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Demonstrate problem with inline kasm clobbering memory
// And the ASM peephole optimizer not realizing this
// Upstart
// Commodore 64 PRG executable file
.file [name="inline-kasm-clobbermem.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
.label SCREEN = $400
.label tile = 2
// [0] main::tile = 0 -- vbuz1=vbuc1
lda #0
sta.z tile
// [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp __b1
// main::@1
__b1:
// [2] if(main::i#2<$a) goto main::@2 -- vbuxx_lt_vbuc1_then_la1
cpx #$a
bcc __b2
jmp __breturn
// main::@return
__breturn:
// [3] return
rts
// main::@2
__b2:
// kickasm( uses main::tile) {{ lda #4 sta tile lda #2 sta $02 }}
lda #4
sta tile
lda #2
sta $02
// [5] main::SCREEN[main::i#2] = main::tile -- pbuc1_derefidx_vbuxx=vbuz1
lda.z tile
sta SCREEN,x
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
inx
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1_from_main:
Removing instruction __breturn:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5UnusedLabelElimination
Replacing instruction ldx #0 with TAX
FINAL SYMBOL TABLE
void main()
__constant char * const main::SCREEN = (char *) 1024
char main::i
char main::i#1 // reg byte x 22.0
char main::i#2 // reg byte x 11.0
__loadstore volatile char main::tile // zp[1]:2 2.1666666666666665
reg byte x [ main::i#2 main::i#1 ]
zp[1]:2 [ main::tile ]
FINAL ASSEMBLER
Score: 2766
// File Comments
// Demonstrate problem with inline kasm clobbering memory
// And the ASM peephole optimizer not realizing this
// Upstart
// Commodore 64 PRG executable file
.file [name="inline-kasm-clobbermem.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
.label SCREEN = $400
.label tile = 2
// __ma char tile = 0
// [0] main::tile = 0 -- vbuz1=vbuc1
lda #0
sta.z tile
// [1] phi from main to main::@1 [phi:main->main::@1]
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
tax
// main::@1
__b1:
// for(char i=0;i<10;i++)
// [2] if(main::i#2<$a) goto main::@2 -- vbuxx_lt_vbuc1_then_la1
cpx #$a
bcc __b2
// main::@return
// }
// [3] return
rts
// main::@2
__b2:
// kickasm
// kickasm( uses main::tile) {{ lda #4 sta tile lda #2 sta $02 }}
lda #4
sta tile
lda #2
sta $02
// SCREEN[i] = tile
// [5] main::SCREEN[main::i#2] = main::tile -- pbuc1_derefidx_vbuxx=vbuz1
lda.z tile
sta SCREEN,x
// for(char i=0;i<10;i++)
// [6] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
inx
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [1] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data

View File

@ -0,0 +1,9 @@
void main()
__constant char * const main::SCREEN = (char *) 1024
char main::i
char main::i#1 // reg byte x 22.0
char main::i#2 // reg byte x 11.0
__loadstore volatile char main::tile // zp[1]:2 2.1666666666666665
reg byte x [ main::i#2 main::i#1 ]
zp[1]:2 [ main::tile ]