diff --git a/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuaa.asm b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuaa.asm new file mode 100644 index 000000000..a1c41f23f --- /dev/null +++ b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuaa.asm @@ -0,0 +1,8 @@ +sta $ff +sec +lda {c1},y +sbc $ff +sta {c1},y +lda {c1}+1,y +sbc #0 +sta {c1},y diff --git a/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuxx.asm b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuxx.asm new file mode 100644 index 000000000..83a8ff87e --- /dev/null +++ b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vbuxx.asm @@ -0,0 +1,8 @@ +stx $ff +sec +lda {c1},y +sbc $ff +sta {c1},y +lda {c1}+1,y +sbc #0 +sta {c1},y diff --git a/src/main/java/dk/camelot64/kickc/KickC.java b/src/main/java/dk/camelot64/kickc/KickC.java index 306817769..6e2db8dac 100644 --- a/src/main/java/dk/camelot64/kickc/KickC.java +++ b/src/main/java/dk/camelot64/kickc/KickC.java @@ -1,6 +1,8 @@ package dk.camelot64.kickc; +import dk.camelot64.kickc.fragment.AsmFragmentTemplate; import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer; +import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.Program; import kickass.KickAssembler; @@ -8,6 +10,7 @@ import picocli.CommandLine; import java.io.*; import java.nio.file.*; +import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; @@ -27,7 +30,7 @@ import java.util.concurrent.Callable; ) public class KickC implements Callable { - @CommandLine.Parameters(index = "0", description = "The KickC source file to compile.") + @CommandLine.Parameters(index = "0", arity="0..1", description = "The KickC source file to compile.") private Path kcFile = null; @CommandLine.Option(names = {"-I", "-libdir" }, description = "Path to a library folder, where the compiler looks for included files. This option can be repeated to add multiple library folders.") @@ -87,6 +90,9 @@ public class KickC implements Callable { @CommandLine.Option(names = {"-vasmoptimize" }, description = "Verbosity Option. Assembler optimization.") private boolean verboseAsmOptimize = false; + @CommandLine.Option(names = {"-fragment" }, description = "Print the ASM code for a named fragment. The fragment is loaded/synthesized and the ASM variations are written to the output.") + private String fragment = null; + public static void main(String[] args) { CommandLine.call(new KickC(), args); } @@ -111,121 +117,134 @@ public class KickC implements Callable { AsmFragmentTemplateSynthesizer.initialize("fragment/"); } - String fileBaseName = getFileBaseName(kcFile); - - Path kcFileDir = kcFile.getParent(); - if(kcFileDir==null) { - kcFileDir = FileSystems.getDefault().getPath("."); + if(fragment!=null) { + compiler.getLog().setSysOut(true); + Collection fragmentTemplates = AsmFragmentTemplateSynthesizer.getFragmentTemplates(fragment, compiler.getLog()); + for(AsmFragmentTemplate fragmentTemplate : fragmentTemplates) { + AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, ""); + } + compiler.getLog().setSysOut(false); } - if(outputDir==null) { - outputDir = kcFileDir; - } - if(!Files.exists(outputDir)) { - Files.createDirectory(outputDir); - } + if(kcFile!=null) { - if(asmFileName == null) { - asmFileName = fileBaseName + ".asm"; - } + String fileBaseName = getFileBaseName(kcFile); - if(optimizeUpliftCombinations!=null) { - compiler.setUpliftCombinations(optimizeUpliftCombinations); - } + Path kcFileDir = kcFile.getParent(); + if(kcFileDir == null) { + kcFileDir = FileSystems.getDefault().getPath("."); + } - if(verbose) { - compiler.getLog().setSysOut(true); - } + if(outputDir == null) { + outputDir = kcFileDir; + } + if(!Files.exists(outputDir)) { + Files.createDirectory(outputDir); + } - if(verboseParse) { - compiler.getLog().setVerboseParse(true); - compiler.getLog().setSysOut(true); - } - if(verboseCreateSsa) { - compiler.getLog().setVerboseCreateSsa(true); - compiler.getLog().setSysOut(true); - } - if(verboseSSAOptimize) { - compiler.getLog().setVerboseSSAOptimize(true); - compiler.getLog().setSysOut(true); - } - if(verboseNonOptimization) { - compiler.getLog().setVerboseNonOptimization(true); - compiler.getLog().setSysOut(true); - } - if(verboseSequencePlan) { - compiler.getLog().setVerboseSequencePlan(true); - compiler.getLog().setSysOut(true); - } - if(verboseLoopAnalysis) { - compiler.getLog().setVerboseLoopAnalysis(true); - compiler.getLog().setSysOut(true); - } - if(verboseLoopUnroll) { - compiler.getLog().setVerboseLoopUnroll(true); - compiler.getLog().setSysOut(true); - } - if(verboseLiveRanges) { - compiler.getLog().setVerboseLiveRanges(true); - compiler.getLog().setSysOut(true); - } - if(verboseUplift) { - compiler.getLog().setVerboseUplift(true); - compiler.getLog().setSysOut(true); - } - if(verboseFragments) { - compiler.getLog().setVerboseFragmentLog(true); - compiler.getLog().setSysOut(true); - } - if(verboseAsmOptimize) { - compiler.getLog().setVerboseAsmOptimize(true); - compiler.getLog().setSysOut(true); - } + if(asmFileName == null) { + asmFileName = fileBaseName + ".asm"; + } - System.out.println("Compiling " + kcFile); - Program program = compiler.compile(kcFile.toString()); + if(optimizeUpliftCombinations != null) { + compiler.setUpliftCombinations(optimizeUpliftCombinations); + } - Path asmPath = outputDir.resolve(asmFileName); - System.out.println("Writing asm file " + asmPath); - FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile()); - OutputStreamWriter asmWriter = new OutputStreamWriter(asmOutputStream); - String asmCodeString = program.getAsm().toString(false); - asmWriter.write(asmCodeString); - asmWriter.close(); - asmOutputStream.close(); + if(verbose) { + compiler.getLog().setSysOut(true); + } - // Copy Resource Files (if out-dir is different from in-dir) - if(!kcFileDir.toAbsolutePath().equals(outputDir.toAbsolutePath())) { - for(Path resourcePath : program.getAsmResourceFiles()) { - Path outResourcePath = outputDir.resolve(resourcePath.getFileName().toString()); - System.out.println("Copying resource " + outResourcePath); - try { - Files.copy(resourcePath, outResourcePath); - } catch(FileAlreadyExistsException e) { - // Ignore this + if(verboseParse) { + compiler.getLog().setVerboseParse(true); + compiler.getLog().setSysOut(true); + } + if(verboseCreateSsa) { + compiler.getLog().setVerboseCreateSsa(true); + compiler.getLog().setSysOut(true); + } + if(verboseSSAOptimize) { + compiler.getLog().setVerboseSSAOptimize(true); + compiler.getLog().setSysOut(true); + } + if(verboseNonOptimization) { + compiler.getLog().setVerboseNonOptimization(true); + compiler.getLog().setSysOut(true); + } + if(verboseSequencePlan) { + compiler.getLog().setVerboseSequencePlan(true); + compiler.getLog().setSysOut(true); + } + if(verboseLoopAnalysis) { + compiler.getLog().setVerboseLoopAnalysis(true); + compiler.getLog().setSysOut(true); + } + if(verboseLoopUnroll) { + compiler.getLog().setVerboseLoopUnroll(true); + compiler.getLog().setSysOut(true); + } + if(verboseLiveRanges) { + compiler.getLog().setVerboseLiveRanges(true); + compiler.getLog().setSysOut(true); + } + if(verboseUplift) { + compiler.getLog().setVerboseUplift(true); + compiler.getLog().setSysOut(true); + } + if(verboseFragments) { + compiler.getLog().setVerboseFragmentLog(true); + compiler.getLog().setSysOut(true); + } + if(verboseAsmOptimize) { + compiler.getLog().setVerboseAsmOptimize(true); + compiler.getLog().setSysOut(true); + } + + System.out.println("Compiling " + kcFile); + Program program = compiler.compile(kcFile.toString()); + + Path asmPath = outputDir.resolve(asmFileName); + System.out.println("Writing asm file " + asmPath); + FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile()); + OutputStreamWriter asmWriter = new OutputStreamWriter(asmOutputStream); + String asmCodeString = program.getAsm().toString(false); + asmWriter.write(asmCodeString); + asmWriter.close(); + asmOutputStream.close(); + + // Copy Resource Files (if out-dir is different from in-dir) + if(!kcFileDir.toAbsolutePath().equals(outputDir.toAbsolutePath())) { + for(Path resourcePath : program.getAsmResourceFiles()) { + Path outResourcePath = outputDir.resolve(resourcePath.getFileName().toString()); + System.out.println("Copying resource " + outResourcePath); + try { + Files.copy(resourcePath, outResourcePath); + } catch(FileAlreadyExistsException e) { + // Ignore this + } } } - } - // Assemble the asm-file if instructed - Path prgPath = outputDir.resolve(fileBaseName + ".prg"); - if(assemble || execute) { - Path kasmLogPath = outputDir.resolve(fileBaseName+".klog"); - System.out.println("Assembling to " + prgPath.toString()); - ByteArrayOutputStream kasmLogOutputStream = new ByteArrayOutputStream(); - System.setOut(new PrintStream(kasmLogOutputStream)); - int kasmResult = KickAssembler.main2(new String[]{asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem"}); - System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); - if(kasmResult != 0) { - throw new CompileError("KickAssembling file failed! " + kasmLogOutputStream.toString()); + // Assemble the asm-file if instructed + Path prgPath = outputDir.resolve(fileBaseName + ".prg"); + if(assemble || execute) { + Path kasmLogPath = outputDir.resolve(fileBaseName + ".klog"); + System.out.println("Assembling to " + prgPath.toString()); + ByteArrayOutputStream kasmLogOutputStream = new ByteArrayOutputStream(); + System.setOut(new PrintStream(kasmLogOutputStream)); + int kasmResult = KickAssembler.main2(new String[]{asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem"}); + System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); + if(kasmResult != 0) { + throw new CompileError("KickAssembling file failed! " + kasmLogOutputStream.toString()); + } + } + + // Execute the prg-file if instructed + if(execute) { + System.out.println("Executing " + prgPath); + Process process = Runtime.getRuntime().exec("x64 " + prgPath.toString()); + process.waitFor(); } - } - // Execute the prg-file if instructed - if(execute) { - System.out.println("Executing " + prgPath); - Process process = Runtime.getRuntime().exec("x64 " + prgPath.toString() ); - process.waitFor(); } return null; diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java index 4857ca3a8..bd72a82b7 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateUsages.java @@ -179,13 +179,17 @@ public class AsmFragmentTemplateUsages { log.append(String.format("%8d", usage) + " " + template.getSignature()+" - templates: " + bestTemplates.size()); if(logBody) { for(AsmFragmentTemplate bestTemplate : bestTemplates) { - log.append(" " + (bestTemplate.isFile() ? "*" : "") + bestTemplate.getName() + " - clobber:" + bestTemplate.getClobber().toString() + " cycles:" + bestTemplate.getCycles()); - log.append(" " + bestTemplate.getBody().replace("\n", "\n ")); + logTemplate(log, bestTemplate, " "); } } } } + public static void logTemplate(CompileLog log, AsmFragmentTemplate template, String indent) { + log.append(indent + (template.isFile() ? "*" : "") + template.getName() + " - clobber:" + template.getClobber().toString() + " cycles:" + template.getCycles()); + log.append(indent+ " " + template.getBody().replace("\n", "\n"+indent+" ")); + } + } diff --git a/src/test/java/dk/camelot64/kickc/test/TestFragments.java b/src/test/java/dk/camelot64/kickc/test/TestFragments.java index a6a5a4628..63260a191 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestFragments.java +++ b/src/test/java/dk/camelot64/kickc/test/TestFragments.java @@ -147,6 +147,7 @@ public class TestFragments { /** * Test that a specific fragment can be succesfully loaded/synthesized + * * @param signature The fragment signature */ private void testFragmentExists(String signature) { @@ -156,10 +157,14 @@ public class TestFragments { log.setVerboseFragmentLog(true); List templates = new ArrayList<>(AsmFragmentTemplateSynthesizer.getFragmentTemplates(signature, log)); - if(templates.size()==0) { - System.out.println(log.toString()); + if(templates.size() > 0) { + log.append(""); + for(AsmFragmentTemplate template : templates) { + AsmFragmentTemplateUsages.logTemplate(log, template, ""); + } + log.append(""); } - assertTrue("Fragment cannot be synthesized "+signature, templates.size() > 0); + assertTrue("Fragment cannot be synthesized " + signature, templates.size() > 0); }