fix assembly for cx16 when zp is not basicsafe

This commit is contained in:
Irmen de Jong 2020-09-06 17:58:05 +02:00
parent 8f9f947c42
commit 1377bed988
23 changed files with 98 additions and 89 deletions

View File

@ -58,6 +58,12 @@ romsub $FFF3 = IOBASE() -> uword @ XY ; read base addr
cx16 { cx16 {
; 65c02 hardware vectors:
&uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in
&uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in
&uword IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in
; ---- Commander X-16 additions on top of C64 kernal routines ---- ; ---- Commander X-16 additions on top of C64 kernal routines ----
; spelling of the names is taken from the Commander X-16 rom sources ; spelling of the names is taken from the Commander X-16 rom sources
@ -205,6 +211,8 @@ asmsub init_system() {
cld cld
stz $00 stz $00
stz $01 stz $01
lda #$80
sta VERA_CTRL
jsr c64.IOINIT jsr c64.IOINIT
jsr c64.RESTOR jsr c64.RESTOR
jsr c64.CINT jsr c64.CINT

View File

@ -4,13 +4,10 @@ import kotlinx.cli.*
import prog8.ast.base.AstException import prog8.ast.base.AstException
import prog8.compiler.CompilationResult import prog8.compiler.CompilationResult
import prog8.compiler.compileProgram import prog8.compiler.compileProgram
import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target
import prog8.compiler.target.CompilationTarget import prog8.compiler.target.CompilationTarget
import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.c64.Petscii
import prog8.compiler.target.c64.codegen.AsmGen
import prog8.compiler.target.cx16.CX16MachineDefinition
import prog8.parser.ParsingFailedError import prog8.parser.ParsingFailedError
import java.io.IOException
import java.nio.file.FileSystems import java.nio.file.FileSystems
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.StandardWatchEventKinds import java.nio.file.StandardWatchEventKinds
@ -52,30 +49,10 @@ private fun compileMain(args: Array<String>) {
when(compilationTarget) { when(compilationTarget) {
"c64" -> { "c64" -> {
with(CompilationTarget) { CompilationTarget.instance = C64Target()
name = "Commodore-64"
machine = C64MachineDefinition
encodeString = { str, altEncoding ->
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
}
decodeString = { bytes, altEncoding ->
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
}
asmGenerator = ::AsmGen
}
} }
"cx16" -> { "cx16" -> {
with(CompilationTarget) { CompilationTarget.instance = Cx16Target()
name = "Commander X16"
machine = CX16MachineDefinition
encodeString = { str, altEncoding ->
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
}
decodeString = { bytes, altEncoding ->
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
}
asmGenerator = ::AsmGen
}
} }
else -> { else -> {
System.err.println("invalid compilation target. Available are: c64, cx16") System.err.println("invalid compilation target. Available are: c64, cx16")
@ -135,7 +112,7 @@ private fun compileMain(args: Array<String>) {
if (compilationResult.programName.isEmpty()) if (compilationResult.programName.isEmpty())
println("\nCan't start emulator because no program was assembled.") println("\nCan't start emulator because no program was assembled.")
else if(startEmulator) { else if(startEmulator) {
CompilationTarget.machine.launchEmulator(compilationResult.programName) CompilationTarget.instance.machine.launchEmulator(compilationResult.programName)
} }
} }
} }

View File

@ -472,7 +472,7 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
litval.charliteral()!=null -> { litval.charliteral()!=null -> {
try { try {
val cc=litval.charliteral() val cc=litval.charliteral()
NumericLiteralValue(DataType.UBYTE, CompilationTarget.encodeString( NumericLiteralValue(DataType.UBYTE, CompilationTarget.instance.encodeString(
unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()), unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()),
litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition()) litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition())
} catch (ce: CharConversionException) { } catch (ce: CharConversionException) {

View File

@ -56,8 +56,8 @@ enum class DataType {
return when(this) { return when(this) {
in ByteDatatypes -> 1 in ByteDatatypes -> 1
in WordDatatypes -> 2 in WordDatatypes -> 2
FLOAT -> CompilationTarget.machine.FLOAT_MEM_SIZE FLOAT -> CompilationTarget.instance.machine.FLOAT_MEM_SIZE
in PassByReferenceDatatypes -> CompilationTarget.machine.POINTER_MEM_SIZE in PassByReferenceDatatypes -> CompilationTarget.instance.machine.POINTER_MEM_SIZE
else -> -9999999 else -> -9999999
} }
} }

View File

@ -671,8 +671,8 @@ class RangeExpr(var from: Expression,
val toString = to as? StringLiteralValue val toString = to as? StringLiteralValue
if(fromString!=null && toString!=null ) { if(fromString!=null && toString!=null ) {
// string range -> int range over character values // string range -> int range over character values
fromVal = CompilationTarget.encodeString(fromString.value, fromString.altEncoding)[0].toInt() fromVal = CompilationTarget.instance.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
toVal = CompilationTarget.encodeString(toString.value, fromString.altEncoding)[0].toInt() toVal = CompilationTarget.instance.encodeString(toString.value, fromString.altEncoding)[0].toInt()
} else { } else {
val fromLv = from as? NumericLiteralValue val fromLv = from as? NumericLiteralValue
val toLv = to as? NumericLiteralValue val toLv = to as? NumericLiteralValue

View File

@ -1155,7 +1155,7 @@ internal class AstChecker(private val program: Program,
// check if the floating point values are all within range // check if the floating point values are all within range
val doubles = value.value.map {it.constValue(program)?.number!!.toDouble()}.toDoubleArray() val doubles = value.value.map {it.constValue(program)?.number!!.toDouble()}.toDoubleArray()
if(doubles.any { it < CompilationTarget.machine.FLOAT_MAX_NEGATIVE || it > CompilationTarget.machine.FLOAT_MAX_POSITIVE }) if(doubles.any { it < CompilationTarget.instance.machine.FLOAT_MAX_NEGATIVE || it > CompilationTarget.instance.machine.FLOAT_MAX_POSITIVE })
return err("floating point value overflow") return err("floating point value overflow")
return true return true
} }

View File

@ -22,7 +22,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
} }
override fun visit(block: Block) { override fun visit(block: Block) {
if(block.name in CompilationTarget.machine.opcodeNames) if(block.name in CompilationTarget.instance.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position) errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position)
val existing = blocks[block.name] val existing = blocks[block.name]
@ -40,7 +40,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
if(decl.name in BuiltinFunctions) if(decl.name in BuiltinFunctions)
errors.err("builtin function cannot be redefined", decl.position) errors.err("builtin function cannot be redefined", decl.position)
if(decl.name in CompilationTarget.machine.opcodeNames) if(decl.name in CompilationTarget.instance.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position) errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
if(decl.datatype==DataType.STRUCT) { if(decl.datatype==DataType.STRUCT) {
@ -74,7 +74,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
} }
override fun visit(subroutine: Subroutine) { override fun visit(subroutine: Subroutine) {
if(subroutine.name in CompilationTarget.machine.opcodeNames) { if(subroutine.name in CompilationTarget.instance.machine.opcodeNames) {
errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position) errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position)
} else if(subroutine.name in BuiltinFunctions) { } else if(subroutine.name in BuiltinFunctions) {
// the builtin functions can't be redefined // the builtin functions can't be redefined
@ -119,7 +119,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
} }
override fun visit(label: Label) { override fun visit(label: Label) {
if(label.name in CompilationTarget.machine.opcodeNames) if(label.name in CompilationTarget.instance.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position) errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
if(label.name in BuiltinFunctions) { if(label.name in BuiltinFunctions) {

View File

@ -91,7 +91,7 @@ private fun parseImports(filepath: Path, errors: ErrorReporter): Triple<Program,
throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.") throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.")
// depending on the mach9ine and compiler options we may have to include some libraries // depending on the mach9ine and compiler options we may have to include some libraries
CompilationTarget.machine.importLibs(compilerOptions, importer, programAst) CompilationTarget.instance.machine.importLibs(compilerOptions, importer, programAst)
// always import prog8lib and math // always import prog8lib and math
importer.importLibraryModule(programAst, "math") importer.importLibraryModule(programAst, "math")
@ -191,11 +191,11 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir:
// printAst(programAst) // printAst(programAst)
CompilationTarget.machine.initializeZeropage(compilerOptions) CompilationTarget.instance.machine.initializeZeropage(compilerOptions)
val assembly = CompilationTarget.asmGenerator( val assembly = CompilationTarget.instance.asmGenerator(
programAst, programAst,
errors, errors,
CompilationTarget.machine.zeropage, CompilationTarget.instance.machine.zeropage,
compilerOptions, compilerOptions,
outputDir).compileToAssembly(optimize) outputDir).compileToAssembly(optimize)
assembly.assemble(compilerOptions) assembly.assemble(compilerOptions)

View File

@ -4,15 +4,44 @@ import prog8.ast.Program
import prog8.ast.base.ErrorReporter import prog8.ast.base.ErrorReporter
import prog8.compiler.CompilationOptions import prog8.compiler.CompilationOptions
import prog8.compiler.Zeropage import prog8.compiler.Zeropage
import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.c64.Petscii
import prog8.compiler.target.c64.codegen.AsmGen
import prog8.compiler.target.cx16.CX16MachineDefinition
import java.nio.file.Path import java.nio.file.Path
internal interface CompilationTarget { internal interface CompilationTarget {
val name: String
val machine: IMachineDefinition
fun encodeString(str: String, altEncoding: Boolean): List<Short>
fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path): IAssemblyGenerator
companion object { companion object {
lateinit var name: String lateinit var instance: CompilationTarget
lateinit var machine: IMachineDefinition
lateinit var encodeString: (str: String, altEncoding: Boolean) -> List<Short>
lateinit var decodeString: (bytes: List<Short>, altEncoding: Boolean) -> String
lateinit var asmGenerator: (Program, ErrorReporter, Zeropage, CompilationOptions, Path) -> IAssemblyGenerator
} }
} }
internal class C64Target: CompilationTarget {
override val name = "c64"
override val machine = C64MachineDefinition
override fun encodeString(str: String, altEncoding: Boolean) =
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) =
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
AsmGen(program, errors, zp, options, path)
}
internal class Cx16Target: CompilationTarget {
override val name = "cx16"
override val machine = CX16MachineDefinition
override fun encodeString(str: String, altEncoding: Boolean) =
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) =
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
AsmGen(program, errors, zp, options, path)
}

View File

@ -28,7 +28,6 @@ internal interface IMachineDefinition {
val opcodeNames: Set<String> val opcodeNames: Set<String>
var zeropage: Zeropage var zeropage: Zeropage
val initSystemProcname: String
val cpu: CpuType val cpu: CpuType
fun initializeZeropage(compilerOptions: CompilationOptions) fun initializeZeropage(compilerOptions: CompilationOptions)

View File

@ -29,7 +29,6 @@ internal object C64MachineDefinition: IMachineDefinition {
override val ESTACK_HI = 0xcf00 // $ce00-$ceff inclusive override val ESTACK_HI = 0xcf00 // $ce00-$ceff inclusive
override lateinit var zeropage: Zeropage override lateinit var zeropage: Zeropage
override val initSystemProcname = "c64.init_system"
override fun getFloat(num: Number) = Mflpt5.fromNumber(num) override fun getFloat(num: Number) = Mflpt5.fromNumber(num)

View File

@ -79,7 +79,7 @@ internal class AsmGen(private val program: Program,
private fun header() { private fun header() {
val ourName = this.javaClass.name val ourName = this.javaClass.name
val cpu = when(CompilationTarget.machine.cpu) { val cpu = when(CompilationTarget.instance.machine.cpu) {
CpuType.CPU6502 -> "6502" CpuType.CPU6502 -> "6502"
CpuType.CPU65c02 -> "65c02" CpuType.CPU65c02 -> "65c02"
else -> "unsupported" else -> "unsupported"
@ -94,18 +94,18 @@ internal class AsmGen(private val program: Program,
program.actualLoadAddress = program.definedLoadAddress program.actualLoadAddress = program.definedLoadAddress
if (program.actualLoadAddress == 0) // fix load address if (program.actualLoadAddress == 0) // fix load address
program.actualLoadAddress = if (options.launcher == LauncherType.BASIC) program.actualLoadAddress = if (options.launcher == LauncherType.BASIC)
CompilationTarget.machine.BASIC_LOAD_ADDRESS else CompilationTarget.machine.RAW_LOAD_ADDRESS CompilationTarget.instance.machine.BASIC_LOAD_ADDRESS else CompilationTarget.instance.machine.RAW_LOAD_ADDRESS
// the global prog8 variables needed // the global prog8 variables needed
val zp = CompilationTarget.machine.zeropage val zp = CompilationTarget.instance.machine.zeropage
val initproc = CompilationTarget.machine.initSystemProcname val initproc = CompilationTarget.instance.name + ".init_system"
out("P8ZP_SCRATCH_B1 = ${zp.SCRATCH_B1}") out("P8ZP_SCRATCH_B1 = ${zp.SCRATCH_B1}")
out("P8ZP_SCRATCH_REG = ${zp.SCRATCH_REG}") out("P8ZP_SCRATCH_REG = ${zp.SCRATCH_REG}")
out("P8ZP_SCRATCH_REG_X = ${zp.SCRATCH_REG_X}") out("P8ZP_SCRATCH_REG_X = ${zp.SCRATCH_REG_X}")
out("P8ZP_SCRATCH_W1 = ${zp.SCRATCH_W1} ; word") out("P8ZP_SCRATCH_W1 = ${zp.SCRATCH_W1} ; word")
out("P8ZP_SCRATCH_W2 = ${zp.SCRATCH_W2} ; word") out("P8ZP_SCRATCH_W2 = ${zp.SCRATCH_W2} ; word")
out("P8ESTACK_LO = ${CompilationTarget.machine.ESTACK_LO.toHex()}") out("P8ESTACK_LO = ${CompilationTarget.instance.machine.ESTACK_LO.toHex()}")
out("P8ESTACK_HI = ${CompilationTarget.machine.ESTACK_HI.toHex()}") out("P8ESTACK_HI = ${CompilationTarget.instance.machine.ESTACK_HI.toHex()}")
when { when {
options.launcher == LauncherType.BASIC -> { options.launcher == LauncherType.BASIC -> {
@ -161,7 +161,7 @@ internal class AsmGen(private val program: Program,
} }
Zeropage.ExitProgramStrategy.SYSTEM_RESET -> { Zeropage.ExitProgramStrategy.SYSTEM_RESET -> {
out(" jsr main.start\t; call program entrypoint") out(" jsr main.start\t; call program entrypoint")
out(" jmp (c64.RESET_VEC)\t; cold reset") out(" jmp (${CompilationTarget.instance.name}.RESET_VEC)\t; cold reset")
} }
} }
} }
@ -170,7 +170,7 @@ internal class AsmGen(private val program: Program,
// the global list of all floating point constants for the whole program // the global list of all floating point constants for the whole program
out("; global float constants") out("; global float constants")
for (flt in globalFloatConsts) { for (flt in globalFloatConsts) {
val floatFill = CompilationTarget.machine.getFloat(flt.key).makeFloatFillAsm() val floatFill = CompilationTarget.instance.machine.getFloat(flt.key).makeFloatFillAsm()
val floatvalue = flt.key val floatvalue = flt.key
out("${flt.value}\t.byte $floatFill ; float $floatvalue") out("${flt.value}\t.byte $floatFill ; float $floatvalue")
} }
@ -340,7 +340,7 @@ internal class AsmGen(private val program: Program,
} }
val floatFills = array.map { val floatFills = array.map {
val number = (it as NumericLiteralValue).number val number = (it as NumericLiteralValue).number
CompilationTarget.machine.getFloat(number).makeFloatFillAsm() CompilationTarget.instance.machine.getFloat(number).makeFloatFillAsm()
} }
out(name) out(name)
for (f in array.zip(floatFills)) for (f in array.zip(floatFills))
@ -474,7 +474,7 @@ internal class AsmGen(private val program: Program,
} }
internal fun getFloatAsmConst(number: Double): String { internal fun getFloatAsmConst(number: Double): String {
var asmName = CompilationTarget.machine.getFloatRomConst(number) var asmName = CompilationTarget.instance.machine.getFloatRomConst(number)
if(asmName.isNullOrEmpty()) { if(asmName.isNullOrEmpty()) {
// no ROM float const for this value, create our own // no ROM float const for this value, create our own
asmName = globalFloatConsts[number] asmName = globalFloatConsts[number]
@ -552,7 +552,7 @@ internal class AsmGen(private val program: Program,
when(register) { when(register) {
CpuRegister.A -> out(" pha") CpuRegister.A -> out(" pha")
CpuRegister.X -> { CpuRegister.X -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
out(" phx") out(" phx")
else else
out(" stx P8ZP_SCRATCH_REG_X") out(" stx P8ZP_SCRATCH_REG_X")
@ -565,7 +565,7 @@ internal class AsmGen(private val program: Program,
when(register) { when(register) {
CpuRegister.A -> out(" pla") CpuRegister.A -> out(" pla")
CpuRegister.X -> { CpuRegister.X -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
out(" plx") out(" plx")
else else
out(" ldx P8ZP_SCRATCH_REG_X") out(" ldx P8ZP_SCRATCH_REG_X")

View File

@ -47,7 +47,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex") RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
RegisterOrPair.X -> { RegisterOrPair.X -> {
// return value in X register has been discarded, just push a zero // return value in X register has been discarded, just push a zero
if(CompilationTarget.machine.cpu==CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
asmgen.out(" stz P8ESTACK_LO,x") asmgen.out(" stz P8ESTACK_LO,x")
else else
asmgen.out(" lda #0 | sta P8ESTACK_LO,x") asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
@ -56,7 +56,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
RegisterOrPair.AX -> { RegisterOrPair.AX -> {
// return value in X register has been discarded, just push a zero in this place // return value in X register has been discarded, just push a zero in this place
asmgen.out(" sta P8ESTACK_LO,x") asmgen.out(" sta P8ESTACK_LO,x")
if(CompilationTarget.machine.cpu==CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
asmgen.out(" stz P8ESTACK_HI,x") asmgen.out(" stz P8ESTACK_HI,x")
else else
asmgen.out(" lda #0 | sta P8ESTACK_HI,x") asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
@ -64,7 +64,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
} }
RegisterOrPair.XY -> { RegisterOrPair.XY -> {
// return value in X register has been discarded, just push a zero in this place // return value in X register has been discarded, just push a zero in this place
if(CompilationTarget.machine.cpu==CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
asmgen.out(" stz P8ESTACK_LO,x") asmgen.out(" stz P8ESTACK_LO,x")
else else
asmgen.out(" lda #0 | sta P8ESTACK_LO,x") asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
@ -85,7 +85,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
when(expr.type) { when(expr.type) {
DataType.UBYTE, DataType.BYTE -> {} DataType.UBYTE, DataType.BYTE -> {}
DataType.UWORD, DataType.WORD -> { DataType.UWORD, DataType.WORD -> {
if(CompilationTarget.machine.cpu==CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
asmgen.out(" stz P8ESTACK_HI+1,x") asmgen.out(" stz P8ESTACK_HI+1,x")
else else
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x") asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")

View File

@ -708,7 +708,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
// optimized case for float zero // optimized case for float zero
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(""" asmgen.out("""
stz ${target.asmVarname} stz ${target.asmVarname}
stz ${target.asmVarname}+1 stz ${target.asmVarname}+1

View File

@ -193,7 +193,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.translateExpression(memory.addressExpression) asmgen.translateExpression(memory.addressExpression)
// TODO buggy?: // TODO buggy?:
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1") asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
val zp = CompilationTarget.machine.zeropage val zp = CompilationTarget.instance.machine.zeropage
when { when {
valueLv != null -> inplaceModification_byte_litval_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv.toInt()) valueLv != null -> inplaceModification_byte_litval_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv.toInt())
ident != null -> inplaceModification_byte_variable_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident) ident != null -> inplaceModification_byte_variable_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident)
@ -747,13 +747,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"&" -> { "&" -> {
when { when {
value == 0 -> { value == 0 -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz $name | stz $name+1") asmgen.out(" stz $name | stz $name+1")
else else
asmgen.out(" lda #0 | sta $name | sta $name+1") asmgen.out(" lda #0 | sta $name | sta $name+1")
} }
value and 255 == 0 -> { value and 255 == 0 -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz $name") asmgen.out(" stz $name")
else else
asmgen.out(" lda #0 | sta $name") asmgen.out(" lda #0 | sta $name")
@ -761,7 +761,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
value < 0x0100 -> { value < 0x0100 -> {
asmgen.out(" lda $name | and #$value | sta $name") asmgen.out(" lda $name | and #$value | sta $name")
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz $name+1") asmgen.out(" stz $name+1")
else else
asmgen.out(" lda #0 | sta $name+1") asmgen.out(" lda #0 | sta $name+1")
@ -1295,20 +1295,20 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
DataType.UBYTE, DataType.BYTE -> { DataType.UBYTE, DataType.BYTE -> {
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz ${target.asmVarname}+1") asmgen.out(" stz ${target.asmVarname}+1")
else else
asmgen.out(" lda #0 | sta ${target.asmVarname}+1") asmgen.out(" lda #0 | sta ${target.asmVarname}+1")
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, target.datatype, CpuRegister.Y, true) asmgen.loadScaledArrayIndexIntoRegister(target.array!!, target.datatype, CpuRegister.Y, true)
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz ${target.asmVarname},y") asmgen.out(" stz ${target.asmVarname},y")
else else
asmgen.out(" lda #0 | sta ${target.asmVarname},y") asmgen.out(" lda #0 | sta ${target.asmVarname},y")
} }
TargetStorageKind.STACK -> { TargetStorageKind.STACK -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02) if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz P8ESTACK_HI+1,x") asmgen.out(" stz P8ESTACK_HI+1,x")
else else
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x") asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")

View File

@ -26,7 +26,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
override val ESTACK_HI = 0x0500 // $0500-$05ff inclusive override val ESTACK_HI = 0x0500 // $0500-$05ff inclusive
override lateinit var zeropage: Zeropage override lateinit var zeropage: Zeropage
override val initSystemProcname = "cx16.init_system"
override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num) override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num)

View File

@ -150,7 +150,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(rangeExpr==null && litval!=null) { if(rangeExpr==null && litval!=null) {
// arraysize initializer is a single int, and we know the size. // arraysize initializer is a single int, and we know the size.
val fillvalue = litval.number.toDouble() val fillvalue = litval.number.toDouble()
if (fillvalue < CompilationTarget.machine.FLOAT_MAX_NEGATIVE || fillvalue > CompilationTarget.machine.FLOAT_MAX_POSITIVE) if (fillvalue < CompilationTarget.instance.machine.FLOAT_MAX_NEGATIVE || fillvalue > CompilationTarget.instance.machine.FLOAT_MAX_POSITIVE)
errors.err("float value overflow", litval.position) errors.err("float value overflow", litval.position)
else { else {
// create the array itself, filled with the fillvalue. // create the array itself, filled with the fillvalue.

View File

@ -104,7 +104,7 @@ internal class StatementOptimizer(private val program: Program,
if(string!=null) { if(string!=null) {
val pos = functionCallStatement.position val pos = functionCallStatement.position
if (string.value.length == 1) { if (string.value.length == 1) {
val firstCharEncoded = CompilationTarget.encodeString(string.value, string.altEncoding)[0] val firstCharEncoded = CompilationTarget.instance.encodeString(string.value, string.altEncoding)[0]
val chrout = FunctionCallStatement( val chrout = FunctionCallStatement(
IdentifierReference(listOf("c64", "CHROUT"), pos), IdentifierReference(listOf("c64", "CHROUT"), pos),
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstCharEncoded.toInt(), pos)), mutableListOf(NumericLiteralValue(DataType.UBYTE, firstCharEncoded.toInt(), pos)),
@ -112,7 +112,7 @@ internal class StatementOptimizer(private val program: Program,
) )
return listOf(IAstModification.ReplaceNode(functionCallStatement, chrout, parent)) return listOf(IAstModification.ReplaceNode(functionCallStatement, chrout, parent))
} else if (string.value.length == 2) { } else if (string.value.length == 2) {
val firstTwoCharsEncoded = CompilationTarget.encodeString(string.value.take(2), string.altEncoding) val firstTwoCharsEncoded = CompilationTarget.instance.encodeString(string.value.take(2), string.altEncoding)
val chrout1 = FunctionCallStatement( val chrout1 = FunctionCallStatement(
IdentifierReference(listOf("c64", "CHROUT"), pos), IdentifierReference(listOf("c64", "CHROUT"), pos),
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstTwoCharsEncoded[0].toInt(), pos)), mutableListOf(NumericLiteralValue(DataType.UBYTE, firstTwoCharsEncoded[0].toInt(), pos)),
@ -220,7 +220,7 @@ internal class StatementOptimizer(private val program: Program,
val size = sv.value.length val size = sv.value.length
if(size==1) { if(size==1) {
// loop over string of length 1 -> just assign the single character // loop over string of length 1 -> just assign the single character
val character = CompilationTarget.encodeString(sv.value, sv.altEncoding)[0] val character = CompilationTarget.instance.encodeString(sv.value, sv.altEncoding)[0]
val byte = NumericLiteralValue(DataType.UBYTE, character, iterable.position) val byte = NumericLiteralValue(DataType.UBYTE, character, iterable.position)
val scope = AnonymousScope(mutableListOf(), forLoop.position) val scope = AnonymousScope(mutableListOf(), forLoop.position)
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, forLoop.position)) scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, forLoop.position))

View File

@ -2,7 +2,8 @@
TODO TODO
==== ====
- optimize assignment codegeneration - further optimize assignment codegeneration
- auto select correct library to import based on target, instead of having c64- and cx16- prefix variants
- get rid of all TODO's ;-) - get rid of all TODO's ;-)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)

View File

@ -1,6 +1,5 @@
%import cx16flt %import cx16flt
%import cx16textio %import cx16textio
; TODO fix compilation when zeropage is not basicsafe
%zeropage basicsafe %zeropage basicsafe
main { main {

View File

@ -1,6 +1,4 @@
%import cx16lib %import cx16lib
; TODO fix compilation when zeropage is not basicsafe
%zeropage basicsafe
main { main {

View File

@ -1,6 +1,4 @@
%import cx16textio %import cx16textio
; TODO fix compilation when zeropage is not basicsafe
%zeropage basicsafe
main { main {

View File

@ -1,8 +1,7 @@
%import c64textio %import cx16textio
%import c64flt ;%import c64flt
%option enable_floats ;%option enable_floats
%zeropage basicsafe ; %zeropage kernalsafe
; TODO fix compilation when zeropage is not basicsafe on cx16
main { main {
@ -10,6 +9,9 @@ main {
sub start() { sub start() {
c64.CHROUT('*')
;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...} ;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...}
; TODO dont cause name conflict if we define sub or sub with param 'color' or even a var 'color' later. ; TODO dont cause name conflict if we define sub or sub with param 'color' or even a var 'color' later.