From a1f4656f796af2224d22951bac1c110b8f2879a1 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 9 Sep 2019 01:31:21 +0200
Subject: [PATCH] Improved selfmod fragments. Added needed fragments that is
 not self-modifying. Fixed -Wfragment in pass4.

---
 .../_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm         |  9 +++++++++
 .../_deref_(pptz1_derefidx_vbuc1)=vbuxx.asm         |  3 +--
 ....asm => _deref_(pptz1_derefidx_vbuyy)=vbuaa.asm} |  1 -
 src/main/java/dk/camelot64/kickc/Compiler.java      | 13 +++----------
 src/main/java/dk/camelot64/kickc/model/Program.java | 11 +++++++++++
 .../passes/Pass4RegisterUpliftCombinations.java     |  2 +-
 .../java/dk/camelot64/kickc/test/TestPrograms.java  |  1 -
 7 files changed, 25 insertions(+), 15 deletions(-)
 create mode 100644 src/main/fragment/mos6502-common/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
 rename src/main/fragment/mos6502-selfmod/{_deref_(pptz1_derefidx_vbuc1)=vbuaa.asm => _deref_(pptz1_derefidx_vbuyy)=vbuaa.asm} (87%)

diff --git a/src/main/fragment/mos6502-common/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm b/src/main/fragment/mos6502-common/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
new file mode 100644
index 000000000..f6cccfc7b
--- /dev/null
+++ b/src/main/fragment/mos6502-common/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
@@ -0,0 +1,9 @@
+pha
+lda ({z1}),y
+sta $fe
+iny
+lda ({z1}),y
+sta $ff
+pla
+ldy #0
+sta ($fe),y
diff --git a/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuxx.asm b/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuxx.asm
index 93e7e2ba9..02216c9fb 100644
--- a/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuxx.asm
+++ b/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuxx.asm
@@ -4,5 +4,4 @@ sta !+ +1
 iny
 lda ({z1}),y
 sta !+ +2
-txa
-!: sta $ffff
+!: stx $ffff
diff --git a/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuaa.asm b/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
similarity index 87%
rename from src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuaa.asm
rename to src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
index 4c93ac158..6671be13c 100644
--- a/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuc1)=vbuaa.asm
+++ b/src/main/fragment/mos6502-selfmod/_deref_(pptz1_derefidx_vbuyy)=vbuaa.asm
@@ -1,5 +1,4 @@
 pha
-ldy #{c1}
 lda ({z1}),y
 sta !+ +1
 iny
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 1c07bb99e..6ddf9b1b9 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -35,9 +35,6 @@ public class Compiler {
     * Currently the optimization is flaky and results in NPE's and wrong values in some programs. */
    private boolean enableLoopHeadConstant = false;
 
-   /** Missing fragments produce a warning instead of an error */
-   private boolean warnFragmentMissing = false;
-
    /** File name of link script to use (from command line parameter). */
    private String linkScriptFileName;
 
@@ -45,12 +42,8 @@ public class Compiler {
       this.program = new Program();
    }
 
-   public boolean isWarnFragmentMissing() {
-      return warnFragmentMissing;
-   }
-
    public void setWarnFragmentMissing(boolean warnFragmentMissing) {
-      this.warnFragmentMissing = warnFragmentMissing;
+      program.setWarnFragmentMissing(warnFragmentMissing);
    }
 
    public void setLinkScriptFileName(String linkScript) {
@@ -509,7 +502,7 @@ public class Compiler {
       new Pass4RegistersFinalize(program).allocate(true);
 
       // Initial Code generation
-      new Pass4CodeGeneration(program, false, warnFragmentMissing).generate();
+      new Pass4CodeGeneration(program, false, program.isWarnFragmentMissing()).generate();
       new Pass4AssertNoCpuClobber(program).check();
       getLog().append("\nINITIAL ASM");
       getLog().append("Target platform is " + program.getTargetPlatform().getName() + " / " +program.getTargetCpu().getName().toUpperCase(Locale.ENGLISH));
@@ -555,7 +548,7 @@ public class Compiler {
 
       // Final ASM code generation before optimization
       program.clearPhiTransitions();
-      new Pass4CodeGeneration(program, false, warnFragmentMissing).generate();
+      new Pass4CodeGeneration(program, false, program.isWarnFragmentMissing()).generate();
       new Pass4AssertNoCpuClobber(program).check();
 
       // Remove unnecessary register savings from interrupts {@link InterruptType#HARDWARE_NOCLOBBER}
diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java
index 5bb1c1176..0abdf2d0d 100644
--- a/src/main/java/dk/camelot64/kickc/model/Program.java
+++ b/src/main/java/dk/camelot64/kickc/model/Program.java
@@ -41,6 +41,9 @@ public class Program {
    /** The ASM fragment synthesizer responsible for loading/synthesizing ASM fragments. Depends on the target CPU. (STATIC) */
    private AsmFragmentTemplateSynthesizer asmFragmentSynthesizer;
 
+   /** Missing fragments produce a warning instead of an error (STATIC) */
+   private boolean warnFragmentMissing = false;
+
    /** Path to any custom link script file used for linking (STATIC) */
    private Path linkScriptFilePath;
    /** Body to any custom link script file used for linking (STATIC) */
@@ -168,6 +171,14 @@ public class Program {
       this.asm = null;
    }
 
+   public boolean isWarnFragmentMissing() {
+      return warnFragmentMissing;
+   }
+
+   public void setWarnFragmentMissing(boolean warnFragmentMissing) {
+      this.warnFragmentMissing = warnFragmentMissing;
+   }
+
    public Path getAsmFragmentCacheFolder() {
       return asmFragmentCacheFolder;
    }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
index b2c62e678..fdb8e10f7 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java
@@ -110,7 +110,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
       // Generate ASM
       try {
          program.clearPhiTransitions();
-         new Pass4CodeGeneration(program, false, false).generate();
+         new Pass4CodeGeneration(program, false, program.isWarnFragmentMissing()).generate();
       } catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
          unknownFragments.add(e.getFragmentSignature());
          if(program.getLog().isVerboseUplift()) {
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 2e39d22de..152223e6c 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.test;
 import dk.camelot64.kickc.CompileLog;
 import dk.camelot64.kickc.Compiler;
 import dk.camelot64.kickc.asm.AsmProgram;
-import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.Program;
 import kickass.KickAssembler;