mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-22 18:33:58 +00:00
Merge remote-tracking branch 'gitlab/master'
This commit is contained in:
commit
27084f8667
@ -2,8 +2,11 @@ package dk.camelot64.kickc.asm;
|
||||
|
||||
/** An assember comment */
|
||||
public class AsmComment implements AsmLine {
|
||||
|
||||
private String comment;
|
||||
|
||||
private int index;
|
||||
|
||||
public AsmComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
@ -22,21 +25,21 @@ public class AsmComment implements AsmLine {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInvocationCountEstimate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEstimatedTotalCycles() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return "// "+comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAsm();
|
||||
|
@ -415,7 +415,7 @@ public class AsmFragment {
|
||||
AsmInstruction instruction;
|
||||
if (paramModeCtx == null) {
|
||||
AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON, null);
|
||||
instruction = new AsmInstruction(type, null, 1);
|
||||
instruction = new AsmInstruction(type, null);
|
||||
} else {
|
||||
instruction = (AsmInstruction) this.visit(paramModeCtx);
|
||||
}
|
||||
@ -467,7 +467,7 @@ public class AsmFragment {
|
||||
String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText();
|
||||
String parameter = (String) this.visit(exprCtx);
|
||||
AsmInstructionType type = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode, parameter);
|
||||
return new AsmInstruction(type, parameter, 1);
|
||||
return new AsmInstruction(type, parameter);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,12 +7,11 @@ public class AsmInstruction implements AsmLine {
|
||||
|
||||
private String parameter;
|
||||
|
||||
private int invocationCountEstimate;
|
||||
private int index;
|
||||
|
||||
public AsmInstruction(AsmInstructionType type, String parameter, int invocationCountEstimate) {
|
||||
public AsmInstruction(AsmInstructionType type, String parameter) {
|
||||
this.type = type;
|
||||
this.parameter = parameter;
|
||||
this.invocationCountEstimate = invocationCountEstimate;
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
@ -33,16 +32,6 @@ public class AsmInstruction implements AsmLine {
|
||||
return type.getCycles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInvocationCountEstimate() {
|
||||
return invocationCountEstimate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEstimatedTotalCycles() {
|
||||
return getInvocationCountEstimate()*getLineCycles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return type.getAsm(parameter);
|
||||
@ -53,4 +42,13 @@ public class AsmInstruction implements AsmLine {
|
||||
return getAsm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ public class AsmLabel implements AsmLine {
|
||||
|
||||
private String label;
|
||||
|
||||
private int index;
|
||||
|
||||
public AsmLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
@ -23,21 +25,21 @@ public class AsmLabel implements AsmLine {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInvocationCountEstimate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEstimatedTotalCycles() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return label+":";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAsm();
|
||||
|
@ -7,10 +7,9 @@ public interface AsmLine {
|
||||
|
||||
public double getLineCycles();
|
||||
|
||||
public int getInvocationCountEstimate();
|
||||
|
||||
public double getEstimatedTotalCycles();
|
||||
|
||||
public String getAsm();
|
||||
|
||||
public int getIndex();
|
||||
|
||||
void setIndex(int index);
|
||||
}
|
||||
|
@ -10,8 +10,11 @@ public class AsmProgram {
|
||||
|
||||
private List<AsmLine> lines;
|
||||
|
||||
private int nextIndex;
|
||||
|
||||
public AsmProgram() {
|
||||
this.lines = new ArrayList<>();
|
||||
this.nextIndex = 0;
|
||||
}
|
||||
|
||||
public List<AsmLine> getLines() {
|
||||
@ -19,6 +22,7 @@ public class AsmProgram {
|
||||
}
|
||||
|
||||
public void addLine(AsmLine line) {
|
||||
line.setIndex(nextIndex++);
|
||||
lines.add(line);
|
||||
}
|
||||
|
||||
@ -32,7 +36,7 @@ public class AsmProgram {
|
||||
|
||||
public void addInstruction(String mnemonic, AsmAddressingMode addressingMode, String parameter) {
|
||||
AsmInstructionType instructionType = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode, parameter);
|
||||
addLine(new AsmInstruction(instructionType, parameter, 1));
|
||||
addLine(new AsmInstruction(instructionType, parameter));
|
||||
}
|
||||
|
||||
public String toString(boolean comments) {
|
||||
|
@ -0,0 +1,2 @@
|
||||
ldy #0
|
||||
lda ({zpptrby1}),y
|
@ -0,0 +1,2 @@
|
||||
cpy #{coby1}
|
||||
bcs {la1}
|
@ -0,0 +1,3 @@
|
||||
ldy #0
|
||||
lda ({zpptrby1}),y
|
||||
tax
|
@ -0,0 +1,4 @@
|
||||
txa
|
||||
sec
|
||||
sbc #{coby1}
|
||||
tax
|
@ -0,0 +1,4 @@
|
||||
lda {zpby1}
|
||||
clc
|
||||
adc {zpby2}
|
||||
tax
|
@ -0,0 +1,3 @@
|
||||
ldy #0
|
||||
lda ({zpptrby1}),y
|
||||
tay
|
@ -0,0 +1,4 @@
|
||||
lda {zpby1}
|
||||
clc
|
||||
adc {zpby2}
|
||||
tay
|
@ -0,0 +1,3 @@
|
||||
tax
|
||||
lda {cowo1},x
|
||||
sta {zpby1}
|
@ -0,0 +1,2 @@
|
||||
lda {cowo1},y
|
||||
sta {zpby1}
|
@ -1,6 +1,8 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.AsmInstruction;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.asm.parser.AsmClobber;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
@ -30,7 +32,7 @@ public class Pass3AssertNoCpuClobber {
|
||||
|
||||
/** Check that no statement clobbers a CPU register used by an alive variable */
|
||||
public void check() {
|
||||
if(hasClobberProblem()) {
|
||||
if(hasClobberProblem(true, null)) {
|
||||
throw new RuntimeException("CLOBBER ERROR! See log for more info.");
|
||||
}
|
||||
}
|
||||
@ -39,15 +41,18 @@ public class Pass3AssertNoCpuClobber {
|
||||
* Determines whether any statement in the program clobbers a CPU register used by an alive variable
|
||||
* @return true if there is a clobber problem in the program
|
||||
*/
|
||||
public boolean hasClobberProblem() {
|
||||
public boolean hasClobberProblem(boolean verbose, RegisterAllocation.Register register) {
|
||||
RegisterAllocation allocation = program.getScope().getAllocation();
|
||||
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
|
||||
boolean error = false;
|
||||
boolean clobberProblem = false;
|
||||
Pass4CodeGeneration.AsmCodegenAluState aluState = new Pass4CodeGeneration.AsmCodegenAluState();
|
||||
int registerCycles = 0;
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
|
||||
// Generate ASM and find clobber
|
||||
Collection<RegisterAllocation.Register> clobberRegisters = getClobberedRegisters(statement, block);
|
||||
AsmProgram asm = getAsmProgram(statement, block, aluState);
|
||||
Collection<RegisterAllocation.Register> clobberRegisters = getClobberedRegisters(asm);
|
||||
|
||||
// Find alive variables
|
||||
List<VariableRef> aliveVars = new ArrayList<>(liveRangeVariables.getAlive(statement));
|
||||
@ -61,20 +66,39 @@ public class Pass3AssertNoCpuClobber {
|
||||
// No need to check a zp-register - here we are only interested in CPU registers
|
||||
continue;
|
||||
}
|
||||
if(aliveVarRegister.equals(register)) {
|
||||
registerCycles += countCycles(asm);
|
||||
}
|
||||
if(assignedVars.contains(aliveVar)) {
|
||||
// No need to register that is assigned by the statement - it will be clobbered
|
||||
continue;
|
||||
}
|
||||
// Alive and not assigned to - clobber not allowed!
|
||||
if(clobberRegisters.contains(aliveVarRegister)) {
|
||||
log.append("Error! Alive variable "+aliveVar+" register "+aliveVarRegister+" clobbered by the ASM generated by statement "+statement);
|
||||
log.append(getAsmProgram(statement, block).toString(false));
|
||||
error = true;
|
||||
if(verbose) {
|
||||
log.append("Error! Alive variable " + aliveVar + " register " + aliveVarRegister + " clobbered by the ASM generated by statement " + statement);
|
||||
log.append(asm.toString(false));
|
||||
}
|
||||
clobberProblem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
if(!clobberProblem && register!=null) {
|
||||
log.append("Register Cycles: "+register+" "+registerCycles);
|
||||
}
|
||||
return clobberProblem;
|
||||
}
|
||||
|
||||
private int countCycles(AsmProgram asm) {
|
||||
int instructionCycles = 0;
|
||||
for (AsmLine asmLine : asm.getLines()) {
|
||||
if(asmLine instanceof AsmInstruction) {
|
||||
double lineCycles = ((AsmInstruction) asmLine).getType().getCycles();
|
||||
instructionCycles += lineCycles;
|
||||
}
|
||||
}
|
||||
return instructionCycles;
|
||||
}
|
||||
|
||||
|
||||
@ -103,12 +127,10 @@ public class Pass3AssertNoCpuClobber {
|
||||
/**
|
||||
* Get all CPU registers clobbered by the ASM generated from a specific statement in the program
|
||||
*
|
||||
* @param statement The statement
|
||||
* @param block The block containing the statement
|
||||
* @param asm The assembler to check
|
||||
* @return The clobbered CPU registers
|
||||
*/
|
||||
private Collection<RegisterAllocation.Register> getClobberedRegisters(Statement statement, ControlFlowBlock block) {
|
||||
AsmProgram asm = getAsmProgram(statement, block);
|
||||
private Collection<RegisterAllocation.Register> getClobberedRegisters(AsmProgram asm) {
|
||||
AsmClobber clobber = asm.getClobber();
|
||||
List<RegisterAllocation.Register> clobberRegisters = new ArrayList<>();
|
||||
if(clobber.isClobberA()) {
|
||||
@ -130,10 +152,10 @@ public class Pass3AssertNoCpuClobber {
|
||||
* @param block The block containing the statement
|
||||
* @return The ASM code
|
||||
*/
|
||||
private AsmProgram getAsmProgram(Statement statement, ControlFlowBlock block) {
|
||||
private AsmProgram getAsmProgram(Statement statement, ControlFlowBlock block, Pass4CodeGeneration.AsmCodegenAluState aluState) {
|
||||
Pass4CodeGeneration codegen = new Pass4CodeGeneration(program);
|
||||
AsmProgram asm = new AsmProgram();
|
||||
codegen.generateStatementAsm(asm, block, statement, new Pass4CodeGeneration.AsmCodegenAluState());
|
||||
codegen.generateStatementAsm(asm, block, statement, aluState);
|
||||
return asm;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class Pass3RegisterUplifting {
|
||||
}
|
||||
program.getScope().setAllocation(allocation);
|
||||
Pass3AssertNoCpuClobber clobber = new Pass3AssertNoCpuClobber(program, log);
|
||||
if (clobber.hasClobberProblem()) {
|
||||
if (clobber.hasClobberProblem(false, register)) {
|
||||
log.append("Uplift to " + register + " resulted in clobber.");
|
||||
} else {
|
||||
log.append("Uplift to " + register + " succesfull.");
|
||||
|
@ -31,12 +31,12 @@ public class Pass3ZeroPageAllocation {
|
||||
}
|
||||
|
||||
// Coalesce over copy assignments
|
||||
EquivalenceClassCopyCoalescer equivalenceClassCopyCoalescer = new EquivalenceClassCopyCoalescer(liveRangeEquivalenceClassSet);
|
||||
equivalenceClassCopyCoalescer.visitGraph(program.getGraph());
|
||||
log.append("Copy Coalesced equivalence classes");
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
log.append(liveRangeEquivalenceClass.toString());
|
||||
}
|
||||
//EquivalenceClassCopyCoalescer equivalenceClassCopyCoalescer = new EquivalenceClassCopyCoalescer(liveRangeEquivalenceClassSet);
|
||||
//equivalenceClassCopyCoalescer.visitGraph(program.getGraph());
|
||||
//log.append("Copy Coalesced equivalence classes");
|
||||
//for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
// log.append(liveRangeEquivalenceClass.toString());
|
||||
//}
|
||||
|
||||
// Add all other variables one by one to an available equivalence class - or create a new one
|
||||
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
|
||||
@ -74,8 +74,8 @@ public class Pass3ZeroPageAllocation {
|
||||
if (assignment.getlValue() instanceof VariableRef) {
|
||||
VariableRef lValVar = (VariableRef) assignment.getlValue();
|
||||
List<VariableRef> preferences = new ArrayList<>();
|
||||
addPreference(preferences, assignment.getrValue1());
|
||||
addPreference(preferences, assignment.getrValue2());
|
||||
//addPreference(preferences, assignment.getrValue1());
|
||||
//addPreference(preferences, assignment.getrValue2());
|
||||
addToEquivalenceClassSet(lValVar, preferences);
|
||||
}
|
||||
return null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user