diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 8a98e1226..0ff72449a 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -7,8 +7,8 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.compiler.CompilationOptions import prog8.compiler.HeapValues -import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE -import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE import prog8.functions.BuiltinFunctions import java.io.File diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 3cfd36487..04157c5ec 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -6,7 +6,7 @@ import prog8.ast.expressions.* import prog8.ast.processing.IAstModifyingVisitor import prog8.ast.processing.IAstVisitor import prog8.compiler.HeapValues -import prog8.compiler.target.c64.Mflpt5 +import prog8.compiler.target.c64.MachineDefinition class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : IStatement { @@ -757,7 +757,7 @@ class StructDecl(override val name: String, when { decl.datatype in ByteDatatypes -> 8 decl.datatype in WordDatatypes -> 16 - decl.datatype==DataType.FLOAT -> Mflpt5.MemorySize + decl.datatype==DataType.FLOAT -> MachineDefinition.Mflpt5.MemorySize decl.datatype in StringDatatypes -> TODO("stringvalue size") decl.datatype in ArrayDatatypes -> decl.arraysize!!.size()!! decl.datatype==DataType.STRUCT -> decl.struct!!.memorySize diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index bb7cd3781..b2921b015 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -7,7 +7,7 @@ import prog8.ast.base.checkValid import prog8.ast.base.reorderStatements import prog8.ast.statements.Directive import prog8.compiler.target.c64.AsmGen -import prog8.compiler.target.c64.C64Zeropage +import prog8.compiler.target.c64.MachineDefinition import prog8.optimizer.constantFold import prog8.optimizer.optimizeStatements import prog8.optimizer.simplifyExpressions @@ -108,7 +108,7 @@ fun compileProgram(filepath: Path, } if (writeAssembly) { - val zeropage = C64Zeropage(compilerOptions) + val zeropage = MachineDefinition.C64Zeropage(compilerOptions) intermediate.allocateZeropage(zeropage) val assembly = AsmGen(compilerOptions, intermediate, programAst.heap, zeropage).compileToAssembly(optimize) assembly.assemble(compilerOptions) diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 927761178..9a6b00fa9 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -147,7 +147,7 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter return name.replace("-", "") } - private fun makeFloatFill(flt: Mflpt5): String { + private fun makeFloatFill(flt: MachineDefinition.Mflpt5): String { val b0 = "$"+flt.b0.toString(16).padStart(2, '0') val b1 = "$"+flt.b1.toString(16).padStart(2, '0') val b2 = "$"+flt.b2.toString(16).padStart(2, '0') @@ -165,7 +165,8 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter out("\n.cpu '6502'\n.enc 'none'\n") if(program.loadAddress==0) // fix load address - program.loadAddress = if(options.launcher==LauncherType.BASIC) BASIC_LOAD_ADDRESS else RAW_LOAD_ADDRESS + program.loadAddress = if(options.launcher==LauncherType.BASIC) + MachineDefinition.BASIC_LOAD_ADDRESS else MachineDefinition.RAW_LOAD_ADDRESS when { options.launcher == LauncherType.BASIC -> { @@ -221,7 +222,7 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter // the global list of all floating point constants for the whole program for(flt in globalFloatConsts) { - val floatFill = makeFloatFill(Mflpt5.fromNumber(flt.key)) + val floatFill = makeFloatFill(MachineDefinition.Mflpt5.fromNumber(flt.key)) out("${flt.value}\t.byte $floatFill ; float ${flt.key}") } } @@ -371,7 +372,7 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter DataType.ARRAY_F -> { // float arraysize val array = heap.get(value.heapId!!).doubleArray!! - val floatFills = array.map { makeFloatFill(Mflpt5.fromNumber(it)) } + val floatFills = array.map { makeFloatFill(MachineDefinition.Mflpt5.fromNumber(it)) } out(varname) for(f in array.zip(floatFills)) out(" .byte ${f.second} ; float ${f.first}") @@ -574,14 +575,14 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_UW -> AsmFragment(" lda $variable+${index*2} | bne + | dec $variable+${index*2+1} |+ | dec $variable+${index*2}") Opcode.INC_INDEXED_VAR_FLOAT -> AsmFragment( """ - lda #<($variable+${index*Mflpt5.MemorySize}) - ldy #>($variable+${index*Mflpt5.MemorySize}) + lda #<($variable+${index* MachineDefinition.Mflpt5.MemorySize}) + ldy #>($variable+${index* MachineDefinition.Mflpt5.MemorySize}) jsr c64flt.inc_var_f """) Opcode.DEC_INDEXED_VAR_FLOAT -> AsmFragment( """ - lda #<($variable+${index*Mflpt5.MemorySize}) - ldy #>($variable+${index*Mflpt5.MemorySize}) + lda #<($variable+${index* MachineDefinition.Mflpt5.MemorySize}) + ldy #>($variable+${index* MachineDefinition.Mflpt5.MemorySize}) jsr c64flt.dec_var_f """) @@ -591,8 +592,8 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter private fun sameIndexedVarOperation(variable: String, indexVar: String, ins: Instruction): AsmFragment? { // an in place operation that consists of a push-value / op / push-index-var / pop-into-indexed-var - val saveX = " stx ${C64Zeropage.SCRATCH_B1} |" - val restoreX = " | ldx ${C64Zeropage.SCRATCH_B1}" + val saveX = " stx ${MachineDefinition.C64Zeropage.SCRATCH_B1} |" + val restoreX = " | ldx ${MachineDefinition.C64Zeropage.SCRATCH_B1}" val loadXWord: String val loadX: String diff --git a/compiler/src/prog8/compiler/target/c64/AsmOptimizer.kt b/compiler/src/prog8/compiler/target/c64/AsmOptimizer.kt index 922e0e647..cfa4a47a8 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmOptimizer.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmOptimizer.kt @@ -1,6 +1,7 @@ package prog8.compiler.target.c64 -import prog8.compiler.toHex +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX // note: see https://wiki.nesdev.com/w/index.php/6502_assembly_optimisations @@ -69,10 +70,10 @@ fun optimizeCmpSequence(linesByFour: List>>): List() for(lines in linesByFour) { - if(lines[0].value.trim()=="lda ${(ESTACK_LO+1).toHex()},x" && + if(lines[0].value.trim()=="lda $ESTACK_LO_PLUS1_HEX,x" && lines[1].value.trim().startsWith("cmp ") && lines[2].value.trim().startsWith("beq ") && - lines[3].value.trim()=="lda ${(ESTACK_LO+1).toHex()},x") { + lines[3].value.trim()=="lda $ESTACK_LO_PLUS1_HEX,x") { removeLines.add(lines[3].index) // remove the second lda } } @@ -84,10 +85,10 @@ fun optimizeUselessStackByteWrites(linesByFour: List>> // this is a lot harder for word values because the instruction sequence varies. val removeLines = mutableListOf() for(lines in linesByFour) { - if(lines[0].value.trim()=="sta ${ESTACK_LO.toHex()},x" && + if(lines[0].value.trim()=="sta $ESTACK_LO_HEX,x" && lines[1].value.trim()=="dex" && lines[2].value.trim()=="inx" && - lines[3].value.trim()=="lda ${ESTACK_LO.toHex()},x") { + lines[3].value.trim()=="lda $ESTACK_LO_HEX,x") { removeLines.add(lines[0].index) removeLines.add(lines[1].index) removeLines.add(lines[2].index) diff --git a/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt b/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt index e5a18722b..3dadf39c0 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt @@ -3,6 +3,11 @@ package prog8.compiler.target.c64 import prog8.ast.base.printWarning import prog8.compiler.intermediate.Instruction import prog8.compiler.intermediate.Opcode +import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX +import prog8.compiler.target.c64.MachineDefinition.C64Zeropage import prog8.compiler.toHex // note: see https://wiki.nesdev.com/w/index.php/6502_assembly_optimisations @@ -1371,7 +1376,7 @@ internal val patterns = listOf( }, // floatvar = floatarray[index] AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> - val index = intVal(segment[0]) * Mflpt5.MemorySize + val index = intVal(segment[0]) * MachineDefinition.Mflpt5.MemorySize """ lda #<${segment[1].callLabel}+$index ldy #>${segment[1].callLabel}+$index @@ -1570,7 +1575,7 @@ internal val patterns = listOf( }, // memfloat = floatarray[index] AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> - val index = intVal(segment[0]) * Mflpt5.MemorySize + val index = intVal(segment[0]) * MachineDefinition.Mflpt5.MemorySize """ lda #<${segment[1].callLabel}+$index ldy #>${segment[1].callLabel}+$index @@ -1584,7 +1589,7 @@ internal val patterns = listOf( // floatarray[idxbyte] = float AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> val floatConst = getFloatConst(segment[0].arg!!) - val index = intVal(segment[1]) * Mflpt5.MemorySize + val index = intVal(segment[1]) * MachineDefinition.Mflpt5.MemorySize """ lda #<$floatConst ldy #>$floatConst @@ -1597,7 +1602,7 @@ internal val patterns = listOf( }, // floatarray[idxbyte] = floatvar AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index = intVal(segment[1]) * Mflpt5.MemorySize + val index = intVal(segment[1]) * MachineDefinition.Mflpt5.MemorySize """ lda #<${segment[0].callLabel} ldy #>${segment[0].callLabel} @@ -1610,7 +1615,7 @@ internal val patterns = listOf( }, // floatarray[idxbyte] = memfloat AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index = intVal(segment[1]) * Mflpt5.MemorySize + val index = intVal(segment[1]) * MachineDefinition.Mflpt5.MemorySize """ lda #<${hexVal(segment[0])} ldy #>${hexVal(segment[0])} @@ -1623,8 +1628,8 @@ internal val patterns = listOf( }, // floatarray[idx2] = floatarray[idx1] AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index1 = intVal(segment[0]) * Mflpt5.MemorySize - val index2 = intVal(segment[2]) * Mflpt5.MemorySize + val index1 = intVal(segment[0]) * MachineDefinition.Mflpt5.MemorySize + val index2 = intVal(segment[2]) * MachineDefinition.Mflpt5.MemorySize """ lda #<(${segment[1].callLabel}+$index1) ldy #>(${segment[1].callLabel}+$index1) @@ -1759,16 +1764,16 @@ internal val patterns = listOf( // push word var as (u)byte AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_UB), listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_B)) { segment -> - " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel} | sta $ESTACK_LO_HEX,x | dex " }, // push uword var as (u)byte AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_UB), listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_B)) { segment -> - " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel} | sta $ESTACK_LO_HEX,x | dex " }, // push msb(word var) AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB)) { segment -> - " lda ${segment[0].callLabel}+1 | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel}+1 | sta $ESTACK_LO_HEX,x | dex " }, // set a register pair to a certain memory address (of a variable) @@ -1785,29 +1790,29 @@ internal val patterns = listOf( // push memory byte | bytevalue AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE), listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${hexVal(segment[0])} | ora #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push memory byte & bytevalue AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE), listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${hexVal(segment[0])} | and #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push memory byte ^ bytevalue AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE), listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push var byte | bytevalue AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> - " lda ${segment[0].callLabel} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel} | ora #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push var byte & bytevalue AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> - " lda ${segment[0].callLabel} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel} | and #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push var byte ^ bytevalue AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> - " lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + " lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta $ESTACK_LO_HEX,x | dex " }, // push memory word | wordvalue @@ -1816,10 +1821,10 @@ internal val patterns = listOf( """ lda ${hexVal(segment[0])} ora #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${hexValPlusOne(segment[0])} ora #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1829,10 +1834,10 @@ internal val patterns = listOf( """ lda ${hexVal(segment[0])} and #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${hexValPlusOne(segment[0])} and #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1842,10 +1847,10 @@ internal val patterns = listOf( """ lda ${hexVal(segment[0])} eor #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${hexValPlusOne(segment[0])} eor #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1854,10 +1859,10 @@ internal val patterns = listOf( """ lda ${segment[0].callLabel} ora #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${segment[0].callLabel}+1 ora #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1866,10 +1871,10 @@ internal val patterns = listOf( """ lda ${segment[0].callLabel} and #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${segment[0].callLabel}+1 and #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1878,10 +1883,10 @@ internal val patterns = listOf( """ lda ${segment[0].callLabel} eor #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${segment[0].callLabel}+1 eor #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -1974,27 +1979,27 @@ internal val patterns = listOf( AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> """ lda ${segment[0].callLabel} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${segment[1].callLabel} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> """ lda #${hexVal(segment[0])} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${segment[1].callLabel} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.MKWORD)) { segment -> """ lda ${segment[0].callLabel} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda #${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ }, @@ -2035,28 +2040,28 @@ internal val patterns = listOf( AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment -> val amount = segment[0].arg!!.integerValue() if (amount in 1..2) { - " inc ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + " inc $ESTACK_LO_PLUS1_HEX,x | ".repeat(amount) } else null }, AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.ADD_UW), listOf(Opcode.PUSH_WORD, Opcode.ADD_W)) { segment -> val amount = segment[0].arg!!.integerValue() if (amount in 1..2) { - " inc ${(ESTACK_LO + 1).toHex()},x | bne + | inc ${(ESTACK_HI + 1).toHex()},x |+ | ".repeat(amount) + " inc $ESTACK_LO_PLUS1_HEX,x | bne + | inc $ESTACK_HI_PLUS1_HEX,x |+ | ".repeat(amount) } else null }, AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.SUB_B), listOf(Opcode.PUSH_BYTE, Opcode.SUB_UB)) { segment -> val amount = segment[0].arg!!.integerValue() if (amount in 1..2) { - " dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + " dec $ESTACK_LO_PLUS1_HEX,x | ".repeat(amount) } else null }, AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.SUB_UW), listOf(Opcode.PUSH_WORD, Opcode.SUB_W)) { segment -> val amount = segment[0].arg!!.integerValue() if (amount in 1..2) { - " lda ${(ESTACK_LO + 1).toHex()},x | bne + | dec ${(ESTACK_HI + 1).toHex()},x |+ | dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + " lda $ESTACK_LO_PLUS1_HEX,x | bne + | dec $ESTACK_HI_PLUS1_HEX,x |+ | dec $ESTACK_LO_PLUS1_HEX,x | ".repeat(amount) } else null }, @@ -2109,14 +2114,14 @@ internal val patterns = listOf( AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.MUL_B), listOf(Opcode.PUSH_BYTE, Opcode.MUL_UB)) { segment -> val amount = segment[0].arg!!.integerValue() val result = optimizedIntMultiplicationsOnStack(segment[1], amount) - result ?: " lda #${hexVal(segment[0])} | sta ${ESTACK_LO.toHex()},x | dex | jsr prog8_lib.mul_byte" + result ?: " lda #${hexVal(segment[0])} | sta $ESTACK_LO_HEX,x | dex | jsr prog8_lib.mul_byte" }, AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.MUL_W), listOf(Opcode.PUSH_WORD, Opcode.MUL_UW)) { segment -> val amount = segment[0].arg!!.integerValue() val result = optimizedIntMultiplicationsOnStack(segment[1], amount) if (result != null) result else { val value = hexVal(segment[0]) - " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex | jsr prog8_lib.mul_word" + " lda #<$value | sta $ESTACK_LO_HEX,x | lda #>$value | sta $ESTACK_HI_HEX,x | dex | jsr prog8_lib.mul_word" } }, @@ -2310,10 +2315,10 @@ internal val patterns = listOf( AsmPattern(listOf(Opcode.DUP_W, Opcode.CMP_UW), listOf(Opcode.DUP_W, Opcode.CMP_W)) { segment -> """ - lda ${(ESTACK_HI+1).toHex()},x + lda $ESTACK_HI_PLUS1_HEX,x cmp #>${segment[1].arg!!.integerValue().toHex()} bne + - lda ${(ESTACK_LO+1).toHex()},x + lda $ESTACK_LO_PLUS1_HEX,x cmp #<${segment[1].arg!!.integerValue().toHex()} ; bne + not necessary? ; lda #0 not necessary? @@ -2322,7 +2327,7 @@ internal val patterns = listOf( }, AsmPattern(listOf(Opcode.DUP_B, Opcode.CMP_UB), listOf(Opcode.DUP_B, Opcode.CMP_B)) { segment -> - """ lda ${(ESTACK_LO+1).toHex()},x | cmp #${segment[1].arg!!.integerValue().toHex()} """ + """ lda $ESTACK_LO_PLUS1_HEX,x | cmp #${segment[1].arg!!.integerValue().toHex()} """ } ) diff --git a/compiler/src/prog8/compiler/target/c64/Commodore64.kt b/compiler/src/prog8/compiler/target/c64/Commodore64.kt deleted file mode 100644 index c16f605fc..000000000 --- a/compiler/src/prog8/compiler/target/c64/Commodore64.kt +++ /dev/null @@ -1,242 +0,0 @@ -package prog8.compiler.target.c64 - -import prog8.compiler.CompilationOptions -import prog8.compiler.CompilerException -import prog8.compiler.Zeropage -import prog8.compiler.ZeropageType -import java.awt.Color -import java.awt.image.BufferedImage -import javax.imageio.ImageIO -import kotlin.math.absoluteValue -import kotlin.math.pow - - -// 5-byte cbm MFLPT format limitations: -const val FLOAT_MAX_POSITIVE = 1.7014118345e+38 // bytes: 255,127,255,255,255 -const val FLOAT_MAX_NEGATIVE = -1.7014118345e+38 // bytes: 255,255,255,255,255 - -const val BASIC_LOAD_ADDRESS = 0x0801 -const val RAW_LOAD_ADDRESS = 0xc000 - -// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations) -const val ESTACK_LO = 0xce00 // $ce00-$ceff inclusive -const val ESTACK_HI = 0xcf00 // $cf00-$cfff inclusive - - -class C64Zeropage(options: CompilationOptions) : Zeropage(options) { - - companion object { - const val SCRATCH_B1 = 0x02 - const val SCRATCH_REG = 0x03 // temp storage for a register - const val SCRATCH_REG_X = 0xfa // temp storage for register X (the evaluation stack pointer) - const val SCRATCH_W1 = 0xfb // $fb+$fc - const val SCRATCH_W2 = 0xfd // $fd+$fe - } - - override val exitProgramStrategy: ExitProgramStrategy = when(options.zeropage) { - ZeropageType.BASICSAFE -> ExitProgramStrategy.CLEAN_EXIT - ZeropageType.FLOATSAFE, ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET - } - - - init { - if(options.floats && options.zeropage!=ZeropageType.FLOATSAFE && options.zeropage!=ZeropageType.BASICSAFE) - throw CompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe'") - - if(options.zeropage == ZeropageType.FULL) { - free.addAll(0x04 .. 0xf9) - free.add(0xff) - free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1+1, SCRATCH_W2, SCRATCH_W2+1)) - free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ - } else { - if(options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) { - free.addAll(listOf(0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - 0x22, 0x23, 0x24, 0x25, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x48, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x51, 0x52, 0x53, - 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, - 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xff - // 0x90-0xfa is 'kernel work storage area' - )) - } - - if(options.zeropage == ZeropageType.FLOATSAFE) { - // remove the zero page locations used for floating point operations from the free list - free.removeAll(listOf( - 0x12, 0x26, 0x27, 0x28, 0x29, 0x2a, - 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, - 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xf - )) - } - - // add the other free Zp addresses, - // these are valid for the C-64 (when no RS232 I/O is performed) but to keep BASIC running fully: - free.addAll(listOf(0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, - 0x94, 0x95, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb5, 0xb6, 0xf7, 0xf8, 0xf9)) - } - assert(SCRATCH_B1 !in free) - assert(SCRATCH_REG !in free) - assert(SCRATCH_REG_X !in free) - assert(SCRATCH_W1 !in free) - assert(SCRATCH_W2 !in free) - - for(reserved in options.zpReserved) - reserve(reserved) - } -} - - -data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short) { - - companion object { - const val MemorySize = 5 - - val zero = Mflpt5(0, 0,0,0,0) - fun fromNumber(num: Number): Mflpt5 { - // see https://en.wikipedia.org/wiki/Microsoft_Binary_Format - // and https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a - // and https://en.wikipedia.org/wiki/IEEE_754-1985 - - val flt = num.toDouble() - if(flt < FLOAT_MAX_NEGATIVE || flt > FLOAT_MAX_POSITIVE) - throw CompilerException("floating point number out of 5-byte mflpt range: $this") - if(flt==0.0) - return zero - - val sign = if(flt<0.0) 0x80L else 0x00L - var exponent = 128 + 32 // 128 is cbm's bias, 32 is this algo's bias - var mantissa = flt.absoluteValue - - // if mantissa is too large, shift right and adjust exponent - while(mantissa >= 0x100000000) { - mantissa /= 2.0 - exponent ++ - } - // if mantissa is too small, shift left and adjust exponent - while(mantissa < 0x80000000) { - mantissa *= 2.0 - exponent -- - } - - return when { - exponent<0 -> zero // underflow, use zero instead - exponent>255 -> throw CompilerException("floating point overflow: $this") - exponent==0 -> zero - else -> { - val mantLong = mantissa.toLong() - Mflpt5( - exponent.toShort(), - (mantLong.and(0x7f000000L) ushr 24).or(sign).toShort(), - (mantLong.and(0x00ff0000L) ushr 16).toShort(), - (mantLong.and(0x0000ff00L) ushr 8).toShort(), - (mantLong.and(0x000000ffL)).toShort()) - } - } - } - } - - fun toDouble(): Double { - if(this == zero) return 0.0 - val exp = b0 - 128 - val sign = (b1.toInt() and 0x80) > 0 - val number = 0x80000000L.or(b1.toLong() shl 24).or(b2.toLong() shl 16).or(b3.toLong() shl 8).or(b4.toLong()) - val result = number.toDouble() * (2.0).pow(exp) / 0x100000000 - return if(sign) -result else result - } -} - -object Charset { - private val normalImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-normal.png")) - private val shiftedImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-shifted.png")) - - private fun scanChars(img: BufferedImage): Array { - - val transparent = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB) - transparent.createGraphics().drawImage(img, 0, 0, null) - - val black = Color(0,0,0).rgb - val nopixel = Color(0,0,0,0).rgb - for(y in 0 until transparent.height) { - for(x in 0 until transparent.width) { - val col = transparent.getRGB(x, y) - if(col==black) - transparent.setRGB(x, y, nopixel) - } - } - - val numColumns = transparent.width / 8 - val charImages = (0..255).map { - val charX = it % numColumns - val charY = it/ numColumns - transparent.getSubimage(charX*8, charY*8, 8, 8) - } - return charImages.toTypedArray() - } - - val normalChars = scanChars(normalImg) - val shiftedChars = scanChars(shiftedImg) - - private val coloredNormalChars = mutableMapOf>() - - fun getColoredChar(screenCode: Short, color: Short): BufferedImage { - val colorIdx = (color % Colors.palette.size).toShort() - val chars = coloredNormalChars[colorIdx] - if(chars!=null) - return chars[screenCode.toInt()] - - val coloredChars = mutableListOf() - val transparent = Color(0,0,0,0).rgb - val rgb = Colors.palette[colorIdx.toInt()].rgb - for(c in normalChars) { - val colored = c.copy() - for(y in 0 until colored.height) - for(x in 0 until colored.width) { - if(colored.getRGB(x, y)!=transparent) { - colored.setRGB(x, y, rgb) - } - } - coloredChars.add(colored) - } - coloredNormalChars[colorIdx] = coloredChars.toTypedArray() - return coloredNormalChars.getValue(colorIdx)[screenCode.toInt()] - } - -} - -private fun BufferedImage.copy(): BufferedImage { - val bcopy = BufferedImage(this.width, this.height, this.type) - val g = bcopy.graphics - g.drawImage(this, 0, 0, null) - g.dispose() - return bcopy -} - - -object Colors { - val palette = listOf( // this is Pepto's Commodore-64 palette http://www.pepto.de/projects/colorvic/ - Color(0x000000), // 0 = black - Color(0xFFFFFF), // 1 = white - Color(0x813338), // 2 = red - Color(0x75cec8), // 3 = cyan - Color(0x8e3c97), // 4 = purple - Color(0x56ac4d), // 5 = green - Color(0x2e2c9b), // 6 = blue - Color(0xedf171), // 7 = yellow - Color(0x8e5029), // 8 = orange - Color(0x553800), // 9 = brown - Color(0xc46c71), // 10 = light red - Color(0x4a4a4a), // 11 = dark grey - Color(0x7b7b7b), // 12 = medium grey - Color(0xa9ff9f), // 13 = light green - Color(0x706deb), // 14 = light blue - Color(0xb2b2b2) // 15 = light grey - ) -} diff --git a/compiler/src/prog8/compiler/target/c64/MachineDefinition.kt b/compiler/src/prog8/compiler/target/c64/MachineDefinition.kt new file mode 100644 index 000000000..526ee38d6 --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/MachineDefinition.kt @@ -0,0 +1,247 @@ +package prog8.compiler.target.c64 + +import prog8.compiler.* +import java.awt.Color +import java.awt.image.BufferedImage +import javax.imageio.ImageIO +import kotlin.math.absoluteValue +import kotlin.math.pow + +object MachineDefinition { + + // 5-byte cbm MFLPT format limitations: + const val FLOAT_MAX_POSITIVE = 1.7014118345e+38 // bytes: 255,127,255,255,255 + const val FLOAT_MAX_NEGATIVE = -1.7014118345e+38 // bytes: 255,255,255,255,255 + + const val BASIC_LOAD_ADDRESS = 0x0801 + const val RAW_LOAD_ADDRESS = 0xc000 + + // the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations) + // and some heavily used string constants derived from the two values above + const val ESTACK_LO_VALUE = 0xce00 // $ce00-$ceff inclusive + const val ESTACK_HI_VALUE = 0xcf00 // $cf00-$cfff inclusive + const val ESTACK_LO_HEX = "\$ce00" + const val ESTACK_LO_PLUS1_HEX = "\$ce01" + const val ESTACK_LO_PLUS2_HEX = "\$ce02" + const val ESTACK_HI_HEX = "\$cf00" + const val ESTACK_HI_PLUS1_HEX = "\$cf01" + const val ESTACK_HI_PLUS2_HEX = "\$cf02" + + + class C64Zeropage(options: CompilationOptions) : Zeropage(options) { + + companion object { + const val SCRATCH_B1 = 0x02 + const val SCRATCH_REG = 0x03 // temp storage for a register + const val SCRATCH_REG_X = 0xfa // temp storage for register X (the evaluation stack pointer) + const val SCRATCH_W1 = 0xfb // $fb+$fc + const val SCRATCH_W2 = 0xfd // $fd+$fe + } + + override val exitProgramStrategy: ExitProgramStrategy = when (options.zeropage) { + ZeropageType.BASICSAFE -> ExitProgramStrategy.CLEAN_EXIT + ZeropageType.FLOATSAFE, ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET + } + + + init { + if (options.floats && options.zeropage != ZeropageType.FLOATSAFE && options.zeropage != ZeropageType.BASICSAFE) + throw CompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe'") + + if (options.zeropage == ZeropageType.FULL) { + free.addAll(0x04..0xf9) + free.add(0xff) + free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) + free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ + } else { + if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) { + free.addAll(listOf(0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + 0x22, 0x23, 0x24, 0x25, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x51, 0x52, 0x53, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xff + // 0x90-0xfa is 'kernel work storage area' + )) + } + + if (options.zeropage == ZeropageType.FLOATSAFE) { + // remove the zero page locations used for floating point operations from the free list + free.removeAll(listOf( + 0x12, 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xf + )) + } + + // add the other free Zp addresses, + // these are valid for the C-64 (when no RS232 I/O is performed) but to keep BASIC running fully: + free.addAll(listOf(0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, + 0x94, 0x95, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb5, 0xb6, 0xf7, 0xf8, 0xf9)) + } + assert(SCRATCH_B1 !in free) + assert(SCRATCH_REG !in free) + assert(SCRATCH_REG_X !in free) + assert(SCRATCH_W1 !in free) + assert(SCRATCH_W2 !in free) + + for (reserved in options.zpReserved) + reserve(reserved) + } + } + + + data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short) { + + companion object { + const val MemorySize = 5 + + val zero = Mflpt5(0, 0, 0, 0, 0) + fun fromNumber(num: Number): Mflpt5 { + // see https://en.wikipedia.org/wiki/Microsoft_Binary_Format + // and https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a + // and https://en.wikipedia.org/wiki/IEEE_754-1985 + + val flt = num.toDouble() + if (flt < FLOAT_MAX_NEGATIVE || flt > FLOAT_MAX_POSITIVE) + throw CompilerException("floating point number out of 5-byte mflpt range: $this") + if (flt == 0.0) + return zero + + val sign = if (flt < 0.0) 0x80L else 0x00L + var exponent = 128 + 32 // 128 is cbm's bias, 32 is this algo's bias + var mantissa = flt.absoluteValue + + // if mantissa is too large, shift right and adjust exponent + while (mantissa >= 0x100000000) { + mantissa /= 2.0 + exponent++ + } + // if mantissa is too small, shift left and adjust exponent + while (mantissa < 0x80000000) { + mantissa *= 2.0 + exponent-- + } + + return when { + exponent < 0 -> zero // underflow, use zero instead + exponent > 255 -> throw CompilerException("floating point overflow: $this") + exponent == 0 -> zero + else -> { + val mantLong = mantissa.toLong() + Mflpt5( + exponent.toShort(), + (mantLong.and(0x7f000000L) ushr 24).or(sign).toShort(), + (mantLong.and(0x00ff0000L) ushr 16).toShort(), + (mantLong.and(0x0000ff00L) ushr 8).toShort(), + (mantLong.and(0x000000ffL)).toShort()) + } + } + } + } + + fun toDouble(): Double { + if (this == zero) return 0.0 + val exp = b0 - 128 + val sign = (b1.toInt() and 0x80) > 0 + val number = 0x80000000L.or(b1.toLong() shl 24).or(b2.toLong() shl 16).or(b3.toLong() shl 8).or(b4.toLong()) + val result = number.toDouble() * (2.0).pow(exp) / 0x100000000 + return if (sign) -result else result + } + } + + object Charset { + private val normalImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-normal.png")) + private val shiftedImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-shifted.png")) + + private fun scanChars(img: BufferedImage): Array { + + val transparent = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB) + transparent.createGraphics().drawImage(img, 0, 0, null) + + val black = Color(0, 0, 0).rgb + val nopixel = Color(0, 0, 0, 0).rgb + for (y in 0 until transparent.height) { + for (x in 0 until transparent.width) { + val col = transparent.getRGB(x, y) + if (col == black) + transparent.setRGB(x, y, nopixel) + } + } + + val numColumns = transparent.width / 8 + val charImages = (0..255).map { + val charX = it % numColumns + val charY = it / numColumns + transparent.getSubimage(charX * 8, charY * 8, 8, 8) + } + return charImages.toTypedArray() + } + + val normalChars = scanChars(normalImg) + val shiftedChars = scanChars(shiftedImg) + + private val coloredNormalChars = mutableMapOf>() + + fun getColoredChar(screenCode: Short, color: Short): BufferedImage { + val colorIdx = (color % colorPalette.size).toShort() + val chars = coloredNormalChars[colorIdx] + if (chars != null) + return chars[screenCode.toInt()] + + val coloredChars = mutableListOf() + val transparent = Color(0, 0, 0, 0).rgb + val rgb = colorPalette[colorIdx.toInt()].rgb + for (c in normalChars) { + val colored = c.copy() + for (y in 0 until colored.height) + for (x in 0 until colored.width) { + if (colored.getRGB(x, y) != transparent) { + colored.setRGB(x, y, rgb) + } + } + coloredChars.add(colored) + } + coloredNormalChars[colorIdx] = coloredChars.toTypedArray() + return coloredNormalChars.getValue(colorIdx)[screenCode.toInt()] + } + + } + + private fun BufferedImage.copy(): BufferedImage { + val bcopy = BufferedImage(this.width, this.height, this.type) + val g = bcopy.graphics + g.drawImage(this, 0, 0, null) + g.dispose() + return bcopy + } + + + val colorPalette = listOf( // this is Pepto's Commodore-64 palette http://www.pepto.de/projects/colorvic/ + Color(0x000000), // 0 = black + Color(0xFFFFFF), // 1 = white + Color(0x813338), // 2 = red + Color(0x75cec8), // 3 = cyan + Color(0x8e3c97), // 4 = purple + Color(0x56ac4d), // 5 = green + Color(0x2e2c9b), // 6 = blue + Color(0xedf171), // 7 = yellow + Color(0x8e5029), // 8 = orange + Color(0x553800), // 9 = brown + Color(0xc46c71), // 10 = light red + Color(0x4a4a4a), // 11 = dark grey + Color(0x7b7b7b), // 12 = medium grey + Color(0xa9ff9f), // 13 = light green + Color(0x706deb), // 14 = light blue + Color(0xb2b2b2) // 15 = light grey + ) + +} diff --git a/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt b/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt index d3006516e..74c987244 100644 --- a/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt +++ b/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt @@ -8,6 +8,13 @@ import prog8.compiler.intermediate.Opcode import prog8.compiler.toHex import prog8.vm.stackvm.Syscall import prog8.vm.stackvm.syscallsForStackVm +import prog8.compiler.target.c64.MachineDefinition.C64Zeropage +import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS2_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX +import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS2_HEX // note: see https://wiki.nesdev.com/w/index.php/6502_assembly_optimisations @@ -66,23 +73,23 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx" Opcode.DUP_B -> { - " lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x | dex | ;DUP_B " + " lda $ESTACK_LO_PLUS1_HEX,x | sta $ESTACK_LO_HEX,x | dex | ;DUP_B " } Opcode.DUP_W -> { - " lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x | lda ${(ESTACK_HI+1).toHex()},x | sta ${ESTACK_HI.toHex()},x | dex " + " lda $ESTACK_LO_PLUS1_HEX,x | sta $ESTACK_LO_HEX,x | lda $ESTACK_HI_PLUS1_HEX,x | sta $ESTACK_HI_HEX,x | dex " } Opcode.CMP_B, Opcode.CMP_UB -> { - " inx | lda ${ESTACK_LO.toHex()},x | cmp #${ins.arg!!.integerValue().toHex()} | ;CMP_B " + " inx | lda $ESTACK_LO_HEX,x | cmp #${ins.arg!!.integerValue().toHex()} | ;CMP_B " } Opcode.CMP_W, Opcode.CMP_UW -> { """ inx - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x cmp #>${ins.arg!!.integerValue().toHex()} bne + - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x cmp #<${ins.arg.integerValue().toHex()} ; bne + not necessary? ; lda #0 not necessary? @@ -130,11 +137,11 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra } Opcode.PUSH_BYTE -> { - " lda #${hexVal(ins)} | sta ${ESTACK_LO.toHex()},x | dex" + " lda #${hexVal(ins)} | sta $ESTACK_LO_HEX,x | dex" } Opcode.PUSH_WORD -> { val value = hexVal(ins) - " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex" + " lda #<$value | sta $ESTACK_LO_HEX,x | lda #>$value | sta $ESTACK_HI_HEX,x | dex" } Opcode.PUSH_FLOAT -> { val floatConst = getFloatConst(ins.arg!!) @@ -143,28 +150,28 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.PUSH_VAR_BYTE -> { when(ins.callLabel) { "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself. You should probably not use the X register (or only in trivial assignments)") - "A" -> " sta ${ESTACK_LO.toHex()},x | dex" - "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex" - else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex" + "A" -> " sta $ESTACK_LO_HEX,x | dex" + "Y" -> " tya | sta $ESTACK_LO_HEX,x | dex" + else -> " lda ${ins.callLabel} | sta $ESTACK_LO_HEX,x | dex" } } Opcode.PUSH_VAR_WORD -> { - " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda ${ins.callLabel}+1 | sta ${ESTACK_HI.toHex()},x | dex" + " lda ${ins.callLabel} | sta $ESTACK_LO_HEX,x | lda ${ins.callLabel}+1 | sta $ESTACK_HI_HEX,x | dex" } Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr c64flt.push_float" Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> { """ lda ${hexVal(ins)} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x dex """ } Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> { """ lda ${hexVal(ins)} - sta ${ESTACK_LO.toHex()},x + sta $ESTACK_LO_HEX,x lda ${hexValPlusOne(ins)} - sta ${ESTACK_HI.toHex()},x + sta $ESTACK_HI_HEX,x dex """ } @@ -173,43 +180,43 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra } Opcode.PUSH_MEMREAD -> { """ - lda ${(ESTACK_LO+1).toHex()},x + lda $ESTACK_LO_PLUS1_HEX,x sta (+) +1 - lda ${(ESTACK_HI+1).toHex()},x + lda $ESTACK_HI_PLUS1_HEX,x sta (+) +2 + lda 65535 ; modified - sta ${(ESTACK_LO+1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x """ } Opcode.PUSH_REGAY_WORD -> { - " sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex " + " sta $ESTACK_LO_HEX,x | tya | sta $ESTACK_HI_HEX,x | dex " } Opcode.PUSH_ADDR_HEAPVAR -> { - " lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex" + " lda #<${ins.callLabel} | sta $ESTACK_LO_HEX,x | lda #>${ins.callLabel} | sta $ESTACK_HI_HEX,x | dex" } Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGAY_WORD -> { - " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x " + " inx | lda $ESTACK_LO_HEX,x | ldy $ESTACK_HI_HEX,x " } Opcode.READ_INDEXED_VAR_BYTE -> { """ - ldy ${(ESTACK_LO+1).toHex()},x + ldy $ESTACK_LO_PLUS1_HEX,x lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x """ } Opcode.READ_INDEXED_VAR_WORD -> { """ - lda ${(ESTACK_LO+1).toHex()},x + lda $ESTACK_LO_PLUS1_HEX,x asl a tay lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x lda ${ins.callLabel}+1,y - sta ${(ESTACK_HI+1).toHex()},x + sta $ESTACK_HI_PLUS1_HEX,x """ } Opcode.READ_INDEXED_VAR_FLOAT -> { @@ -222,22 +229,22 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.WRITE_INDEXED_VAR_BYTE -> { """ inx - ldy ${ESTACK_LO.toHex()},x + ldy $ESTACK_LO_HEX,x inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta ${ins.callLabel},y """ } Opcode.WRITE_INDEXED_VAR_WORD -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x asl a tay inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta ${ins.callLabel},y - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x sta ${ins.callLabel}+1,y """ } @@ -251,16 +258,16 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POP_MEM_BYTE -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta ${hexVal(ins)} """ } Opcode.POP_MEM_WORD -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta ${hexVal(ins)} - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x sta ${hexValPlusOne(ins)} """ } @@ -270,12 +277,12 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POP_MEMWRITE -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta (+) +1 - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x sta (+) +2 inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x + sta 65535 ; modified """ } @@ -283,13 +290,13 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POP_VAR_BYTE -> { when (ins.callLabel) { "X" -> throw CompilerException("makes no sense to pop X, it's used as a stack pointer itself") - "A" -> " inx | lda ${ESTACK_LO.toHex()},x" - "Y" -> " inx | ldy ${ESTACK_LO.toHex()},x" - else -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${ins.callLabel}" + "A" -> " inx | lda $ESTACK_LO_HEX,x" + "Y" -> " inx | ldy $ESTACK_LO_HEX,x" + else -> " inx | lda $ESTACK_LO_HEX,x | sta ${ins.callLabel}" } } Opcode.POP_VAR_WORD -> { - " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x | sta ${ins.callLabel} | sty ${ins.callLabel}+1" + " inx | lda $ESTACK_LO_HEX,x | ldy $ESTACK_HI_HEX,x | sta ${ins.callLabel} | sty ${ins.callLabel}+1" } Opcode.POP_VAR_FLOAT -> { " lda #<${ins.callLabel} | ldy #>${ins.callLabel} | jsr c64flt.pop_float" @@ -316,9 +323,9 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POP_INC_MEMORY -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta (+) +1 - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x sta (+) +2 + inc 65535 ; modified """ @@ -326,9 +333,9 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POP_DEC_MEMORY -> { """ inx - lda ${ESTACK_LO.toHex()},x + lda $ESTACK_LO_HEX,x sta (+) +1 - lda ${ESTACK_HI.toHex()},x + lda $ESTACK_HI_HEX,x sta (+) +2 + dec 65535 ; modified """ @@ -353,8 +360,8 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra } Opcode.INC_MEMORY -> " inc ${hexVal(ins)}" Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}" - Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | inc ${ins.callLabel},x | pla | tax" - Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | dec ${ins.callLabel},x | pla | tax" + Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> " inx | txa | pha | lda $ESTACK_LO_HEX,x | tax | inc ${ins.callLabel},x | pla | tax" + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> " inx | txa | pha | lda $ESTACK_LO_HEX,x | tax | dec ${ins.callLabel},x | pla | tax" Opcode.NEG_B -> " jsr prog8_lib.neg_b" Opcode.NEG_W -> " jsr prog8_lib.neg_w" @@ -365,9 +372,9 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.POW_F -> " jsr c64flt.pow_f" Opcode.INV_BYTE -> { """ - lda ${(ESTACK_LO + 1).toHex()},x + lda $ESTACK_LO_PLUS1_HEX,x eor #255 - sta ${(ESTACK_LO + 1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x """ } Opcode.INV_WORD -> " jsr prog8_lib.inv_word" @@ -409,7 +416,7 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra val label = ins.callLabel ?: hexVal(ins) """ inx - lda ${(ESTACK_LO).toHex()},x + lda $ESTACK_LO_HEX,x beq $label """ } @@ -417,9 +424,9 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra val label = ins.callLabel ?: hexVal(ins) """ inx - lda ${(ESTACK_LO).toHex()},x + lda $ESTACK_LO_HEX,x beq $label - lda ${(ESTACK_HI).toHex()},x + lda $ESTACK_HI_HEX,x beq $label """ } @@ -427,7 +434,7 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra val label = ins.callLabel ?: hexVal(ins) """ inx - lda ${(ESTACK_LO).toHex()},x + lda $ESTACK_LO_HEX,x bne $label """ } @@ -435,9 +442,9 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra val label = ins.callLabel ?: hexVal(ins) """ inx - lda ${(ESTACK_LO).toHex()},x + lda $ESTACK_LO_HEX,x bne $label - lda ${(ESTACK_HI).toHex()},x + lda $ESTACK_HI_HEX,x bne $label """ } @@ -457,27 +464,27 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.CAST_F_TO_B -> " jsr c64flt.stack_float2w" Opcode.CAST_F_TO_UW -> " jsr c64flt.stack_float2uw" Opcode.CAST_F_TO_W -> " jsr c64flt.stack_float2w" - Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb - Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1).toHex()},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb - Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x" - Opcode.MKWORD -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${(ESTACK_HI+1).toHex()},x " + Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta $ESTACK_HI_PLUS1_HEX,x" // clear the msb + Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda $ESTACK_LO_PLUS1_HEX,x | ${signExtendA("$ESTACK_HI_PLUS1_HEX,x")}" // sign extend the lsb + Opcode.MSB -> " lda $ESTACK_HI_PLUS1_HEX,x | sta $ESTACK_LO_PLUS1_HEX,x" + Opcode.MKWORD -> " inx | lda $ESTACK_LO_HEX,x | sta $ESTACK_HI_PLUS1_HEX,x " Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better (pattern with more opcodes) """ - lda ${(ESTACK_LO + 2).toHex()},x + lda $ESTACK_LO_PLUS2_HEX,x clc - adc ${(ESTACK_LO + 1).toHex()},x + adc $ESTACK_LO_PLUS1_HEX,x inx - sta ${(ESTACK_LO + 1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x """ } Opcode.SUB_UB, Opcode.SUB_B -> { // TODO inline better (pattern with more opcodes) """ - lda ${(ESTACK_LO + 2).toHex()},x + lda $ESTACK_LO_PLUS2_HEX,x sec - sbc ${(ESTACK_LO + 1).toHex()},x + sbc $ESTACK_LO_PLUS1_HEX,x inx - sta ${(ESTACK_LO + 1).toHex()},x + sta $ESTACK_LO_PLUS1_HEX,x """ } Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_w" @@ -541,12 +548,12 @@ internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.Progra Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w" Opcode.LESSEQ_F -> " jsr c64flt.lesseq_f" - Opcode.SHIFTEDL_BYTE -> " asl ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDL_WORD -> " asl ${(ESTACK_LO+1).toHex()},x | rol ${(ESTACK_HI+1).toHex()},x" - Opcode.SHIFTEDR_SBYTE -> " lda ${(ESTACK_LO+1).toHex()},x | asl a | ror ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_UBYTE -> " lsr ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_SWORD -> " lda ${(ESTACK_HI+1).toHex()},x | asl a | ror ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_UWORD -> " lsr ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" + Opcode.SHIFTEDL_BYTE -> " asl $ESTACK_LO_PLUS1_HEX,x" + Opcode.SHIFTEDL_WORD -> " asl $ESTACK_LO_PLUS1_HEX,x | rol $ESTACK_HI_PLUS1_HEX,x" + Opcode.SHIFTEDR_SBYTE -> " lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x" + Opcode.SHIFTEDR_UBYTE -> " lsr $ESTACK_LO_PLUS1_HEX,x" + Opcode.SHIFTEDR_SWORD -> " lda $ESTACK_HI_PLUS1_HEX,x | asl a | ror $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x" + Opcode.SHIFTEDR_UWORD -> " lsr $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x" else -> null } diff --git a/compiler/src/prog8/optimizer/ConstantFolding.kt b/compiler/src/prog8/optimizer/ConstantFolding.kt index 3fcd99a84..7db70e60d 100644 --- a/compiler/src/prog8/optimizer/ConstantFolding.kt +++ b/compiler/src/prog8/optimizer/ConstantFolding.kt @@ -7,8 +7,8 @@ import prog8.ast.processing.IAstModifyingVisitor import prog8.ast.statements.* import prog8.compiler.HeapValues import prog8.compiler.IntegerOrAddressOf -import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE -import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE import kotlin.math.floor diff --git a/compiler/src/prog8/vm/astvm/AstVm.kt b/compiler/src/prog8/vm/astvm/AstVm.kt index 316b0fc4a..741e1df93 100644 --- a/compiler/src/prog8/vm/astvm/AstVm.kt +++ b/compiler/src/prog8/vm/astvm/AstVm.kt @@ -6,7 +6,7 @@ import prog8.ast.base.initvarsSubName import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.LiteralValue import prog8.ast.statements.* -import prog8.compiler.target.c64.Mflpt5 +import prog8.compiler.target.c64.MachineDefinition import prog8.vm.RuntimeValue import prog8.vm.RuntimeValueRange import prog8.compiler.target.c64.Petscii @@ -621,7 +621,7 @@ class AstVm(val program: Program) { DataType.BYTE -> mem.setSByte(address+index, value.byteval!!) DataType.UWORD -> mem.setUWord(address+index*2, value.wordval!!) DataType.WORD -> mem.setSWord(address+index*2, value.wordval!!) - DataType.FLOAT -> mem.setFloat(address+index*Mflpt5.MemorySize, value.floatval!!) + DataType.FLOAT -> mem.setFloat(address+index* MachineDefinition.Mflpt5.MemorySize, value.floatval!!) else -> throw VmExecutionException("strange array elt type $elementType") } } diff --git a/compiler/src/prog8/vm/astvm/Memory.kt b/compiler/src/prog8/vm/astvm/Memory.kt index ca1d8ff4c..36dac7f1c 100644 --- a/compiler/src/prog8/vm/astvm/Memory.kt +++ b/compiler/src/prog8/vm/astvm/Memory.kt @@ -1,6 +1,6 @@ package prog8.vm.astvm -import prog8.compiler.target.c64.Mflpt5 +import prog8.compiler.target.c64.MachineDefinition import prog8.compiler.target.c64.Petscii import kotlin.math.abs @@ -80,7 +80,7 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short, } fun setFloat(address: Int, value: Double) { - val mflpt5 = Mflpt5.fromNumber(value) + val mflpt5 = MachineDefinition.Mflpt5.fromNumber(value) setUByte(address, mflpt5.b0) setUByte(address+1, mflpt5.b1) setUByte(address+2, mflpt5.b2) @@ -89,7 +89,7 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short, } fun getFloat(address: Int): Double { - return Mflpt5(getUByte(address), getUByte(address + 1), getUByte(address + 2), + return MachineDefinition.Mflpt5(getUByte(address), getUByte(address + 1), getUByte(address + 2), getUByte(address + 3), getUByte(address + 4)).toDouble() } diff --git a/compiler/src/prog8/vm/astvm/ScreenDialog.kt b/compiler/src/prog8/vm/astvm/ScreenDialog.kt index 94a4679ec..254c8b540 100644 --- a/compiler/src/prog8/vm/astvm/ScreenDialog.kt +++ b/compiler/src/prog8/vm/astvm/ScreenDialog.kt @@ -1,7 +1,6 @@ package prog8.vm.astvm -import prog8.compiler.target.c64.Charset -import prog8.compiler.target.c64.Colors +import prog8.compiler.target.c64.MachineDefinition import prog8.compiler.target.c64.Petscii import java.awt.* import java.awt.event.KeyEvent @@ -51,16 +50,16 @@ class BitmapScreenPanel : KeyListener, JPanel() { } fun clearScreen(color: Short) { - g2d.background = Colors.palette[color % Colors.palette.size] + g2d.background = MachineDefinition.colorPalette[color % MachineDefinition.colorPalette.size] g2d.clearRect(0, 0, SCREENWIDTH, SCREENHEIGHT) cursorX = 0 cursorY = 0 } fun setPixel(x: Int, y: Int, color: Short) { - image.setRGB(x, y, Colors.palette[color % Colors.palette.size].rgb) + image.setRGB(x, y, MachineDefinition.colorPalette[color % MachineDefinition.colorPalette.size].rgb) } fun drawLine(x1: Int, y1: Int, x2: Int, y2: Int, color: Short) { - g2d.color = Colors.palette[color % Colors.palette.size] + g2d.color = MachineDefinition.colorPalette[color % MachineDefinition.colorPalette.size] g2d.drawLine(x1, y1, x2, y2) } @@ -95,7 +94,7 @@ class BitmapScreenPanel : KeyListener, JPanel() { val graphics = image.graphics as Graphics2D graphics.drawImage(screen, 0, -8, null) val color = graphics.color - graphics.color = Colors.palette[6] + graphics.color = MachineDefinition.colorPalette[6] graphics.fillRect(0, 24*8, SCREENWIDTH, 25*8) graphics.color=color cursorY-- @@ -103,7 +102,7 @@ class BitmapScreenPanel : KeyListener, JPanel() { } fun writeTextAt(x: Int, y: Int, text: String, color: Short, lowercase: Boolean, inverseVideo: Boolean=false) { - val colorIdx = (color % Colors.palette.size).toShort() + val colorIdx = (color % MachineDefinition.colorPalette.size).toShort() var xx=x for(clearx in xx until xx+text.length) { g2d.clearRect(8*clearx, 8*y, 8, 8) @@ -117,16 +116,16 @@ class BitmapScreenPanel : KeyListener, JPanel() { fun setPetscii(x: Int, y: Int, petscii: Short, color: Short, inverseVideo: Boolean) { g2d.clearRect(8*x, 8*y, 8, 8) - val colorIdx = (color % Colors.palette.size).toShort() + val colorIdx = (color % MachineDefinition.colorPalette.size).toShort() val screencode = Petscii.petscii2scr(petscii, inverseVideo) - val coloredImage = Charset.getColoredChar(screencode, colorIdx) + val coloredImage = MachineDefinition.Charset.getColoredChar(screencode, colorIdx) g2d.drawImage(coloredImage, 8*x, 8*y , null) } fun setChar(x: Int, y: Int, screencode: Short, color: Short) { g2d.clearRect(8*x, 8*y, 8, 8) - val colorIdx = (color % Colors.palette.size).toShort() - val coloredImage = Charset.getColoredChar(screencode, colorIdx) + val colorIdx = (color % MachineDefinition.colorPalette.size).toShort() + val coloredImage = MachineDefinition.Charset.getColoredChar(screencode, colorIdx) g2d.drawImage(coloredImage, 8*x, 8*y , null) } @@ -160,19 +159,19 @@ class ScreenDialog(title: String) : JFrame(title) { // the borders (top, left, right, bottom) val borderTop = JPanel().apply { preferredSize = Dimension(BitmapScreenPanel.SCALING * (BitmapScreenPanel.SCREENWIDTH +2*borderWidth), BitmapScreenPanel.SCALING * borderWidth) - background = Colors.palette[14] + background = MachineDefinition.colorPalette[14] } val borderBottom = JPanel().apply { preferredSize =Dimension(BitmapScreenPanel.SCALING * (BitmapScreenPanel.SCREENWIDTH +2*borderWidth), BitmapScreenPanel.SCALING * borderWidth) - background = Colors.palette[14] + background = MachineDefinition.colorPalette[14] } val borderLeft = JPanel().apply { preferredSize =Dimension(BitmapScreenPanel.SCALING * borderWidth, BitmapScreenPanel.SCALING * BitmapScreenPanel.SCREENHEIGHT) - background = Colors.palette[14] + background = MachineDefinition.colorPalette[14] } val borderRight = JPanel().apply { preferredSize =Dimension(BitmapScreenPanel.SCALING * borderWidth, BitmapScreenPanel.SCALING * BitmapScreenPanel.SCREENHEIGHT) - background = Colors.palette[14] + background = MachineDefinition.colorPalette[14] } var c = GridBagConstraints() c.gridx=0; c.gridy=1; c.gridwidth=3 diff --git a/compiler/test/UnitTests.kt b/compiler/test/UnitTests.kt index cfa28ef06..5348c2b7e 100644 --- a/compiler/test/UnitTests.kt +++ b/compiler/test/UnitTests.kt @@ -10,7 +10,11 @@ import prog8.ast.base.Position import prog8.ast.expressions.LiteralValue import prog8.vm.RuntimeValue import prog8.compiler.* -import prog8.compiler.target.c64.* +import prog8.compiler.target.c64.MachineDefinition.Mflpt5 +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE +import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE +import prog8.compiler.target.c64.MachineDefinition.C64Zeropage +import prog8.compiler.target.c64.Petscii import java.io.CharConversionException import kotlin.test.*