diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
similarity index 98%
rename from src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java
rename to src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
index 0b1f54343..87d3191a5 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
@@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.Map;
/** ASM Code Fragment with register/variable bindings that can be used for generating ASM code for a specific statement . */
-public class AsmFragment {
+public class AsmFragmentInstance {
/** The symbol table. */
private Program program;
@@ -27,7 +27,7 @@ public class AsmFragment {
/** The scope containing the fragment. Used when referencing symbols defined in other scopes. */
private ScopeRef codeScopeRef;
- public AsmFragment(
+ public AsmFragmentInstance(
Program program,
String name,
ScopeRef codeScopeRef,
@@ -134,9 +134,9 @@ public class AsmFragment {
private String name;
private AsmProgram program;
- private AsmFragment bindings;
+ private AsmFragmentInstance bindings;
- public AsmSequenceGenerator(String name, AsmFragment bindings, AsmProgram program) {
+ public AsmSequenceGenerator(String name, AsmFragmentInstance bindings, AsmProgram program) {
this.name = name;
this.bindings = bindings;
this.program = program;
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
similarity index 88%
rename from src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
rename to src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
index 35ee1722b..d9f00f7f5 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
@@ -6,9 +6,9 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
- * A fragment signature generated from a {@link Statement} used to load/synthesize an AsmFragent for creating ASM code for the statement
+ * A fragment specification generated from a {@link Statement} used to load/synthesize an {@link AsmFragmentInstance} for creating ASM code for the statement
*/
-public class AsmFragmentSignature {
+public class AsmFragmentInstanceSpec {
/**
* The symbol table.
@@ -16,7 +16,7 @@ public class AsmFragmentSignature {
private Program program;
/**
- * The string signature/name of the fragment fragment.
+ * The string signature/name of the fragment template.
*/
private String signature;
@@ -37,7 +37,7 @@ public class AsmFragmentSignature {
private int nextConstByteIdx = 1;
private int nextLabelIdx = 1;
- public AsmFragmentSignature(
+ public AsmFragmentInstanceSpec(
StatementConditionalJump conditionalJump,
ControlFlowBlock block,
Program program,
@@ -49,7 +49,7 @@ public class AsmFragmentSignature {
setSignature(conditionalJumpSignature);
}
- public AsmFragmentSignature(StatementAssignment assignment, Program program) {
+ public AsmFragmentInstanceSpec(StatementAssignment assignment, Program program) {
this.codeScopeRef = program.getStatementInfos().getBlock(assignment).getScope();
this.bindings = new LinkedHashMap<>();
this.program = program;
@@ -60,14 +60,14 @@ public class AsmFragmentSignature {
assignment.getrValue2()));
}
- public AsmFragmentSignature(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
+ public AsmFragmentInstanceSpec(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
this.codeScopeRef = codeScopeRef;
this.bindings = new LinkedHashMap<>();
this.program = program;
setSignature(assignmentSignature(lValue, null, null, rValue));
}
- public AsmFragmentSignature(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
+ public AsmFragmentInstanceSpec(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
this.codeScopeRef = program.getStatementInfos().getBlock(assignment).getScope();
this.bindings = new LinkedHashMap<>();
this.program = program;
@@ -81,14 +81,14 @@ public class AsmFragmentSignature {
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
this.codeScopeRef = program.getStatementInfos().getBlock(assignment).getScope();
if(!(assignment.getrValue2() instanceof VariableRef)) {
- throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
+ throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
}
VariableRef assignmentRValue2 = (VariableRef) assignment.getrValue2();
Variable assignmentRValue2Var = program.getSymbolInfos().getVariable(assignmentRValue2);
Registers.Register rVal2Register = assignmentRValue2Var.getAllocation();
if(!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) {
- throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
+ throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
}
StringBuilder signature = new StringBuilder();
signature.append(bind(assignment.getlValue()));
@@ -309,7 +309,7 @@ public class AsmFragmentSignature {
} else if(Registers.RegisterType.REG_Y_BYTE.equals(register.getType())) {
return "yy";
} else if(Registers.RegisterType.REG_ALU.equals(register.getType())) {
- throw new AsmFragment.AluNotApplicableException();
+ throw new AsmFragmentInstance.AluNotApplicableException();
} else {
throw new RuntimeException("Not implemented " + register.getType());
}
@@ -363,4 +363,24 @@ public class AsmFragmentSignature {
str.append(") ");
return str.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+
+ AsmFragmentInstanceSpec that = (AsmFragmentInstanceSpec) o;
+
+ if(signature != null ? !signature.equals(that.signature) : that.signature != null) return false;
+ if(bindings != null ? !bindings.equals(that.bindings) : that.bindings != null) return false;
+ return codeScopeRef != null ? codeScopeRef.equals(that.codeScopeRef) : that.codeScopeRef == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = signature != null ? signature.hashCode() : 0;
+ result = 31 * result + (bindings != null ? bindings.hashCode() : 0);
+ result = 31 * result + (codeScopeRef != null ? codeScopeRef.hashCode() : 0);
+ return result;
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java
deleted file mode 100644
index 0eeb6e57a..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java
+++ /dev/null
@@ -1,562 +0,0 @@
-package dk.camelot64.kickc.fragment;
-
-import dk.camelot64.kickc.CompileLog;
-import dk.camelot64.kickc.asm.AsmProgram;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.CharStreams;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.*;
-
-/**
- * Provides fragments from their signature.
- *
- * The first priority is loading a fragment file from the fragment-folder.
- * If no fragment file is found for the signature the manager attempts to synthesise a fragment from another fragment.
- */
-public class AsmFragmentManager {
-
- /** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. */
- private static Map bestFragmentCache = new HashMap<>();
-
- /** Caches all asm fragment templates for all encountered signatures. */
- private static Map> fragmentTemplateCache = new LinkedHashMap<>();
-
- /** Special singleton representing that the fragment can not be synthesized or loaded. */
- private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
- /**
- * All the synthesize rules available.
- */
- private static List fragmentSyntheses;
-
- static Map> getFragmentTemplateCache() {
- return fragmentTemplateCache;
- }
-
- public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
- AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
- if(bestTemplate == UNKNOWN) {
- if(log.isVerboseFragmentLog()) {
- log.append("Unknown fragment " + signature.getSignature());
- }
- throw new UnknownFragmentException(signature.getSignature());
- }
- if(bestTemplate == null) {
- AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature.getSignature(), log);
- List candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature(), new AsmSynthesisPath());
- if(candidates.size() == 0) {
- if(log.isVerboseFragmentLog()) {
- log.append("Unknown fragment " + signature.toString());
- }
- bestFragmentCache.put(signature.getSignature(), UNKNOWN);
- throw new UnknownFragmentException(signature.getSignature());
- }
- double minScore = Double.MAX_VALUE;
- double maxScore = Double.MIN_VALUE;
- AsmFragmentTemplate maxTemplate = null;
- for(AsmFragmentTemplate candidateTemplate : candidates) {
- AsmFragment candidateFragment = new AsmFragment(
- signature.getProgram(),
- signature.getSignature(),
- signature.getCodeScope(),
- candidateTemplate,
- signature.getBindings());
- AsmProgram candidateAsm = new AsmProgram();
- candidateAsm.startSegment(null, signature.toString());
- candidateFragment.generate(candidateAsm);
- double score = candidateAsm.getCycles();
- if(score < minScore) {
- minScore = score;
- bestTemplate = candidateTemplate;
- }
- if(score > maxScore) {
- maxScore = score;
- maxTemplate = candidateTemplate;
- }
- }
- if(log.isVerboseFragmentLog()) {
- log.append("Found fragment " + bestTemplate.getName() + " score: " + minScore + " from " + candidates.size() + " candidates");
- }
- bestFragmentCache.put(signature.getSignature(), bestTemplate);
- }
- // Count usages
- AsmFragmentUsages.incUsage(bestTemplate);
- // Return the resulting fragment instance
- return new AsmFragment(
- signature.getProgram(),
- signature.getSignature(),
- signature.getCodeScope(),
- bestTemplate,
- signature.getBindings());
- }
-
- /**
- * Look for a fragment on the disk.
- *
- * @param signature The fragment signature
- * @return The fragment file contents. Null if the fragment is not on the disk.
- */
- private static CharStream loadFragment(String signature) {
- ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
- URL fragmentUrl = classLoader.getResource("dk/camelot64/kickc/fragment/asm/" + signature + ".asm");
- if(fragmentUrl == null) {
- return null;
- }
- try {
- InputStream fragmentStream = fragmentUrl.openStream();
- return CharStreams.fromStream(fragmentStream);
- } catch(IOException e) {
- throw new RuntimeException("Error loading fragment file " + fragmentUrl);
- }
- }
-
- static File[] allFragmentFiles() {
- ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
- String path = classLoader.getResource("dk/camelot64/kickc/fragment/asm/").getPath();
- return new File(path).listFiles((dir, name) -> name.endsWith(".asm"));
-
- }
-
- private static List getFragmentSyntheses() {
- if(fragmentSyntheses == null) {
- fragmentSyntheses = initFragmentSyntheses();
- }
- return fragmentSyntheses;
- }
-
- private static List initFragmentSyntheses() {
- Map mapZ = new LinkedHashMap<>();
- mapZ.put("z2", "z1");
- mapZ.put("z3", "z2");
- Map mapZ2 = new LinkedHashMap<>();
- mapZ2.put("z3", "z1");
- Map mapZ3 = new LinkedHashMap<>();
- mapZ3.put("z3", "z2");
- Map mapC = new LinkedHashMap<>();
- mapC.put("c2", "c1");
- mapC.put("c3", "c2");
- Map mapC3 = new LinkedHashMap<>();
- mapC3.put("c3", "c2");
- Map mapZC = new LinkedHashMap<>();
- mapZC.putAll(mapZ);
- mapZC.putAll(mapC);
- Map mapSToU = new LinkedHashMap<>();
- mapSToU.put("vbsz1", "vbuz1");
- mapSToU.put("vbsz2", "vbuz2");
- mapSToU.put("vbsz3", "vbuz3");
- mapSToU.put("vbsc1", "vbuc1");
- mapSToU.put("vbsc2", "vbuc2");
- mapSToU.put("vbsc3", "vbuc3");
- mapSToU.put("vbsaa", "vbuaa");
- mapSToU.put("vbsxx", "vbuxx");
- mapSToU.put("vbsyy", "vbuyy");
- mapSToU.put("vwsz1", "vwuz1");
- mapSToU.put("vwsz2", "vwuz2");
- mapSToU.put("vwsz3", "vwuz3");
- mapSToU.put("vwsc1", "vwuc1");
- mapSToU.put("vwsc2", "vwuc2");
- mapSToU.put("vwsc3", "vwuc3");
-
- List synths = new ArrayList<>();
-
- // NEW STYLE REWRITES - Utilizes that all combinations are tried
-
- // Replace first AA with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2", null, null));
- // Replace two AAs with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2xx$3", null, null));
- // Replace second (not first) AA with XX
- synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1aa$2xx$3", null, null));
-
- // Replace first AA with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2", null, null));
- // Replace two AAs with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2yy$3", null, null));
- // Replace second (not first) AA with YY
- synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1aa$2yy$3", null, null));
-
- // Replace first XX with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2", null, null));
- // Replace two XXs with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2aa$3", null, null));
- // Replace second (not first) XX with AA
- synths.add(new AsmFragmentSynthesis("(.*)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1xx$2aa$3", null, null));
-
- // Replace first YY with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2", null, null));
- // Replace two YYs with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2aa$3", null, null));
- // Replace second (not first) YY with AA
- synths.add(new AsmFragmentSynthesis("(.*)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1yy$2aa$3", null, null));
-
- // Replace Z1 with AA (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2", null, mapZ));
- // Replace two Z1s with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2aa$3", null, mapZ));
- // Replace first (not second) Z1 with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1aa$2z1$3", null, null));
- // Replace second (not first) Z1 with AA
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1z1$2aa$3", null, null));
-
- // Replace Z1 with YY (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2", null, mapZ));
- // Replace two Z1s with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2yy$3", null, mapZ));
- // Replace first (not second) Z1 with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1yy$2z1$3", null, null));
- // Replace second (not first) Z1 with YY
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1z1$2yy$3", null, null));
-
- // Replace Z1 with XX (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2", null, mapZ));
- // Replace two Z1s with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2xx$3", null, mapZ));
- // Replace first (not second) Z1 with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1xx$2z1$3", null, null));
- // Replace second (not first) Z1 with XX
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1z1$2xx$3", null, null));
-
- // Replace Z2 with AA (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2", null, mapZ3));
- // Replace two Z2s with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2aa$3", null, mapZ3));
- // Replace first (of 2) Z2 with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1aa$2z2$3", null, null));
- // Replace second (of 2) Z2 with AA
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1z2$2aa$3", null, null));
-
- // Replace Z2 with YY (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2", null, mapZ3));
- // Replace two Z2s with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2yy$3", null, mapZ3));
- // Replace first (of 2) Z2 with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1yy$2z2$3", null, null));
- // Replace second (of 2) Z2 with YY
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1z2$2yy$3", null, null));
-
- // Replace Z2 with XX(only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2", null, mapZ3));
- // Replace two Z2s with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2xx$3", null, mapZ3));
- // Replace first (of 2) Z2 with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1xx$2z2$3", null, null));
- // Replace second (of 2) Z2 with XX
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1z2$2xx$3", null, null));
-
- // Rewrite comparisons < to >
- //synths.add(new AsmFragmentSynthesis("(.*)_gt_(.*)_then_(.*)", null, null, "$2_lt_$1_then_$3", null, null));
- // Rewrite comparisons > to <
- //synths.add(new AsmFragmentSynthesis("(.*)_lt_(.*)_then_(.*)", null, null, "$2_gt_$1_then_$3", null, null));
- // Rewrite comparisons <= to >=
- //synths.add(new AsmFragmentSynthesis("(.*)_le_(.*)_then_(.*)", null, null, "$2_ge_$1_then_$3", null, null));
- // Rewrite comparisons >= to <=
- //synths.add(new AsmFragmentSynthesis("(.*)_ge_(.*)_then_(.*)", null, null, "$2_le_$1_then_$3", null, null));
- // Rewrite comparisons swap ==
- //synths.add(new AsmFragmentSynthesis("(.*)_eq_(.*)_then_(.*)", null, null, "$2_eq_$1_then_$3", null, null));
- // Rewrite comparisons swap !=
- //synths.add(new AsmFragmentSynthesis("(.*)_neq_(.*)_then_(.*)", null, null, "$2_neq_$1_then_$3", null, null));
-
-
- // OLD STYLE REWRITES - written when only one rule could be taken
-
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.aa)", ".*=vb.aa_.*", null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.xx)", ".*=vb.[ax][ax]_.*", null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.yy)", ".*=vb.[axy][axy]_.*", null, "$1=$4_$3_$2", null, null));
-
- synths.add(new AsmFragmentSynthesis("vbuxx=(.*)", null, null, "vbuaa=$1", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("vbsxx=(.*)", null, null, "vbsaa=$1", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("vbuyy=(.*)", null, null, "vbuaa=$1", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("vbsyy=(.*)", null, null, "vbsaa=$1", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("vbuz1=(.*)", ".*=.*vb.z1.*", null, "vbuaa=$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1=(.*)", ".*=.*vb.z1.*", null, "vbsaa=$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1}\n", mapC));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1}\n", null));
- synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*)", ".*z1.*z1.*", null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*z1.*)", null, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", null));
-
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*)", ".*z1.*z1.*|.*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},y\n", mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x\n", mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y\n", mapZ2));
-
- synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}\n", "$1=vb$2aa$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*=.*yy.*", "ldy #0\n" + "lda ({z1}),y\n", "$1=vb$2aa$3", null, mapZ));
-
- // Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*xx.*", "tax\n", "$1=$2_derefidx_vbuxx$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*yy.*", "tay\n", "$1=$2_derefidx_vbuyy$3", null, null));
- // Convert array indexing with zero page to x/y register by prefixing ldx z1 / ldy z1 ( ..._derefidx_vbuzn... -> ..._derefidx_vbuxx... / ..._derefidx_vbuyy... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*xx.*|.*z1.*z1.*", "ldx {z1}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*yy.*|.*z1.*z1.*", "ldy {z1}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*xx.*|.*z2.*z2.*", "ldx {z2}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*yy.*|.*z2.*z2.*", "ldy {z2}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*yy.*", "ldy {z3}\n", "$1=$2_derefidx_vbuyy$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*xx.*", "ldx {z3}\n", "$1=$2_derefidx_vbuxx$3", null, null));
- // Convert array indexing twice with A/zp1/zp2 to X/Y register with a ldx/ldy prefix ( ..._derefidx_vbunn..._derefidx_vbunn... -> ..._derefidx_vbuxx..._derefidx_vbuxx... )
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z2}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z2}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*c1.*)", ".*z1.*z1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*z1.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapC));
-
- // Convert X/Y-based array indexing of a constant pointer into A-register by prefixing lda cn,x / lda cn,y ( ...pb.c1_derefidx_vbuxx... / ...pb.c1_derefidx_vbuyy... -> ...vb.aa... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*c1.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*c1.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, mapC3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*c2.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, mapC3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*c2.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
-
- // Convert zeropage/constants/X/Y in assignments to A-register using LDA/TXA/TYA prefix
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbuaa$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbsaa$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, mapZ3));
-
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbsaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuyy", ".*=.*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsyy", ".*=-*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbsaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbuaa", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbsaa", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz2", ".*=.*aa.*|.*z2.*z2.*", "lda {z2}\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz3", ".*=.*aa.*|.*z3.*z3.*", "lda {z3}\n", "$1=$2_vbuaa", null, null));
-
- synths.add(new AsmFragmentSynthesis("vbuz1=vbuz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbuaa=vbuaa$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1=vbsz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbsaa=vbsaa$1", "sta {z1}\n", mapZ));
-
- synths.add(new AsmFragmentSynthesis("vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbuaa_$1_$2", null, mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbsaa_$1_$2", null, mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*", "lda {c1}\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)z1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*vb.yy.*|.*z1.*z1.*", "ldy #0\n" + "lda ({z1}),y\n", "vb$1aa_$2_$3", null, mapZ));
-
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(.*)", ".*z1.*z1.*|.*.yy.*", "ldy {z1}\n", "$1_derefidx_vbuyy_$2", null, mapZ));
-
-
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*z1.*z1.*|.*vb.xx.*", "ldx {z1}\n", "$1_derefidx_vbuxx_$2_$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, null));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, null));
-
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.aa)_then_(.*)", ".*vb.aa.*_ge.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_ge.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_ge.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.aa)_then_(.*)", ".*vb.aa.*_lt.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_lt.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_lt.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.aa)_then_(.*)", ".*vb.aa.*_gt.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_gt.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_gt.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.aa)_then_(.*)", ".*vb.aa.*_le.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_le.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_le.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.aa)_then_(.*)", ".*vb.aa.*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.aa)_then_(.*)", ".*vb.aa.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
-
- // Use unsigned ASM to synthesize signed ASM ( ...vbs... -> ...vbu... )
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(eq|neq)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(plus|band|bxor|bor)_(vbsz.|csoby.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2_$3_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=_(inc|dec)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=_$2_$3", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vwsz.|vwsc.)_(eq|neq)_(vwsz.|vwsc.)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.|vwsc.)", null, null, "$1=$2", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(v.sz.)=(v.s..)_(band|bxor|bor)_(v.s..)", null, null, "$1=$2_$3_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbuz.|vbuaa|vbuxx|vbuyy)=_(lo|hi)_vws(z.|c.)", null, null, "$1=_$2_vwu$3", null, mapSToU));
-
- // Use constant word ASM to synthesize unsigned constant byte ASM ( ...vb.c... -> vw.c... )
- synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwuc$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwuz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwuz.)", null, null, "$1=vwuc$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwsc$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwsz.)", null, null, "$1=vwsc$2_$3_$4", null, null));
-
- // Move constant words to the end of the ASM signature for symmetric operators ( ...vw.c...vw.z... -> ...vw.z...vw.c... )
- synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuc.)_(plus|band|bxor|bor)_(vwuz.)", null, null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsc.)_(plus|band|bxor|bor)_(vwsz.)", null, null, "$1=$4_$3_$2", null, null));
-
- // Use Z1/Z2 ASM to synthesize Z1-only code ( ...z1...z1... -> ...z1...z2... )
- synths.add(new AsmFragmentSynthesis("(v..)z1=(v..)z1_(plus|minus|band|bxor|bor)_(.*)", ".*z2.*", null, "$1z1=$2z2_$3_$4", null, mapZ, false));
- synths.add(new AsmFragmentSynthesis("(v..)z1=(.*)_(plus|minus|band|bxor|bor)_(v..)z1", ".*z2.*", null, "$1z1=$2_$3_$4z2", null, mapZ, false));
- synths.add(new AsmFragmentSynthesis("(v..)z1=_(neg|lo|hi)_(v..)z1", ".*z2.*", null, "$1z1=_$2_$3z2", null, mapZ, false));
-
- // Convert INC/DEC to +1/-1 ( ..._inc_xxx... -> ...xxx_plus_1_... / ..._dec_xxx... -> ...xxx_minus_1_... )
- synths.add(new AsmFragmentSynthesis("vb(.)aa=_inc_(.*)", null, null, "vb$1aa=$2_plus_1", null, null));
- synths.add(new AsmFragmentSynthesis("vb(.)aa=_dec_(.*)", null, null, "vb$1aa=$2_minus_1", null, null));
-
- // Synthesize XX/YY using AA
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbsaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbsaa$3", null, null));
- // Synthesize constants using AA
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbuaa$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbsaa$3", null, mapC));
-
- // Synthesize some constant pointers as constant words
- synths.add(new AsmFragmentSynthesis("(.*)_(lt|gt|le|ge|eq|neq)_p..([cz].)_then_(.*)", null, null, "$1_$2_vwu$3_then_$4", null, null));
- synths.add(new AsmFragmentSynthesis("p..([cz].)_(lt|gt|le|ge|eq|neq)_(.*)", null, null, "vwu$1_$2_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([zc].)", null, null, "$1=vwu$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(plus|minus|bor|bxor)_p..([cz].)", null, null, "$1=$2_$3_vwu$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(plus|minus|bor|bxor)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("p..([cz].)=(.*)_(sethi|setlo|plus|minus)_(.*)", null, null, "vwu$1=$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(sethi|setlo|plus|minus)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
-
- return synths;
- }
-
- /**
- * The synthesis path describes the different signatures being attempted to synthesize a fragment.
- * Used to avoid infinite loops during synthesis.
- */
- static class AsmSynthesisPath {
-
- private ArrayDeque signatures;
-
- public AsmSynthesisPath() {
- this.signatures = new ArrayDeque<>();
- }
-
- private AsmSynthesisPath(ArrayDeque signatures) {
- this.signatures = signatures;
- }
-
- AsmSynthesisPath add(String signature) {
- ArrayDeque signatures = new ArrayDeque<>(this.signatures);
- signatures.add(signature);
- return new AsmSynthesisPath(signatures);
- }
-
- boolean has(String signature) {
- return signatures.contains(signature);
- }
-
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder();
- boolean first = true;
- for(String signature : signatures) {
- if(first) {
- first = false;
- } else {
- str.append(" < ");
- }
- str.append(signature);
- }
- return str.toString();
- }
- }
-
- /**
- * Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
- *
- * The synthesizer tries a lot of different combinations and keeps track of what has already been attempted.
- */
- static class AsmFragmentTemplateSynthesizer {
-
- /** Signature of the fragment being synthesized. */
- private String creating;
-
- /** The log. */
- private CompileLog log;
-
- AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
- this.creating = creating;
- this.log = log;
- }
-
- List loadOrSynthesizeFragment(String signature, AsmSynthesisPath path) {
- if(path.has(signature)) {
- // Synthesis loop - stop it here
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Stopping synthesis loop at " + signature);
- }
- return new ArrayList<>();
- }
- // Add the current signature to the path
- path = path.add(signature);
- if(fragmentTemplateCache.get(signature) != null) {
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Using cached " + signature);
- }
- return fragmentTemplateCache.get(signature);
- }
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Attempting " + signature);
- }
- List candidates = new ArrayList<>();
- // Synthesize the fragment from other fragments
- List synths = getFragmentSyntheses();
- for(AsmFragmentSynthesis synth : synths) {
- List synthesized = synth.synthesize(signature, path, this);
- if(synthesized != null) {
- if(log.isVerboseFragmentLog() && synthesized.size() > 0) {
- log.append("Finding fragment " + path.toString() + " - Successfully synthesized " + synthesized.size() + " fragments ");
- }
- candidates.addAll(synthesized);
- }
- }
- // Load the fragment from disk
- CharStream fragmentCharStream = loadFragment(signature);
- if(fragmentCharStream != null) {
- try {
- String body = fragmentCharStream.toString();
- candidates.add(new AsmFragmentTemplate(signature, body));
-
- } catch(StringIndexOutOfBoundsException e) {
- throw new RuntimeException("Problem reading fragment file " + signature, e);
- }
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Successfully loaded " + signature + ".asm");
- }
- }
- if(candidates.size() == 0) {
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - No synthesis/file found!");
- }
- }
- fragmentTemplateCache.put(signature, candidates);
- return candidates;
- }
-
- public String getCreating() {
- return creating;
- }
-
- public CompileLog getLog() {
- return log;
- }
- }
-
- public static class UnknownFragmentException extends RuntimeException {
-
- private String fragmentSignature;
-
- UnknownFragmentException(String signature) {
- super("Fragment not found " + signature );
- this.fragmentSignature = signature;
- }
-
- public String getFragmentSignature() {
- return fragmentSignature;
- }
- }
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
index 6b24feefc..bb3d563b0 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
@@ -19,7 +19,7 @@ public class AsmFragmentTemplate {
/** The parsed ASM lines. Initially null. Will be non-null, is the template is ever used to generate ASM code. */
private KickCParser.AsmLinesContext bodyAsm;
/** The synthesis that created the fragment. null if the fragment template was loaded. */
- private AsmFragmentSynthesis synthesis;
+ private AsmFragmentTemplateSynthesisRule synthesis;
/** The sub fragment template that the synthesis modified to create this. null if the fragment template was loaded. */
private AsmFragmentTemplate subFragment;
@@ -30,7 +30,7 @@ public class AsmFragmentTemplate {
this.file = true;
}
- AsmFragmentTemplate(String signature, String body, AsmFragmentSynthesis synthesis, AsmFragmentTemplate subFragment) {
+ AsmFragmentTemplate(String signature, String body, AsmFragmentTemplateSynthesisRule synthesis, AsmFragmentTemplate subFragment) {
this.signature = signature;
this.body = body;
this.synthesis = synthesis;
@@ -89,7 +89,7 @@ public class AsmFragmentTemplate {
return file;
}
- public AsmFragmentSynthesis getSynthesis() {
+ public AsmFragmentTemplateSynthesisRule getSynthesis() {
return synthesis;
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateManager.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateManager.java
new file mode 100644
index 000000000..e94452ecf
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateManager.java
@@ -0,0 +1,570 @@
+package dk.camelot64.kickc.fragment;
+
+import dk.camelot64.kickc.CompileLog;
+import dk.camelot64.kickc.asm.AsmProgram;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CharStreams;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * Provides fragments from their signature.
+ *
+ * The first priority is loading a fragment file from the fragment-folder.
+ * If no fragment file is found for the signature the manager attempts to synthesise a fragment from another fragment.
+ */
+public class AsmFragmentTemplateManager {
+
+ /** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. */
+ private static Map bestFragmentCache = new HashMap<>();
+
+ /** Caches all asm fragment templates for all encountered signatures. */
+ private static Map> fragmentTemplateCache = new LinkedHashMap<>();
+
+ /** Special singleton representing that the fragment can not be synthesized or loaded. */
+ private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
+ /**
+ * All the synthesize rules available.
+ */
+ private static List fragmentSyntheses;
+
+ static Map> getFragmentTemplateCache() {
+ return fragmentTemplateCache;
+ }
+
+ public static AsmFragmentInstance getFragment(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
+ AsmFragmentTemplate bestTemplate = bestFragmentCache.get(instanceSpec.getSignature());
+ if(bestTemplate == UNKNOWN) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Unknown fragment " + instanceSpec.getSignature());
+ }
+ throw new UnknownFragmentException(instanceSpec);
+ }
+ if(bestTemplate == null) {
+ AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(instanceSpec.getSignature(), log);
+ List candidates = synthesizer.loadOrSynthesizeFragment(instanceSpec.getSignature(), new AsmSynthesisPath());
+ if(candidates.size() == 0) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Unknown fragment " + instanceSpec.getSignature());
+ }
+ bestFragmentCache.put(instanceSpec.getSignature(), UNKNOWN);
+ throw new UnknownFragmentException(instanceSpec);
+ }
+ double minScore = Double.MAX_VALUE;
+ double maxScore = Double.MIN_VALUE;
+ AsmFragmentTemplate maxTemplate = null;
+ for(AsmFragmentTemplate candidateTemplate : candidates) {
+ AsmFragmentInstance candidateFragment = new AsmFragmentInstance(
+ instanceSpec.getProgram(),
+ instanceSpec.getSignature(),
+ instanceSpec.getCodeScope(),
+ candidateTemplate,
+ instanceSpec.getBindings());
+ AsmProgram candidateAsm = new AsmProgram();
+ candidateAsm.startSegment(null, instanceSpec.toString());
+ candidateFragment.generate(candidateAsm);
+ double score = candidateAsm.getCycles();
+ if(score < minScore) {
+ minScore = score;
+ bestTemplate = candidateTemplate;
+ }
+ if(score > maxScore) {
+ maxScore = score;
+ maxTemplate = candidateTemplate;
+ }
+ }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Found fragment " + bestTemplate.getName() + " score: " + minScore + " from " + candidates.size() + " candidates");
+ }
+ bestFragmentCache.put(instanceSpec.getSignature(), bestTemplate);
+ }
+ // Count usages
+ AsmFragmentTemplateUsages.incUsage(bestTemplate);
+ // Return the resulting fragment instance
+ return new AsmFragmentInstance(
+ instanceSpec.getProgram(),
+ instanceSpec.getSignature(),
+ instanceSpec.getCodeScope(),
+ bestTemplate,
+ instanceSpec.getBindings());
+ }
+
+ /**
+ * Look for a fragment on the disk.
+ *
+ * @param signature The fragment signature
+ * @return The fragment file contents. Null if the fragment is not on the disk.
+ */
+ private static CharStream loadFragment(String signature) {
+ ClassLoader classLoader = AsmFragmentTemplateManager.class.getClassLoader();
+ URL fragmentUrl = classLoader.getResource("dk/camelot64/kickc/fragment/asm/" + signature + ".asm");
+ if(fragmentUrl == null) {
+ return null;
+ }
+ try {
+ InputStream fragmentStream = fragmentUrl.openStream();
+ return CharStreams.fromStream(fragmentStream);
+ } catch(IOException e) {
+ throw new RuntimeException("Error loading fragment file " + fragmentUrl);
+ }
+ }
+
+ static File[] allFragmentFiles() {
+ ClassLoader classLoader = AsmFragmentTemplateManager.class.getClassLoader();
+ String path = classLoader.getResource("dk/camelot64/kickc/fragment/asm/").getPath();
+ return new File(path).listFiles((dir, name) -> name.endsWith(".asm"));
+
+ }
+
+ private static List getFragmentSyntheses() {
+ if(fragmentSyntheses == null) {
+ fragmentSyntheses = initFragmentSyntheses();
+ }
+ return fragmentSyntheses;
+ }
+
+ private static List initFragmentSyntheses() {
+ Map mapZ = new LinkedHashMap<>();
+ mapZ.put("z2", "z1");
+ mapZ.put("z3", "z2");
+ Map mapZ2 = new LinkedHashMap<>();
+ mapZ2.put("z3", "z1");
+ Map mapZ3 = new LinkedHashMap<>();
+ mapZ3.put("z3", "z2");
+ Map mapC = new LinkedHashMap<>();
+ mapC.put("c2", "c1");
+ mapC.put("c3", "c2");
+ Map mapC3 = new LinkedHashMap<>();
+ mapC3.put("c3", "c2");
+ Map mapZC = new LinkedHashMap<>();
+ mapZC.putAll(mapZ);
+ mapZC.putAll(mapC);
+ Map mapSToU = new LinkedHashMap<>();
+ mapSToU.put("vbsz1", "vbuz1");
+ mapSToU.put("vbsz2", "vbuz2");
+ mapSToU.put("vbsz3", "vbuz3");
+ mapSToU.put("vbsc1", "vbuc1");
+ mapSToU.put("vbsc2", "vbuc2");
+ mapSToU.put("vbsc3", "vbuc3");
+ mapSToU.put("vbsaa", "vbuaa");
+ mapSToU.put("vbsxx", "vbuxx");
+ mapSToU.put("vbsyy", "vbuyy");
+ mapSToU.put("vwsz1", "vwuz1");
+ mapSToU.put("vwsz2", "vwuz2");
+ mapSToU.put("vwsz3", "vwuz3");
+ mapSToU.put("vwsc1", "vwuc1");
+ mapSToU.put("vwsc2", "vwuc2");
+ mapSToU.put("vwsc3", "vwuc3");
+
+ List synths = new ArrayList<>();
+
+ // NEW STYLE REWRITES - Utilizes that all combinations are tried
+
+ // Replace first AA with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2", null, null));
+ // Replace two AAs with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2xx$3", null, null));
+ // Replace second (not first) AA with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1aa$2xx$3", null, null));
+
+ // Replace first AA with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2", null, null));
+ // Replace two AAs with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2yy$3", null, null));
+ // Replace second (not first) AA with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1aa$2yy$3", null, null));
+
+ // Replace first XX with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2", null, null));
+ // Replace two XXs with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2aa$3", null, null));
+ // Replace second (not first) XX with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1xx$2aa$3", null, null));
+
+ // Replace first YY with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2", null, null));
+ // Replace two YYs with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2aa$3", null, null));
+ // Replace second (not first) YY with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1yy$2aa$3", null, null));
+
+ // Replace Z1 with AA (only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2", null, mapZ));
+ // Replace two Z1s with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2aa$3", null, mapZ));
+ // Replace first (not second) Z1 with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1aa$2z1$3", null, null));
+ // Replace second (not first) Z1 with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1z1$2aa$3", null, null));
+
+ // Replace Z1 with YY (only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2", null, mapZ));
+ // Replace two Z1s with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2yy$3", null, mapZ));
+ // Replace first (not second) Z1 with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1yy$2z1$3", null, null));
+ // Replace second (not first) Z1 with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1z1$2yy$3", null, null));
+
+ // Replace Z1 with XX (only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2", null, mapZ));
+ // Replace two Z1s with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2xx$3", null, mapZ));
+ // Replace first (not second) Z1 with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1xx$2z1$3", null, null));
+ // Replace second (not first) Z1 with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1z1$2xx$3", null, null));
+
+ // Replace Z2 with AA (only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2", null, mapZ3));
+ // Replace two Z2s with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2aa$3", null, mapZ3));
+ // Replace first (of 2) Z2 with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1aa$2z2$3", null, null));
+ // Replace second (of 2) Z2 with AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1z2$2aa$3", null, null));
+
+ // Replace Z2 with YY (only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2", null, mapZ3));
+ // Replace two Z2s with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2yy$3", null, mapZ3));
+ // Replace first (of 2) Z2 with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1yy$2z2$3", null, null));
+ // Replace second (of 2) Z2 with YY
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1z2$2yy$3", null, null));
+
+ // Replace Z2 with XX(only one)
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2", null, mapZ3));
+ // Replace two Z2s with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2xx$3", null, mapZ3));
+ // Replace first (of 2) Z2 with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1xx$2z2$3", null, null));
+ // Replace second (of 2) Z2 with XX
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1z2$2xx$3", null, null));
+
+ // Rewrite comparisons < to >
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_gt_(.*)_then_(.*)", null, null, "$2_lt_$1_then_$3", null, null));
+ // Rewrite comparisons > to <
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_lt_(.*)_then_(.*)", null, null, "$2_gt_$1_then_$3", null, null));
+ // Rewrite comparisons <= to >=
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_le_(.*)_then_(.*)", null, null, "$2_ge_$1_then_$3", null, null));
+ // Rewrite comparisons >= to <=
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_ge_(.*)_then_(.*)", null, null, "$2_le_$1_then_$3", null, null));
+ // Rewrite comparisons swap ==
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_eq_(.*)_then_(.*)", null, null, "$2_eq_$1_then_$3", null, null));
+ // Rewrite comparisons swap !=
+ //synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_neq_(.*)_then_(.*)", null, null, "$2_neq_$1_then_$3", null, null));
+
+
+ // OLD STYLE REWRITES - written when only one rule could be taken
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_(band|bor|bxor|plus)_(vb.aa)", ".*=vb.aa_.*", null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_(band|bor|bxor|plus)_(vb.xx)", ".*=vb.[ax][ax]_.*", null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_(band|bor|bxor|plus)_(vb.yy)", ".*=vb.[axy][axy]_.*", null, "$1=$4_$3_$2", null, null));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbuxx=(.*)", null, null, "vbuaa=$1", "tax\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbsxx=(.*)", null, null, "vbsaa=$1", "tax\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbuyy=(.*)", null, null, "vbuaa=$1", "tay\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbsyy=(.*)", null, null, "vbsaa=$1", "tay\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbuz1=(.*)", ".*=.*vb.z1.*", null, "vbuaa=$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbsz1=(.*)", ".*=.*vb.z1.*", null, "vbsaa=$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)c1=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1}\n", mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)c1=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1}\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pbuz1=(.*)", ".*z1.*z1.*", null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pbuz1=(.*z1.*)", null, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", null));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuz1=(.*)", ".*z1.*z1.*|.*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},y\n", mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x\n", mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y\n", mapZ2));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}\n", "$1=vb$2aa$3", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*=.*yy.*", "ldy #0\n" + "lda ({z1}),y\n", "$1=vb$2aa$3", null, mapZ));
+
+ // Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*xx.*", "tax\n", "$1=$2_derefidx_vbuxx$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*yy.*", "tay\n", "$1=$2_derefidx_vbuyy$3", null, null));
+ // Convert array indexing with zero page to x/y register by prefixing ldx z1 / ldy z1 ( ..._derefidx_vbuzn... -> ..._derefidx_vbuxx... / ..._derefidx_vbuyy... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*xx.*|.*z1.*z1.*", "ldx {z1}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*yy.*|.*z1.*z1.*", "ldy {z1}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*xx.*|.*z2.*z2.*", "ldx {z2}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ3));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*yy.*|.*z2.*z2.*", "ldy {z2}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ3));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*yy.*", "ldy {z3}\n", "$1=$2_derefidx_vbuyy$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*xx.*", "ldx {z3}\n", "$1=$2_derefidx_vbuxx$3", null, null));
+ // Convert array indexing twice with A/zp1/zp2 to X/Y register with a ldx/ldy prefix ( ..._derefidx_vbunn..._derefidx_vbunn... -> ..._derefidx_vbuxx..._derefidx_vbuxx... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "tax\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "tay\n", null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z1}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z1}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z2}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z2}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuz1=(.*c1.*)", ".*z1.*z1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuz1=(.*z1.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapC));
+
+ // Convert X/Y-based array indexing of a constant pointer into A-register by prefixing lda cn,x / lda cn,y ( ...pb.c1_derefidx_vbuxx... / ...pb.c1_derefidx_vbuyy... -> ...vb.aa... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*c1.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*c1.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, mapC3));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*c2.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, mapC3));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*c2.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
+
+ // Convert zeropage/constants/X/Y in assignments to A-register using LDA/TXA/TYA prefix
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbuaa$3", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbsaa$3", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, mapZ3));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, mapZ3));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbuxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbsxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbsaa", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbuyy", ".*=.*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbsyy", ".*=-*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbsaa", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbuz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbuaa", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbsz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbsaa", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbuz2", ".*=.*aa.*|.*z2.*z2.*", "lda {z2}\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_vbuz3", ".*=.*aa.*|.*z3.*z3.*", "lda {z3}\n", "$1=$2_vbuaa", null, null));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbuz1=vbuz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbuaa=vbuaa$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbsz1=vbsz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbsaa=vbsaa$1", "sta {z1}\n", mapZ));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbuaa_$1_$2", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vbsz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbsaa_$1_$2", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)c1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*", "lda {c1}\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)z1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*vb.yy.*|.*z1.*z1.*", "ldy #0\n" + "lda ({z1}),y\n", "vb$1aa_$2_$3", null, mapZ));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz1_(.*)", ".*z1.*z1.*|.*.yy.*", "ldy {z1}\n", "$1_derefidx_vbuyy_$2", null, mapZ));
+
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_derefidx_vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*z1.*z1.*|.*vb.xx.*", "ldx {z1}\n", "$1_derefidx_vbuxx_$2_$3", null, mapZ));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, null));
+
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_ge_(vb.aa)_then_(.*)", ".*vb.aa.*_ge.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_ge_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_ge.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_ge_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_ge.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_lt_(vb.aa)_then_(.*)", ".*vb.aa.*_lt.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_lt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_lt.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_lt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_lt.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_gt_(vb.aa)_then_(.*)", ".*vb.aa.*_gt.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_gt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_gt.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_gt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_gt.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_le_(vb.aa)_then_(.*)", ".*vb.aa.*_le.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_le_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_le.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_le_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_le.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_neq_(vb.aa)_then_(.*)", ".*vb.aa.*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_neq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_neq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_eq_(vb.aa)_then_(.*)", ".*vb.aa.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_eq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_eq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+
+ // Use unsigned ASM to synthesize signed ASM ( ...vbs... -> ...vbu... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(eq|neq)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(plus|band|bxor|bor)_(vbsz.|csoby.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2_$3_$4", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=_(inc|dec)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=_$2_$3", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwsz.|vwsc.)_(eq|neq)_(vwsz.|vwsc.)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwsz.)=(vwsz.|vwsc.)", null, null, "$1=$2", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(v.sz.)=(v.s..)_(band|bxor|bor)_(v.s..)", null, null, "$1=$2_$3_$4", null, mapSToU));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vbuz.|vbuaa|vbuxx|vbuyy)=_(lo|hi)_vws(z.|c.)", null, null, "$1=_$2_vwu$3", null, mapSToU));
+
+ // Use constant word ASM to synthesize unsigned constant byte ASM ( ...vb.c... -> vw.c... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwuz.)=(vwuz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwuc$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwuz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwuz.)", null, null, "$1=vwuc$2_$3_$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwsz.)=(vwsz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwsc$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwsz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwsz.)", null, null, "$1=vwsc$2_$3_$4", null, null));
+
+ // Move constant words to the end of the ASM signature for symmetric operators ( ...vw.c...vw.z... -> ...vw.z...vw.c... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwuz.)=(vwuc.)_(plus|band|bxor|bor)_(vwuz.)", null, null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(vwsz.)=(vwsc.)_(plus|band|bxor|bor)_(vwsz.)", null, null, "$1=$4_$3_$2", null, null));
+
+ // Use Z1/Z2 ASM to synthesize Z1-only code ( ...z1...z1... -> ...z1...z2... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("(v..)z1=(v..)z1_(plus|minus|band|bxor|bor)_(.*)", ".*z2.*", null, "$1z1=$2z2_$3_$4", null, mapZ, false));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(v..)z1=(.*)_(plus|minus|band|bxor|bor)_(v..)z1", ".*z2.*", null, "$1z1=$2_$3_$4z2", null, mapZ, false));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(v..)z1=_(neg|lo|hi)_(v..)z1", ".*z2.*", null, "$1z1=_$2_$3z2", null, mapZ, false));
+
+ // Convert INC/DEC to +1/-1 ( ..._inc_xxx... -> ...xxx_plus_1_... / ..._dec_xxx... -> ...xxx_minus_1_... )
+ synths.add(new AsmFragmentTemplateSynthesisRule("vb(.)aa=_inc_(.*)", null, null, "vb$1aa=$2_plus_1", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("vb(.)aa=_dec_(.*)", null, null, "vb$1aa=$2_minus_1", null, null));
+
+ // Synthesize XX/YY using AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbsaa$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbsaa$3", null, null));
+ // Synthesize constants using AA
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbuc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbuaa$3", null, mapC));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)vbsc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbsaa$3", null, mapC));
+
+ // Synthesize some constant pointers as constant words
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_(lt|gt|le|ge|eq|neq)_p..([cz].)_then_(.*)", null, null, "$1_$2_vwu$3_then_$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("p..([cz].)_(lt|gt|le|ge|eq|neq)_(.*)", null, null, "vwu$1_$2_$3", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=p..([zc].)", null, null, "$1=vwu$2", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=(.*)_(plus|minus|bor|bxor)_p..([cz].)", null, null, "$1=$2_$3_vwu$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=p..([cz].)_(plus|minus|bor|bxor)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("p..([cz].)=(.*)_(sethi|setlo|plus|minus)_(.*)", null, null, "vwu$1=$2_$3_$4", null, null));
+ synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=p..([cz].)_(sethi|setlo|plus|minus)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
+
+ return synths;
+ }
+
+ /**
+ * The synthesis path describes the different signatures being attempted to synthesize a fragment.
+ * Used to avoid infinite loops during synthesis.
+ */
+ static class AsmSynthesisPath {
+
+ private ArrayDeque signatures;
+
+ public AsmSynthesisPath() {
+ this.signatures = new ArrayDeque<>();
+ }
+
+ private AsmSynthesisPath(ArrayDeque signatures) {
+ this.signatures = signatures;
+ }
+
+ AsmSynthesisPath add(String signature) {
+ ArrayDeque signatures = new ArrayDeque<>(this.signatures);
+ signatures.add(signature);
+ return new AsmSynthesisPath(signatures);
+ }
+
+ boolean has(String signature) {
+ return signatures.contains(signature);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ boolean first = true;
+ for(String signature : signatures) {
+ if(first) {
+ first = false;
+ } else {
+ str.append(" < ");
+ }
+ str.append(signature);
+ }
+ return str.toString();
+ }
+ }
+
+ /**
+ * Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
+ *
+ * The synthesizer tries a lot of different combinations and keeps track of what has already been attempted.
+ */
+ static class AsmFragmentTemplateSynthesizer {
+
+ /** Signature of the fragment being synthesized. */
+ private String creating;
+
+ /** The log. */
+ private CompileLog log;
+
+ AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
+ this.creating = creating;
+ this.log = log;
+ }
+
+ List loadOrSynthesizeFragment(String signature, AsmSynthesisPath path) {
+ if(path.has(signature)) {
+ // Synthesis loop - stop it here
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Stopping synthesis loop at " + signature);
+ }
+ return new ArrayList<>();
+ }
+ // Add the current signature to the path
+ path = path.add(signature);
+ if(fragmentTemplateCache.get(signature) != null) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Using cached " + signature);
+ }
+ return fragmentTemplateCache.get(signature);
+ }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Attempting " + signature);
+ }
+ List candidates = new ArrayList<>();
+ // Synthesize the fragment from other fragments
+ List synths = getFragmentSyntheses();
+ for(AsmFragmentTemplateSynthesisRule synth : synths) {
+ List synthesized = synth.synthesize(signature, path, this);
+ if(synthesized != null) {
+ if(log.isVerboseFragmentLog() && synthesized.size() > 0) {
+ log.append("Finding fragment " + path.toString() + " - Successfully synthesized " + synthesized.size() + " fragments ");
+ }
+ candidates.addAll(synthesized);
+ }
+ }
+ // Load the fragment from disk
+ CharStream fragmentCharStream = loadFragment(signature);
+ if(fragmentCharStream != null) {
+ try {
+ String body = fragmentCharStream.toString();
+ candidates.add(new AsmFragmentTemplate(signature, body));
+
+ } catch(StringIndexOutOfBoundsException e) {
+ throw new RuntimeException("Problem reading fragment file " + signature, e);
+ }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Successfully loaded " + signature + ".asm");
+ }
+ }
+ if(candidates.size() == 0) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - No synthesis/file found!");
+ }
+ }
+ fragmentTemplateCache.put(signature, candidates);
+ return candidates;
+ }
+
+ public String getCreating() {
+ return creating;
+ }
+
+ public CompileLog getLog() {
+ return log;
+ }
+ }
+
+ public static class UnknownFragmentException extends RuntimeException {
+
+ private AsmFragmentInstanceSpec fragmentInstanceSpec;
+
+ UnknownFragmentException(AsmFragmentInstanceSpec fragmentInstanceSpec) {
+ super("Fragment not found " + fragmentInstanceSpec.getSignature() );
+ this.fragmentInstanceSpec = fragmentInstanceSpec;
+ }
+
+ public String getFragmentSignature() {
+ return fragmentInstanceSpec.getSignature();
+ }
+
+ public String getFragmentDescription() {
+ return fragmentInstanceSpec.toString();
+ }
+
+ public AsmFragmentInstanceSpec getFragmentInstanceSpec() {
+ return fragmentInstanceSpec;
+ }
+ }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java
similarity index 88%
rename from src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java
rename to src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java
index b4ed0ed36..66ae24214 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java
@@ -8,7 +8,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** AsmFragment synthesis mechanism based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings */
-class AsmFragmentSynthesis {
+class AsmFragmentTemplateSynthesisRule {
private String sigMatch;
private String sigAvoid;
@@ -19,7 +19,7 @@ class AsmFragmentSynthesis {
private boolean mapSignature;
private String subSignature;
- AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings, boolean mapSignature) {
+ AsmFragmentTemplateSynthesisRule(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings, boolean mapSignature) {
this.sigMatch = sigMatch;
this.sigAvoid = sigAvoid;
this.asmPrefix = asmPrefix;
@@ -29,7 +29,7 @@ class AsmFragmentSynthesis {
this.mapSignature = mapSignature;
}
- public AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings) {
+ public AsmFragmentTemplateSynthesisRule(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings) {
this(sigMatch, sigAvoid, asmPrefix, sigReplace, asmPostfix, bindMappings, true);
}
@@ -48,7 +48,7 @@ class AsmFragmentSynthesis {
return sigMatch + (sigAvoid == null ? "" : ("/" + sigAvoid));
}
- public List synthesize(String signature, AsmFragmentManager.AsmSynthesisPath path, AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer) {
+ public List synthesize(String signature, AsmFragmentTemplateManager.AsmSynthesisPath path, AsmFragmentTemplateManager.AsmFragmentTemplateSynthesizer synthesizer) {
ArrayList candidates = new ArrayList<>();
if(signature.matches(sigMatch)) {
if(sigAvoid == null || !signature.matches(sigAvoid)) {
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java
similarity index 94%
rename from src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
rename to src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java
index 3d980dce4..349ee2c42 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java
@@ -5,8 +5,8 @@ import dk.camelot64.kickc.CompileLog;
import java.io.File;
import java.util.*;
-/** Statistics for usage of the ASM fragments. Also contains a methos for identifying redundant/unused files. */
-public class AsmFragmentUsages {
+/** Statistics for usage of the ASM fragments. Also contains a methods for identifying redundant/unused files. */
+public class AsmFragmentTemplateUsages {
/** Usage Statistics for fragment templates. */
private static Map fragmentTemplateUsage = new HashMap<>();
@@ -35,10 +35,10 @@ public class AsmFragmentUsages {
*/
public static void logUsages(CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logFileDetails, boolean logAllDetails) {
- Map> fragmentTemplateCache = AsmFragmentManager.getFragmentTemplateCache();
+ Map> fragmentTemplateCache = AsmFragmentTemplateManager.getFragmentTemplateCache();
ArrayList signatures = new ArrayList<>(fragmentTemplateCache.keySet());
Collections.sort(signatures);
- File[] files = AsmFragmentManager.allFragmentFiles();
+ File[] files = AsmFragmentTemplateManager.allFragmentFiles();
if(logRedundantFiles) {
// Find all file fragments that were bested by a synthesized fragment
@@ -71,8 +71,8 @@ public class AsmFragmentUsages {
String fileName = file.getName();
String signature = fileName.substring(0, fileName.length() - 4);
// Try to synthesize the fragment - and check if the synthesis is as good as the file body
- AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentManager.AsmFragmentTemplateSynthesizer(signature, log);
- List templates = synthesizer.loadOrSynthesizeFragment(signature, new AsmFragmentManager.AsmSynthesisPath());
+ AsmFragmentTemplateManager.AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateManager.AsmFragmentTemplateSynthesizer(signature, log);
+ List templates = synthesizer.loadOrSynthesizeFragment(signature, new AsmFragmentTemplateManager.AsmSynthesisPath());
AsmFragmentTemplate fileTemplate = null;
for(AsmFragmentTemplate template : templates) {
if(template.isFile()) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
index 20636df49..1e2e5e661 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
@@ -217,13 +217,13 @@ public class Pass4CodeGeneration {
if(aluState.hasAluAssignment()) {
StatementAssignment assignmentAlu = aluState.getAluAssignment();
if(!(statement instanceof StatementAssignment)) {
- throw new AsmFragment.AluNotApplicableException();
+ throw new AsmFragmentInstance.AluNotApplicableException();
}
StatementAssignment assignment = (StatementAssignment) statement;
- AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program);
- AsmFragment asmFragment = AsmFragmentManager.getFragment(signature, program.getLog());
- asm.getCurrentSegment().setFragment(asmFragment.getFragmentName());
- asmFragment.generate(asm);
+ AsmFragmentInstanceSpec signature = new AsmFragmentInstanceSpec(assignment, assignmentAlu, program);
+ AsmFragmentInstance asmFragmentInstance = AsmFragmentTemplateManager.getFragment(signature, program.getLog());
+ asm.getCurrentSegment().setFragment(asmFragmentInstance.getFragmentName());
+ asmFragmentInstance.generate(asm);
aluState.clear();
return;
}
@@ -247,17 +247,17 @@ public class Pass4CodeGeneration {
if(assignment.getOperator() == null && assignment.getrValue1() == null && isRegisterCopy(lValue, assignment.getrValue2())) {
asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
} else {
- AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program);
- AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature, program.getLog());
- asm.getCurrentSegment().setFragment(asmFragment.getFragmentName());
- asmFragment.generate(asm);
+ AsmFragmentInstanceSpec asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(assignment, program);
+ AsmFragmentInstance asmFragmentInstance = AsmFragmentTemplateManager.getFragment(asmFragmentInstanceSpec, program.getLog());
+ asm.getCurrentSegment().setFragment(asmFragmentInstance.getFragmentName());
+ asmFragmentInstance.generate(asm);
}
}
} else if(statement instanceof StatementConditionalJump) {
- AsmFragmentSignature asmSignature = new AsmFragmentSignature((StatementConditionalJump) statement, block, program, getGraph());
- AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog());
- asm.getCurrentSegment().setFragment(asmFragment.getFragmentName());
- asmFragment.generate(asm);
+ AsmFragmentInstanceSpec asmSignature = new AsmFragmentInstanceSpec((StatementConditionalJump) statement, block, program, getGraph());
+ AsmFragmentInstance asmFragmentInstance = AsmFragmentTemplateManager.getFragment(asmSignature, program.getLog());
+ asm.getCurrentSegment().setFragment(asmFragmentInstance.getFragmentName());
+ asmFragmentInstance.generate(asm);
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
if(genCallPhiEntry) {
@@ -276,8 +276,8 @@ public class Pass4CodeGeneration {
} else if(statement instanceof StatementAsm) {
StatementAsm statementAsm = (StatementAsm) statement;
HashMap bindings = new HashMap<>();
- AsmFragment asmFragment = new AsmFragment(program, "inline", block.getScope(), new AsmFragmentTemplate(statementAsm.getAsmLines()), bindings);
- asmFragment.generate(asm);
+ AsmFragmentInstance asmFragmentInstance = new AsmFragmentInstance(program, "inline", block.getScope(), new AsmFragmentTemplate(statementAsm.getAsmLines()), bindings);
+ asmFragmentInstance.generate(asm);
} else {
throw new RuntimeException("Statement not supported " + statement);
}
@@ -340,10 +340,10 @@ public class Pass4CodeGeneration {
if(isRegisterCopy(lValue, rValue)) {
asm.getCurrentSegment().setFragment("register_copy");
} else {
- AsmFragmentSignature asmSignature = new AsmFragmentSignature(lValue, rValue, program, scope);
- AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog());
- asm.getCurrentSegment().setFragment(asmFragment.getFragmentName());
- asmFragment.generate(asm);
+ AsmFragmentInstanceSpec asmSignature = new AsmFragmentInstanceSpec(lValue, rValue, program, scope);
+ AsmFragmentInstance asmFragmentInstance = AsmFragmentTemplateManager.getFragment(asmSignature, program.getLog());
+ asm.getCurrentSegment().setFragment(asmFragmentInstance.getFragmentName());
+ asmFragmentInstance.generate(asm);
}
}
transition.setGenerated(true);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
index d0a2ac57a..db9113441 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
@@ -2,8 +2,9 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.asm.AsmSegment;
-import dk.camelot64.kickc.fragment.AsmFragment;
-import dk.camelot64.kickc.fragment.AsmFragmentManager;
+import dk.camelot64.kickc.fragment.AsmFragmentInstance;
+import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec;
+import dk.camelot64.kickc.fragment.AsmFragmentTemplateManager;
import dk.camelot64.kickc.model.*;
import java.util.*;
@@ -27,7 +28,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
*/
static void chooseBestUpliftCombination(
RegisterCombinationIterator combinationIterator, int maxCombinations,
- Set unknownFragments,
+ Set unknownFragments,
ScopeRef scope,
Program program
) {
@@ -85,7 +86,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
public static boolean generateCombinationAsm(
RegisterCombination combination,
Program program,
- Set unknownFragments,
+ Set unknownFragments,
ScopeRef scope) {
// Reset register allocation to original zero page allocation
new Pass4RegistersFinalize(program).allocate(false);
@@ -106,8 +107,8 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
// Generate ASM
try {
new Pass4CodeGeneration(program, false).generate();
- } catch(AsmFragmentManager.UnknownFragmentException e) {
- unknownFragments.add(e.getFragmentSignature());
+ } catch(AsmFragmentTemplateManager.UnknownFragmentException e) {
+ unknownFragments.add(e.getFragmentInstanceSpec());
if(program.getLog().isVerboseUplift()) {
StringBuilder msg = new StringBuilder();
msg.append("Uplift attempt [" + (scope == null ? "" : scope) + "] ");
@@ -116,7 +117,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
program.getLog().append(msg.toString());
}
return false;
- } catch(AsmFragment.AluNotApplicableException e) {
+ } catch(AsmFragmentInstance.AluNotApplicableException e) {
if(program.getLog().isVerboseUplift()) {
StringBuilder msg = new StringBuilder();
msg.append("Uplift attempt [" + (scope == null ? "" : scope) + "] ");
@@ -234,7 +235,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
public void performUplift(int maxCombinations) {
// Test uplift combinations to find the best one.
- Set unknownFragments = new LinkedHashSet<>();
+ Set unknownFragments = new LinkedHashSet<>();
List registerUpliftScopes = getProgram().getRegisterUpliftProgram().getRegisterUpliftScopes();
for(RegisterUpliftScope upliftScope : registerUpliftScopes) {
RegisterCombinationIterator combinationIterator = upliftScope.getCombinationIterator(getProgram().getRegisterPotentials());
@@ -248,8 +249,8 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
if(unknownFragments.size() > 0) {
getLog().append("MISSING FRAGMENTS");
- for(String unknownFragment : unknownFragments) {
- getLog().append(" " + unknownFragment);
+ for(AsmFragmentInstanceSpec unknownFragment : unknownFragments) {
+ getLog().append(" " + unknownFragment.toString());
}
}
}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftPotentialRegisterAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftPotentialRegisterAnalysis.java
index c4e2eb227..f075db339 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftPotentialRegisterAnalysis.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftPotentialRegisterAnalysis.java
@@ -2,8 +2,8 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.asm.AsmClobber;
import dk.camelot64.kickc.asm.AsmProgram;
-import dk.camelot64.kickc.fragment.AsmFragment;
-import dk.camelot64.kickc.fragment.AsmFragmentManager;
+import dk.camelot64.kickc.fragment.AsmFragmentInstance;
+import dk.camelot64.kickc.fragment.AsmFragmentTemplateManager;
import dk.camelot64.kickc.model.*;
import java.util.*;
@@ -196,15 +196,15 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
Pass4CodeGeneration.AsmCodegenAluState aluState = new Pass4CodeGeneration.AsmCodegenAluState();
try {
(new Pass4CodeGeneration(getProgram(), false)).generateStatementAsm(asm, block, statement, aluState, false);
- } catch(AsmFragmentManager.UnknownFragmentException e) {
- unknownFragments.add(e.getFragmentSignature());
+ } catch(AsmFragmentTemplateManager.UnknownFragmentException e) {
+ unknownFragments.add(e.getFragmentDescription());
StringBuilder msg = new StringBuilder();
msg.append("Potential register analysis " + statement);
msg.append(" missing fragment " + e.getFragmentSignature());
msg.append(" allocation: ").append(combination.toString());
getLog().append(msg.toString());
continue;
- } catch(AsmFragment.AluNotApplicableException e) {
+ } catch(AsmFragmentInstance.AluNotApplicableException e) {
if(getProgram().getLog().isVerboseUplift()) {
StringBuilder msg = new StringBuilder();
msg.append("Potential register analysis ");
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
index e5cafb65c..718f80f74 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
@@ -1,5 +1,6 @@
package dk.camelot64.kickc.passes;
+import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec;
import dk.camelot64.kickc.model.*;
import java.util.*;
@@ -23,7 +24,7 @@ public class Pass4RegisterUpliftRemains extends Pass2Base {
}
});
- Set unknownFragments = new LinkedHashSet<>();
+ Set unknownFragments = new LinkedHashSet<>();
for(LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
if(equivalenceClass.getRegister().getType().equals(Registers.RegisterType.ZP_BYTE)) {
@@ -37,8 +38,8 @@ public class Pass4RegisterUpliftRemains extends Pass2Base {
if(unknownFragments.size() > 0) {
getLog().append("MISSING FRAGMENTS");
- for(String unknownFragment : unknownFragments) {
- getLog().append(" " + unknownFragment);
+ for(AsmFragmentInstanceSpec unknownFragment : unknownFragments) {
+ getLog().append(" " + unknownFragment.toString());
}
}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java
index fffc542e6..3efebac74 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java
@@ -1,5 +1,6 @@
package dk.camelot64.kickc.passes;
+import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec;
import dk.camelot64.kickc.model.*;
import java.util.HashSet;
@@ -87,7 +88,7 @@ public class Pass4RegisterUpliftStatic extends Pass2Base {
boolean success = Pass4RegisterUpliftCombinations.generateCombinationAsm(
combination,
getProgram(),
- new HashSet(),
+ new HashSet<>(),
null);
if(success) {
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 7a6ebc1a7..e519b7504 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -2,7 +2,7 @@ package dk.camelot64.kickc.test;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.Compiler;
-import dk.camelot64.kickc.fragment.AsmFragmentUsages;
+import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import org.junit.AfterClass;
@@ -32,7 +32,7 @@ public class TestPrograms {
public static void tearDown() throws Exception {
CompileLog log = new CompileLog();
log.setSysOut(true);
- AsmFragmentUsages.logUsages(log, false, false, false, false);
+ AsmFragmentTemplateUsages.logUsages(log, false, false, false, false);
}
@Test
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/callconstparam.log b/src/test/java/dk/camelot64/kickc/test/ref/callconstparam.log
index 984f6de78..0f40ea4db 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/callconstparam.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/callconstparam.log
@@ -500,8 +500,12 @@ Uplift Scope [main]
Uplifting [line] best 426 combination reg byte x [ line::x#2 line::x#0 line::x#1 ] zp ZP_BYTE:2 [ line::x1#3 ]
Uplifting [] best 426 combination zp ZP_WORD:4 [ screen#10 screen#14 screen#11 ]
Uplifting [main] best 426 combination
+MISSING FRAGMENTS
+ vbuxx_lt_vbuaa_then_la1(line:: vbuxx=(byte) line::x#1 vbuaa=(byte) line::x1#3 la1=(label) line::b1_from_b1 )
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ line::x1#3 ]
Uplifting [line] best 426 combination zp ZP_BYTE:2 [ line::x1#3 ]
+MISSING FRAGMENTS
+ vbuxx_lt_vbuaa_then_la1(line:: vbuxx=(byte) line::x#1 vbuaa=(byte) line::x1#3 la1=(label) line::b1_from_b1 )
Allocated (was zp ZP_WORD:4) zp ZP_WORD:3 [ screen#10 screen#14 screen#11 ]
ASSEMBLER BEFORE OPTIMIZATION
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/inline-word.log b/src/test/java/dk/camelot64/kickc/test/ref/inline-word.log
index aaec9c226..50cf5d382 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/inline-word.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/inline-word.log
@@ -447,8 +447,8 @@ main: {
}
REGISTER UPLIFT POTENTIAL REGISTERS
-Potential register analysis [7] main::w#0 ← *(main::his#0 + main::h#4) w= main::l#2 missing fragment vwuz1=pbuc1_derefidx_vbuaa_word_vbuxx(main:: vwuz1=(word) main::w#0 pbuc1=(const byte[]) main::his#0 vbuaa=(byte) main::h#4 vbuxx=(byte) main::l#2 ) allocation: reg byte a [ main::h#4 main::h#1 ] reg byte x [ main::l#2 main::l#1 ] zp ZP_WORD:4 [ main::w#0 ]
-Potential register analysis [7] main::w#0 ← *(main::his#0 + main::h#4) w= main::l#2 missing fragment vwuz1=pbuc1_derefidx_vbuaa_word_vbuyy(main:: vwuz1=(word) main::w#0 pbuc1=(const byte[]) main::his#0 vbuaa=(byte) main::h#4 vbuyy=(byte) main::l#2 ) allocation: reg byte a [ main::h#4 main::h#1 ] reg byte y [ main::l#2 main::l#1 ] zp ZP_WORD:4 [ main::w#0 ]
+Potential register analysis [7] main::w#0 ← *(main::his#0 + main::h#4) w= main::l#2 missing fragment vwuz1=pbuc1_derefidx_vbuaa_word_vbuxx allocation: reg byte a [ main::h#4 main::h#1 ] reg byte x [ main::l#2 main::l#1 ] zp ZP_WORD:4 [ main::w#0 ]
+Potential register analysis [7] main::w#0 ← *(main::his#0 + main::h#4) w= main::l#2 missing fragment vwuz1=pbuc1_derefidx_vbuaa_word_vbuyy allocation: reg byte a [ main::h#4 main::h#1 ] reg byte y [ main::l#2 main::l#1 ] zp ZP_WORD:4 [ main::w#0 ]
MISSING FRAGMENTS
vwuz1=pbuc1_derefidx_vbuaa_word_vbuxx(main:: vwuz1=(word) main::w#0 pbuc1=(const byte[]) main::his#0 vbuaa=(byte) main::h#4 vbuxx=(byte) main::l#2 )
vwuz1=pbuc1_derefidx_vbuaa_word_vbuyy(main:: vwuz1=(word) main::w#0 pbuc1=(const byte[]) main::his#0 vbuaa=(byte) main::h#4 vbuyy=(byte) main::l#2 )
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/scrollbig.log b/src/test/java/dk/camelot64/kickc/test/ref/scrollbig.log
index 7ffc53afe..956adcbb9 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/scrollbig.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/scrollbig.log
@@ -3050,8 +3050,8 @@ Statement [7] if(*((const byte*) RASTER#0)!=(byte/word/signed word) 254) goto ma
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ scroll#18 scroll#10 scroll#3 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ current_bit#29 current_bit#12 current_bit#21 current_bit#5 ]
Statement [8] if(*((const byte*) RASTER#0)!=(byte/word/signed word) 255) goto main::@3 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ( main:2 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ) always clobbers reg byte a
-Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuxx(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuxx=(byte~) scroll_bit::$3 ) allocation: reg byte x [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
-Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuyy(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuyy=(byte~) scroll_bit::$3 ) allocation: reg byte y [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
+Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
+Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuxx=(byte~) scroll_bit::$3 )
vwuz1=_word_vbuyy(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuyy=(byte~) scroll_bit::$3 )
@@ -3081,8 +3081,8 @@ Statement [68] *((byte*) fillscreen::cursor#2) ← (const byte) fillscreen::fill
Statement [70] if((byte*) fillscreen::cursor#1<(const byte*) SCREEN#0+(word/signed word) 1000) goto fillscreen::@1 [ fillscreen::cursor#1 ] ( main:2::fillscreen:5 [ fillscreen::cursor#1 ] ) always clobbers reg byte a
Statement [7] if(*((const byte*) RASTER#0)!=(byte/word/signed word) 254) goto main::@2 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ( main:2 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ) always clobbers reg byte a
Statement [8] if(*((const byte*) RASTER#0)!=(byte/word/signed word) 255) goto main::@3 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ( main:2 [ scroll#18 current_bit#29 nxt#31 current_chargen#27 ] ) always clobbers reg byte a
-Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuxx(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuxx=(byte~) scroll_bit::$3 ) allocation: reg byte x [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
-Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuyy(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuyy=(byte~) scroll_bit::$3 ) allocation: reg byte y [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
+Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
+Potential register analysis [27] scroll_bit::c#0 ← ((word)) scroll_bit::$3 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ scroll_bit::$3 ] zp ZP_WORD:18 [ scroll_bit::c#0 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuxx=(byte~) scroll_bit::$3 )
vwuz1=_word_vbuyy(scroll_bit:: vwuz1=(word) scroll_bit::c#0 vbuyy=(byte~) scroll_bit::$3 )
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/signed-bytes.log b/src/test/java/dk/camelot64/kickc/test/ref/signed-bytes.log
index 8164b2577..14f594e7f 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/signed-bytes.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/signed-bytes.log
@@ -354,16 +354,16 @@ main: {
}
REGISTER UPLIFT POTENTIAL REGISTERS
-Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsxx_lt_vbuc1_then_la1(main:: vbsxx=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 ) allocation: reg byte x [ main::i#2 main::i#1 ]
-Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsyy_lt_vbuc1_then_la1(main:: vbsyy=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 ) allocation: reg byte y [ main::i#2 main::i#1 ]
+Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsxx_lt_vbuc1_then_la1 allocation: reg byte x [ main::i#2 main::i#1 ]
+Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsyy_lt_vbuc1_then_la1 allocation: reg byte y [ main::i#2 main::i#1 ]
MISSING FRAGMENTS
vbsxx_lt_vbuc1_then_la1(main:: vbsxx=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 )
vbsyy_lt_vbuc1_then_la1(main:: vbsyy=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 )
Statement [6] if((signed byte) main::i#2<(byte/signed byte/word/signed word) 127) goto main::@2 [ main::i#2 main::j#2 ] ( main:2 [ main::i#2 main::j#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::j#2 main::j#1 ]
-Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsxx_lt_vbuc1_then_la1(main:: vbsxx=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 ) allocation: reg byte x [ main::i#2 main::i#1 ]
-Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsyy_lt_vbuc1_then_la1(main:: vbsyy=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 ) allocation: reg byte y [ main::i#2 main::i#1 ]
+Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsxx_lt_vbuc1_then_la1 allocation: reg byte x [ main::i#2 main::i#1 ]
+Potential register analysis [6] if(main::i#2<127) goto main::@2 missing fragment vbsyy_lt_vbuc1_then_la1 allocation: reg byte y [ main::i#2 main::i#1 ]
MISSING FRAGMENTS
vbsxx_lt_vbuc1_then_la1(main:: vbsxx=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 )
vbsyy_lt_vbuc1_then_la1(main:: vbsyy=(signed byte) main::i#2 vbuc1=(byte/signed byte/word/signed word) 127 la1=(label) main::@2 )
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/sinus-basic.log b/src/test/java/dk/camelot64/kickc/test/ref/sinus-basic.log
index 3f9f8bca7..b7153ca29 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/sinus-basic.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/sinus-basic.log
@@ -3178,8 +3178,8 @@ divFACby10: {
}
REGISTER UPLIFT POTENTIAL REGISTERS
-Potential register analysis [11] setFAC::w#1 ← ((word)) main::i#10 missing fragment vwuz1=_word_vbuxx(main:: vwuz1=(word) setFAC::w#1 vbuxx=(byte) main::i#10 ) allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_WORD:13 [ setFAC::w#3 setFAC::w#1 ]
-Potential register analysis [11] setFAC::w#1 ← ((word)) main::i#10 missing fragment vwuz1=_word_vbuyy(main:: vwuz1=(word) setFAC::w#1 vbuyy=(byte) main::i#10 ) allocation: reg byte y [ main::i#10 main::i#1 ] zp ZP_WORD:13 [ setFAC::w#3 setFAC::w#1 ]
+Potential register analysis [11] setFAC::w#1 ← ((word)) main::i#10 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_WORD:13 [ setFAC::w#3 setFAC::w#1 ]
+Potential register analysis [11] setFAC::w#1 ← ((word)) main::i#10 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ main::i#10 main::i#1 ] zp ZP_WORD:13 [ setFAC::w#3 setFAC::w#1 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(main:: vwuz1=(word) setFAC::w#1 vbuxx=(byte) main::i#10 )
vwuz1=_word_vbuyy(main:: vwuz1=(word) setFAC::w#1 vbuyy=(byte) main::i#10 )
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/sinus-sprites.log b/src/test/java/dk/camelot64/kickc/test/ref/sinus-sprites.log
index caf2a7d8b..f13cc316f 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/sinus-sprites.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/sinus-sprites.log
@@ -7643,8 +7643,8 @@ Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ in
Statement [49] *((const byte*) COLS#0+(byte/signed byte/word/signed word) 40 + (byte) init::i#2) ← (byte/signed byte/word/signed word) 11 [ init::i#2 ] ( main:2::init:5 [ init::i#2 ] ) always clobbers reg byte a
Statement [69] *((byte*) clear_screen::sc#2) ← (byte) ' ' [ clear_screen::sc#2 ] ( main:2::init:5::clear_screen:46 [ clear_screen::sc#2 ] main:2::init:5::clear_screen:65 [ clear_screen::sc#2 ] ) always clobbers reg byte a reg byte y
Statement [71] if((byte*) clear_screen::sc#1<(const byte*) SCREEN#0+(word/signed word) 1000) goto clear_screen::@1 [ clear_screen::sc#1 ] ( main:2::init:5::clear_screen:46 [ clear_screen::sc#1 ] main:2::init:5::clear_screen:65 [ clear_screen::sc#1 ] ) always clobbers reg byte a
-Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuxx=(byte) gen_sintab::max#2 ) allocation: reg byte x [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
-Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuyy=(byte) gen_sintab::max#2 ) allocation: reg byte y [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
+Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
+Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuxx=(byte) gen_sintab::max#2 )
vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuyy=(byte) gen_sintab::max#2 )
@@ -7657,8 +7657,8 @@ Removing always clobbered register reg byte y as potential for zp ZP_BYTE:13 [ g
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:14 [ gen_sintab::length#10 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:14 [ gen_sintab::length#10 ]
Statement [79] (word) setFAC::w#1 ← ((word)) (byte) gen_sintab::min#2 [ gen_sintab::length#10 gen_sintab::sintab#12 setFAC::w#1 progress_init::line#2 ] ( main:2::init:5::gen_sintab:59 [ gen_sintab::length#10 gen_sintab::sintab#12 setFAC::w#1 progress_init::line#2 ] main:2::init:5::gen_sintab:63 [ gen_sintab::length#10 gen_sintab::sintab#12 setFAC::w#1 progress_init::line#2 ] ) always clobbers reg byte a
-Potential register analysis [98] setFAC::w#3 ← ((word)) gen_sintab::i#10 missing fragment vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#3 vbuxx=(byte) gen_sintab::i#10 ) allocation: zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ] reg byte x [ gen_sintab::i#10 gen_sintab::i#1 ]
-Potential register analysis [98] setFAC::w#3 ← ((word)) gen_sintab::i#10 missing fragment vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#3 vbuyy=(byte) gen_sintab::i#10 ) allocation: zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ] reg byte y [ gen_sintab::i#10 gen_sintab::i#1 ]
+Potential register analysis [98] setFAC::w#3 ← ((word)) gen_sintab::i#10 missing fragment vwuz1=_word_vbuxx allocation: zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ] reg byte x [ gen_sintab::i#10 gen_sintab::i#1 ]
+Potential register analysis [98] setFAC::w#3 ← ((word)) gen_sintab::i#10 missing fragment vwuz1=_word_vbuyy allocation: zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ] reg byte y [ gen_sintab::i#10 gen_sintab::i#1 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#3 vbuxx=(byte) gen_sintab::i#10 )
vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#3 vbuyy=(byte) gen_sintab::i#10 )
@@ -7669,7 +7669,7 @@ Statement [104] (word) setFAC::w#4 ← ((word)) (byte) gen_sintab::length#10 [ g
Statement [116] (word) getFAC::return#2 ← (word) getFAC::return#0 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 getFAC::return#2 ] ( main:2::init:5::gen_sintab:59 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 getFAC::return#2 ] main:2::init:5::gen_sintab:63 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 getFAC::return#2 ] ) always clobbers reg byte a
Statement [117] (word~) gen_sintab::$23 ← (word) getFAC::return#2 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$23 ] ( main:2::init:5::gen_sintab:59 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$23 ] main:2::init:5::gen_sintab:63 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$23 ] ) always clobbers reg byte a
Statement [118] (byte~) gen_sintab::$24 ← ((byte)) (word~) gen_sintab::$23 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$24 ] ( main:2::init:5::gen_sintab:59 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$24 ] main:2::init:5::gen_sintab:63 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_idx#34 progress_cursor#34 gen_sintab::$24 ] ) always clobbers reg byte a
-Potential register analysis [119] *(gen_sintab::sintab#12 + gen_sintab::i#10) ← gen_sintab::$24 missing fragment pbuz1_derefidx_vbuxx=vbuyy(gen_sintab:: pbuz1=(byte*) gen_sintab::sintab#12 vbuxx=(byte) gen_sintab::i#10 vbuyy=(byte~) gen_sintab::$24 ) allocation: zp ZP_WORD:15 [ gen_sintab::sintab#12 ] reg byte y [ gen_sintab::$24 ] reg byte x [ gen_sintab::i#10 gen_sintab::i#1 ]
+Potential register analysis [119] *(gen_sintab::sintab#12 + gen_sintab::i#10) ← gen_sintab::$24 missing fragment pbuz1_derefidx_vbuxx=vbuyy allocation: zp ZP_WORD:15 [ gen_sintab::sintab#12 ] reg byte y [ gen_sintab::$24 ] reg byte x [ gen_sintab::i#10 gen_sintab::i#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuxx=vbuyy(gen_sintab:: pbuz1=(byte*) gen_sintab::sintab#12 vbuxx=(byte) gen_sintab::i#10 vbuyy=(byte~) gen_sintab::$24 )
Statement [126] *((byte*) progress_cursor#34) ← *((const byte[]) progress_inc::progress_chars#0+(byte/signed byte/word/signed word) 8) [ progress_cursor#34 ] ( main:2::init:5::gen_sintab:59::progress_inc:120 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_cursor#34 ] main:2::init:5::gen_sintab:63::progress_inc:120 [ gen_sintab::length#10 gen_sintab::sintab#12 gen_sintab::i#10 progress_cursor#34 ] ) always clobbers reg byte a reg byte y
@@ -7695,8 +7695,8 @@ Statement [176] (byte*) gen_chargen_sprite::sprite#0 ← (byte*) gen_sprites::sp
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:33 [ gen_sprites::i#2 gen_sprites::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:64 [ gen_chargen_sprite::ch#0 ]
Statement [178] (byte*) gen_sprites::spr#1 ← (byte*) gen_sprites::spr#2 + (byte/signed byte/word/signed word) 64 [ gen_sprites::i#2 gen_sprites::spr#1 ] ( main:2::init:5::gen_sprites:55 [ gen_sprites::i#2 gen_sprites::spr#1 ] ) always clobbers reg byte a
-Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuxx(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuxx=(byte) gen_chargen_sprite::ch#0 ) allocation: reg byte x [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
-Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuyy(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuyy=(byte) gen_chargen_sprite::ch#0 ) allocation: reg byte y [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
+Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
+Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuxx=(byte) gen_chargen_sprite::ch#0 )
vwuz1=_word_vbuyy(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuyy=(byte) gen_chargen_sprite::ch#0 )
@@ -7715,8 +7715,8 @@ Statement [195] (byte~) gen_chargen_sprite::$6 ← (byte) gen_chargen_sprite::s_
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:39 [ gen_chargen_sprite::c#3 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:42 [ gen_chargen_sprite::b#2 gen_chargen_sprite::b#1 ]
Statement [196] (byte) gen_chargen_sprite::s_gen#1 ← (byte~) gen_chargen_sprite::$6 | (byte) gen_chargen_sprite::c#3 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ) always clobbers reg byte a
-Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
-Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuyy(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuyy=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte y [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuyy allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte y [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
pbuz1_derefidx_vbuc1=vbuyy(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuyy=(byte) gen_chargen_sprite::s_gen#1 )
@@ -7728,11 +7728,11 @@ Removing always clobbered register reg byte y as potential for zp ZP_BYTE:38 [ g
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:39 [ gen_chargen_sprite::c#3 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:42 [ gen_chargen_sprite::b#2 gen_chargen_sprite::b#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:40 [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
-Potential register analysis [200] *(gen_chargen_sprite::sprite#3 + 3) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 3 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [200] *(gen_chargen_sprite::sprite#3 + 3) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 3 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
Statement [200] *((byte*) gen_chargen_sprite::sprite#3 + (byte/signed byte/word/signed word) 3) ← (byte) gen_chargen_sprite::s_gen#1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ) always clobbers reg byte a reg byte y
-Potential register analysis [201] *(gen_chargen_sprite::sprite#3 + 6) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 6 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [201] *(gen_chargen_sprite::sprite#3 + 6) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 6 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
Statement [201] *((byte*) gen_chargen_sprite::sprite#3 + (byte/signed byte/word/signed word) 6) ← (byte) gen_chargen_sprite::s_gen#1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 ] ) always clobbers reg byte a reg byte y
@@ -7764,8 +7764,8 @@ Statement [48] *((const byte*) COLS#0 + (byte) init::i#2) ← (byte/signed byte/
Statement [49] *((const byte*) COLS#0+(byte/signed byte/word/signed word) 40 + (byte) init::i#2) ← (byte/signed byte/word/signed word) 11 [ init::i#2 ] ( main:2::init:5 [ init::i#2 ] ) always clobbers reg byte a
Statement [69] *((byte*) clear_screen::sc#2) ← (byte) ' ' [ clear_screen::sc#2 ] ( main:2::init:5::clear_screen:46 [ clear_screen::sc#2 ] main:2::init:5::clear_screen:65 [ clear_screen::sc#2 ] ) always clobbers reg byte a reg byte y
Statement [71] if((byte*) clear_screen::sc#1<(const byte*) SCREEN#0+(word/signed word) 1000) goto clear_screen::@1 [ clear_screen::sc#1 ] ( main:2::init:5::clear_screen:46 [ clear_screen::sc#1 ] main:2::init:5::clear_screen:65 [ clear_screen::sc#1 ] ) always clobbers reg byte a
-Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuxx=(byte) gen_sintab::max#2 ) allocation: reg byte x [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
-Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuyy=(byte) gen_sintab::max#2 ) allocation: reg byte y [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
+Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
+Potential register analysis [74] setFAC::w#0 ← ((word)) gen_sintab::max#2 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ gen_sintab::max#2 ] zp ZP_WORD:29 [ setFAC::w#5 setFAC::w#0 setFAC::w#3 setFAC::w#4 setFAC::w#1 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuxx=(byte) gen_sintab::max#2 )
vwuz1=_word_vbuyy(gen_sintab:: vwuz1=(word) setFAC::w#0 vbuyy=(byte) gen_sintab::max#2 )
@@ -7797,8 +7797,8 @@ Statement [163] (byte*) prepareMEM::mem#1 ← (byte*) setMEMtoFAC::mem#5 [ prepa
Statement asm { ldx$fe ldy$ff jsr$bbd4 } always clobbers reg byte x reg byte y
Statement [176] (byte*) gen_chargen_sprite::sprite#0 ← (byte*) gen_sprites::spr#2 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::ch#0 gen_chargen_sprite::sprite#0 ] ( main:2::init:5::gen_sprites:55 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::ch#0 gen_chargen_sprite::sprite#0 ] ) always clobbers reg byte a
Statement [178] (byte*) gen_sprites::spr#1 ← (byte*) gen_sprites::spr#2 + (byte/signed byte/word/signed word) 64 [ gen_sprites::i#2 gen_sprites::spr#1 ] ( main:2::init:5::gen_sprites:55 [ gen_sprites::i#2 gen_sprites::spr#1 ] ) always clobbers reg byte a
-Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuxx(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuxx=(byte) gen_chargen_sprite::ch#0 ) allocation: reg byte x [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
-Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuyy(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuyy=(byte) gen_chargen_sprite::ch#0 ) allocation: reg byte y [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
+Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuxx allocation: reg byte x [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
+Potential register analysis [182] gen_chargen_sprite::$0 ← ((word)) gen_chargen_sprite::ch#0 missing fragment vwuz1=_word_vbuyy allocation: reg byte y [ gen_chargen_sprite::ch#0 ] zp ZP_WORD:65 [ gen_chargen_sprite::$0 ]
MISSING FRAGMENTS
vwuz1=_word_vbuxx(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuxx=(byte) gen_chargen_sprite::ch#0 )
vwuz1=_word_vbuyy(gen_chargen_sprite:: vwuz1=(word~) gen_chargen_sprite::$0 vbuyy=(byte) gen_chargen_sprite::ch#0 )
@@ -7810,15 +7810,15 @@ Statement [188] (byte) gen_chargen_sprite::bits#0 ← *((byte*) gen_chargen_spri
Statement [190] (byte~) gen_chargen_sprite::$3 ← (byte) gen_chargen_sprite::bits#2 & (byte/word/signed word) 128 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen_cnt#4 gen_chargen_sprite::sprite#10 gen_chargen_sprite::x#6 gen_chargen_sprite::$3 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen_cnt#4 gen_chargen_sprite::sprite#10 gen_chargen_sprite::x#6 gen_chargen_sprite::$3 ] ) always clobbers reg byte a
Statement [195] (byte~) gen_chargen_sprite::$6 ← (byte) gen_chargen_sprite::s_gen#3 << (byte/signed byte/word/signed word) 1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::$6 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::$6 ] ) always clobbers reg byte a
Statement [196] (byte) gen_chargen_sprite::s_gen#1 ← (byte~) gen_chargen_sprite::$6 | (byte) gen_chargen_sprite::c#3 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::s_gen_cnt#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ) always clobbers reg byte a
-Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [199] *(gen_chargen_sprite::sprite#3 + 0) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 0 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
Statement [199] *((byte*) gen_chargen_sprite::sprite#3 + (byte/signed byte/word/signed word) 0) ← (byte) gen_chargen_sprite::s_gen#1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ) always clobbers reg byte a reg byte y
-Potential register analysis [200] *(gen_chargen_sprite::sprite#3 + 3) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 3 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [200] *(gen_chargen_sprite::sprite#3 + 3) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 3 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
Statement [200] *((byte*) gen_chargen_sprite::sprite#3 + (byte/signed byte/word/signed word) 3) ← (byte) gen_chargen_sprite::s_gen#1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 gen_chargen_sprite::s_gen#1 ] ) always clobbers reg byte a reg byte y
-Potential register analysis [201] *(gen_chargen_sprite::sprite#3 + 6) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 6 vbuxx=(byte) gen_chargen_sprite::s_gen#1 ) allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
+Potential register analysis [201] *(gen_chargen_sprite::sprite#3 + 6) ← gen_chargen_sprite::s_gen#1 missing fragment pbuz1_derefidx_vbuc1=vbuxx allocation: zp ZP_WORD:43 [ gen_chargen_sprite::sprite#3 gen_chargen_sprite::sprite#10 gen_chargen_sprite::sprite#11 gen_chargen_sprite::sprite#0 gen_chargen_sprite::sprite#2 gen_chargen_sprite::sprite#4 gen_chargen_sprite::sprite#1 ] reg byte x [ gen_chargen_sprite::s_gen#3 gen_chargen_sprite::s_gen#5 gen_chargen_sprite::s_gen#6 gen_chargen_sprite::s_gen#1 ]
MISSING FRAGMENTS
pbuz1_derefidx_vbuc1=vbuxx(gen_chargen_sprite:: pbuz1=(byte*) gen_chargen_sprite::sprite#3 vbuc1=(byte/signed byte/word/signed word) 6 vbuxx=(byte) gen_chargen_sprite::s_gen#1 )
Statement [201] *((byte*) gen_chargen_sprite::sprite#3 + (byte/signed byte/word/signed word) 6) ← (byte) gen_chargen_sprite::s_gen#1 [ gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 ] ( main:2::init:5::gen_sprites:55::gen_chargen_sprite:177 [ gen_sprites::i#2 gen_sprites::spr#2 gen_chargen_sprite::chargen#0 gen_chargen_sprite::y#2 gen_chargen_sprite::bits#2 gen_chargen_sprite::x#6 gen_chargen_sprite::c#3 gen_chargen_sprite::b#2 gen_chargen_sprite::sprite#3 ] ) always clobbers reg byte a reg byte y
diff --git a/src/test/java/dk/camelot64/kickc/test/ref/test-comparisons.log b/src/test/java/dk/camelot64/kickc/test/ref/test-comparisons.log
index 86fbbdac5..b86a8f76f 100644
--- a/src/test/java/dk/camelot64/kickc/test/ref/test-comparisons.log
+++ b/src/test/java/dk/camelot64/kickc/test/ref/test-comparisons.log
@@ -8647,10 +8647,10 @@ Potential register analysis [21] if(main::a#10>=*(main::cs#0 + main::i#10)) goto
Potential register analysis [21] if(main::a#10>=*(main::cs#0 + main::i#10)) goto main::@4 missing fragment vbuyy_ge_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
Potential register analysis [21] if(main::a#10>=*(main::cs#0 + main::i#10)) goto main::@4 missing fragment vbuyy_ge_pbuc1_derefidx_vbuyy_then_la1 allocation: reg byte y [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_ge_pbuc1_derefidx_vbuz1_then_la1
- vbuyy_ge_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_ge_pbuc1_derefidx_vbuyy_then_la1
+ vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b4_from_b47 )
+ vbuyy_ge_pbuc1_derefidx_vbuz1_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuz1=(byte) main::i#10 la1=(label) main::b4_from_b47 )
+ vbuyy_ge_pbuc1_derefidx_vbuxx_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b4_from_b47 )
+ vbuyy_ge_pbuc1_derefidx_vbuyy_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 la1=(label) main::b4_from_b47 )
Statement [21] if((byte) main::a#10>=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@4 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:39 [ main::b#0 ]
Statement [28] if((byte) main::a#10>=(byte) main::a#10) goto main::@5 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
@@ -8663,28 +8663,28 @@ Potential register analysis [51] if(main::a#10<=*(main::cs#0 + main::i#10)) goto
Potential register analysis [51] if(main::a#10<=*(main::cs#0 + main::i#10)) goto main::@8 missing fragment vbuyy_le_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
Potential register analysis [51] if(main::a#10<=*(main::cs#0 + main::i#10)) goto main::@8 missing fragment vbuyy_le_pbuc1_derefidx_vbuyy_then_la1 allocation: reg byte y [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_le_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_le_pbuc1_derefidx_vbuz1_then_la1
- vbuyy_le_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_le_pbuc1_derefidx_vbuyy_then_la1
+ vbuz1_le_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b8_from_b52 )
+ vbuyy_le_pbuc1_derefidx_vbuz1_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuz1=(byte) main::i#10 la1=(label) main::b8_from_b52 )
+ vbuyy_le_pbuc1_derefidx_vbuxx_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b8_from_b52 )
+ vbuyy_le_pbuc1_derefidx_vbuyy_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 la1=(label) main::b8_from_b52 )
Statement [51] if((byte) main::a#10<=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@8 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [58] if((byte) main::a#10<=(byte) main::a#10) goto main::@9 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [73] (byte*~) char_cursor#138 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ) always clobbers reg byte a
Potential register analysis [75] if(main::a#10>55) goto main::@11 missing fragment vbuxx_gt_vbuc1_then_la1 allocation: reg byte x [ main::a#10 main::a#1 ]
Potential register analysis [75] if(main::a#10>55) goto main::@11 missing fragment vbuyy_gt_vbuc1_then_la1 allocation: reg byte y [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuxx_gt_vbuc1_then_la1
- vbuyy_gt_vbuc1_then_la1
+ vbuxx_gt_vbuc1_then_la1(main:: vbuxx=(byte) main::a#10 vbuc1=(byte/signed byte/word/signed word) 55 la1=(label) main::b11_from_b56 )
+ vbuyy_gt_vbuc1_then_la1(main:: vbuyy=(byte) main::a#10 vbuc1=(byte/signed byte/word/signed word) 55 la1=(label) main::b11_from_b56 )
Statement [75] if((byte) main::a#10>(byte/signed byte/word/signed word) 55) goto main::@11 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuyy_gt_pbuc1_derefidx_vbuz1_then_la1 allocation: zp ZP_BYTE:3 [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuyy_gt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuyy_gt_pbuc1_derefidx_vbuyy_then_la1 allocation: reg byte y [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_gt_pbuc1_derefidx_vbuz1_then_la1
- vbuyy_gt_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_gt_pbuc1_derefidx_vbuyy_then_la1
+ vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b12_from_b57 )
+ vbuyy_gt_pbuc1_derefidx_vbuz1_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuz1=(byte) main::i#10 la1=(label) main::b12_from_b57 )
+ vbuyy_gt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b12_from_b57 )
+ vbuyy_gt_pbuc1_derefidx_vbuyy_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 la1=(label) main::b12_from_b57 )
Statement [81] if((byte) main::a#10>*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@12 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [88] if((byte) main::a#10>(byte) main::a#10) goto main::@13 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [103] (byte*~) char_cursor#142 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ) always clobbers reg byte a
@@ -8693,16 +8693,16 @@ Potential register analysis [111] if(main::a#10<*(main::cs#0 + main::i#10)) goto
Potential register analysis [111] if(main::a#10<*(main::cs#0 + main::i#10)) goto main::@16 missing fragment vbuyy_lt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
Potential register analysis [111] if(main::a#10<*(main::cs#0 + main::i#10)) goto main::@16 missing fragment vbuyy_lt_pbuc1_derefidx_vbuyy_then_la1 allocation: reg byte y [ main::i#10 main::i#1 ] reg byte y [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_lt_pbuc1_derefidx_vbuz1_then_la1
- vbuyy_lt_pbuc1_derefidx_vbuxx_then_la1
- vbuyy_lt_pbuc1_derefidx_vbuyy_then_la1
+ vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b16_from_b62 )
+ vbuyy_lt_pbuc1_derefidx_vbuz1_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuz1=(byte) main::i#10 la1=(label) main::b16_from_b62 )
+ vbuyy_lt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b16_from_b62 )
+ vbuyy_lt_pbuc1_derefidx_vbuyy_then_la1(main:: vbuyy=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 la1=(label) main::b16_from_b62 )
Statement [111] if((byte) main::a#10<*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@16 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Potential register analysis [118] if(main::a#10=*(main::cs#0 + main::i#10)) goto main::@4 missing fragment vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b4_from_b47 )
Statement [21] if((byte) main::a#10>=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@4 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [25] (byte) printu::b#2 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#21 main::b#0 main::r#42 printu::a#2 printu::b#2 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 main::r#42 printu::a#2 printu::b#2 char_cursor#52 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ main::r#42 ]
@@ -8748,7 +8748,7 @@ Statement [28] if((byte) main::a#10>=(byte) main::a#10) goto main::@5 [ main::a#
Statement [43] (byte*~) char_cursor#154 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#4 printu::b#4 printu::res#4 char_cursor#154 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#4 printu::b#4 printu::res#4 char_cursor#154 ] ) always clobbers reg byte a
Potential register analysis [51] if(main::a#10<=*(main::cs#0 + main::i#10)) goto main::@8 missing fragment vbuz1_le_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_le_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_le_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b8_from_b52 )
Statement [51] if((byte) main::a#10<=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@8 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [55] (byte) printu::b#6 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#46 printu::a#6 printu::b#6 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#46 printu::a#6 printu::b#6 char_cursor#52 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:10 [ main::r#46 ]
@@ -8756,11 +8756,11 @@ Statement [58] if((byte) main::a#10<=(byte) main::a#10) goto main::@9 [ main::a#
Statement [73] (byte*~) char_cursor#138 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ) always clobbers reg byte a
Potential register analysis [75] if(main::a#10>55) goto main::@11 missing fragment vbuxx_gt_vbuc1_then_la1 allocation: reg byte x [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuxx_gt_vbuc1_then_la1
+ vbuxx_gt_vbuc1_then_la1(main:: vbuxx=(byte) main::a#10 vbuc1=(byte/signed byte/word/signed word) 55 la1=(label) main::b11_from_b56 )
Statement [75] if((byte) main::a#10>(byte/signed byte/word/signed word) 55) goto main::@11 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b12_from_b57 )
Statement [81] if((byte) main::a#10>*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@12 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [85] (byte) printu::b#10 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#50 printu::a#10 printu::b#10 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#50 printu::a#10 printu::b#10 char_cursor#52 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:14 [ main::r#50 ]
@@ -8768,18 +8768,18 @@ Statement [88] if((byte) main::a#10>(byte) main::a#10) goto main::@13 [ main::a#
Statement [103] (byte*~) char_cursor#142 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ) always clobbers reg byte a
Potential register analysis [111] if(main::a#10<*(main::cs#0 + main::i#10)) goto main::@16 missing fragment vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b16_from_b62 )
Statement [111] if((byte) main::a#10<*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@16 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [115] (byte) printu::b#14 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#54 printu::a#14 printu::b#14 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#54 printu::a#14 printu::b#14 char_cursor#52 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:18 [ main::r#54 ]
Potential register analysis [118] if(main::a#10=*(main::cs#0 + main::i#10)) goto main::@4 missing fragment vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_ge_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b4_from_b47 )
Statement [21] if((byte) main::a#10>=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@4 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [25] (byte) printu::b#2 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#21 main::b#0 main::r#42 printu::a#2 printu::b#2 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 main::r#42 printu::a#2 printu::b#2 char_cursor#52 ] ) always clobbers reg byte a
Statement [28] if((byte) main::a#10>=(byte) main::a#10) goto main::@5 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#21 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [43] (byte*~) char_cursor#154 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#4 printu::b#4 printu::res#4 char_cursor#154 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#4 printu::b#4 printu::res#4 char_cursor#154 ] ) always clobbers reg byte a
Potential register analysis [51] if(main::a#10<=*(main::cs#0 + main::i#10)) goto main::@8 missing fragment vbuz1_le_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_le_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_le_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b8_from_b52 )
Statement [51] if((byte) main::a#10<=*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@8 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [55] (byte) printu::b#6 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#46 printu::a#6 printu::b#6 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#46 printu::a#6 printu::b#6 char_cursor#52 ] ) always clobbers reg byte a
Statement [58] if((byte) main::a#10<=(byte) main::a#10) goto main::@9 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [73] (byte*~) char_cursor#138 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#8 printu::b#8 printu::res#8 char_cursor#138 ] ) always clobbers reg byte a
Potential register analysis [75] if(main::a#10>55) goto main::@11 missing fragment vbuxx_gt_vbuc1_then_la1 allocation: reg byte x [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuxx_gt_vbuc1_then_la1
+ vbuxx_gt_vbuc1_then_la1(main:: vbuxx=(byte) main::a#10 vbuc1=(byte/signed byte/word/signed word) 55 la1=(label) main::b11_from_b56 )
Statement [75] if((byte) main::a#10>(byte/signed byte/word/signed word) 55) goto main::@11 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Potential register analysis [81] if(main::a#10>*(main::cs#0 + main::i#10)) goto main::@12 missing fragment vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_gt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b12_from_b57 )
Statement [81] if((byte) main::a#10>*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@12 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [85] (byte) printu::b#10 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#50 printu::a#10 printu::b#10 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#50 printu::a#10 printu::b#10 char_cursor#52 ] ) always clobbers reg byte a
Statement [88] if((byte) main::a#10>(byte) main::a#10) goto main::@13 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a
Statement [103] (byte*~) char_cursor#142 ← (byte*) line_cursor#1 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 printu::a#12 printu::b#12 printu::res#12 char_cursor#142 ] ) always clobbers reg byte a
Potential register analysis [111] if(main::a#10<*(main::cs#0 + main::i#10)) goto main::@16 missing fragment vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1 allocation: reg byte x [ main::i#10 main::i#1 ] zp ZP_BYTE:2 [ main::a#10 main::a#1 ]
MISSING FRAGMENTS
- vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1
+ vbuz1_lt_pbuc1_derefidx_vbuxx_then_la1(main:: vbuz1=(byte) main::a#10 pbuc1=(const byte[5]) main::cs#0 vbuxx=(byte) main::i#10 la1=(label) main::b16_from_b62 )
Statement [111] if((byte) main::a#10<*((const byte[5]) main::cs#0 + (byte) main::i#10)) goto main::@16 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 char_cursor#52 ] ) always clobbers reg byte a reg byte y
Statement [115] (byte) printu::b#14 ← *((const byte[5]) main::cs#0 + (byte) main::i#10) [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#54 printu::a#14 printu::b#14 char_cursor#52 ] ( main:2 [ main::a#10 main::i#10 line_cursor#1 main::b#0 main::r#54 printu::a#14 printu::b#14 char_cursor#52 ] ) always clobbers reg byte a
Potential register analysis [118] if(main::a#10