From 42f4b06ac8b52eccce4f65d40a5fbd1894d09188 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 9 Apr 2024 23:59:54 +0200 Subject: [PATCH] added options -bytes2float and -float2bytes to be able to do float conversions from the command line --- .../src/prog8/code/core/IMachineDefinition.kt | 3 +++ codeCore/src/prog8/code/target/C64Target.kt | 12 ++++++++++ .../target/atari/AtariMachineDefinition.kt | 2 ++ .../code/target/c128/C128MachineDefinition.kt | 11 +++++++++ .../code/target/c64/C64MachineDefinition.kt | 11 +++++++++ .../code/target/cx16/CX16MachineDefinition.kt | 12 ++++++++++ .../code/target/pet/PETMachineDefinition.kt | 11 +++++++++ .../virtual/VirtualMachineDefinition.kt | 20 ++++++++++++++++ compiler/src/prog8/CompilerMain.kt | 24 +++++++++++++++++++ compiler/src/prog8/compiler/Compiler.kt | 17 ++++--------- docs/source/compiling.rst | 7 ++++++ .../src/prog8/intermediate/IRFileReader.kt | 14 +++-------- 12 files changed, 121 insertions(+), 23 deletions(-) diff --git a/codeCore/src/prog8/code/core/IMachineDefinition.kt b/codeCore/src/prog8/code/core/IMachineDefinition.kt index c35ff597f..7e8b54b11 100644 --- a/codeCore/src/prog8/code/core/IMachineDefinition.kt +++ b/codeCore/src/prog8/code/core/IMachineDefinition.kt @@ -26,6 +26,9 @@ interface IMachineDefinition { fun initializeMemoryAreas(compilerOptions: CompilationOptions) fun getFloatAsmBytes(num: Number): String + fun convertFloatToBytes(num: Double): List + fun convertBytesToFloat(bytes: List): Double + fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) fun isIOAddress(address: UInt): Boolean diff --git a/codeCore/src/prog8/code/target/C64Target.kt b/codeCore/src/prog8/code/target/C64Target.kt index 563b6908f..30fb4797f 100644 --- a/codeCore/src/prog8/code/target/C64Target.kt +++ b/codeCore/src/prog8/code/target/C64Target.kt @@ -19,3 +19,15 @@ class C64Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by Cb fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list" } } + + + +fun getCompilationTargetByName(name: String) = when(name.lowercase()) { + C64Target.NAME -> C64Target() + C128Target.NAME -> C128Target() + Cx16Target.NAME -> Cx16Target() + PETTarget.NAME -> PETTarget() + AtariTarget.NAME -> AtariTarget() + VMTarget.NAME -> VMTarget() + else -> throw IllegalArgumentException("invalid compilation target") + } diff --git a/codeCore/src/prog8/code/target/atari/AtariMachineDefinition.kt b/codeCore/src/prog8/code/target/atari/AtariMachineDefinition.kt index e152dca65..60c54dd94 100644 --- a/codeCore/src/prog8/code/target/atari/AtariMachineDefinition.kt +++ b/codeCore/src/prog8/code/target/atari/AtariMachineDefinition.kt @@ -22,6 +22,8 @@ class AtariMachineDefinition: IMachineDefinition { override lateinit var golden: GoldenRam override fun getFloatAsmBytes(num: Number) = TODO("atari float asm bytes from number") + override fun convertFloatToBytes(num: Double): List = TODO("atari float to bytes") + override fun convertBytesToFloat(bytes: List): Double = TODO("atari bytes to float") override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.output == OutputType.XEX) diff --git a/codeCore/src/prog8/code/target/c128/C128MachineDefinition.kt b/codeCore/src/prog8/code/target/c128/C128MachineDefinition.kt index 1c418e143..975a60008 100644 --- a/codeCore/src/prog8/code/target/c128/C128MachineDefinition.kt +++ b/codeCore/src/prog8/code/target/c128/C128MachineDefinition.kt @@ -25,6 +25,17 @@ class C128MachineDefinition: IMachineDefinition { override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() + override fun convertFloatToBytes(num: Double): List { + val m5 = Mflpt5.fromNumber(num) + return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) + } + + override fun convertBytesToFloat(bytes: List): Double { + require(bytes.size==5) { "need 5 bytes" } + val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) + return m5.toDouble() + } + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) listOf("syslib") diff --git a/codeCore/src/prog8/code/target/c64/C64MachineDefinition.kt b/codeCore/src/prog8/code/target/c64/C64MachineDefinition.kt index b5825e635..a5e4db8a6 100644 --- a/codeCore/src/prog8/code/target/c64/C64MachineDefinition.kt +++ b/codeCore/src/prog8/code/target/c64/C64MachineDefinition.kt @@ -26,6 +26,17 @@ class C64MachineDefinition: IMachineDefinition { override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() + override fun convertFloatToBytes(num: Double): List { + val m5 = Mflpt5.fromNumber(num) + return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) + } + + override fun convertBytesToFloat(bytes: List): Double { + require(bytes.size==5) { "need 5 bytes" } + val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) + return m5.toDouble() + } + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) listOf("syslib") diff --git a/codeCore/src/prog8/code/target/cx16/CX16MachineDefinition.kt b/codeCore/src/prog8/code/target/cx16/CX16MachineDefinition.kt index d4dca0ead..1ac80d1d8 100644 --- a/codeCore/src/prog8/code/target/cx16/CX16MachineDefinition.kt +++ b/codeCore/src/prog8/code/target/cx16/CX16MachineDefinition.kt @@ -24,6 +24,18 @@ class CX16MachineDefinition: IMachineDefinition { override lateinit var golden: GoldenRam override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() + + override fun convertFloatToBytes(num: Double): List { + val m5 = Mflpt5.fromNumber(num) + return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) + } + + override fun convertBytesToFloat(bytes: List): Double { + require(bytes.size==5) { "need 5 bytes" } + val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) + return m5.toDouble() + } + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) listOf("syslib") diff --git a/codeCore/src/prog8/code/target/pet/PETMachineDefinition.kt b/codeCore/src/prog8/code/target/pet/PETMachineDefinition.kt index abc0d9ffe..66f2bd4e3 100644 --- a/codeCore/src/prog8/code/target/pet/PETMachineDefinition.kt +++ b/codeCore/src/prog8/code/target/pet/PETMachineDefinition.kt @@ -25,6 +25,17 @@ class PETMachineDefinition: IMachineDefinition { override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() + override fun convertFloatToBytes(num: Double): List { + val m5 = Mflpt5.fromNumber(num) + return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) + } + + override fun convertBytesToFloat(bytes: List): Double { + require(bytes.size==5) { "need 5 bytes" } + val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) + return m5.toDouble() + } + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) listOf("syslib") diff --git a/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt b/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt index 96a3d2a02..7d2b2dbfb 100644 --- a/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt +++ b/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt @@ -30,6 +30,26 @@ class VirtualMachineDefinition: IMachineDefinition { return parts.joinToString(", ") } + override fun convertFloatToBytes(num: Double): List { + val bits = num.toBits().toULong() + val hexStr = bits.toString(16).padStart(16, '0') + val parts = hexStr.chunked(2).map { it.toInt(16).toUByte() } + return parts + } + + override fun convertBytesToFloat(bytes: List): Double { + require(bytes.size==8) { "need 8 bytes" } + val b0 = bytes[0].toLong() shl (8*7) + val b1 = bytes[1].toLong() shl (8*6) + val b2 = bytes[2].toLong() shl (8*5) + val b3 = bytes[3].toLong() shl (8*4) + val b4 = bytes[4].toLong() shl (8*3) + val b5 = bytes[5].toLong() shl (8*2) + val b6 = bytes[6].toLong() shl (8*1) + val b7 = bytes[7].toLong() shl (8*0) + return Double.fromBits(b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) + } + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return listOf("syslib") } diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index 4f2e5b4f8..408cb643c 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -57,6 +57,8 @@ private fun compileMain(args: Array): Boolean { val printAst2 by cli.option(ArgType.Boolean, fullName = "printast2", description = "print out the intermediate AST that is used for code generation") val breakpointCpuInstruction by cli.option(ArgType.Choice(listOf("brk", "stp"), { it }), fullName = "breakinstr", description = "the CPU instruction to use as well for %breakpoint") val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${PETTarget.NAME}', '${VMTarget.NAME}') (required)") + val bytes2float by cli.option(ArgType.String, fullName = "bytes2float", description = "convert a comma separated list of bytes from the target system to a float value. NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well!") + val float2bytes by cli.option(ArgType.String, fullName = "float2bytes", description = "convert floating point number to a list of bytes for the target system. NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well!") val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM") val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)") val varsGolden by cli.option(ArgType.Boolean, fullName = "varsgolden", description = "put uninitialized variables in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.") @@ -100,6 +102,11 @@ private fun compileMain(args: Array): Boolean { } } + if(bytes2float!=null) + return convertBytesToFloat(bytes2float!!, compilationTarget!!) + if(float2bytes!=null) + return convertFloatToBytes(float2bytes!!, compilationTarget!!) + if(varsHighBank==0 && compilationTarget==Cx16Target.NAME) { System.err.println("On the Commander X16, HiRAM bank 0 is used by the kernal and can't be used.") return false @@ -290,6 +297,23 @@ private fun compileMain(args: Array): Boolean { return true } +fun convertFloatToBytes(number: String, target: String): Boolean { + val tgt = getCompilationTargetByName(target) + val dbl = number.toDouble() + val bytes = tgt.machine.convertFloatToBytes(dbl) + print("$dbl in bytes on '$target': ") + println(bytes.joinToString(",")) + return true +} + +fun convertBytesToFloat(bytelist: String, target: String): Boolean { + val tgt = getCompilationTargetByName(target) + val bytes = bytelist.split(',').map { it.trim().toUByte() } + val number = tgt.machine.convertBytesToFloat(bytes) + println("floating point value on '$target': $number") + return true +} + private fun processSymbolDefs(symbolDefs: List): Map? { val result = mutableMapOf() val defPattern = """(.+)\s*=\s*(.+)""".toRegex() diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 6deb2752f..463b53dcb 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -14,7 +14,10 @@ import prog8.code.ast.PtProgram import prog8.code.ast.printAst import prog8.code.core.* import prog8.code.optimize.optimizeIntermediateAst -import prog8.code.target.* +import prog8.code.target.AtariTarget +import prog8.code.target.Cx16Target +import prog8.code.target.VMTarget +import prog8.code.target.getCompilationTargetByName import prog8.codegen.vm.VmCodeGen import prog8.compiler.astprocessing.* import prog8.optimizer.* @@ -60,17 +63,7 @@ class CompilerArguments(val filepath: Path, fun compileProgram(args: CompilerArguments): CompilationResult? { - val compTarget = - when(args.compilationTarget) { - C64Target.NAME -> C64Target() - C128Target.NAME -> C128Target() - Cx16Target.NAME -> Cx16Target() - PETTarget.NAME -> PETTarget() - AtariTarget.NAME -> AtariTarget() - VMTarget.NAME -> VMTarget() - else -> throw IllegalArgumentException("invalid compilation target") - } - + val compTarget = getCompilationTargetByName(args.compilationTarget) var compilationOptions: CompilationOptions var ast: PtProgram? = null var resultingProgram: Program? = null diff --git a/docs/source/compiling.rst b/docs/source/compiling.rst index e94e2738b..8e8c86eb7 100644 --- a/docs/source/compiling.rst +++ b/docs/source/compiling.rst @@ -260,6 +260,13 @@ One or more .p8 module files put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems. +``-bytes2float `` + convert a comma separated list of bytes from the target system to a float value. + NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well! + +``-float2bytes `` + convert floating point number to a list of bytes for the target system. + NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well! Module source code files diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index 435d39e06..888f77518 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -3,7 +3,8 @@ package prog8.intermediate import prog8.code.* import prog8.code.ast.PtVariable import prog8.code.core.* -import prog8.code.target.* +import prog8.code.target.VMTarget +import prog8.code.target.getCompilationTargetByName import java.io.StringReader import java.nio.file.Path import javax.xml.stream.XMLEventReader @@ -95,16 +96,7 @@ class IRFileReader { text.lineSequence().forEach { line -> val (name, value) = line.split('=', limit=2) when(name) { - "compTarget" -> { - target = when(value) { - VMTarget.NAME -> VMTarget() - C64Target.NAME -> C64Target() - C128Target.NAME -> C128Target() - AtariTarget.NAME -> AtariTarget() - Cx16Target.NAME -> Cx16Target() - else -> throw IRParseException("invalid target $value") - } - } + "compTarget" -> target = getCompilationTargetByName(value) "output" -> outputType = OutputType.valueOf(value) "launcher" -> launcher = CbmPrgLauncherType.valueOf(value) "zeropage" -> zeropage = ZeropageType.valueOf(value)