mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-21 22:29:07 +00:00
Added special ALU register support
This commit is contained in:
parent
357bbecade
commit
4aa00d4536
@ -35,27 +35,8 @@ public class AsmFragment {
|
||||
public AsmFragment(StatementConditionalJump conditionalJump, ControlFlowBlock block, SymbolTable symbols, ControlFlowGraph graph) {
|
||||
this.bindings = new HashMap<>();
|
||||
this.symbols = symbols;
|
||||
StringBuilder signature = new StringBuilder();
|
||||
if (conditionalJump.getRValue1() != null) {
|
||||
signature.append(bind(conditionalJump.getRValue1()));
|
||||
}
|
||||
if (conditionalJump.getOperator() != null) {
|
||||
signature.append(getOperatorFragmentName(conditionalJump.getOperator()));
|
||||
}
|
||||
if (conditionalJump.getRValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getRValue2()).getNumber() == 0) {
|
||||
signature.append("0");
|
||||
} else {
|
||||
signature.append(bind(conditionalJump.getRValue2()));
|
||||
}
|
||||
signature.append("_then_");
|
||||
Label destination = conditionalJump.getDestination();
|
||||
ControlFlowBlock destinationBlock = graph.getBlock(destination);
|
||||
String destinationLabel = destination.getName();
|
||||
if (destinationBlock.hasPhiStatements()) {
|
||||
destinationLabel = destination.getName() + "_from_" + block.getLabel().getName();
|
||||
}
|
||||
signature.append(bind(new Label(destinationLabel, false)));
|
||||
setSignature(signature.toString());
|
||||
String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph);
|
||||
setSignature(conditionalJumpSignature);
|
||||
}
|
||||
|
||||
public AsmFragment(StatementAssignment assignment, SymbolTable symbols) {
|
||||
@ -70,10 +51,42 @@ public class AsmFragment {
|
||||
setSignature(assignmentSignature(lValue, null, null, rValue));
|
||||
}
|
||||
|
||||
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, SymbolTable symbols) {
|
||||
this.bindings = new HashMap<>();
|
||||
this.symbols = symbols;
|
||||
setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
|
||||
|
||||
}
|
||||
|
||||
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
|
||||
RValue assignmentRValue2 = assignment.getRValue2();
|
||||
RegisterAllocation.Register rVal2Register = symbols.getRegister((Variable) assignmentRValue2);
|
||||
if(!rVal2Register.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
|
||||
throw new RuntimeException("Error! ALU register only allowed as rValue2. "+assignment);
|
||||
}
|
||||
StringBuilder signature = new StringBuilder();
|
||||
signature.append(bind(assignment.getLValue()));
|
||||
signature.append("=");
|
||||
if (assignment.getRValue1() != null) {
|
||||
signature.append(bind(assignment.getRValue1()));
|
||||
}
|
||||
if (assignment.getOperator() != null) {
|
||||
signature.append(getOperatorFragmentName(assignment.getOperator()));
|
||||
}
|
||||
signature.append(assignmentRightSideSignature(assignmentAlu.getRValue1(), assignmentAlu.getOperator(), assignmentAlu.getRValue2()));
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
private String assignmentSignature(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) {
|
||||
StringBuilder signature = new StringBuilder();
|
||||
signature.append(bind(lValue));
|
||||
signature.append("=");
|
||||
signature.append(assignmentRightSideSignature(rValue1, operator, rValue2));
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
private String assignmentRightSideSignature(RValue rValue1, Operator operator, RValue rValue2) {
|
||||
StringBuilder signature = new StringBuilder();
|
||||
if (rValue1 != null) {
|
||||
signature.append(bind(rValue1));
|
||||
}
|
||||
@ -104,6 +117,30 @@ public class AsmFragment {
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
private String conditionalJumpSignature(StatementConditionalJump conditionalJump, ControlFlowBlock block, ControlFlowGraph graph) {
|
||||
StringBuilder signature = new StringBuilder();
|
||||
if (conditionalJump.getRValue1() != null) {
|
||||
signature.append(bind(conditionalJump.getRValue1()));
|
||||
}
|
||||
if (conditionalJump.getOperator() != null) {
|
||||
signature.append(getOperatorFragmentName(conditionalJump.getOperator()));
|
||||
}
|
||||
if (conditionalJump.getRValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getRValue2()).getNumber() == 0) {
|
||||
signature.append("0");
|
||||
} else {
|
||||
signature.append(bind(conditionalJump.getRValue2()));
|
||||
}
|
||||
signature.append("_then_");
|
||||
Label destination = conditionalJump.getDestination();
|
||||
ControlFlowBlock destinationBlock = graph.getBlock(destination);
|
||||
String destinationLabel = destination.getName();
|
||||
if (destinationBlock.hasPhiStatements()) {
|
||||
destinationLabel = destination.getName() + "_from_" + block.getLabel().getName();
|
||||
}
|
||||
signature.append(bind(new Label(destinationLabel, false)));
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
private static String getOperatorFragmentName(Operator operator) {
|
||||
String op = operator.getOperator();
|
||||
switch (op) {
|
||||
|
@ -0,0 +1,2 @@
|
||||
clc
|
||||
adc {cowo1},x
|
@ -0,0 +1 @@
|
||||
lda {cowo1},x
|
@ -0,0 +1,3 @@
|
||||
clc
|
||||
adc {zpby2}
|
||||
sta {zpby1}
|
@ -21,28 +21,43 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
boolean subOpt = false;
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getLValue() instanceof PointerDereferenceIndexed) {
|
||||
optimized |= optimizePointerDereferenceIndexed(assignment);
|
||||
}
|
||||
Operator operator = assignment.getOperator();
|
||||
if (operator != null) {
|
||||
switch (operator.getOperator()) {
|
||||
case "+":
|
||||
subOpt = optimizePlus(assignment);
|
||||
optimized |= optimizePlus(assignment);
|
||||
break;
|
||||
case "*idx":
|
||||
subOpt = optimizeArrayDeref(assignment);
|
||||
optimized |= optimizeArrayDeref(assignment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (subOpt) {
|
||||
optimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimized;
|
||||
}
|
||||
|
||||
private boolean optimizePointerDereferenceIndexed(StatementAssignment assignment) {
|
||||
PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) assignment.getLValue();
|
||||
if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Variable) {
|
||||
Variable variable = (Variable) pointerDereferenceIndexed.getIndex();
|
||||
ConstantInteger consolidated = consolidateSubConstants(variable);
|
||||
if (consolidated != null) {
|
||||
ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer();
|
||||
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
|
||||
pointerDereferenceIndexed.setPointer(new ConstantInteger(newPtr));
|
||||
System.out.println("Consolidated assigned array index constant in assignment " + assignment.getLValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean optimizeArrayDeref(StatementAssignment assignment) {
|
||||
if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof Variable) {
|
||||
Variable variable = (Variable) assignment.getRValue2();
|
||||
@ -51,7 +66,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
ConstantInteger ptrConstant = (ConstantInteger) assignment.getRValue1();
|
||||
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
|
||||
assignment.setRValue1(new ConstantInteger(newPtr));
|
||||
System.out.println("Consolidated constant in assignment " + assignment.getLValue());
|
||||
System.out.println("Consolidated referenced array index constant in assignment " + assignment.getLValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package dk.camelot64.kickc.icl;
|
||||
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Code Generation of 6502 Assembler from ICL/SSA Control Flow Graph
|
||||
*/
|
||||
@ -27,7 +29,7 @@ public class Pass3CodeGeneration {
|
||||
// Generate exit
|
||||
ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor();
|
||||
if (defaultSuccessor != null) {
|
||||
if(defaultSuccessor.hasPhiStatements()) {
|
||||
if (defaultSuccessor.hasPhiStatements()) {
|
||||
genBlockPhiTransition(asm, block, defaultSuccessor);
|
||||
}
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getName().replace('@', 'B'));
|
||||
@ -37,31 +39,50 @@ public class Pass3CodeGeneration {
|
||||
}
|
||||
|
||||
private void genStatements(AsmProgram asm, ControlFlowBlock block) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
Iterator<Statement> statementsIt = block.getStatements().iterator();
|
||||
while (statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if (!(statement instanceof StatementPhi)) {
|
||||
genStatement(asm, statement, block);
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
LValue lValue = assignment.getLValue();
|
||||
boolean isAlu = false;
|
||||
if (lValue instanceof Variable) {
|
||||
RegisterAllocation.Register lValRegister = symbols.getRegister((Variable) lValue);
|
||||
if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
|
||||
asm.addComment(statement + " // ALU");
|
||||
StatementAssignment assignmentAlu = assignment;
|
||||
statement = statementsIt.next();
|
||||
if (!(statement instanceof StatementAssignment)) {
|
||||
throw new RuntimeException("Error! ALU statement must be followed immidiately by assignment using the ALU. " + statement);
|
||||
}
|
||||
assignment = (StatementAssignment) statement;
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols);
|
||||
asm.addComment(statement + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
isAlu = true;
|
||||
}
|
||||
}
|
||||
if (!isAlu) {
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, symbols);
|
||||
asm.addComment(statement + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
}
|
||||
} else if (statement instanceof StatementConditionalJump) {
|
||||
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph);
|
||||
asm.addComment(statement + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
} else {
|
||||
throw new RuntimeException("Statement not supported " + statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void genStatement(AsmProgram asm, Statement statement, ControlFlowBlock block) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
AsmFragment asmFragment = new AsmFragment((StatementAssignment) statement, symbols);
|
||||
asm.addComment(statement + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
} else if (statement instanceof StatementConditionalJump) {
|
||||
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph);
|
||||
asm.addComment(statement + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
} else {
|
||||
throw new RuntimeException("Statement not supported "+statement);
|
||||
}
|
||||
}
|
||||
|
||||
private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) {
|
||||
if(block.hasPhiStatements()) {
|
||||
if (block.hasPhiStatements()) {
|
||||
for (ControlFlowBlock predecessor : block.getPredecessors()) {
|
||||
if(block.equals(predecessor.getConditionalSuccessor())) {
|
||||
if (block.equals(predecessor.getConditionalSuccessor())) {
|
||||
genBlockPhiTransition(asm, predecessor, block);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getName().replace('@', 'B'));
|
||||
}
|
||||
@ -87,7 +108,7 @@ public class Pass3CodeGeneration {
|
||||
}
|
||||
|
||||
private RegisterAllocation.Register getRegister(RValue rValue) {
|
||||
if(rValue instanceof Variable) {
|
||||
if (rValue instanceof Variable) {
|
||||
return symbols.getRegister((Variable) rValue);
|
||||
} else {
|
||||
return null;
|
||||
@ -95,9 +116,9 @@ public class Pass3CodeGeneration {
|
||||
}
|
||||
|
||||
private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) {
|
||||
if(getRegister(lValue).equals(getRegister(rValue))) {
|
||||
if (getRegister(lValue).equals(getRegister(rValue))) {
|
||||
// Do not move from register to itself
|
||||
asm.addComment(lValue + " = " + rValue + " // register copy " );
|
||||
asm.addComment(lValue + " = " + rValue + " // register copy ");
|
||||
return;
|
||||
}
|
||||
AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols);
|
||||
|
@ -64,9 +64,13 @@ public class Pass3RegisterAllocation {
|
||||
allocation.allocate(symbols.getVariable("v#4"), new RegisterAllocation.RegisterAByte());
|
||||
allocation.allocate(symbols.getVariable("v#5"), new RegisterAllocation.RegisterAByte());
|
||||
//allocation.allocate(symbols.getVariable("$0"), new RegisterAllocation.RegisterAByte());
|
||||
//allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterAByte());
|
||||
//allocation.allocate(symbols.getVariable("$2"), new RegisterAllocation.RegisterAByte());
|
||||
//allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterAByte());
|
||||
allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterAByte());
|
||||
allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterALUByte());
|
||||
allocation.allocate(symbols.getVariable("$4"), new RegisterAllocation.RegisterAByte());
|
||||
allocation.allocate(symbols.getVariable("$6"), new RegisterAllocation.RegisterALUByte());
|
||||
allocation.allocate(symbols.getVariable("$7"), new RegisterAllocation.RegisterAByte());
|
||||
symbols.setAllocation(allocation);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ public class RegisterAllocation {
|
||||
|
||||
/** The register type. */
|
||||
public enum RegisterType {
|
||||
ZP_BYTE, ZP_BOOL, REG_A_BYTE, REG_Y_BYTE, REG_X_BYTE, ZP_PTR_BYTE, ZP_WORD
|
||||
ZP_BYTE, ZP_BOOL, REG_A_BYTE, REG_ALU_BYTE, REG_Y_BYTE, REG_X_BYTE, ZP_PTR_BYTE, ZP_WORD
|
||||
}
|
||||
|
||||
/** A zero page address used as a register for a single byte variable. */
|
||||
@ -247,6 +247,26 @@ public class RegisterAllocation {
|
||||
}
|
||||
}
|
||||
|
||||
/** The special ALU register. */
|
||||
public static class RegisterALUByte implements Register {
|
||||
@Override
|
||||
public RegisterType getType() {
|
||||
return RegisterType.REG_ALU_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reg byte alu";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Register getRegisterX() {
|
||||
return new RegisterXByte();
|
||||
}
|
||||
@ -259,6 +279,10 @@ public class RegisterAllocation {
|
||||
return new RegisterAByte();
|
||||
}
|
||||
|
||||
public static Register getRegisterALU() {
|
||||
return new RegisterALUByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
@ -1,8 +1,8 @@
|
||||
byte[15] fibs = $1100;
|
||||
fibs[0] = 0;
|
||||
fibs[1] = 1;
|
||||
byte i = 2;
|
||||
byte i = 0;
|
||||
do {
|
||||
fibs[i] = fibs[i-2]+fibs[i-1];
|
||||
fibs[i+2] = fibs[i]+fibs[i+1];
|
||||
i = i + 1;
|
||||
} while(i<15)
|
||||
|
Loading…
x
Reference in New Issue
Block a user