1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Eliminating ZP_BYTE/ZP_WORD/ZP_DWORD register calses & types.

This commit is contained in:
Jesper Gravgaard 2019-10-06 20:42:52 +02:00
parent 9877da213d
commit 9f523beeaf
7 changed files with 127 additions and 104 deletions

View File

@ -453,6 +453,7 @@ public class AsmFragmentInstanceSpecFactory {
Registers.RegisterType.ZP_BOOL.equals(register.getType()) ||
Registers.RegisterType.ZP_BYTE.equals(register.getType()) ||
Registers.RegisterType.ZP_WORD.equals(register.getType()) ||
Registers.RegisterType.ZP_MEM.equals(register.getType()) ||
Registers.RegisterType.ZP_DWORD.equals(register.getType()) ||
Registers.RegisterType.ZP_STRUCT.equals(register.getType())
) {

View File

@ -44,7 +44,7 @@ public class AsmFragmentTemplate {
/** The cycles consumed by the ASM of the fragment. */
private Double cycles;
public AsmFragmentTemplate(String signature, String body, boolean cache) {
AsmFragmentTemplate(String signature, String body, boolean cache) {
this.signature = signature;
this.body = body;
this.file = true;
@ -72,8 +72,6 @@ public class AsmFragmentTemplate {
/**
* Initialize the fields that require parsing the ASM (bodyAsm, clobber, cycles).
*
* @return The parsed fragment ready for generating
*/
private void initAsm() {
// Parse the body ASM
@ -88,12 +86,12 @@ public class AsmFragmentTemplate {
Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
v1.setAllocation(new Registers.RegisterZpByte(2));
v2.setAllocation(new Registers.RegisterZpByte(4));
v3.setAllocation(new Registers.RegisterZpByte(6));
v4.setAllocation(new Registers.RegisterZpByte(8));
v5.setAllocation(new Registers.RegisterZpByte(9));
v6.setAllocation(new Registers.RegisterZpByte(10));
v1.setAllocation(new Registers.RegisterZpMem(2, 1));
v2.setAllocation(new Registers.RegisterZpMem(4, 1));
v3.setAllocation(new Registers.RegisterZpMem(6, 1));
v4.setAllocation(new Registers.RegisterZpMem(8, 1));
v5.setAllocation(new Registers.RegisterZpMem(9, 1));
v6.setAllocation(new Registers.RegisterZpMem(10, 1));
if(signature.contains("z1")) bindings.put("z1", v1);
if(signature.contains("z2")) bindings.put("z2", v2);
if(signature.contains("z3")) bindings.put("z3", v3);
@ -108,12 +106,12 @@ public class AsmFragmentTemplate {
Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
v1.setAllocation(new Registers.RegisterMemory(v1.getRef()));
v2.setAllocation(new Registers.RegisterMemory(v2.getRef()));
v3.setAllocation(new Registers.RegisterMemory(v3.getRef()));
v4.setAllocation(new Registers.RegisterMemory(v4.getRef()));
v5.setAllocation(new Registers.RegisterMemory(v5.getRef()));
v6.setAllocation(new Registers.RegisterMemory(v6.getRef()));
v1.setAllocation(new Registers.RegisterMemory(v1.getRef(), 1));
v2.setAllocation(new Registers.RegisterMemory(v2.getRef(), 1));
v3.setAllocation(new Registers.RegisterMemory(v3.getRef(), 1));
v4.setAllocation(new Registers.RegisterMemory(v4.getRef(), 1));
v5.setAllocation(new Registers.RegisterMemory(v5.getRef(), 1));
v6.setAllocation(new Registers.RegisterMemory(v6.getRef(), 1));
if(signature.contains("m1")) bindings.put("m1", v1);
if(signature.contains("m2")) bindings.put("m2", v2);
if(signature.contains("m3")) bindings.put("m3", v3);
@ -138,7 +136,7 @@ public class AsmFragmentTemplate {
this.cycles = asm.getCycles();
}
public String getSignature() {
String getSignature() {
return signature;
}
@ -146,7 +144,7 @@ public class AsmFragmentTemplate {
return body;
}
public KickCParser.AsmLinesContext getBodyAsm() {
KickCParser.AsmLinesContext getBodyAsm() {
if(bodyAsm == null) {
initAsm();
}
@ -175,11 +173,11 @@ public class AsmFragmentTemplate {
return cache;
}
public AsmFragmentTemplateSynthesisRule getSynthesis() {
AsmFragmentTemplateSynthesisRule getSynthesis() {
return synthesis;
}
public AsmFragmentTemplate getSubFragment() {
AsmFragmentTemplate getSubFragment() {
return subFragment;
}

View File

@ -52,6 +52,7 @@ public class Registers {
ZP_STRUCT,
ZP_BOOL,
ZP_VAR,
ZP_MEM,
CONSTANT,
MEMORY
}
@ -63,14 +64,19 @@ public class Registers {
boolean isZp();
int getBytes();
}
public static class RegisterMemory implements Register {
private VariableRef variableRef;
public RegisterMemory(VariableRef variableRef) {
private int bytes;
public RegisterMemory(VariableRef variableRef, int bytes ) {
this.variableRef = variableRef;
this.bytes = bytes;
}
public VariableRef getVariableRef() {
@ -87,6 +93,11 @@ public class Registers {
return false;
}
@Override
public int getBytes() {
return bytes;
}
@Override
public String toString() {
return "mem "+variableRef.toString();
@ -116,7 +127,7 @@ public class Registers {
/** The ZP address used for the byte. */
private int zp;
public RegisterZp(int zp) {
RegisterZp(int zp) {
this.zp = zp;
}
@ -124,6 +135,8 @@ public class Registers {
return zp;
}
public abstract int getBytes();
@Override
public boolean isZp() {
return true;
@ -158,6 +171,51 @@ public class Registers {
}
/** Two zero page addresses used as a register for a single unsigned word variable. */
public static class RegisterZpMem extends RegisterZp {
int bytes;
public RegisterZpMem(int zp, int bytes) {
super(zp);
this.bytes = bytes;
}
@Override
public RegisterType getType() {
return RegisterType.ZP_MEM;
}
public int getBytes() {
return bytes;
}
@Override
public String toString() {
String typeString;
if(getBytes()==1) {
typeString = RegisterType.ZP_BYTE.toString();
} else if(getBytes()==2) {
typeString = RegisterType.ZP_WORD.toString();
} else if(getBytes()==4) {
typeString = RegisterType.ZP_DWORD.toString();
} else {
typeString = RegisterType.ZP_MEM.toString();
}
return "zp " + typeString + ":" + getZp();
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
/** A zero page address used as a register for a declared register allocation. Size is initially unknown and will be resolved when performing allocation by setting the type. */
public static class RegisterZpDeclared extends RegisterZp {
@ -177,6 +235,11 @@ public class Registers {
this.type = type;
}
@Override
public int getBytes() {
return -1;
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
@ -194,58 +257,14 @@ public class Registers {
}
/** A zero page address used as a register for a single unsigned byte variable. */
public static class RegisterZpByte extends RegisterZp {
public RegisterZpByte(int zp) {
super(zp);
}
@Override
public RegisterType getType() {
return RegisterType.ZP_BYTE;
}
}
/** Two zero page addresses used as a register for a single unsigned word variable. */
public static class RegisterZpWord extends RegisterZp {
public RegisterZpWord(int zp) {
super(zp);
}
@Override
public RegisterType getType() {
return RegisterType.ZP_WORD;
}
}
/** Four zero page addresses used as a register for a single unsigned word variable. */
public static class RegisterZpDWord extends RegisterZp {
public RegisterZpDWord(int zp) {
super(zp);
}
@Override
public RegisterType getType() {
return RegisterType.ZP_DWORD;
}
}
/** Zero page addresses used as a register for a struct variable. */
public static class RegisterZpStruct extends RegisterZp {
public RegisterZpStruct(int zp) {
super(zp);
}
private int bytes;
public RegisterZpStructMember getMemberRegister(long memberByteOffset) {
return new RegisterZpStructMember((int) (getZp()+memberByteOffset));
public RegisterZpStruct(int zp, int bytes) {
super(zp);
this.bytes = bytes;
}
@Override
@ -253,20 +272,10 @@ public class Registers {
return RegisterType.ZP_STRUCT;
}
}
/** Zero page addresses used as a register for a struct member variable. */
public static class RegisterZpStructMember extends RegisterZp {
public RegisterZpStructMember(int zp) {
super(zp);
}
@Override
public RegisterType getType() {
return RegisterType.ZP_STRUCT;
public int getBytes() {
return bytes;
}
}
/** A zero page address used as a register for a boolean variable. */
@ -281,7 +290,10 @@ public class Registers {
return RegisterType.ZP_BOOL;
}
@Override
public int getBytes() {
return 1;
}
}
/** A CPU byte register. */
@ -294,6 +306,11 @@ public class Registers {
return false;
}
@Override
public int getBytes() {
return 1;
}
@Override
public abstract String toString();
@ -302,10 +319,7 @@ public class Registers {
if(this == obj) {
return true;
}
if(obj == null || getClass() != obj.getClass()) {
return false;
}
return true;
return obj != null && getClass() == obj.getClass();
}
@Override
@ -396,6 +410,11 @@ public class Registers {
return false;
}
@Override
public int getBytes() {
return 0;
}
public ConstantValue getConstantValue() {
return constantValue;
}

View File

@ -45,7 +45,9 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
Registers.RegisterType registerType = defaultRegister.getType();
List<Registers.Register> potentials = new ArrayList<>();
potentials.add(defaultRegister);
if(registerType.equals(Registers.RegisterType.ZP_BYTE) && !varVolatile(equivalenceClass)) {
boolean isByte1 = registerType.equals(Registers.RegisterType.ZP_BYTE);
boolean isByte2 = defaultRegister instanceof Registers.RegisterZpMem && ((Registers.RegisterZpMem) defaultRegister).getBytes() == 1;
if((isByte1 || isByte2) && !varVolatile(equivalenceClass)) {
potentials.add(Registers.getRegisterA());
potentials.add(Registers.getRegisterX());
potentials.add(Registers.getRegisterY());

View File

@ -23,7 +23,10 @@ public class Pass4RegisterUpliftRemains extends Pass2Base {
Set<String> unknownFragments = new LinkedHashSet<>();
for(LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
if(equivalenceClass.getRegister().getType().equals(Registers.RegisterType.ZP_BYTE)) {
Registers.Register register = equivalenceClass.getRegister();
boolean isByte1 = register.getType().equals(Registers.RegisterType.ZP_BYTE);
boolean isByte2 = register instanceof Registers.RegisterZpMem && ((Registers.RegisterZpMem) register).getBytes()==1;
if(isByte1 || isByte2) {
getLog().append("Attempting to uplift remaining variables in" + equivalenceClass);
RegisterCombinationIterator combinationIterator = new RegisterCombinationIterator(Arrays.asList(equivalenceClass), getProgram().getRegisterPotentials());
VariableRef variableRef = equivalenceClass.getVariables().get(0);

View File

@ -185,7 +185,7 @@ public class Pass4RegistersFinalize extends Pass2Base {
VariableRef variableRef = equivalenceClass.getVariables().get(0);
Variable variable = getProgram().getSymbolInfos().getVariable(variableRef);
if(variable.isStorageMemory()) {
register = new Registers.RegisterMemory(variableRef);
register = new Registers.RegisterMemory(variableRef, variable.getType().getSizeBytes());
} else {
register = allocateNewRegisterZp(variable);
}
@ -233,24 +233,24 @@ public class Pass4RegistersFinalize extends Pass2Base {
private Registers.Register allocateNewRegisterZp(Variable variable) {
SymbolType varType = variable.getType();
if(SymbolType.BYTE.equals(varType)) {
return new Registers.RegisterZpByte(allocateZp((1)));
return new Registers.RegisterZpMem(allocateZp(1), 1);
} else if(SymbolType.SBYTE.equals(varType)) {
return new Registers.RegisterZpByte(allocateZp(1));
return new Registers.RegisterZpMem(allocateZp(1),1);
} else if(SymbolType.WORD.equals(varType)) {
Registers.RegisterZpWord registerZpWord =
new Registers.RegisterZpWord(allocateZp(2));
Registers.RegisterZpMem registerZpWord =
new Registers.RegisterZpMem(allocateZp(2), 2);
return registerZpWord;
} else if(SymbolType.SWORD.equals(varType)) {
Registers.RegisterZpWord registerZpWord =
new Registers.RegisterZpWord(allocateZp(2));
Registers.RegisterZpMem registerZpWord =
new Registers.RegisterZpMem(allocateZp(2), 2);
return registerZpWord;
} else if(SymbolType.DWORD.equals(varType)) {
Registers.RegisterZpDWord registerZpDWord =
new Registers.RegisterZpDWord(allocateZp(4));
Registers.RegisterZpMem registerZpDWord =
new Registers.RegisterZpMem(allocateZp(4), 4);
return registerZpDWord;
} else if(SymbolType.SDWORD.equals(varType)) {
Registers.RegisterZpDWord registerZpDWord =
new Registers.RegisterZpDWord(allocateZp(4));
Registers.RegisterZpMem registerZpDWord =
new Registers.RegisterZpMem(allocateZp(4), 4);
return registerZpDWord;
} else if(varType.equals(SymbolType.BOOLEAN)) {
return new Registers.RegisterZpBool(allocateZp(1));
@ -258,12 +258,12 @@ public class Pass4RegistersFinalize extends Pass2Base {
// No need to setRegister register for VOID value
return null;
} else if(varType instanceof SymbolTypePointer) {
Registers.RegisterZpWord registerZpWord =
new Registers.RegisterZpWord(allocateZp(2));
Registers.RegisterZpMem registerZpWord =
new Registers.RegisterZpMem(allocateZp(2), 2);
return registerZpWord;
} else if(varType instanceof SymbolTypeStruct) {
Registers.RegisterZpStruct registerZpStruct =
new Registers.RegisterZpStruct(allocateZp(varType.getSizeBytes()));
new Registers.RegisterZpStruct(allocateZp(varType.getSizeBytes()), varType.getSizeBytes());
return registerZpStruct;
} else {
throw new RuntimeException("Unhandled variable type " + varType);

View File

@ -63,7 +63,7 @@ public abstract class Pass4ZeroPageCoalesce extends Pass2Base {
}
/**
* Determines if two lice range equivalence classes are candidates for coalescing by checking that they are not the same
* Determines if two live range equivalence classes are candidates for coalescing by checking that they are not the same
*
* @param ec1 One equivalence class
* @param ec2 Another equivalence class
@ -142,7 +142,7 @@ public abstract class Pass4ZeroPageCoalesce extends Pass2Base {
private static boolean canCoalesceClobber(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Set<String> unknownFragments, Program program) {
Registers.Register register1 = ec1.getRegister();
Registers.Register register2 = ec2.getRegister();
if(register1.isZp() && register2.isZp() && register1.getType().equals(register2.getType())) {
if(register1.isZp() && register2.isZp() && register1.getBytes()==register2.getBytes()) {
// Both registers are on Zero Page & have the same zero page size
// Try out the coalesce to test if it works
RegisterCombination combination = new RegisterCombination();