added options -bytes2float and -float2bytes to be able to do float conversions from the command line

This commit is contained in:
Irmen de Jong 2024-04-09 23:59:54 +02:00
parent f4b50368ba
commit 42f4b06ac8
12 changed files with 121 additions and 23 deletions

View File

@ -26,6 +26,9 @@ interface IMachineDefinition {
fun initializeMemoryAreas(compilerOptions: CompilationOptions) fun initializeMemoryAreas(compilerOptions: CompilationOptions)
fun getFloatAsmBytes(num: Number): String fun getFloatAsmBytes(num: Number): String
fun convertFloatToBytes(num: Double): List<UByte>
fun convertBytesToFloat(bytes: List<UByte>): Double
fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String>
fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path)
fun isIOAddress(address: UInt): Boolean fun isIOAddress(address: UInt): Boolean

View File

@ -19,3 +19,15 @@ class C64Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by Cb
fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list" 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")
}

View File

@ -22,6 +22,8 @@ class AtariMachineDefinition: IMachineDefinition {
override lateinit var golden: GoldenRam override lateinit var golden: GoldenRam
override fun getFloatAsmBytes(num: Number) = TODO("atari float asm bytes from number") override fun getFloatAsmBytes(num: Number) = TODO("atari float asm bytes from number")
override fun convertFloatToBytes(num: Double): List<UByte> = TODO("atari float to bytes")
override fun convertBytesToFloat(bytes: List<UByte>): Double = TODO("atari bytes to float")
override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.output == OutputType.XEX) return if (compilerOptions.output == OutputType.XEX)

View File

@ -25,6 +25,17 @@ class C128MachineDefinition: IMachineDefinition {
override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm()
override fun convertFloatToBytes(num: Double): List<UByte> {
val m5 = Mflpt5.fromNumber(num)
return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4)
}
override fun convertBytesToFloat(bytes: List<UByte>): 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<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib") listOf("syslib")

View File

@ -26,6 +26,17 @@ class C64MachineDefinition: IMachineDefinition {
override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm()
override fun convertFloatToBytes(num: Double): List<UByte> {
val m5 = Mflpt5.fromNumber(num)
return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4)
}
override fun convertBytesToFloat(bytes: List<UByte>): 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<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib") listOf("syslib")

View File

@ -24,6 +24,18 @@ class CX16MachineDefinition: IMachineDefinition {
override lateinit var golden: GoldenRam override lateinit var golden: GoldenRam
override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm()
override fun convertFloatToBytes(num: Double): List<UByte> {
val m5 = Mflpt5.fromNumber(num)
return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4)
}
override fun convertBytesToFloat(bytes: List<UByte>): 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<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib") listOf("syslib")

View File

@ -25,6 +25,17 @@ class PETMachineDefinition: IMachineDefinition {
override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm()
override fun convertFloatToBytes(num: Double): List<UByte> {
val m5 = Mflpt5.fromNumber(num)
return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4)
}
override fun convertBytesToFloat(bytes: List<UByte>): 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<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG) return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib") listOf("syslib")

View File

@ -30,6 +30,26 @@ class VirtualMachineDefinition: IMachineDefinition {
return parts.joinToString(", ") return parts.joinToString(", ")
} }
override fun convertFloatToBytes(num: Double): List<UByte> {
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<UByte>): 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<String> { override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return listOf("syslib") return listOf("syslib")
} }

View File

@ -57,6 +57,8 @@ private fun compileMain(args: Array<String>): Boolean {
val printAst2 by cli.option(ArgType.Boolean, fullName = "printast2", description = "print out the intermediate AST that is used for code generation") 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 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 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 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 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.") 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<String>): Boolean {
} }
} }
if(bytes2float!=null)
return convertBytesToFloat(bytes2float!!, compilationTarget!!)
if(float2bytes!=null)
return convertFloatToBytes(float2bytes!!, compilationTarget!!)
if(varsHighBank==0 && compilationTarget==Cx16Target.NAME) { 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.") System.err.println("On the Commander X16, HiRAM bank 0 is used by the kernal and can't be used.")
return false return false
@ -290,6 +297,23 @@ private fun compileMain(args: Array<String>): Boolean {
return true 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<String>): Map<String, String>? { private fun processSymbolDefs(symbolDefs: List<String>): Map<String, String>? {
val result = mutableMapOf<String, String>() val result = mutableMapOf<String, String>()
val defPattern = """(.+)\s*=\s*(.+)""".toRegex() val defPattern = """(.+)\s*=\s*(.+)""".toRegex()

View File

@ -14,7 +14,10 @@ import prog8.code.ast.PtProgram
import prog8.code.ast.printAst import prog8.code.ast.printAst
import prog8.code.core.* import prog8.code.core.*
import prog8.code.optimize.optimizeIntermediateAst 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.codegen.vm.VmCodeGen
import prog8.compiler.astprocessing.* import prog8.compiler.astprocessing.*
import prog8.optimizer.* import prog8.optimizer.*
@ -60,17 +63,7 @@ class CompilerArguments(val filepath: Path,
fun compileProgram(args: CompilerArguments): CompilationResult? { fun compileProgram(args: CompilerArguments): CompilationResult? {
val compTarget = val compTarget = getCompilationTargetByName(args.compilationTarget)
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")
}
var compilationOptions: CompilationOptions var compilationOptions: CompilationOptions
var ast: PtProgram? = null var ast: PtProgram? = null
var resultingProgram: Program? = null var resultingProgram: Program? = null

View File

@ -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. 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. On the cx16 target this is $0400-07ff. This is unavailable on other systems.
``-bytes2float <bytes>``
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 <number>``
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 Module source code files

View File

@ -3,7 +3,8 @@ package prog8.intermediate
import prog8.code.* import prog8.code.*
import prog8.code.ast.PtVariable import prog8.code.ast.PtVariable
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.* import prog8.code.target.VMTarget
import prog8.code.target.getCompilationTargetByName
import java.io.StringReader import java.io.StringReader
import java.nio.file.Path import java.nio.file.Path
import javax.xml.stream.XMLEventReader import javax.xml.stream.XMLEventReader
@ -95,16 +96,7 @@ class IRFileReader {
text.lineSequence().forEach { line -> text.lineSequence().forEach { line ->
val (name, value) = line.split('=', limit=2) val (name, value) = line.split('=', limit=2)
when(name) { when(name) {
"compTarget" -> { "compTarget" -> target = getCompilationTargetByName(value)
target = when(value) {
VMTarget.NAME -> VMTarget()
C64Target.NAME -> C64Target()
C128Target.NAME -> C128Target()
AtariTarget.NAME -> AtariTarget()
Cx16Target.NAME -> Cx16Target()
else -> throw IRParseException("invalid target $value")
}
}
"output" -> outputType = OutputType.valueOf(value) "output" -> outputType = OutputType.valueOf(value)
"launcher" -> launcher = CbmPrgLauncherType.valueOf(value) "launcher" -> launcher = CbmPrgLauncherType.valueOf(value)
"zeropage" -> zeropage = ZeropageType.valueOf(value) "zeropage" -> zeropage = ZeropageType.valueOf(value)