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:
parent
ae21d82383
commit
f962948ef8
@ -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>
|
13
.idea/libraries/Maven__org_antlr_antlr4_4_9_2.xml
Normal file
13
.idea/libraries/Maven__org_antlr_antlr4_4_9_2.xml
Normal 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>
|
@ -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>
|
@ -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" />
|
||||
|
4
pom.xml
4
pom.xml
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
|
||||
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
|
||||
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE db0ab6caa db0ab911c
|
||||
//KICKC FRAGMENT CACHE d8c3d291d d8c3d4dd4
|
||||
//FRAGMENT vbuz1=_deref_pbuc1
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
|
@ -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)
|
||||
*
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
16
src/test/kc/inline-kasm-clobbermem.c
Normal file
16
src/test/kc/inline-kasm-clobbermem.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
38
src/test/ref/inline-kasm-clobbermem.asm
Normal file
38
src/test/ref/inline-kasm-clobbermem.asm
Normal 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
|
||||
}
|
21
src/test/ref/inline-kasm-clobbermem.cfg
Normal file
21
src/test/ref/inline-kasm-clobbermem.cfg
Normal 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
|
288
src/test/ref/inline-kasm-clobbermem.log
Normal file
288
src/test/ref/inline-kasm-clobbermem.log
Normal 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
|
||||
|
9
src/test/ref/inline-kasm-clobbermem.sym
Normal file
9
src/test/ref/inline-kasm-clobbermem.sym
Normal 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 ]
|
Loading…
Reference in New Issue
Block a user