From e371d304f646db56c57a7214418b34b6baf8ddcc Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Tue, 16 Jan 2024 08:01:05 +0300 Subject: [PATCH] - Fixed test cases. Full retest of all test cases. - Create the possibility of forward declaration of structs as part of the language. - Generation of forward declarations in the .asm header files. - Treat global variables as part of global memory, even in libraries. Ensure that globals are not overwritten when importing. - Ensure that the various compilation models (stack, var, phi) in combination with the memory models (zp, mem) result in proper execution of code and proper memory allocation etc, etc. - Added the lru-cache logic to properly test the compilation and memory model combinations. (A lot of bugfixes as a result!) --- .../dk/camelot64/kickc/parser/KickCParser.g4 | 7 +- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../dk/camelot64/kickc/asm/AsmFormat.java | 4 +- .../camelot64/kickc/asm/AsmImportLibrary.java | 5 +- .../dk/camelot64/kickc/asm/AsmLibrary.java | 113 +++-- .../dk/camelot64/kickc/model/Program.java | 22 +- .../kickc/model/VariableBuilder.java | 19 +- .../camelot64/kickc/model/symbols/Scope.java | 3 +- .../kickc/model/symbols/Variable.java | 4 + .../Pass0GenerateStatementSequence.java | 56 ++- .../kickc/passes/Pass4CodeGeneration.java | 34 +- .../kickc/passes/Pass4MemoryCoalesce.java | 14 +- .../PassNAsmLibraryGlobalVarsExport.java | 43 ++ src/main/kc/lib/conio-c128.c | 4 +- src/main/kc/lib/cx16-conio.c | 2 +- .../export-global-variables-1/header_copy.h | 5 - .../library/export-global-variables-1/main.c | 20 - .../library/export-global-variables-1/set.c | 23 - .../export-global-variables-2/header_copy.h | 5 - .../library/export-global-variables-2/main.c | 29 -- .../library/export-global-variables-2/set.c | 42 -- .../lru-cache-1-zp-varcall/conio-zp-varcall.c | 25 ++ .../lru-cache-1-zp-varcall.c} | 67 +-- .../lru-cache-zp-varcall.c} | 12 +- .../lru-cache-zp-varcall.h | 65 +++ .../conio-mem-varcall.c | 25 ++ .../lru-cache-2-mem-varcall.c | 97 ++++ .../lru-cache-mem-varcall.c} | 16 +- .../lru-cache-mem-varcall.h | 65 +++ .../conio-zp-stackcall.c} | 17 +- .../lru-cache-3-zp-phicall.c} | 6 +- .../lru-cache-zp-stackcall.c | 418 ++++++++++++++++++ .../lru-cache-zp-stackcall.h} | 2 +- .../conio-mem-stackcall.c | 25 ++ .../lru-cache-4-mem-phicall.c | 90 ++++ .../lru-cache-mem-stackcall.c | 418 ++++++++++++++++++ .../lru-cache-mem-stackcall.h} | 2 +- src/test/kc/library/lru-cache2/conio_var.c | 33 -- src/test/kc/library/printf/printf_lib.c | 12 +- src/test/kc/library/printf/printf_lib.ld | 6 - src/test/kc/library/printf/printf_test.c | 8 +- src/test/kc/library/test1/calc.c | 21 - src/test/kc/library/test1/main.c | 8 - src/test/kc/library/test10-global-zp/calc.c | 37 ++ src/test/kc/library/test10-global-zp/main.c | 16 + src/test/kc/library/test2/calc.c | 33 +- src/test/kc/library/test2/main.c | 7 - src/test/kc/library/test3/calc.c | 23 - src/test/kc/library/test3/main.c | 13 - src/test/kc/library/test4/calc.c | 24 +- src/test/kc/library/test4/main.c | 10 +- src/test/kc/library/test5/calc.c | 21 - src/test/kc/library/test5/main.c | 10 +- .../kc/library/test6-multiple-returns/calc.c | 21 - .../kc/library/test6-multiple-returns/main.c | 10 +- .../kc/library/test7-two-libs-call/main.c | 10 +- src/test/kc/library/test7-two-libs-call/min.c | 6 - .../kc/library/test7-two-libs-call/plus.c | 4 - .../kc/library/test8-two-libs-struct/cx.c | 6 - .../kc/library/test8-two-libs-struct/cy.c | 4 - .../kc/library/test8-two-libs-struct/main.c | 8 - src/test/kc/library/test9-nested/main.c | 8 - src/test/kc/library/test9-nested/min.c | 6 - src/test/kc/library/test9-nested/plus.c | 6 - 64 files changed, 1605 insertions(+), 571 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAsmLibraryGlobalVarsExport.java delete mode 100644 src/test/kc/library/export-global-variables-1/header_copy.h delete mode 100644 src/test/kc/library/export-global-variables-1/main.c delete mode 100644 src/test/kc/library/export-global-variables-1/set.c delete mode 100644 src/test/kc/library/export-global-variables-2/header_copy.h delete mode 100644 src/test/kc/library/export-global-variables-2/main.c delete mode 100644 src/test/kc/library/export-global-variables-2/set.c create mode 100644 src/test/kc/library/lru-cache-1-zp-varcall/conio-zp-varcall.c rename src/test/kc/library/{lru-cache1/lru-cache-test-1.c => lru-cache-1-zp-varcall/lru-cache-1-zp-varcall.c} (52%) rename src/test/kc/library/{lru-cache2/lru-cache.c => lru-cache-1-zp-varcall/lru-cache-zp-varcall.c} (98%) create mode 100644 src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.h create mode 100644 src/test/kc/library/lru-cache-2-mem-varcall/conio-mem-varcall.c create mode 100644 src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-2-mem-varcall.c rename src/test/kc/library/{lru-cache1/lru-cache.c => lru-cache-2-mem-varcall/lru-cache-mem-varcall.c} (98%) create mode 100644 src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.h rename src/test/kc/library/{lru-cache1/conio_var.c => lru-cache-3-zp-stackcall/conio-zp-stackcall.c} (59%) rename src/test/kc/library/{lru-cache2/lru-cache-test-2.c => lru-cache-3-zp-stackcall/lru-cache-3-zp-phicall.c} (92%) create mode 100644 src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.c rename src/test/kc/library/{lru-cache1/lru-cache.h => lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.h} (98%) create mode 100644 src/test/kc/library/lru-cache-4-mem-stackcall/conio-mem-stackcall.c create mode 100644 src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-4-mem-phicall.c create mode 100644 src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.c rename src/test/kc/library/{lru-cache2/lru-cache.h => lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.h} (98%) delete mode 100644 src/test/kc/library/lru-cache2/conio_var.c delete mode 100644 src/test/kc/library/printf/printf_lib.ld create mode 100644 src/test/kc/library/test10-global-zp/calc.c create mode 100644 src/test/kc/library/test10-global-zp/main.c diff --git a/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 b/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 index 56b917ec1..177335baf 100644 --- a/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 +++ b/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 @@ -36,6 +36,7 @@ declSeq decl : declVariables ';' | declFunction + | structForwardDef | structDef ';' | enumDef ';' | pragma @@ -97,8 +98,12 @@ structRef : (STRUCT|UNION) NAME ; +structForwardDef + : (STRUCT|UNION) NAME ';' + ; + structDef - : (STRUCT|UNION) NAME? CURLY_BEGIN structMembers+ CURLY_END + : (STRUCT|UNION) NAME? CURLY_BEGIN structMembers+ CURLY_END #structDefinition ; structMembers diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d34ba9849..208d003da 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -421,6 +421,7 @@ public class Compiler { optimizations.add(new PassNEliminateUnusedVars(program, true)); // Notice sequence is important optimizations.add(new PassNEliminateEmptyProcedure(program)); optimizations.add(new PassNEliminateEmptyStart(program)); + optimizations.add(new PassNAsmLibraryGlobalVarsExport(program)); if(enableLoopHeadConstant) { optimizations.add(new PassNStatementIndices(program)); optimizations.add(() -> { diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmFormat.java b/src/main/java/dk/camelot64/kickc/asm/AsmFormat.java index 3c8bfeca9..5680691a1 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmFormat.java @@ -298,9 +298,9 @@ public class AsmFormat { if(!symbolScopeRef.getFullName().isEmpty()) { if (codeScopeRef instanceof ProcedureRef procedureRef) { Procedure procedure = program.getScope().getProcedure(procedureRef); - String procedureAsmLibraryLabal = procedure.getAsmLibraryLabel(); + String procedureAsmLibraryLabel = procedure.getAsmLibraryLabel(); if (asmLibraryLabel != null) { - if (procedureAsmLibraryLabal != null && procedureAsmLibraryLabal.equals(asmLibraryLabel)) { + if (procedureAsmLibraryLabel != null && procedureAsmLibraryLabel.equals(asmLibraryLabel)) { return asmFix2(symbolScopeRef.getFullName() + "." + asmName, symbolScopeRef.getFullName()); } else { return asmFix2(asmLibraryLabel + "." + symbolScopeRef.getFullName() + "." + asmName, symbolScopeRef.getFullName()); diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmImportLibrary.java b/src/main/java/dk/camelot64/kickc/asm/AsmImportLibrary.java index fe64f1f6a..2d96e2bd7 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmImportLibrary.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmImportLibrary.java @@ -1,9 +1,6 @@ package dk.camelot64.kickc.asm; -import dk.camelot64.kickc.model.symbols.Procedure; - import java.nio.file.Path; -import java.util.HashMap; public class AsmImportLibrary extends AsmLibrary { @@ -15,7 +12,7 @@ public class AsmImportLibrary extends AsmLibrary { public String getAsm() { StringBuilder asm = new StringBuilder(); asm.append(" // Asm import library ").append(getAsmLibraryName()).append(":").append("\n"); - asm.append("#define __asm_import__").append(getLabelName()).append("__").append("\n"); + asm.append("#define __asm_import__").append(getAsmLibraryIdentifier()).append("__").append("\n"); asm.append("#import \"").append(getAsmLibraryName()).append(".asm\"").append("\n"); return asm.toString(); } diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java b/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java index 1038e2c5e..69981ce48 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java @@ -12,28 +12,29 @@ import dk.camelot64.kickc.model.values.*; import java.nio.file.Path; import java.util.*; -/** Define a KickAss library that is exported. */ +/** + * A Kick assembler "library" helper class used to import and export assembler from a C source. + */ public class AsmLibrary extends AsmLine { public String getAsmLibraryName() { - return asmLibraryName.toString(); + return this.asmLibraryName.toString(); } - public String getLabelName() { return asmLibraryName.getAsm(); } + + public String getAsmLibraryIdentifier() { + return this.asmLibraryName.getAsm(); + } + private final AsmIdentifier asmLibraryName; - private final Path resource; - - private final HashMap procedures; - private boolean exportAll; - public AsmLibrary(String asmLibraryName, Path resource, HashMap procedures) { - if(asmLibraryName != null) + if(asmLibraryName!=null) { this.asmLibraryName = new AsmIdentifier(asmLibraryName); - else + } else { this.asmLibraryName = null; - this.resource = resource; + } this.procedures = procedures; } @@ -45,9 +46,8 @@ public class AsmLibrary extends AsmLine { return this.procedures.keySet(); } - public AsmLibrary addProcedure(String procedureName, Procedure.CallingConvention callingConvention) { + public void addProcedure(String procedureName, Procedure.CallingConvention callingConvention) { procedures.put(procedureName, callingConvention); - return this; } public Procedure.CallingConvention getProcedureCallingConvention(String procedureName) { @@ -70,7 +70,7 @@ public class AsmLibrary extends AsmLine { if (param == null) return; if (param.isKindPhiMaster()) { List versions = new ArrayList<>(scope.getVersions(param)); - if (versions.size() > 0) if (param.getLocalName().equals("return")) { + if (!versions.isEmpty()) if (param.getLocalName().equals("return")) { // Choose the last version for return values param = versions.get(versions.size() - 1); } else { @@ -88,18 +88,14 @@ public class AsmLibrary extends AsmLine { zp.add(Integer.toString(registerZp.getZp()+b)); } } - - return; } void generatePrototypeVar(Variable var, StringBuilder signature) { Registers.Register allocation = var.getAllocation(); - if (allocation instanceof Registers.RegisterZpMem) { - Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) allocation; - signature.append("__zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(") "); - } else if (allocation instanceof Registers.RegisterMainMem) { - Registers.RegisterMainMem registerMainMem = (Registers.RegisterMainMem) allocation; - signature.append("__mem(").append(registerMainMem.getAddress() == null ? "" : AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(") "); + if (allocation instanceof Registers.RegisterZpMem registerZp) { + signature.append("__zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(") "); + } else if (allocation instanceof Registers.RegisterMainMem registerMainMem) { + signature.append("__mem(").append(registerMainMem.getAddress() == null ? "" : AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(") "); } else if (allocation instanceof Registers.RegisterAByte) { signature.append("__register(A) "); } else if (allocation instanceof Registers.RegisterXByte) { @@ -136,9 +132,7 @@ public class AsmLibrary extends AsmLine { return param; } - if(!isStackCall) { - generatePrototypeVar(param, signature); - } + generatePrototypeVar(param, signature); return param; } @@ -163,7 +157,8 @@ public class AsmLibrary extends AsmLine { } } Procedure procedure = program.getScope().getProcedure(procedureRef); - for (Symbol symbol : procedure.getSymbols().values()) { + HashMap procedureSymbols = procedure.getSymbols(); + for (Symbol symbol : procedureSymbols.values()) { if (symbol instanceof Variable variable) { generateZPVar(zp, variable, procedure); } @@ -212,6 +207,33 @@ public class AsmLibrary extends AsmLine { return signature.toString(); } + /** + * Generate struct forward declarations for C function prototypes for .asm library import, + * that use structs in the parameters or return values. + * @param procedure The procedure to generate the struct forward for. + * @return A String with the generated function prototype. + */ + private String generateProcedureStructForwards(Procedure procedure, Program program) { + StringBuilder signature = new StringBuilder(); + HashSet structForwards = new HashSet<>(); + + Variable returnVariable = procedure.getLocalVar("return"); + if(returnVariable != null && returnVariable.isStruct()) { + String structReturn = generateVariableStructForward(returnVariable, program); + structForwards.add(structReturn); + } + + for (Variable parameter : procedure.getParameters()) { + if(parameter.isStruct()) { + String paramStruct = generateVariableStructForward(parameter, program); + structForwards.add(paramStruct); + } + } + if(!structForwards.isEmpty()) + signature.append(String.join(";\n", structForwards)).append(";\n"); + return signature.toString(); + } + private boolean hasData(Variable constantVar) { ConstantValue constantValue = constantVar.getInitValue(); if (constantValue instanceof ConstantArray) return true; @@ -233,6 +255,16 @@ public class AsmLibrary extends AsmLine { } } + private String generateVariableStructForward(Variable variable, Program program) { + StringBuilder signature = new StringBuilder(); + if(variable.isStruct()) { + String structName = variable.getType().toCDecl(); + signature.append(structName).append(";\n"); + } + return signature.toString(); + + } + private String generateVariableHeader(Variable variable, Program program) { StringBuilder signature = new StringBuilder(); signature.append("extern "); @@ -264,26 +296,41 @@ public class AsmLibrary extends AsmLine { */ public String generateHeaders(Program program) { StringBuilder headers = new StringBuilder(); - // Generate the global variables headers. + StringBuilder structs = new StringBuilder(); + // Generate the global variables headers. Scope scope = program.getScope().getScope(ScopeRef.ROOT); - Collection scopeConstants = scope.getAllVars(false); - Set added = new LinkedHashSet<>(); + Collection globalVariables = scope.getAllVars(false); + Set zp = new HashSet<>(); // Add all constants arrays incl. strings with data - for (Variable constantVar : scopeConstants) { - if (hasExportAsmLibrary(constantVar, this.getAsmLibraryName())) { - headers.append(generateVariableHeader(constantVar, program)); + for (Variable globalVariable : globalVariables) { + if (hasExportAsmLibrary(globalVariable, this.getAsmLibraryName())) { + if(globalVariable.isMemoryAreaZP()) { + Registers.RegisterZpMem registerZpMem = (Registers.RegisterZpMem)globalVariable.getAllocation(); + if(registerZpMem != null) { + for(byte b=0; b T add(T symbol) { if(symbols.get(symbol.getLocalName()) != null) { - throw new CompileError("Symbol already declared " + symbol.getLocalName()); +// throw new CompileError("Symbol already declared " + symbol.getLocalName()); +// symbols.remove(symbol.getLocalName()); } symbols.put(symbol.getLocalName(), symbol); return symbol; diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java index 43a26ce45..3c424f8d9 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -546,6 +546,10 @@ public class Variable implements Symbol { return MemoryArea.MAIN_MEMORY.equals(getMemoryArea()); } + public boolean isMemoryAreaZP() { + return MemoryArea.ZEROPAGE_MEMORY.equals(getMemoryArea()); + } + public Integer getMemoryAlignment() { return memoryAlignment; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 7ba6d70f3..cf2714f93 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -222,7 +222,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(), StatementSource.NONE, Comment.NO_COMMENTS)); @@ -354,31 +354,41 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor { // Defines that the result is an asm routine or capability library instead of a program. - String asmLibraryName = ""; + String asmLibraryName = null; boolean exportAll = true; if(ctx.pragmaParam().size() == 0) { StatementSource stmtSource = new StatementSource(ctx); Path filePath = Paths.get(stmtSource.getFileName()); - asmLibraryName = filePath.getFileName().toString(); - asmLibraryName = FileNameUtils.removeExtension(asmLibraryName); + String mainBase = program.getOutputFileManager().getOutputBaseName(); + String stmtBase = filePath.getFileName().toString(); + stmtBase = FileNameUtils.removeExtension(stmtBase); + if(mainBase.equals(stmtBase)) { + asmLibraryName = stmtBase; + } } else if(ctx.pragmaParam().size() == 1) { asmLibraryName = pragmaParamString(pragmaParamSingle(ctx)); exportAll = false; } else { throw new CompileError("#pragma asm_library: too many parameters!", new StatementSource(ctx)); } - if(!program.hasAsmImportLibrary(asmLibraryName)) { - program.setAsmLibraryName(asmLibraryName); - program.addAsmExportLibrary(asmLibraryName, exportAll); + if(asmLibraryName != null) { + if(!program.hasAsmImportLibrary(asmLibraryName)) { + program.setAsmLibraryName(asmLibraryName); + program.addAsmExportLibrary(asmLibraryName, exportAll); + } } } case CParser.PRAGMA_ASM_EXPORT -> { // Defines that an C routine is exported into the asm_library. - String libraryName = program.getAsmLibraryName(); - Procedure.CallingConvention callingConvention = currentCallingConvention; - List procedures = pragmaParamAsmExportProcedures(ctx.pragmaParam()); + String asmExportLibraryName = program.getAsmLibraryName(); - AsmExportLibrary asmLibrary = program.addAsmExportLibrary(libraryName, false); - program.addAsmExportProcedures(asmLibrary, callingConvention, procedures); + if(asmExportLibraryName != null) { + // Only export the procedures when there is a library declared in the main program! + // Otherwise ignore the asm_export #pragma. + Procedure.CallingConvention callingConvention = currentCallingConvention; + List procedures = pragmaParamAsmExportProcedures(ctx.pragmaParam()); + AsmExportLibrary asmExportLibrary = program.addAsmExportLibrary(asmExportLibraryName, false); + program.addAsmExportProcedures(asmExportLibrary, callingConvention, procedures); + } } case CParser.PRAGMA_ASM_IMPORT -> { // Defines that an asm routine or capability library is imported into the program. String libraryName = pragmaParamString(pragmaParamFirst(ctx)); @@ -658,6 +668,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor added = new LinkedHashSet<>(); Collection scopeConstants = scope.getAllConstants(false); + String asmExportLibraryName = program.getAsmLibraryName(); - // First add all constants without data that can become constants in KickAsm - for (Variable constantVar : scopeConstants) { - if (!hasData(constantVar)) { - String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName(); - if (asmName != null && !added.contains(asmName)) { - if ((constantVar.getLocalName().equals("SIZEOF_" + var.getType().getConstantFriendlyName()))) { - // Use constant otherwise - added.add(asmName); - // Find the constant value calculation - String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getInitValue(), 99, scopeRef); - addConstant(asmName, constantVar, asmConstant, asm); + if(var.isStruct()) { + String typeVar = "SIZEOF_" + var.getType().getConstantFriendlyName(); + // First add all constants without data that can become constants in KickAsm + for (Variable constantVar : scopeConstants) { + if (!hasData(constantVar)) { + String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName(); + if (asmName != null && !added.contains(asmName)) { + if (constantVar.getLocalName().equals(typeVar)) { + // Use constant otherwise + added.add(asmName); + // Find the constant value calculation + String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getInitValue(), 99, scopeRef); + addConstant(asmName, constantVar, asmConstant, asm); + } } } } @@ -1075,6 +1076,7 @@ public class Pass4CodeGeneration { } else { if (toProcedure.getAsmLibrary() == null) { AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program); + asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL); } else { AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.callBanked(toProcedure, callingDistance, program), program); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java index ced764646..ea4eca44f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java @@ -113,7 +113,10 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base { Collection threads1 = getEquivalenceClassThreads(ec1, program, threadHeads, callGraph); Collection threads2 = getEquivalenceClassThreads(ec2, program, threadHeads, callGraph); if(threads1.isEmpty() || threads2.isEmpty()) { - return true; + // Global variables in .asm libraries are not linked to main because it is not there! + // Therefore, the threads can be empty if the equivalence class concerns a global variable. + // In this case, never coalesce with a global variable (those zero-pages should stay persistent)! + return false; } @@ -147,7 +150,8 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base { ScopeRef scopeRef = variable.getScope().getRef(); if(scopeRef.equals(ScopeRef.ROOT) ) { Procedure localProcedure = program.getScope().getLocalProcedure(SymbolRef.MAIN_PROC_NAME); - if(localProcedure != null && program.getAsmLibraryName() != "") { + // Global variables in .asm libraries are not linked to main because it is not there! + if(localProcedure != null && program.getAsmLibraryName() != null) { ProcedureRef mainThreadHead = localProcedure.getRef(); if(!threads.contains(mainThreadHead)) { threads.add(mainThreadHead); @@ -190,12 +194,14 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base { return false; // check if either are in the reserved zp registers if(register1 instanceof Registers.RegisterZpMem) { - int zp = ((Registers.RegisterZpMem) register1).getZp(); + Integer zp = ((Registers.RegisterZpMem) register1).getZp(); if(program.getReservedZps().contains(zp)) return false; + if(register1.isAddressHardcoded()) + return false; } if(register2 instanceof Registers.RegisterZpMem) { - int zp = ((Registers.RegisterZpMem) register2).getZp(); + Integer zp = ((Registers.RegisterZpMem) register2).getZp(); if(program.getReservedZps().contains(zp)) return false; if(register2.isAddressHardcoded()) diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAsmLibraryGlobalVarsExport.java b/src/main/java/dk/camelot64/kickc/passes/PassNAsmLibraryGlobalVarsExport.java new file mode 100644 index 000000000..e646bb616 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAsmLibraryGlobalVarsExport.java @@ -0,0 +1,43 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Directive; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.VariableReferenceInfos; +import dk.camelot64.kickc.model.statements.*; +import dk.camelot64.kickc.model.symbols.*; +import dk.camelot64.kickc.model.values.LValue; +import dk.camelot64.kickc.model.values.ScopeRef; +import dk.camelot64.kickc.model.values.StructUnwoundPlaceholder; +import dk.camelot64.kickc.model.values.VariableRef; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.ListIterator; +import java.util.Set; + +/** + * Declare all global variables in a library as exported. But only in a library! + */ +public class PassNAsmLibraryGlobalVarsExport extends Pass2SsaOptimization { + + public PassNAsmLibraryGlobalVarsExport(Program program) { + super(program); + } + + @Override + public boolean step() { + boolean modified = false; + Scope scope = getProgram().getScope().getScope(ScopeRef.ROOT); // + Collection scopeConstants = scope.getAllVars(false); + String asmLibraryName = getProgram().getAsmLibraryName(); + if(asmLibraryName != null) { + for (Variable constantVar : scopeConstants) { + if(constantVar.isKindLoadStore()) { + constantVar.setAsmExportLibrary(asmLibraryName); + } + } + } + + return modified; + } +} diff --git a/src/main/kc/lib/conio-c128.c b/src/main/kc/lib/conio-c128.c index be02b2733..1daebd34c 100644 --- a/src/main/kc/lib/conio-c128.c +++ b/src/main/kc/lib/conio-c128.c @@ -1,4 +1,4 @@ -// Commodore 64 conio.h implementation +// Commodore 128 conio.h implementation #include #include @@ -16,7 +16,7 @@ #endif // The default text color #ifndef CONIO_TEXTCOLOR_DEFAULT -#define CONIO_TEXTCOLOR_DEFAULT LIGHT_BLUE +#define CONIO_TEXTCOLOR_DEFAULT LIGHT_GREEN #endif // Use the shared CMB flat memory implementation diff --git a/src/main/kc/lib/cx16-conio.c b/src/main/kc/lib/cx16-conio.c index 248b66d60..f2e415747 100644 --- a/src/main/kc/lib/cx16-conio.c +++ b/src/main/kc/lib/cx16-conio.c @@ -26,7 +26,7 @@ #define CONIO_TEXTCOLOR_DEFAULT WHITE // The default text color #define CONIO_BACKCOLOR_DEFAULT BLUE // The default back color -typedef struct { +typedef struct __cx16_conio_s { unsigned char cursor_x; ///< current cursor x-position unsigned char cursor_y; ///< current cursor y-position unsigned char layer; diff --git a/src/test/kc/library/export-global-variables-1/header_copy.h b/src/test/kc/library/export-global-variables-1/header_copy.h deleted file mode 100644 index 5be853034..000000000 --- a/src/test/kc/library/export-global-variables-1/header_copy.h +++ /dev/null @@ -1,5 +0,0 @@ - -extern __asm_import("set") char set_total; -extern __asm_import("set") char set_array[10]; - -extern __varcall __asm_import("set") __zp_reserve( 2,3 ) __zp(2) char get(__zp(3) char idx); diff --git a/src/test/kc/library/export-global-variables-1/main.c b/src/test/kc/library/export-global-variables-1/main.c deleted file mode 100644 index 2ef99b8f7..000000000 --- a/src/test/kc/library/export-global-variables-1/main.c +++ /dev/null @@ -1,20 +0,0 @@ -#pragma encoding(screencode_mixed) -#pragma var_model(zp) - -#include - -// #include "set.c" - -#include -#include -#include - -__export char r; // Ensure that r does not get deleted by the optimizer by exporting it. - -void main() { - clrscr(); - for(char i=0; i - -//#include "set.c" - -#include -#include -#include - -__export char r; // Ensure that r does not get deleted by the optimizer by exporting it. - -void main() { - clrscr(); - for(char i=0; i - -#define ARRAY_SIZE 10 -#define DUMMY_SIZE 1024 - -struct set_array_s { - char x[ARRAY_SIZE]; - char dummy[DUMMY_SIZE]; - char y[ARRAY_SIZE]; -}; - -__asm_export char set_total = 10; -__asm_export struct set_array_s set_array; - -char get_x(char idx) { - return set_array.x[idx]; -} - -char get_y(char idx) { - return set_array.y[idx]; -} - -void set_x(char idx, char n) { - set_array.x[idx] = n; -} - -void set_y(char idx, char n) { - set_array.y[idx] = n; -} - -char sum2(char idx) { - char r = set_array.x[idx]; - idx++; - r += set_array.y[idx]; - return r; -} diff --git a/src/test/kc/library/lru-cache-1-zp-varcall/conio-zp-varcall.c b/src/test/kc/library/lru-cache-1-zp-varcall/conio-zp-varcall.c new file mode 100644 index 000000000..1153dc59c --- /dev/null +++ b/src/test/kc/library/lru-cache-1-zp-varcall/conio-zp-varcall.c @@ -0,0 +1,25 @@ + +// Create an .asm library of important conio functions. + +#pragma encoding(screencode_mixed) +#pragma var_model(zp) + +#pragma asm_library + +#pragma calling(__stackcall) +#pragma asm_export(cputc) + +#pragma calling(__varcall) +#pragma asm_export(clrscr) +#pragma asm_export(gotoxy) +#pragma asm_export(wherex, wherey) +#pragma asm_export(screensize, screensizex, screensizey, cputln) +#pragma asm_export(cputcxy, cputs, cputsxy, textcolor, bgcolor, bordercolor) +#pragma asm_export(kbhit, cursor, scroll) +#pragma asm_export(screenlayer1, screenlayer2) +#pragma asm_export(cpeekc, cpeekcxy) + +#pragma calling(__phicall) + +#include + diff --git a/src/test/kc/library/lru-cache1/lru-cache-test-1.c b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-1-zp-varcall.c similarity index 52% rename from src/test/kc/library/lru-cache1/lru-cache-test-1.c rename to src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-1-zp-varcall.c index b7a71eb0f..6f58281c6 100644 --- a/src/test/kc/library/lru-cache1/lru-cache-test-1.c +++ b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-1-zp-varcall.c @@ -1,27 +1,21 @@ #pragma var_model(zp) -#include +#include +#include #include #include #include -#include "lru-cache.h" +#include "lru-cache-zp-varcall.h" #include - -volatile unsigned char row = 0; -volatile unsigned char col = 0; -volatile unsigned char count = 0; - -// lru_cache_table_t lru_cache; - +#include <6502.h> void wait_key() { - while (!kbhit()) - ; + // while (!kbhit()) + // ; } - void display() { lru_cache_display(0, 2); @@ -62,28 +56,39 @@ void delete (lru_cache_key_t key) display(); } -void main() { +void main() +{ + SEI(); lru_cache_init(); clrscr(); + scroll(0); - insert(0x0, 0x0); - insert(0x80, 0x80); - insert(0x100, 0x100); - insert(0x1, 0x1); - insert(0x200, 0x200); - insert(0x2, 0x2); - insert(0x82, 0x82); - delete(0x0); - delete(0x100); - delete(0x80); - delete(0x1); - insert(0x201, 0x201); - insert(0x81, 0x81); - delete(0x2); - delete(0x81); - delete(0x201); - delete(0x82); - delete(0x200); + int cache[128]; + + // char ch = kbhit(); + char ch = 0; + do { + if (lru_cache_is_max()) { + lru_cache_key_t last = lru_cache_find_last(); + delete(last); + } else { + lru_cache_key_t key = rand() % 0x20; + lru_cache_data_t data = get(key); + if (data != LRU_CACHE_NOTHING) { + data += 1; + if (data < 20) { + set(key, data); + } else { + delete(key); + } + } else { + insert(key, 0); + } + } + // ch = kbhit(); + } while (ch != 'x'); + + CLI(); } diff --git a/src/test/kc/library/lru-cache2/lru-cache.c b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.c similarity index 98% rename from src/test/kc/library/lru-cache2/lru-cache.c rename to src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.c index 226233e01..392fc32b1 100644 --- a/src/test/kc/library/lru-cache2/lru-cache.c +++ b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.c @@ -10,13 +10,12 @@ * */ -// // Register the compilation as an export library output artefact. -// // There is no main() function! -#pragma asm_library -#pragma calling(__varcall) #pragma var_model(zp) +#pragma asm_library + +#pragma calling(__varcall) #pragma asm_export(lru_cache_init) #pragma asm_export(lru_cache_find_last) #pragma asm_export(lru_cache_is_max) @@ -30,10 +29,13 @@ #pragma calling(__phicall) +#include + #define LRU_CACHE_MAX 24 #define LRU_CACHE_SIZE 32 -#include "lru-cache.h" +#include "lru-cache-zp-varcall.h" + #include #include #include diff --git a/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.h b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.h new file mode 100644 index 000000000..2f0a63ddd --- /dev/null +++ b/src/test/kc/library/lru-cache-1-zp-varcall/lru-cache-zp-varcall.h @@ -0,0 +1,65 @@ +/** + * @file lru_cache.h + * @author Sven Van de Velde (sven.van.de.velde@telenet.be) + * @brief Least Recently Used Cache using a hash table and a double linked list, searchable. + * To store fast and retrieve fast elements from an array. To search fast the last used element and delete it. + * @version 0.1 + * @date 2022-09-02 + * + * @copyright Copyright (c) 2022 + * + */ + + + +#ifndef LRU_CACHE_SIZE + #define LRU_CACHE_SIZE 128 +#endif + +#ifndef LRU_CACHE_MAX + #define LRU_CACHE_MAX 96 +#endif + + +#define LRU_CACHE_NOTHING 0xFFFF +#define LRU_CACHE_USED 0xFFFE + +#define LRU_CACHE_INDEX_NULL 0xFF + + +typedef unsigned int lru_cache_key_t; +typedef unsigned int lru_cache_data_t; +typedef unsigned char lru_cache_index_t; + + + +typedef struct lru_cache_table_s { + lru_cache_key_t key[LRU_CACHE_SIZE]; + lru_cache_data_t data[LRU_CACHE_SIZE]; + lru_cache_index_t prev[LRU_CACHE_SIZE]; + lru_cache_index_t next[LRU_CACHE_SIZE]; + lru_cache_index_t link[LRU_CACHE_SIZE]; + lru_cache_index_t count; + lru_cache_index_t first; + lru_cache_index_t last; + lru_cache_index_t size; +} lru_cache_table_t; + + +void lru_cache_init(); + +lru_cache_index_t lru_cache_hash(lru_cache_key_t key); + +lru_cache_key_t lru_cache_find_last(); +inline bool lru_cache_is_max(); + +lru_cache_index_t lru_cache_index(lru_cache_key_t key); +lru_cache_data_t lru_cache_get(lru_cache_index_t index); +lru_cache_data_t lru_cache_set(lru_cache_index_t index, lru_cache_data_t data); +lru_cache_data_t lru_cache_data(lru_cache_index_t index); + +lru_cache_index_t lru_cache_insert(lru_cache_key_t key, lru_cache_data_t data); +lru_cache_data_t lru_cache_delete(lru_cache_key_t key); + +void lru_cache_display(char x, char y); + diff --git a/src/test/kc/library/lru-cache-2-mem-varcall/conio-mem-varcall.c b/src/test/kc/library/lru-cache-2-mem-varcall/conio-mem-varcall.c new file mode 100644 index 000000000..5e22dc2d9 --- /dev/null +++ b/src/test/kc/library/lru-cache-2-mem-varcall/conio-mem-varcall.c @@ -0,0 +1,25 @@ + +// Create an .asm library of important conio functions. + +#pragma encoding(screencode_mixed) +#pragma var_model(mem) + +#pragma asm_library + +#pragma calling(__stackcall) +#pragma asm_export(cputc) + +#pragma calling(__varcall) +#pragma asm_export(clrscr) +#pragma asm_export(gotoxy) +#pragma asm_export(wherex, wherey) +#pragma asm_export(screensize, screensizex, screensizey, cputln) +#pragma asm_export(cputcxy, cputs, cputsxy, textcolor, bgcolor, bordercolor) +#pragma asm_export(kbhit, cursor, scroll) +#pragma asm_export(screenlayer1, screenlayer2) +#pragma asm_export(cpeekc, cpeekcxy) + +#pragma calling(__phicall) + +#include + diff --git a/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-2-mem-varcall.c b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-2-mem-varcall.c new file mode 100644 index 000000000..ad68d7c12 --- /dev/null +++ b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-2-mem-varcall.c @@ -0,0 +1,97 @@ +#pragma var_model(mem) + +// #include +#include + +#include +#include +#include +#include "lru-cache-mem-varcall.h" +#include +#include <6502.h> + +void wait_key() +{ + // while (!kbhit()) + // ; +} + +void display() +{ + lru_cache_display(0, 2); + wait_key(); +} + +lru_cache_data_t get(lru_cache_key_t key) +{ + gotoxy(0, 0); + printf("get: %04x ", key); + lru_cache_data_t data = lru_cache_get(lru_cache_index(key)); + printf(":%04x", data); + display(); + return data; +} + +void set(lru_cache_key_t key, lru_cache_data_t data) +{ + gotoxy(0, 0); + printf("set: %04x:%04x", key, data); + lru_cache_set(lru_cache_index(key), data); + display(); +} + +void insert(lru_cache_key_t key, lru_cache_data_t data) +{ + gotoxy(0, 0); + printf("add: %04x:%04x ", key, data); + lru_cache_insert(key, data); + display(); +} + +void delete (lru_cache_key_t key) +{ + gotoxy(0, 0); + printf("del: %04x ", key); + lru_cache_delete(key); + display(); +} + +void main() +{ + + SEI(); + + + lru_cache_init(); + + clrscr(); + scroll(0); + + int cache[128]; + + // char ch = kbhit(); + char ch = 0; + do { + if (lru_cache_is_max()) { + lru_cache_key_t last = lru_cache_find_last(); + delete(last); + } else { + lru_cache_key_t key = rand() % 0x20; + lru_cache_data_t data = get(key); + if (data != LRU_CACHE_NOTHING) { + data += 1; + if (data < 20) { + set(key, data); + } else { + delete(key); + } + } else { + insert(key, 0); + } + } + // ch = kbhit(); + } while (ch != 'x'); + +CLI(); + +} diff --git a/src/test/kc/library/lru-cache1/lru-cache.c b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.c similarity index 98% rename from src/test/kc/library/lru-cache1/lru-cache.c rename to src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.c index b7003108f..e07601916 100644 --- a/src/test/kc/library/lru-cache1/lru-cache.c +++ b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.c @@ -1,3 +1,4 @@ + /** * @file lru-cache.c * @author Sven Van de Velde (sven.van.de.velde@telenet.be) @@ -10,13 +11,11 @@ * */ -// // Register the compilation as an export library output artefact. -// // There is no main() function! +#pragma var_model(mem, local_mem, global_zp, parameter_zp) + #pragma asm_library + #pragma calling(__varcall) - -#pragma var_model(zp) - #pragma asm_export(lru_cache_init) #pragma asm_export(lru_cache_find_last) #pragma asm_export(lru_cache_is_max) @@ -30,10 +29,13 @@ #pragma calling(__phicall) +#include + #define LRU_CACHE_MAX 24 #define LRU_CACHE_SIZE 32 -#include "lru-cache.h" +#include "lru-cache-mem-varcall.h" + #include #include #include @@ -405,7 +407,7 @@ void lru_cache_display(char x, char y) { lru_cache_index_t count = 0; col = 0; - while (count < 8) { + while (count < 6) { if (count < lru_cache.count) printf(" %4x", lru_cache.key[index]); else diff --git a/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.h b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.h new file mode 100644 index 000000000..2f0a63ddd --- /dev/null +++ b/src/test/kc/library/lru-cache-2-mem-varcall/lru-cache-mem-varcall.h @@ -0,0 +1,65 @@ +/** + * @file lru_cache.h + * @author Sven Van de Velde (sven.van.de.velde@telenet.be) + * @brief Least Recently Used Cache using a hash table and a double linked list, searchable. + * To store fast and retrieve fast elements from an array. To search fast the last used element and delete it. + * @version 0.1 + * @date 2022-09-02 + * + * @copyright Copyright (c) 2022 + * + */ + + + +#ifndef LRU_CACHE_SIZE + #define LRU_CACHE_SIZE 128 +#endif + +#ifndef LRU_CACHE_MAX + #define LRU_CACHE_MAX 96 +#endif + + +#define LRU_CACHE_NOTHING 0xFFFF +#define LRU_CACHE_USED 0xFFFE + +#define LRU_CACHE_INDEX_NULL 0xFF + + +typedef unsigned int lru_cache_key_t; +typedef unsigned int lru_cache_data_t; +typedef unsigned char lru_cache_index_t; + + + +typedef struct lru_cache_table_s { + lru_cache_key_t key[LRU_CACHE_SIZE]; + lru_cache_data_t data[LRU_CACHE_SIZE]; + lru_cache_index_t prev[LRU_CACHE_SIZE]; + lru_cache_index_t next[LRU_CACHE_SIZE]; + lru_cache_index_t link[LRU_CACHE_SIZE]; + lru_cache_index_t count; + lru_cache_index_t first; + lru_cache_index_t last; + lru_cache_index_t size; +} lru_cache_table_t; + + +void lru_cache_init(); + +lru_cache_index_t lru_cache_hash(lru_cache_key_t key); + +lru_cache_key_t lru_cache_find_last(); +inline bool lru_cache_is_max(); + +lru_cache_index_t lru_cache_index(lru_cache_key_t key); +lru_cache_data_t lru_cache_get(lru_cache_index_t index); +lru_cache_data_t lru_cache_set(lru_cache_index_t index, lru_cache_data_t data); +lru_cache_data_t lru_cache_data(lru_cache_index_t index); + +lru_cache_index_t lru_cache_insert(lru_cache_key_t key, lru_cache_data_t data); +lru_cache_data_t lru_cache_delete(lru_cache_key_t key); + +void lru_cache_display(char x, char y); + diff --git a/src/test/kc/library/lru-cache1/conio_var.c b/src/test/kc/library/lru-cache-3-zp-stackcall/conio-zp-stackcall.c similarity index 59% rename from src/test/kc/library/lru-cache1/conio_var.c rename to src/test/kc/library/lru-cache-3-zp-stackcall/conio-zp-stackcall.c index ce856df66..6eec52b36 100644 --- a/src/test/kc/library/lru-cache1/conio_var.c +++ b/src/test/kc/library/lru-cache-3-zp-stackcall/conio-zp-stackcall.c @@ -1,15 +1,15 @@ -// Create an .asm library of imporant conio functions. -// Export to conio_var.asm +// Create an .asm library of important conio functions. #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Declare this compilation to generate the conio_var_asm file! #pragma asm_library -// Declare the procedures to be exported to the .asm libary with the indicated calling convention. -#pragma calling(__varcall) +#pragma calling(__stackcall) +#pragma asm_export(cputc) + +#pragma calling(__stackcall) #pragma asm_export(__conio_var_start, conio_x16_init) #pragma asm_export(clrscr) #pragma asm_export(gotoxy) @@ -20,14 +20,7 @@ #pragma asm_export(screenlayer1, screenlayer2) #pragma asm_export(cpeekc, cpeekcxy) -#pragma calling(__stackcall) -#pragma asm_export(cputc ) - #pragma calling(__phicall) -// Allocate local procedure variables to memory. -#pragma var_model(zp) - #include -//#include diff --git a/src/test/kc/library/lru-cache2/lru-cache-test-2.c b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-3-zp-phicall.c similarity index 92% rename from src/test/kc/library/lru-cache2/lru-cache-test-2.c rename to src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-3-zp-phicall.c index 7ec162ba4..dcaa3164f 100644 --- a/src/test/kc/library/lru-cache2/lru-cache-test-2.c +++ b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-3-zp-phicall.c @@ -1,11 +1,13 @@ #pragma var_model(zp) +#pragma calling(__phicall) -#include +#include +#include #include #include #include -#include "lru-cache.h" +#include "lru-cache-zp-stackcall.h" #include void wait_key() diff --git a/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.c b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.c new file mode 100644 index 000000000..e847836b0 --- /dev/null +++ b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.c @@ -0,0 +1,418 @@ +/** + * @file lru-cache.c + * @author Sven Van de Velde (sven.van.de.velde@telenet.be) + * @brief Least Recently Used Cache using a hash table and a double linked list, searchable. + * To store fast and retrieve fast elements from an array. To search fast the last used element and delete it. + * @version 0.1 + * @date 2022-09-02 + * + * @copyright Copyright (c) 2022 + * + */ + +#pragma var_model(zp) + +#pragma asm_library + +#pragma calling(__stackcall) +#pragma asm_export(lru_cache_init) +#pragma asm_export(lru_cache_find_last) +#pragma asm_export(lru_cache_is_max) +#pragma asm_export(lru_cache_index) +#pragma asm_export(lru_cache_get) +#pragma asm_export(lru_cache_set) +#pragma asm_export(lru_cache_data) +#pragma asm_export(lru_cache_insert) +#pragma asm_export(lru_cache_delete) +#pragma asm_export(lru_cache_display) + +#pragma calling(__phicall) + +#include + +#define LRU_CACHE_MAX 24 +#define LRU_CACHE_SIZE 32 + +#include "lru-cache-zp-stackcall.h" +#include +#include +#include +#include + +lru_cache_table_t lru_cache; + +void lru_cache_init() +{ + // The size of the elements can never exceed 256 bytes!!! + memset_fast(lru_cache.key, 0xFF, sizeof(lru_cache_key_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.data, 0xFF, sizeof(lru_cache_data_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.next, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.prev, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.link, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + lru_cache.first = 0xFF; + lru_cache.last = 0xFF; + lru_cache.count = 0; + lru_cache.size = LRU_CACHE_SIZE; +} + +// __mem unsigned char lru_cache_seed; + +lru_cache_index_t lru_cache_hash(lru_cache_key_t key) +{ + lru_cache_index_t hash_result = (lru_cache_index_t)(key % LRU_CACHE_SIZE); + return hash_result; +} + +// inline lru_cache_index_t lru_cache_hash(lru_cache_key_t key) { +// lru_cache_seed = key; +// asm { +// lda lru_cache_seed +// beq !doEor+ +// asl +// beq !noEor+ +// bcc !noEor+ +// !doEor: eor #$2b +// !noEor: sta lru_cache_seed +// } +// return lru_cache_seed % LRU_CACHE_SIZE; +// } + +inline bool lru_cache_is_max() +{ + return lru_cache.count >= LRU_CACHE_MAX; +} + +lru_cache_key_t lru_cache_find_last() +{ + return lru_cache.key[lru_cache.last]; +} + +lru_cache_index_t lru_cache_find_empty(lru_cache_index_t index) +{ + while (lru_cache.key[index] != LRU_CACHE_NOTHING) { + index++; + index %= LRU_CACHE_SIZE; + } + return index; +} + +lru_cache_index_t lru_cache_find_duplicate(lru_cache_index_t index, lru_cache_index_t link) +{ + // First find the last duplicate node. + while (lru_cache.link[index] != link && lru_cache.link[index] != LRU_CACHE_INDEX_NULL) { + index = lru_cache.link[index]; + } + return index; +} + +lru_cache_index_t lru_cache_index(lru_cache_key_t key) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // Search till index == 0xFF, following the links. + while (index != LRU_CACHE_INDEX_NULL) { + if (lru_cache.key[index] == key) { + return index; + } + index = lru_cache.link[index]; + } + return LRU_CACHE_INDEX_NULL; +} + +lru_cache_data_t lru_cache_get(lru_cache_index_t index) +{ + if (index != LRU_CACHE_INDEX_NULL) { + lru_cache_data_t data = lru_cache.data[index]; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + // Delete the node from the list. + lru_cache.next[prev] = next; + //lru_cache.next[next] = prev; + lru_cache.prev[next] = prev; + //lru_cache.prev[prev] = next; + + // Reassign first and last node. + if (index == lru_cache.first) { + lru_cache.first = next; + } + if (index == lru_cache.last) { + lru_cache.last = prev; + } + + // Now insert the node as the first node in the list. + + lru_cache.next[index] = lru_cache.first; + lru_cache.prev[lru_cache.first] = index; + lru_cache.next[lru_cache.last] = index; + lru_cache.prev[index] = lru_cache.last; + + // Now the first node in the list is the node referenced! + // All other nodes are moved one position down! + lru_cache.first = index; + lru_cache.last = lru_cache.prev[index]; + + return data; + } + return LRU_CACHE_NOTHING; +} + +lru_cache_data_t lru_cache_set(lru_cache_index_t index, lru_cache_data_t data) +{ + if (index != LRU_CACHE_INDEX_NULL) { + lru_cache.data[index] = data; + lru_cache_data_t data = lru_cache_get(index); + return data; + } + return LRU_CACHE_NOTHING; +} + + +lru_cache_data_t lru_cache_data(lru_cache_index_t index) +{ + return lru_cache.data[index]; +} + + +inline void lru_cache_move_link(lru_cache_index_t link, lru_cache_index_t index) +{ + // Here we move the node at the index to the new link, and set the head link to the new link. + + lru_cache_index_t l = lru_cache.link[index]; + lru_cache.link[link] = l; + + // This results in incorrect code! + // lru_cache.key[link] = lru_cache.key[index]; + // lru_cache.data[link] = lru_cache.data[index]; + + lru_cache_key_t key = lru_cache.key[index]; + lru_cache.key[link] = key; + lru_cache_data_t data = lru_cache.data[index]; + lru_cache.data[link] = data; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + lru_cache.next[link] = next; + lru_cache.prev[link] = prev; + + lru_cache.next[prev] = link; + lru_cache.prev[next] = link; + + // todo first and last + if (lru_cache.last == index) { + lru_cache.last = link; + } + + if (lru_cache.first == index) { + lru_cache.first = link; + } + + lru_cache.key[index] = LRU_CACHE_NOTHING; + lru_cache.data[index] = LRU_CACHE_NOTHING; + lru_cache.next[index] = LRU_CACHE_INDEX_NULL; + lru_cache.prev[index] = LRU_CACHE_INDEX_NULL; + lru_cache.link[index] = LRU_CACHE_INDEX_NULL; +} + +lru_cache_index_t lru_cache_find_head(lru_cache_index_t index) +{ + lru_cache_key_t key_link = lru_cache.key[index]; + lru_cache_index_t head_link = lru_cache_hash(key_link); + if (head_link != index) { + return head_link; + } else { + return LRU_CACHE_INDEX_NULL; + } +} + +lru_cache_index_t lru_cache_insert(lru_cache_key_t key, lru_cache_data_t data) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // Check if there is already a link node in place in the hash table at the index. + + lru_cache_index_t link_head = lru_cache_find_head(index); + lru_cache_index_t link_prev = lru_cache_find_duplicate(link_head, index); + + if (lru_cache.key[index] != LRU_CACHE_NOTHING && link_head != LRU_CACHE_INDEX_NULL) { + // There is already a link node, so this node is not a head node and needs to be moved. + // Get the head node of this chain, we know this because we can get the head of the key. + // The link of the head_link must be changed once the new place of the link node has been found. + lru_cache_index_t link = lru_cache_find_empty(index); + lru_cache_move_link(link, index); + lru_cache.link[link_prev] = link; + } + + // The index is at the head of a chain and is either duplicates or empty. + + // We just follow the duplicate chain and find the last duplicate. + lru_cache_index_t index_prev = lru_cache_find_duplicate(index, LRU_CACHE_INDEX_NULL); + + // From the last duplicate position, we search for the first free node. + index = lru_cache_find_empty(index_prev); + + // We set the link of the free node to INDEX_NULL, + // and point the link of the previous node to the empty node. + // index != index_prev indicates there is a duplicate chain. + lru_cache.link[index] = LRU_CACHE_INDEX_NULL; + if (index_prev != index) { + lru_cache.link[index_prev] = index; + } + + // Now assign the key and the data. + lru_cache.key[index] = key; + lru_cache.data[index] = data; + + // And set the lru chain. + if (lru_cache.first == 0xff) { + lru_cache.first = index; + } + if (lru_cache.last == 0xff) { + lru_cache.last = index; + } + + // Now insert the node as the first node in the list. + lru_cache.next[index] = lru_cache.first; + lru_cache.prev[lru_cache.first] = index; + + lru_cache.next[lru_cache.last] = index; + lru_cache.prev[index] = lru_cache.last; + + lru_cache.first = index; + + lru_cache.count++; + + return index; +} + + +lru_cache_data_t lru_cache_delete(lru_cache_key_t key) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // move in array until an empty + lru_cache_index_t index_prev = LRU_CACHE_INDEX_NULL; + while (lru_cache.key[index] != LRU_CACHE_NOTHING) { + + if (lru_cache.key[index] == key) { + + lru_cache_data_t data = lru_cache.data[index]; + + // First remove the index node. + lru_cache.key[index] = LRU_CACHE_NOTHING; + lru_cache.data[index] = LRU_CACHE_NOTHING; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + lru_cache.next[index] = LRU_CACHE_INDEX_NULL; + lru_cache.prev[index] = LRU_CACHE_INDEX_NULL; + if (lru_cache.next[index] == index) { + // Reset first and last node. + lru_cache.first = 0xff; + lru_cache.last = 0xff; + } else { + // Delete the node from the list. + lru_cache.next[prev] = next; + lru_cache.prev[next] = prev; + // Reassign first and last node. + if (index == lru_cache.first) { + lru_cache.first = next; + } + if (index == lru_cache.last) { + lru_cache.last = prev; + } + } + + lru_cache_index_t link = lru_cache.link[index]; + + if (index_prev != LRU_CACHE_INDEX_NULL) { + // The node is not the first node but the middle of a list. + lru_cache.link[index_prev] = link; + } + + if (link != LRU_CACHE_INDEX_NULL) { + // The head is the start of a duplicate chain. + // Simply move the next node in the duplicate chain as the new head. + lru_cache_move_link(index, link); + } + + + lru_cache.count--; + + return data; + } + + index_prev = index; + index = lru_cache.link[index]; + } + + return LRU_CACHE_NOTHING; +} + +// Only for debugging +void lru_cache_display(char x, char y) { + unsigned char col = 0; + + gotoxy(x, y); + + printf("least recently used cache statistics\n"); + printf("size:%02x, first:%02x, last:%02x, cnt:%2x\n\n", LRU_CACHE_SIZE, lru_cache.first, lru_cache.last, lru_cache.count); + + printf(" "); + do { + printf(" %1x/%1x ", col, col + 8); + col++; + } while (col < 4); + printf("\n"); + + col = 0; + lru_cache_index_t index_row = 0; + do { + + lru_cache_index_t index = index_row; + printf("%02x:", index); + do { + if (lru_cache.key[index] != LRU_CACHE_NOTHING) { + printf(" %04x:", lru_cache.key[index]); + printf("%02x", lru_cache.link[index]); + } else { + printf(" ----:--"); + } + index++; + } while (index < index_row + 4); + printf("\n"); + + index = index_row; + printf(" :"); + do { + printf(" %02x:", lru_cache.next[index]); + printf("%02x ", lru_cache.prev[index]); + index++; + } while (index < index_row + 4); + printf("\n"); + + index_row += 4; + } while (index_row < 4*4*2); + + printf("\n"); + + printf("least recently used sequence\n"); + + lru_cache_index_t index = lru_cache.first; + lru_cache_index_t count = 0; + col = 0; + + while (count < 6) { + if (count < lru_cache.count) + printf(" %4x", lru_cache.key[index]); + else + printf(" "); + //printf(" %4x %3uN %3uP ", lru_cache.key[cache_index], lru_cache.next[cache_index], lru_cache.prev[cache_index]); + + index = lru_cache.next[index]; + count++; + } +} diff --git a/src/test/kc/library/lru-cache1/lru-cache.h b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.h similarity index 98% rename from src/test/kc/library/lru-cache1/lru-cache.h rename to src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.h index b377f5d14..a73a39f74 100644 --- a/src/test/kc/library/lru-cache1/lru-cache.h +++ b/src/test/kc/library/lru-cache-3-zp-stackcall/lru-cache-zp-stackcall.h @@ -33,7 +33,7 @@ typedef unsigned char lru_cache_index_t; -typedef struct { +typedef struct lru_cache_s { lru_cache_key_t key[LRU_CACHE_SIZE]; lru_cache_data_t data[LRU_CACHE_SIZE]; lru_cache_index_t prev[LRU_CACHE_SIZE]; diff --git a/src/test/kc/library/lru-cache-4-mem-stackcall/conio-mem-stackcall.c b/src/test/kc/library/lru-cache-4-mem-stackcall/conio-mem-stackcall.c new file mode 100644 index 000000000..7d3be5b90 --- /dev/null +++ b/src/test/kc/library/lru-cache-4-mem-stackcall/conio-mem-stackcall.c @@ -0,0 +1,25 @@ + +// Create an .asm library of important conio functions. + +#pragma encoding(screencode_mixed) +#pragma var_model(mem) + +#pragma asm_library + +#pragma calling(__stackcall) +#pragma asm_export(cputc) + +#pragma calling(__stackcall) +#pragma asm_export(clrscr) +#pragma asm_export(gotoxy) +#pragma asm_export(wherex, wherey) +#pragma asm_export(screensize, screensizex, screensizey, cputln) +#pragma asm_export(cputcxy, cputs, cputsxy, textcolor, bgcolor, bordercolor) +#pragma asm_export(kbhit, cursor, scroll, cscroll) +#pragma asm_export(screenlayer1, screenlayer2) +#pragma asm_export(cpeekc, cpeekcxy) + +#pragma calling(__phicall) + +#include + diff --git a/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-4-mem-phicall.c b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-4-mem-phicall.c new file mode 100644 index 000000000..9c057a78c --- /dev/null +++ b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-4-mem-phicall.c @@ -0,0 +1,90 @@ +#pragma var_model(mem) +#pragma calling(__phicall) + +#include +#include + +#include +#include +#include +#include "lru-cache-mem-stackcall.h" +#include + +void wait_key() +{ + // while (!kbhit()) + // ; +} + +void display() +{ + lru_cache_display(0, 2); + wait_key(); +} + +lru_cache_data_t get(lru_cache_key_t key) +{ + gotoxy(0, 0); + printf("get: %04x ", key); + lru_cache_data_t data = lru_cache_get(lru_cache_index(key)); + printf(":%04x", data); + display(); + return data; +} + +void set(lru_cache_key_t key, lru_cache_data_t data) +{ + gotoxy(0, 0); + printf("set: %04x:%04x", key, data); + lru_cache_set(lru_cache_index(key), data); + display(); +} + +void insert(lru_cache_key_t key, lru_cache_data_t data) +{ + gotoxy(0, 0); + printf("add: %04x:%04x ", key, data); + lru_cache_insert(key, data); + display(); +} + +void delete (lru_cache_key_t key) +{ + gotoxy(0, 0); + printf("del: %04x ", key); + lru_cache_delete(key); + display(); +} + +void main() +{ + lru_cache_init(); + + clrscr(); + scroll(0); + + int cache[128]; + + // char ch = kbhit(); + char ch = 0; + do { + if (lru_cache_is_max()) { + lru_cache_key_t last = lru_cache_find_last(); + delete(last); + } else { + lru_cache_key_t key = rand() % 0x20; + lru_cache_data_t data = get(key); + if (data != LRU_CACHE_NOTHING) { + data += 1; + if (data < 20) { + set(key, data); + } else { + delete(key); + } + } else { + insert(key, 0); + } + } + // ch = kbhit(); + } while (ch != 'x'); +} diff --git a/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.c b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.c new file mode 100644 index 000000000..208575a6e --- /dev/null +++ b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.c @@ -0,0 +1,418 @@ +/** + * @file lru-cache.c + * @author Sven Van de Velde (sven.van.de.velde@telenet.be) + * @brief Least Recently Used Cache using a hash table and a double linked list, searchable. + * To store fast and retrieve fast elements from an array. To search fast the last used element and delete it. + * @version 0.1 + * @date 2022-09-02 + * + * @copyright Copyright (c) 2022 + * + */ + +#pragma var_model(mem) + +#pragma asm_library + +#pragma calling(__stackcall) +#pragma asm_export(lru_cache_init) +#pragma asm_export(lru_cache_find_last) +#pragma asm_export(lru_cache_is_max) +#pragma asm_export(lru_cache_index) +#pragma asm_export(lru_cache_get) +#pragma asm_export(lru_cache_set) +#pragma asm_export(lru_cache_data) +#pragma asm_export(lru_cache_insert) +#pragma asm_export(lru_cache_delete) +#pragma asm_export(lru_cache_display) + +#pragma calling(__phicall) + +#include + +#define LRU_CACHE_MAX 24 +#define LRU_CACHE_SIZE 32 + +#include "lru-cache-mem-stackcall.h" +#include +#include +#include +#include + +lru_cache_table_t lru_cache; + +void lru_cache_init() +{ + // The size of the elements can never exceed 256 bytes!!! + memset_fast(lru_cache.key, 0xFF, sizeof(lru_cache_key_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.data, 0xFF, sizeof(lru_cache_data_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.next, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.prev, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + memset_fast(lru_cache.link, 0xFF, sizeof(lru_cache_index_t)*LRU_CACHE_SIZE); + lru_cache.first = 0xFF; + lru_cache.last = 0xFF; + lru_cache.count = 0; + lru_cache.size = LRU_CACHE_SIZE; +} + +// __mem unsigned char lru_cache_seed; + +lru_cache_index_t lru_cache_hash(lru_cache_key_t key) +{ + lru_cache_index_t hash_result = (lru_cache_index_t)(key % LRU_CACHE_SIZE); + return hash_result; +} + +// inline lru_cache_index_t lru_cache_hash(lru_cache_key_t key) { +// lru_cache_seed = key; +// asm { +// lda lru_cache_seed +// beq !doEor+ +// asl +// beq !noEor+ +// bcc !noEor+ +// !doEor: eor #$2b +// !noEor: sta lru_cache_seed +// } +// return lru_cache_seed % LRU_CACHE_SIZE; +// } + +inline bool lru_cache_is_max() +{ + return lru_cache.count >= LRU_CACHE_MAX; +} + +lru_cache_key_t lru_cache_find_last() +{ + return lru_cache.key[lru_cache.last]; +} + +lru_cache_index_t lru_cache_find_empty(lru_cache_index_t index) +{ + while (lru_cache.key[index] != LRU_CACHE_NOTHING) { + index++; + index %= LRU_CACHE_SIZE; + } + return index; +} + +lru_cache_index_t lru_cache_find_duplicate(lru_cache_index_t index, lru_cache_index_t link) +{ + // First find the last duplicate node. + while (lru_cache.link[index] != link && lru_cache.link[index] != LRU_CACHE_INDEX_NULL) { + index = lru_cache.link[index]; + } + return index; +} + +lru_cache_index_t lru_cache_index(lru_cache_key_t key) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // Search till index == 0xFF, following the links. + while (index != LRU_CACHE_INDEX_NULL) { + if (lru_cache.key[index] == key) { + return index; + } + index = lru_cache.link[index]; + } + return LRU_CACHE_INDEX_NULL; +} + +lru_cache_data_t lru_cache_get(lru_cache_index_t index) +{ + if (index != LRU_CACHE_INDEX_NULL) { + lru_cache_data_t data = lru_cache.data[index]; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + // Delete the node from the list. + lru_cache.next[prev] = next; + //lru_cache.next[next] = prev; + lru_cache.prev[next] = prev; + //lru_cache.prev[prev] = next; + + // Reassign first and last node. + if (index == lru_cache.first) { + lru_cache.first = next; + } + if (index == lru_cache.last) { + lru_cache.last = prev; + } + + // Now insert the node as the first node in the list. + + lru_cache.next[index] = lru_cache.first; + lru_cache.prev[lru_cache.first] = index; + lru_cache.next[lru_cache.last] = index; + lru_cache.prev[index] = lru_cache.last; + + // Now the first node in the list is the node referenced! + // All other nodes are moved one position down! + lru_cache.first = index; + lru_cache.last = lru_cache.prev[index]; + + return data; + } + return LRU_CACHE_NOTHING; +} + +lru_cache_data_t lru_cache_set(lru_cache_index_t index, lru_cache_data_t data) +{ + if (index != LRU_CACHE_INDEX_NULL) { + lru_cache.data[index] = data; + lru_cache_data_t data = lru_cache_get(index); + return data; + } + return LRU_CACHE_NOTHING; +} + + +lru_cache_data_t lru_cache_data(lru_cache_index_t index) +{ + return lru_cache.data[index]; +} + + +inline void lru_cache_move_link(lru_cache_index_t link, lru_cache_index_t index) +{ + // Here we move the node at the index to the new link, and set the head link to the new link. + + lru_cache_index_t l = lru_cache.link[index]; + lru_cache.link[link] = l; + + // This results in incorrect code! + // lru_cache.key[link] = lru_cache.key[index]; + // lru_cache.data[link] = lru_cache.data[index]; + + lru_cache_key_t key = lru_cache.key[index]; + lru_cache.key[link] = key; + lru_cache_data_t data = lru_cache.data[index]; + lru_cache.data[link] = data; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + lru_cache.next[link] = next; + lru_cache.prev[link] = prev; + + lru_cache.next[prev] = link; + lru_cache.prev[next] = link; + + // todo first and last + if (lru_cache.last == index) { + lru_cache.last = link; + } + + if (lru_cache.first == index) { + lru_cache.first = link; + } + + lru_cache.key[index] = LRU_CACHE_NOTHING; + lru_cache.data[index] = LRU_CACHE_NOTHING; + lru_cache.next[index] = LRU_CACHE_INDEX_NULL; + lru_cache.prev[index] = LRU_CACHE_INDEX_NULL; + lru_cache.link[index] = LRU_CACHE_INDEX_NULL; +} + +lru_cache_index_t lru_cache_find_head(lru_cache_index_t index) +{ + lru_cache_key_t key_link = lru_cache.key[index]; + lru_cache_index_t head_link = lru_cache_hash(key_link); + if (head_link != index) { + return head_link; + } else { + return LRU_CACHE_INDEX_NULL; + } +} + +lru_cache_index_t lru_cache_insert(lru_cache_key_t key, lru_cache_data_t data) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // Check if there is already a link node in place in the hash table at the index. + + lru_cache_index_t link_head = lru_cache_find_head(index); + lru_cache_index_t link_prev = lru_cache_find_duplicate(link_head, index); + + if (lru_cache.key[index] != LRU_CACHE_NOTHING && link_head != LRU_CACHE_INDEX_NULL) { + // There is already a link node, so this node is not a head node and needs to be moved. + // Get the head node of this chain, we know this because we can get the head of the key. + // The link of the head_link must be changed once the new place of the link node has been found. + lru_cache_index_t link = lru_cache_find_empty(index); + lru_cache_move_link(link, index); + lru_cache.link[link_prev] = link; + } + + // The index is at the head of a chain and is either duplicates or empty. + + // We just follow the duplicate chain and find the last duplicate. + lru_cache_index_t index_prev = lru_cache_find_duplicate(index, LRU_CACHE_INDEX_NULL); + + // From the last duplicate position, we search for the first free node. + index = lru_cache_find_empty(index_prev); + + // We set the link of the free node to INDEX_NULL, + // and point the link of the previous node to the empty node. + // index != index_prev indicates there is a duplicate chain. + lru_cache.link[index] = LRU_CACHE_INDEX_NULL; + if (index_prev != index) { + lru_cache.link[index_prev] = index; + } + + // Now assign the key and the data. + lru_cache.key[index] = key; + lru_cache.data[index] = data; + + // And set the lru chain. + if (lru_cache.first == 0xff) { + lru_cache.first = index; + } + if (lru_cache.last == 0xff) { + lru_cache.last = index; + } + + // Now insert the node as the first node in the list. + lru_cache.next[index] = lru_cache.first; + lru_cache.prev[lru_cache.first] = index; + + lru_cache.next[lru_cache.last] = index; + lru_cache.prev[index] = lru_cache.last; + + lru_cache.first = index; + + lru_cache.count++; + + return index; +} + + +lru_cache_data_t lru_cache_delete(lru_cache_key_t key) +{ + lru_cache_index_t index = lru_cache_hash(key); + + // move in array until an empty + lru_cache_index_t index_prev = LRU_CACHE_INDEX_NULL; + while (lru_cache.key[index] != LRU_CACHE_NOTHING) { + + if (lru_cache.key[index] == key) { + + lru_cache_data_t data = lru_cache.data[index]; + + // First remove the index node. + lru_cache.key[index] = LRU_CACHE_NOTHING; + lru_cache.data[index] = LRU_CACHE_NOTHING; + + lru_cache_index_t next = lru_cache.next[index]; + lru_cache_index_t prev = lru_cache.prev[index]; + + lru_cache.next[index] = LRU_CACHE_INDEX_NULL; + lru_cache.prev[index] = LRU_CACHE_INDEX_NULL; + if (lru_cache.next[index] == index) { + // Reset first and last node. + lru_cache.first = 0xff; + lru_cache.last = 0xff; + } else { + // Delete the node from the list. + lru_cache.next[prev] = next; + lru_cache.prev[next] = prev; + // Reassign first and last node. + if (index == lru_cache.first) { + lru_cache.first = next; + } + if (index == lru_cache.last) { + lru_cache.last = prev; + } + } + + lru_cache_index_t link = lru_cache.link[index]; + + if (index_prev != LRU_CACHE_INDEX_NULL) { + // The node is not the first node but the middle of a list. + lru_cache.link[index_prev] = link; + } + + if (link != LRU_CACHE_INDEX_NULL) { + // The head is the start of a duplicate chain. + // Simply move the next node in the duplicate chain as the new head. + lru_cache_move_link(index, link); + } + + + lru_cache.count--; + + return data; + } + + index_prev = index; + index = lru_cache.link[index]; + } + + return LRU_CACHE_NOTHING; +} + +// Only for debugging +void lru_cache_display(char x, char y) { + unsigned char col = 0; + + gotoxy(x, y); + + printf("least recently used cache statistics\n"); + printf("size:%02x, first:%02x, last:%02x, cnt:%2x\n\n", LRU_CACHE_SIZE, lru_cache.first, lru_cache.last, lru_cache.count); + + printf(" "); + do { + printf(" %1x/%1x ", col, col + 8); + col++; + } while (col < 4); + printf("\n"); + + col = 0; + lru_cache_index_t index_row = 0; + do { + + lru_cache_index_t index = index_row; + printf("%02x:", index); + do { + if (lru_cache.key[index] != LRU_CACHE_NOTHING) { + printf(" %04x:", lru_cache.key[index]); + printf("%02x", lru_cache.link[index]); + } else { + printf(" ----:--"); + } + index++; + } while (index < index_row + 4); + printf("\n"); + + index = index_row; + printf(" :"); + do { + printf(" %02x:", lru_cache.next[index]); + printf("%02x ", lru_cache.prev[index]); + index++; + } while (index < index_row + 4); + printf("\n"); + + index_row += 4; + } while (index_row < 4*4*2); + + printf("\n"); + + printf("least recently used sequence\n"); + + lru_cache_index_t index = lru_cache.first; + lru_cache_index_t count = 0; + col = 0; + + while (count < 6) { + if (count < lru_cache.count) + printf(" %4x", lru_cache.key[index]); + else + printf(" "); + //printf(" %4x %3uN %3uP ", lru_cache.key[cache_index], lru_cache.next[cache_index], lru_cache.prev[cache_index]); + + index = lru_cache.next[index]; + count++; + } +} diff --git a/src/test/kc/library/lru-cache2/lru-cache.h b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.h similarity index 98% rename from src/test/kc/library/lru-cache2/lru-cache.h rename to src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.h index b377f5d14..a73a39f74 100644 --- a/src/test/kc/library/lru-cache2/lru-cache.h +++ b/src/test/kc/library/lru-cache-4-mem-stackcall/lru-cache-mem-stackcall.h @@ -33,7 +33,7 @@ typedef unsigned char lru_cache_index_t; -typedef struct { +typedef struct lru_cache_s { lru_cache_key_t key[LRU_CACHE_SIZE]; lru_cache_data_t data[LRU_CACHE_SIZE]; lru_cache_index_t prev[LRU_CACHE_SIZE]; diff --git a/src/test/kc/library/lru-cache2/conio_var.c b/src/test/kc/library/lru-cache2/conio_var.c deleted file mode 100644 index ce856df66..000000000 --- a/src/test/kc/library/lru-cache2/conio_var.c +++ /dev/null @@ -1,33 +0,0 @@ - -// Create an .asm library of imporant conio functions. -// Export to conio_var.asm - -#pragma encoding(screencode_mixed) -#pragma var_model(zp) - -// Declare this compilation to generate the conio_var_asm file! -#pragma asm_library - -// Declare the procedures to be exported to the .asm libary with the indicated calling convention. -#pragma calling(__varcall) -#pragma asm_export(__conio_var_start, conio_x16_init) -#pragma asm_export(clrscr) -#pragma asm_export(gotoxy) -#pragma asm_export(wherex, wherey) -#pragma asm_export(screensize, screensizex, screensizey, cputln ) -#pragma asm_export(cputcxy, cputs, cputsxy, textcolor, bgcolor, bordercolor ) -#pragma asm_export(kbhit, cursor, scroll ) -#pragma asm_export(screenlayer1, screenlayer2) -#pragma asm_export(cpeekc, cpeekcxy) - -#pragma calling(__stackcall) -#pragma asm_export(cputc ) - -#pragma calling(__phicall) - -// Allocate local procedure variables to memory. -#pragma var_model(zp) - -#include -//#include - diff --git a/src/test/kc/library/printf/printf_lib.c b/src/test/kc/library/printf/printf_lib.c index 3da9076a3..8476716e6 100644 --- a/src/test/kc/library/printf/printf_lib.c +++ b/src/test/kc/library/printf/printf_lib.c @@ -1,13 +1,10 @@ - -#pragma link("printf_lib.ld") - #pragma encoding(screencode_mixed) #pragma var_model(mem) +#pragma struct_model(classic) // This is important or kickc messes up the parameters ... #pragma asm_library -#pragma calling(__stackcall) -#pragma asm_export(__printf_lib_start, conio_c64_init) +#pragma calling(__varcall) #pragma asm_export(clrscr) #pragma asm_export(gotoxy) #pragma asm_export(wherex, wherey) @@ -17,17 +14,16 @@ #pragma asm_export(screenlayer1, screenlayer2) #pragma asm_export(cpeekc, cpeekcxy) -#pragma calling(__stackcall) +#pragma calling(__varcall) #pragma asm_export(printf_str) #pragma asm_export(printf_uint, printf_sint) #pragma asm_export(printf_ulong, printf_slong) #pragma asm_export(printf_uchar, printf_schar) - #pragma calling(__stackcall) #pragma asm_export(cputc) -#pragma calling(__phicall) +#pragma calling(__varcall) #include #include diff --git a/src/test/kc/library/printf/printf_lib.ld b/src/test/kc/library/printf/printf_lib.ld deleted file mode 100644 index cb09bbf25..000000000 --- a/src/test/kc/library/printf/printf_lib.ld +++ /dev/null @@ -1,6 +0,0 @@ - -#if __asm_import__ -#else -.segmentdef Code [start=%P] -.segmentdef Data [startAfter="Code"] -#endif \ No newline at end of file diff --git a/src/test/kc/library/printf/printf_test.c b/src/test/kc/library/printf/printf_test.c index 7bbbb7d26..f6edb7d84 100644 --- a/src/test/kc/library/printf/printf_test.c +++ b/src/test/kc/library/printf/printf_test.c @@ -1,13 +1,11 @@ #pragma encoding(screencode_mixed) -#pragma struct_model(classic) +#pragma struct_model(classic) // This is important or kickc messes up the parameters ... +#pragma zp_reserve($0..$1f) -// #include "printf_lib_asm.h" +#include "printf_lib_asm.h" #include #include -#include - -__zp char test; void main() { diff --git a/src/test/kc/library/test1/calc.c b/src/test/kc/library/test1/calc.c index 80ebd1dbe..eb908c459 100644 --- a/src/test/kc/library/test1/calc.c +++ b/src/test/kc/library/test1/calc.c @@ -1,36 +1,15 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library -// Register the exported procedures that should be included in the calc.asm export library. #pragma calling(__varcall) #pragma asm_export(plus, min) -// The plus function. char plus(char a, char b) { return a+b; } -// The min function. char min(char a, char b) { return a-b; } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test1/main.c b/src/test/kc/library/test1/main.c index cfaa8ba43..4b113b691 100644 --- a/src/test/kc/library/test1/main.c +++ b/src/test/kc/library/test1/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include "calc_asm.h" __export char r; // Ensure that r does not get deleted by the optimizer by exporting it. diff --git a/src/test/kc/library/test10-global-zp/calc.c b/src/test/kc/library/test10-global-zp/calc.c new file mode 100644 index 000000000..20f82116b --- /dev/null +++ b/src/test/kc/library/test10-global-zp/calc.c @@ -0,0 +1,37 @@ +#pragma encoding(screencode_mixed) +#pragma var_model(zp) +#pragma struct_model(classic) + +#pragma asm_library +#pragma calling(__varcall) + +#pragma calling(__stackcall) +#pragma asm_export(cputc) + +#pragma calling(__varcall) +#pragma asm_export(clrscr) +#pragma asm_export(gotoxy) +#pragma asm_export(wherex, wherey) +#pragma asm_export(screensize, screensizex, screensizey, cputln) +#pragma asm_export(cputcxy, cputs, cputsxy, textcolor, bgcolor, bordercolor) +#pragma asm_export(kbhit, cursor, scroll, cscroll) +#pragma asm_export(screenlayer1, screenlayer2) +#pragma asm_export(cpeekc, cpeekcxy) +#pragma asm_export(plus) + +#pragma calling(__phicall) + +#include +#include +#include + + +__export char color = 10; + +char plus(char a, char p) { + char r = a + p; + color = r; + printf("color = %02u\n", r); + return r; +} + diff --git a/src/test/kc/library/test10-global-zp/main.c b/src/test/kc/library/test10-global-zp/main.c new file mode 100644 index 000000000..86f534ee0 --- /dev/null +++ b/src/test/kc/library/test10-global-zp/main.c @@ -0,0 +1,16 @@ +#pragma encoding(screencode_mixed) +#pragma var_model(zp) + + struct printf_buffer_number; + #include + +__export char r = 5; // Ensure that r does not get deleted by the optimizer by exporting it. + +void main() { + asm {sei} + clrscr(); + r = 10; + r = plus(r, 2); + r = plus(r, 4); + asm {cli} +} \ No newline at end of file diff --git a/src/test/kc/library/test2/calc.c b/src/test/kc/library/test2/calc.c index c868e5403..f22cfb448 100644 --- a/src/test/kc/library/test2/calc.c +++ b/src/test/kc/library/test2/calc.c @@ -1,39 +1,22 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library -// For the moment, allocated local procedure variables to memory. #pragma var_model(local_mem) -// Register the exported procedures that should be included in the calc.asm export library. #pragma calling(__varcall) #pragma asm_export(plus, min) -// The plus function. +char internal(char d) { + return d * 2; +} + char plus(char a, char b) { - return a+b; + char d = internal(a); + return a + b + d; } -// The min function. -char min(char a, char b) { - return a-b; +char min(char a, char b) { + return a - b; } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test2/main.c b/src/test/kc/library/test2/main.c index f1da964e1..9054349b2 100644 --- a/src/test/kc/library/test2/main.c +++ b/src/test/kc/library/test2/main.c @@ -1,13 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a compile that allows to display the result using printf. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include "calc_asm.h" #include diff --git a/src/test/kc/library/test3/calc.c b/src/test/kc/library/test3/calc.c index ebb9f5817..f08487816 100644 --- a/src/test/kc/library/test3/calc.c +++ b/src/test/kc/library/test3/calc.c @@ -1,32 +1,13 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. - -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library - -// Register the exported procedures that should be included in the calc.asm export library. #pragma asm_export(plus_min) -// The plus function. char plus(char a, char b) { return a+b; } -// The min function. char min(char a, char b) { return a-b; } @@ -36,7 +17,3 @@ char plus_min(char a, char p, char m) { char mr = min(pr,m); return mr; } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test3/main.c b/src/test/kc/library/test3/main.c index e7899cc62..89ec57768 100644 --- a/src/test/kc/library/test3/main.c +++ b/src/test/kc/library/test3/main.c @@ -1,23 +1,10 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include "calc_asm.h" -// We include the C64 and printf stuff. - __export char r; -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! - void main() { r = plus_min(5,4,1); r = plus_min(r,4,1); diff --git a/src/test/kc/library/test4/calc.c b/src/test/kc/library/test4/calc.c index e28aaeae9..cd3a484fc 100644 --- a/src/test/kc/library/test4/calc.c +++ b/src/test/kc/library/test4/calc.c @@ -1,33 +1,15 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. - -*/ - #pragma encoding(screencode_mixed) -#pragma var_model(zp) +#pragma var_model(mem) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library -// Register the exported procedures that should be included in the calc.asm export library. #pragma calling(__varcall) #pragma asm_export(plus_min) -// The plus function. char plus(char a, char b) { return a+b; } -// The min function. char min(char a, char b) { return a-b; } @@ -37,7 +19,3 @@ char plus_min(char a, char p, char m) { char mr = min(pr,m); return mr; } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test4/main.c b/src/test/kc/library/test4/main.c index 3b780613e..2c41ba8d4 100644 --- a/src/test/kc/library/test4/main.c +++ b/src/test/kc/library/test4/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - We also use the printf to nicely display the result and to document how the - imported calc.asm library works and how it compiles with the main source. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include "calc_asm.h" #include @@ -22,4 +14,4 @@ void main() { printf("5 + 4 - 1 = %u\n", r); r = plus_min(4,2,3); printf("4 + 2 - 3 = %u\n", r); -} \ No newline at end of file +} diff --git a/src/test/kc/library/test5/calc.c b/src/test/kc/library/test5/calc.c index a322f4ee1..91630faa5 100644 --- a/src/test/kc/library/test5/calc.c +++ b/src/test/kc/library/test5/calc.c @@ -1,26 +1,9 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. - -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) -// The plus functions - char plus1(char d) { d = d + 1; return d; @@ -43,7 +26,3 @@ char plus3(char d) { // char plus5(char d) { // return d+5; // } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test5/main.c b/src/test/kc/library/test5/main.c index 6d0267a36..4a476abb6 100644 --- a/src/test/kc/library/test5/main.c +++ b/src/test/kc/library/test5/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include __export char r; // Ensure that r does not get deleted by the optimizer by exporting it. @@ -19,4 +11,4 @@ void main() { r = plus3(0); // r = plus4(r); // r = plus5(r); -} \ No newline at end of file +} diff --git a/src/test/kc/library/test6-multiple-returns/calc.c b/src/test/kc/library/test6-multiple-returns/calc.c index e993a4be3..9f8d06123 100644 --- a/src/test/kc/library/test6-multiple-returns/calc.c +++ b/src/test/kc/library/test6-multiple-returns/calc.c @@ -1,32 +1,15 @@ -/* Testing an export library calc.asm file generation. - - The result of this compile should result in: - - A new calc.asm file created in the compiler output directory. - - A new calc_asm.h file created in the compiler output directory. - - The compile ensures that the exported procedures are coalesced per procedure, but - cross procedure there is overlap of ZP, so that the least zeropage is consumed by the library. - Nested functions should have been taken into consideration during ZP allocation, and there - should be no overlap of nested function parameters. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library -// Register the exported procedures that should be included in the calc.asm export library. #pragma calling(__varcall) #pragma asm_export(plus, min, check) -// The plus function. char plus(char a, char b) { return a+b; } -// The min function. char min(char a, char b) { return a-b; } @@ -46,7 +29,3 @@ char check(char a, char b, char r) { } } } - - -// Note that both functions stand on its own in this source, there is no main! -// Parameters a and b are taken into consideration when allocating the ZP! diff --git a/src/test/kc/library/test6-multiple-returns/main.c b/src/test/kc/library/test6-multiple-returns/main.c index cfaa8ba43..cb011911a 100644 --- a/src/test/kc/library/test6-multiple-returns/main.c +++ b/src/test/kc/library/test6-multiple-returns/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include "calc_asm.h" __export char r; // Ensure that r does not get deleted by the optimizer by exporting it. @@ -17,4 +9,4 @@ void main() { r = 10; r = plus(5,4); r = min(5,4); -} \ No newline at end of file +} diff --git a/src/test/kc/library/test7-two-libs-call/main.c b/src/test/kc/library/test7-two-libs-call/main.c index 3c5adca51..42f46775f 100644 --- a/src/test/kc/library/test7-two-libs-call/main.c +++ b/src/test/kc/library/test7-two-libs-call/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include #include #include @@ -22,4 +14,4 @@ void main() { r = min(r, 1); printf("r = %u", r); -} \ No newline at end of file +} diff --git a/src/test/kc/library/test7-two-libs-call/min.c b/src/test/kc/library/test7-two-libs-call/min.c index 4997f24ee..c64de213e 100644 --- a/src/test/kc/library/test7-two-libs-call/min.c +++ b/src/test/kc/library/test7-two-libs-call/min.c @@ -1,15 +1,9 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) -// The plus functions - char min(char a, char m) { return a - m; } diff --git a/src/test/kc/library/test7-two-libs-call/plus.c b/src/test/kc/library/test7-two-libs-call/plus.c index 8ca40d1d4..5c7828201 100644 --- a/src/test/kc/library/test7-two-libs-call/plus.c +++ b/src/test/kc/library/test7-two-libs-call/plus.c @@ -1,10 +1,6 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) diff --git a/src/test/kc/library/test8-two-libs-struct/cx.c b/src/test/kc/library/test8-two-libs-struct/cx.c index 89f3bbc80..e90a55dd2 100644 --- a/src/test/kc/library/test8-two-libs-struct/cx.c +++ b/src/test/kc/library/test8-two-libs-struct/cx.c @@ -1,10 +1,6 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(local_zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) @@ -17,8 +13,6 @@ struct data { }; -// The plus functions - char get_x(char i) { struct data x = {0,1,2}; diff --git a/src/test/kc/library/test8-two-libs-struct/cy.c b/src/test/kc/library/test8-two-libs-struct/cy.c index a54cd0c11..ba3da9957 100644 --- a/src/test/kc/library/test8-two-libs-struct/cy.c +++ b/src/test/kc/library/test8-two-libs-struct/cy.c @@ -1,10 +1,6 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(local_zp) -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) diff --git a/src/test/kc/library/test8-two-libs-struct/main.c b/src/test/kc/library/test8-two-libs-struct/main.c index b5a32b6e7..a83908bba 100644 --- a/src/test/kc/library/test8-two-libs-struct/main.c +++ b/src/test/kc/library/test8-two-libs-struct/main.c @@ -1,14 +1,6 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include #include #include diff --git a/src/test/kc/library/test9-nested/main.c b/src/test/kc/library/test9-nested/main.c index cc3221042..3abf89b33 100644 --- a/src/test/kc/library/test9-nested/main.c +++ b/src/test/kc/library/test9-nested/main.c @@ -1,16 +1,8 @@ -/* Here we use the calc.asm library functions. - This is a minimal source compilation for asm debugging, to test the asm library functionality - and compilation result. -*/ - #pragma encoding(screencode_mixed) #pragma var_model(zp) #include -// We include the calc_asm.h generated C function prototype file. -// This file contains the function prototypes for plus and min, which are -// contained in the calc.asm file in assembler. #include #include diff --git a/src/test/kc/library/test9-nested/min.c b/src/test/kc/library/test9-nested/min.c index dee1883e7..71e2ed9c2 100644 --- a/src/test/kc/library/test9-nested/min.c +++ b/src/test/kc/library/test9-nested/min.c @@ -1,19 +1,13 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(zp) #include -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) #include -// The plus functions - char min(char a, char m) { char r = a - m; printf("min r = %u\n", r); diff --git a/src/test/kc/library/test9-nested/plus.c b/src/test/kc/library/test9-nested/plus.c index 56455c82f..c4e942610 100644 --- a/src/test/kc/library/test9-nested/plus.c +++ b/src/test/kc/library/test9-nested/plus.c @@ -1,19 +1,13 @@ -// Testing two libraries with zero-page for parameters. - #pragma encoding(screencode_mixed) #pragma var_model(zp) #include -// Register the compilation as an calc.asm export library output artefact. -// There is no main() function! #pragma asm_library #pragma calling(__varcall) #include -// The plus functions - char plus(char a, char p) { char r = a + p; printf("plus r = %u\n", r);