mirror of
https://github.com/irmen/prog8.git
synced 2025-08-07 05:27:10 +00:00
vm: treat floats as 64 bits doubles. 0.0 printed as "0".
This commit is contained in:
@@ -12,7 +12,7 @@ class VirtualMachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
override val FLOAT_MAX_POSITIVE = Float.MAX_VALUE.toDouble()
|
override val FLOAT_MAX_POSITIVE = Float.MAX_VALUE.toDouble()
|
||||||
override val FLOAT_MAX_NEGATIVE = -Float.MAX_VALUE.toDouble()
|
override val FLOAT_MAX_NEGATIVE = -Float.MAX_VALUE.toDouble()
|
||||||
override val FLOAT_MEM_SIZE = 4 // 32-bits floating point
|
override val FLOAT_MEM_SIZE = 8 // 64-bits double
|
||||||
override val PROGRAM_LOAD_ADDRESS = 0u // not actually used
|
override val PROGRAM_LOAD_ADDRESS = 0u // not actually used
|
||||||
|
|
||||||
override val BSSHIGHRAM_START = 0u // not actually used
|
override val BSSHIGHRAM_START = 0u // not actually used
|
||||||
@@ -22,8 +22,8 @@ class VirtualMachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
override fun getFloatAsmBytes(num: Number): String {
|
override fun getFloatAsmBytes(num: Number): String {
|
||||||
// little endian binary representation
|
// little endian binary representation
|
||||||
val bits = num.toFloat().toBits().toUInt()
|
val bits = num.toDouble().toBits().toULong()
|
||||||
val hexStr = bits.toString(16).padStart(8, '0')
|
val hexStr = bits.toString(16).padStart(16, '0')
|
||||||
val parts = hexStr.chunked(2).map { "\$" + it }
|
val parts = hexStr.chunked(2).map { "\$" + it }
|
||||||
return parts.joinToString(", ")
|
return parts.joinToString(", ")
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
val resultFpRegister = codeGen.registers.nextFreeFloat()
|
val resultFpRegister = codeGen.registers.nextFreeFloat()
|
||||||
code += IRInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, immediateFp = expr.number.toFloat())
|
code += IRInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, immediateFp = expr.number)
|
||||||
ExpressionCodeResult(code, vmDt,-1, resultFpRegister)
|
ExpressionCodeResult(code, vmDt,-1, resultFpRegister)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -713,7 +713,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
val tr = translateExpression(binExpr.left)
|
val tr = translateExpression(binExpr.left)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number
|
||||||
result += codeGen.divideByConstFloat(tr.resultFpReg, factor)
|
result += codeGen.divideByConstFloat(tr.resultFpReg, factor)
|
||||||
return ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
return ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
||||||
} else {
|
} else {
|
||||||
@@ -769,13 +769,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
return if(constFactorLeft!=null) {
|
return if(constFactorLeft!=null) {
|
||||||
val tr = translateExpression(binExpr.right)
|
val tr = translateExpression(binExpr.right)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
val factor = constFactorLeft.number.toFloat()
|
val factor = constFactorLeft.number
|
||||||
result += codeGen.multiplyByConstFloat(tr.resultFpReg, factor)
|
result += codeGen.multiplyByConstFloat(tr.resultFpReg, factor)
|
||||||
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
||||||
} else if(constFactorRight!=null) {
|
} else if(constFactorRight!=null) {
|
||||||
val tr = translateExpression(binExpr.left)
|
val tr = translateExpression(binExpr.left)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number
|
||||||
result += codeGen.multiplyByConstFloat(tr.resultFpReg, factor)
|
result += codeGen.multiplyByConstFloat(tr.resultFpReg, factor)
|
||||||
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
||||||
} else {
|
} else {
|
||||||
@@ -823,7 +823,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
return if(binExpr.right is PtNumber) {
|
return if(binExpr.right is PtNumber) {
|
||||||
val tr = translateExpression(binExpr.left)
|
val tr = translateExpression(binExpr.left)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
addInstr(result, IRInstruction(Opcode.SUB, vmDt, fpReg1 = tr.resultFpReg, immediateFp = (binExpr.right as PtNumber).number.toFloat()), null)
|
addInstr(result, IRInstruction(Opcode.SUB, vmDt, fpReg1 = tr.resultFpReg, immediateFp = (binExpr.right as PtNumber).number), null)
|
||||||
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
||||||
} else {
|
} else {
|
||||||
val leftTr = translateExpression(binExpr.left)
|
val leftTr = translateExpression(binExpr.left)
|
||||||
@@ -878,7 +878,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
return if(binExpr.right is PtNumber) {
|
return if(binExpr.right is PtNumber) {
|
||||||
val tr = translateExpression(binExpr.left)
|
val tr = translateExpression(binExpr.left)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
addInstr(result, IRInstruction(Opcode.ADD, vmDt, fpReg1 = tr.resultFpReg, immediateFp = (binExpr.right as PtNumber).number.toFloat()), null)
|
addInstr(result, IRInstruction(Opcode.ADD, vmDt, fpReg1 = tr.resultFpReg, immediateFp = (binExpr.right as PtNumber).number), null)
|
||||||
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
ExpressionCodeResult(result, vmDt, -1, tr.resultFpReg)
|
||||||
} else {
|
} else {
|
||||||
val leftTr = translateExpression(binExpr.left)
|
val leftTr = translateExpression(binExpr.left)
|
||||||
@@ -950,7 +950,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number
|
||||||
result += codeGen.divideByConstFloatInplace(knownAddress, symbol, factor)
|
result += codeGen.divideByConstFloatInplace(knownAddress, symbol, factor)
|
||||||
} else {
|
} else {
|
||||||
val tr = translateExpression(operand)
|
val tr = translateExpression(operand)
|
||||||
@@ -999,7 +999,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
if(constFactorRight!=null) {
|
if(constFactorRight!=null) {
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number
|
||||||
result += codeGen.multiplyByConstFloatInplace(knownAddress, symbol, factor)
|
result += codeGen.multiplyByConstFloatInplace(knownAddress, symbol, factor)
|
||||||
} else {
|
} else {
|
||||||
val tr = translateExpression(operand)
|
val tr = translateExpression(operand)
|
||||||
@@ -1324,7 +1324,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
// in-place modify a memory location
|
// in-place modify a memory location
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = knownAddress)
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = knownAddress)
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number.toFloat())
|
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number)
|
||||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
||||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||||
@@ -1335,7 +1335,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
// in-place modify a symbol (variable)
|
// in-place modify a symbol (variable)
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number.toFloat())
|
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number)
|
||||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
||||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||||
|
@@ -710,23 +710,23 @@ class IRCodeGen(
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun multiplyByConstFloat(fpReg: Int, factor: Float): IRCodeChunk {
|
internal fun multiplyByConstFloat(fpReg: Int, factor: Double): IRCodeChunk {
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(factor==1f)
|
if(factor==1.0)
|
||||||
return code
|
return code
|
||||||
code += if(factor==0f) {
|
code += if(factor==0.0) {
|
||||||
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = 0f)
|
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = 0.0)
|
||||||
} else {
|
} else {
|
||||||
IRInstruction(Opcode.MUL, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
IRInstruction(Opcode.MUL, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun multiplyByConstFloatInplace(knownAddress: Int?, symbol: String?, factor: Float): IRCodeChunk {
|
internal fun multiplyByConstFloatInplace(knownAddress: Int?, symbol: String?, factor: Double): IRCodeChunk {
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(factor==1f)
|
if(factor==1.0)
|
||||||
return code
|
return code
|
||||||
if(factor==0f) {
|
if(factor==0.0) {
|
||||||
code += if(knownAddress!=null)
|
code += if(knownAddress!=null)
|
||||||
IRInstruction(Opcode.STOREZM, IRDataType.FLOAT, address = knownAddress)
|
IRInstruction(Opcode.STOREZM, IRDataType.FLOAT, address = knownAddress)
|
||||||
else
|
else
|
||||||
@@ -807,25 +807,25 @@ class IRCodeGen(
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun divideByConstFloat(fpReg: Int, factor: Float): IRCodeChunk {
|
internal fun divideByConstFloat(fpReg: Int, factor: Double): IRCodeChunk {
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(factor==1f)
|
if(factor==1.0)
|
||||||
return code
|
return code
|
||||||
code += if(factor==0f) {
|
code += if(factor==0.0) {
|
||||||
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = Float.MAX_VALUE)
|
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = Double.MAX_VALUE)
|
||||||
} else {
|
} else {
|
||||||
IRInstruction(Opcode.DIVS, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
IRInstruction(Opcode.DIVS, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun divideByConstFloatInplace(knownAddress: Int?, symbol: String?, factor: Float): IRCodeChunk {
|
internal fun divideByConstFloatInplace(knownAddress: Int?, symbol: String?, factor: Double): IRCodeChunk {
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(factor==1f)
|
if(factor==1.0)
|
||||||
return code
|
return code
|
||||||
if(factor==0f) {
|
if(factor==0.0) {
|
||||||
val maxvalueReg = registers.nextFreeFloat()
|
val maxvalueReg = registers.nextFreeFloat()
|
||||||
code += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = maxvalueReg, immediateFp = Float.MAX_VALUE)
|
code += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = maxvalueReg, immediateFp = Double.MAX_VALUE)
|
||||||
code += if(knownAddress!=null)
|
code += if(knownAddress!=null)
|
||||||
IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = maxvalueReg, address = knownAddress)
|
IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = maxvalueReg, address = knownAddress)
|
||||||
else
|
else
|
||||||
@@ -1189,7 +1189,7 @@ class IRCodeGen(
|
|||||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
val rightFpReg = registers.nextFreeFloat()
|
val rightFpReg = registers.nextFreeFloat()
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, immediateFp = 0f)
|
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, immediateFp = 0.0)
|
||||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg)
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg)
|
||||||
}
|
}
|
||||||
when (condition.operator) {
|
when (condition.operator) {
|
||||||
|
@@ -23,8 +23,7 @@ Future Things and Ideas
|
|||||||
Compiler:
|
Compiler:
|
||||||
|
|
||||||
- Currently "320*240/8/8" gives integer overflow, so: allow constant integer subexpressions to contain out of range integers (>65535 etc) as long as the final constant value is within byte/word range.
|
- Currently "320*240/8/8" gives integer overflow, so: allow constant integer subexpressions to contain out of range integers (>65535 etc) as long as the final constant value is within byte/word range.
|
||||||
- allow 'chained' array indexing for expressions: value = ptrarray[0][0]
|
- Multidimensional arrays and chained indexing, purely as syntactic sugar over regular arrays.
|
||||||
- allow 'chained' array indexing for assign targets: ptrarray[0][0] = 42 this is just evaluating the lhs as a uword pointer expression
|
|
||||||
- fix the other cases of "TODO index could also be a binexpr" (in AssignmentAsmGen), but these are for float arrays so rarely used.
|
- fix the other cases of "TODO index could also be a binexpr" (in AssignmentAsmGen), but these are for float arrays so rarely used.
|
||||||
|
|
||||||
- [much work:] more support for (64tass) SEGMENTS ?
|
- [much work:] more support for (64tass) SEGMENTS ?
|
||||||
@@ -68,6 +67,7 @@ Libraries:
|
|||||||
|
|
||||||
Optimizations:
|
Optimizations:
|
||||||
|
|
||||||
|
- give a warning for variables that could be a const - or even make them a const (if not @shared)?
|
||||||
- treat every scalar variable decl with initialization value, as const by default, unless the variable gets assigned to somewhere (or has its address taken, or is @shared)
|
- treat every scalar variable decl with initialization value, as const by default, unless the variable gets assigned to somewhere (or has its address taken, or is @shared)
|
||||||
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
|
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
|
||||||
for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest
|
for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import floats
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
str key = "test"
|
float fl1 = 999.8877
|
||||||
txt.print(":")
|
float fl2 = sqrt(fl1) * fl1 + fl1*33.44
|
||||||
if key != ":" {
|
floats.print_f(fl2)
|
||||||
cx16.r0++
|
txt.nl()
|
||||||
}
|
fl1=0
|
||||||
|
floats.print_f(fl1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ Intermediate Representation instructions for the IR Virtual machine.
|
|||||||
Specs of the virtual machine this will run on:
|
Specs of the virtual machine this will run on:
|
||||||
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
||||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||||
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
65536 virtual floating point registers (64 bits double precision) fr0-fr65535
|
||||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||||
Value stack, max 128 entries of 1 byte each.
|
Value stack, max 128 entries of 1 byte each.
|
||||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
||||||
@@ -21,7 +21,7 @@ Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by t
|
|||||||
|
|
||||||
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
|
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
|
||||||
|
|
||||||
Value types: integers (.b=byte=8 bits, .w=word=16 bits) and float (.f=32 bits). Omitting it defaults to b if the instruction requires a type.
|
Value types: integers (.b=byte=8 bits, .w=word=16 bits) and float (.f=64 bits). Omitting it defaults to b if the instruction requires a type.
|
||||||
Currently ther is NO support for 24 or 32 bits integers.
|
Currently ther is NO support for 24 or 32 bits integers.
|
||||||
There is no distinction between signed and unsigned integers.
|
There is no distinction between signed and unsigned integers.
|
||||||
Instead, a different instruction is used if a distinction should be made (for example div and divs).
|
Instead, a different instruction is used if a distinction should be made (for example div and divs).
|
||||||
@@ -691,7 +691,7 @@ data class IRInstruction(
|
|||||||
val fpReg1: Int?=null, // 0-$ffff
|
val fpReg1: Int?=null, // 0-$ffff
|
||||||
val fpReg2: Int?=null, // 0-$ffff
|
val fpReg2: Int?=null, // 0-$ffff
|
||||||
val immediate: Int?=null, // 0-$ff or $ffff if word
|
val immediate: Int?=null, // 0-$ff or $ffff if word
|
||||||
val immediateFp: Float?=null,
|
val immediateFp: Double?=null,
|
||||||
val address: Int?=null, // 0-$ffff
|
val address: Int?=null, // 0-$ffff
|
||||||
val labelSymbol: String?=null, // symbolic label name as alternative to address (so only for Branch/jump/call Instructions!)
|
val labelSymbol: String?=null, // symbolic label name as alternative to address (so only for Branch/jump/call Instructions!)
|
||||||
var branchTarget: IRCodeChunkBase? = null, // Will be linked after loading in IRProgram.linkChunks()! This is the chunk that the branch labelSymbol points to.
|
var branchTarget: IRCodeChunkBase? = null, // Will be linked after loading in IRProgram.linkChunks()! This is the chunk that the branch labelSymbol points to.
|
||||||
|
@@ -62,15 +62,15 @@ fun convertIRType(typestr: String): IRDataType? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseIRValue(value: String): Float {
|
fun parseIRValue(value: String): Double {
|
||||||
return if(value.startsWith("-"))
|
return if(value.startsWith("-"))
|
||||||
-parseIRValue(value.substring(1))
|
-parseIRValue(value.substring(1))
|
||||||
else if(value.startsWith('$'))
|
else if(value.startsWith('$'))
|
||||||
value.substring(1).toInt(16).toFloat()
|
value.substring(1).toInt(16).toDouble()
|
||||||
else if(value.startsWith('%'))
|
else if(value.startsWith('%'))
|
||||||
value.substring(1).toInt(2).toFloat()
|
value.substring(1).toInt(2).toDouble()
|
||||||
else if(value.startsWith("0x"))
|
else if(value.startsWith("0x"))
|
||||||
value.substring(2).toInt(16).toFloat()
|
value.substring(2).toInt(16).toDouble()
|
||||||
else if(value.startsWith('_'))
|
else if(value.startsWith('_'))
|
||||||
throw IRParseException("attempt to parse a label as numeric value")
|
throw IRParseException("attempt to parse a label as numeric value")
|
||||||
else if(value.startsWith('&'))
|
else if(value.startsWith('&'))
|
||||||
@@ -78,7 +78,7 @@ fun parseIRValue(value: String): Float {
|
|||||||
else if(value.startsWith('@'))
|
else if(value.startsWith('@'))
|
||||||
throw IRParseException("address-of @ should have been handled earlier")
|
throw IRParseException("address-of @ should have been handled earlier")
|
||||||
else
|
else
|
||||||
return value.toFloat()
|
return value.toDouble()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -119,11 +119,11 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
|||||||
var fpReg1: Int? = null
|
var fpReg1: Int? = null
|
||||||
var fpReg2: Int? = null
|
var fpReg2: Int? = null
|
||||||
var immediateInt: Int? = null
|
var immediateInt: Int? = null
|
||||||
var immediateFp: Float? = null
|
var immediateFp: Double? = null
|
||||||
var address: Int? = null
|
var address: Int? = null
|
||||||
var labelSymbol: String? = null
|
var labelSymbol: String? = null
|
||||||
|
|
||||||
fun parseValueOrPlaceholder(operand: String): Float? {
|
fun parseValueOrPlaceholder(operand: String): Double? {
|
||||||
return if(operand[0].isLetter()) {
|
return if(operand[0].isLetter()) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
@@ -47,7 +47,7 @@ class Memory {
|
|||||||
mem[address] = uv.toUByte()
|
mem[address] = uv.toUByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFloat(address: Int, value: Float) {
|
fun setFloat(address: Int, value: Double) {
|
||||||
var bits = value.toBits()
|
var bits = value.toBits()
|
||||||
mem[address] = bits.toUByte()
|
mem[address] = bits.toUByte()
|
||||||
bits = bits ushr 8
|
bits = bits ushr 8
|
||||||
@@ -56,11 +56,26 @@ class Memory {
|
|||||||
mem[address+2] = bits.toUByte()
|
mem[address+2] = bits.toUByte()
|
||||||
bits = bits ushr 8
|
bits = bits ushr 8
|
||||||
mem[address+3] = bits.toUByte()
|
mem[address+3] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+4] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+5] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+6] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+7] = bits.toUByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFloat(address: Int): Float {
|
fun getFloat(address: Int): Double {
|
||||||
val bits = mem[address] + 256u*mem[address+1] + 65536u*mem[address+2] + 16777216u*mem[address+3]
|
val bits = mem[address].toLong() +
|
||||||
return Float.fromBits(bits.toInt())
|
(1L shl 8)*mem[address+1].toLong() +
|
||||||
|
(1L shl 16)*mem[address+2].toLong() +
|
||||||
|
(1L shl 24)*mem[address+3].toLong() +
|
||||||
|
(1L shl 32)*mem[address+4].toLong() +
|
||||||
|
(1L shl 40)*mem[address+5].toLong() +
|
||||||
|
(1L shl 48)*mem[address+6].toLong() +
|
||||||
|
(1L shl 56)*mem[address+7].toLong()
|
||||||
|
return Double.fromBits(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
// for now, no LONG 32-bits and no FLOAT support.
|
// for now, no LONG 32-bits and no FLOAT support.
|
||||||
|
@@ -7,14 +7,14 @@ package prog8.vm
|
|||||||
*/
|
*/
|
||||||
class Registers {
|
class Registers {
|
||||||
private val registers = Array<UShort>(65536) { 0u }
|
private val registers = Array<UShort>(65536) { 0u }
|
||||||
private val floatRegisters = Array(65536) { 0f }
|
private val floatRegisters = Array(65536) { 0.0 }
|
||||||
var cpuA: UByte = 0u
|
var cpuA: UByte = 0u
|
||||||
var cpuX: UByte = 0u
|
var cpuX: UByte = 0u
|
||||||
var cpuY: UByte = 0u
|
var cpuY: UByte = 0u
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
registers.fill(0u)
|
registers.fill(0u)
|
||||||
floatRegisters.fill(0f)
|
floatRegisters.fill(0.0)
|
||||||
cpuA = 0u
|
cpuA = 0u
|
||||||
cpuX = 0u
|
cpuX = 0u
|
||||||
cpuY = 0u
|
cpuY = 0u
|
||||||
@@ -46,7 +46,7 @@ class Registers {
|
|||||||
|
|
||||||
fun getFloat(reg:Int) = floatRegisters[reg]
|
fun getFloat(reg:Int) = floatRegisters[reg]
|
||||||
|
|
||||||
fun setFloat(reg:Int, value: Float) {
|
fun setFloat(reg:Int, value: Double) {
|
||||||
floatRegisters[reg] = value
|
floatRegisters[reg] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -124,15 +124,16 @@ object SysCalls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun returnValue(returns: FunctionCallArgs.RegSpec, value: Comparable<Nothing>, vm: VirtualMachine) {
|
private fun returnValue(returns: FunctionCallArgs.RegSpec, value: Comparable<Nothing>, vm: VirtualMachine) {
|
||||||
val vv: Float = when(value) {
|
val vv: Double = when(value) {
|
||||||
is UByte -> value.toFloat()
|
is UByte -> value.toDouble()
|
||||||
is UShort -> value.toFloat()
|
is UShort -> value.toDouble()
|
||||||
is UInt -> value.toFloat()
|
is UInt -> value.toDouble()
|
||||||
is Byte -> value.toFloat()
|
is Byte -> value.toDouble()
|
||||||
is Short -> value.toFloat()
|
is Short -> value.toDouble()
|
||||||
is Int -> value.toFloat()
|
is Int -> value.toDouble()
|
||||||
is Float -> value
|
is Float -> value.toDouble()
|
||||||
else -> (value as Number).toFloat()
|
is Double -> value
|
||||||
|
else -> (value as Number).toDouble()
|
||||||
}
|
}
|
||||||
when(returns.dt) {
|
when(returns.dt) {
|
||||||
IRDataType.BYTE -> vm.registers.setUB(returns.registerNum, vv.toInt().toUByte())
|
IRDataType.BYTE -> vm.registers.setUB(returns.registerNum, vv.toInt().toUByte())
|
||||||
@@ -346,8 +347,11 @@ object SysCalls {
|
|||||||
returnValue(callspec.returns!!, 0, vm)
|
returnValue(callspec.returns!!, 0, vm)
|
||||||
}
|
}
|
||||||
Syscall.PRINT_F -> {
|
Syscall.PRINT_F -> {
|
||||||
val value = getArgValues(callspec.arguments, vm).single() as Float
|
val value = getArgValues(callspec.arguments, vm).single() as Double
|
||||||
print(value)
|
if(value==0.0)
|
||||||
|
print("0")
|
||||||
|
else
|
||||||
|
print(value)
|
||||||
}
|
}
|
||||||
Syscall.STR_TO_UWORD -> {
|
Syscall.STR_TO_UWORD -> {
|
||||||
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
|
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
|
||||||
@@ -373,7 +377,7 @@ object SysCalls {
|
|||||||
Syscall.STR_TO_FLOAT -> {
|
Syscall.STR_TO_FLOAT -> {
|
||||||
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
|
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
|
||||||
val memstring = vm.memory.getString(stringAddr.toInt())
|
val memstring = vm.memory.getString(stringAddr.toInt())
|
||||||
returnValue(callspec.returns!!, memstring.toFloat(), vm)
|
returnValue(callspec.returns!!, memstring.toDouble(), vm)
|
||||||
}
|
}
|
||||||
Syscall.COMPARE_STRINGS -> {
|
Syscall.COMPARE_STRINGS -> {
|
||||||
val (firstV, secondV) = getArgValues(callspec.arguments, vm)
|
val (firstV, secondV) = getArgValues(callspec.arguments, vm)
|
||||||
@@ -390,7 +394,7 @@ object SysCalls {
|
|||||||
returnValue(callspec.returns!!, 1, vm)
|
returnValue(callspec.returns!!, 1, vm)
|
||||||
}
|
}
|
||||||
Syscall.RNDFSEED -> {
|
Syscall.RNDFSEED -> {
|
||||||
val seed = getArgValues(callspec.arguments, vm).single() as Float
|
val seed = getArgValues(callspec.arguments, vm).single() as Double
|
||||||
if(seed>0) // always use negative seed, this mimics the behavior on CBM machines
|
if(seed>0) // always use negative seed, this mimics the behavior on CBM machines
|
||||||
vm.randomSeedFloat(-seed)
|
vm.randomSeedFloat(-seed)
|
||||||
else
|
else
|
||||||
@@ -474,9 +478,9 @@ object SysCalls {
|
|||||||
}
|
}
|
||||||
Syscall.CLAMP_FLOAT -> {
|
Syscall.CLAMP_FLOAT -> {
|
||||||
val (valueU, minimumU, maximumU) = getArgValues(callspec.arguments, vm)
|
val (valueU, minimumU, maximumU) = getArgValues(callspec.arguments, vm)
|
||||||
val value = valueU as Float
|
val value = valueU as Double
|
||||||
val minimum = minimumU as Float
|
val minimum = minimumU as Double
|
||||||
val maximum = maximumU as Float
|
val maximum = maximumU as Double
|
||||||
val result = min(max(value, minimum), maximum)
|
val result = min(max(value, minimum), maximum)
|
||||||
returnValue(callspec.returns!!, result, vm)
|
returnValue(callspec.returns!!, result, vm)
|
||||||
}
|
}
|
||||||
|
@@ -357,7 +357,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
when(value.dt!!) {
|
when(value.dt!!) {
|
||||||
IRDataType.BYTE -> valueStack.push(value.value as UByte)
|
IRDataType.BYTE -> valueStack.push(value.value as UByte)
|
||||||
IRDataType.WORD -> valueStack.pushw(value.value as UShort)
|
IRDataType.WORD -> valueStack.pushw(value.value as UShort)
|
||||||
IRDataType.FLOAT -> valueStack.pushf(value.value as Float)
|
IRDataType.FLOAT -> valueStack.pushf(value.value as Double)
|
||||||
}
|
}
|
||||||
value.dt=null
|
value.dt=null
|
||||||
}
|
}
|
||||||
@@ -531,7 +531,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
IRDataType.BYTE -> memory.setUB(i.address!!, 0u)
|
IRDataType.BYTE -> memory.setUB(i.address!!, 0u)
|
||||||
IRDataType.WORD -> memory.setUW(i.address!!, 0u)
|
IRDataType.WORD -> memory.setUW(i.address!!, 0u)
|
||||||
IRDataType.FLOAT -> memory.setFloat(i.address!!, 0f)
|
IRDataType.FLOAT -> memory.setFloat(i.address!!, 0.0)
|
||||||
}
|
}
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
@@ -540,7 +540,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
when (i.type!!) {
|
when (i.type!!) {
|
||||||
IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg1!!).toInt(), 0u)
|
IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg1!!).toInt(), 0u)
|
||||||
IRDataType.WORD -> memory.setUW(registers.getUW(i.reg1!!).toInt(), 0u)
|
IRDataType.WORD -> memory.setUW(registers.getUW(i.reg1!!).toInt(), 0u)
|
||||||
IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), 0f)
|
IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), 0.0)
|
||||||
}
|
}
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
@@ -549,7 +549,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
when (i.type!!) {
|
when (i.type!!) {
|
||||||
IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
|
IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
|
||||||
IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
|
IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
|
||||||
IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), 0f)
|
IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), 0.0)
|
||||||
}
|
}
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
@@ -1592,16 +1592,16 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
memory.setSW(address, result.toShort())
|
memory.setSW(address, result.toShort())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun arithFloat(left: Float, operator: String, right: Float): Float = when(operator) {
|
private fun arithFloat(left: Double, operator: String, right: Double): Double = when(operator) {
|
||||||
"+" -> left + right
|
"+" -> left + right
|
||||||
"-" -> left - right
|
"-" -> left - right
|
||||||
"*" -> left * right
|
"*" -> left * right
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if(right==0f) Float.MAX_VALUE
|
if(right==0.0) Double.MAX_VALUE
|
||||||
else left / right
|
else left / right
|
||||||
}
|
}
|
||||||
"%" -> {
|
"%" -> {
|
||||||
if(right==0f) Float.MAX_VALUE
|
if(right==0.0) Double.MAX_VALUE
|
||||||
else left % right
|
else left % right
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("operator word $operator")
|
else -> throw IllegalArgumentException("operator word $operator")
|
||||||
@@ -2108,22 +2108,22 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InsFFROMUB(i: IRInstruction) {
|
private fun InsFFROMUB(i: IRInstruction) {
|
||||||
registers.setFloat(i.fpReg1!!, registers.getUB(i.reg1!!).toFloat())
|
registers.setFloat(i.fpReg1!!, registers.getUB(i.reg1!!).toDouble())
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsFFROMSB(i: IRInstruction) {
|
private fun InsFFROMSB(i: IRInstruction) {
|
||||||
registers.setFloat(i.fpReg1!!, registers.getSB(i.reg1!!).toFloat())
|
registers.setFloat(i.fpReg1!!, registers.getSB(i.reg1!!).toDouble())
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsFFROMUW(i: IRInstruction) {
|
private fun InsFFROMUW(i: IRInstruction) {
|
||||||
registers.setFloat(i.fpReg1!!, registers.getUW(i.reg1!!).toFloat())
|
registers.setFloat(i.fpReg1!!, registers.getUW(i.reg1!!).toDouble())
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsFFROMSW(i: IRInstruction) {
|
private fun InsFFROMSW(i: IRInstruction) {
|
||||||
registers.setFloat(i.fpReg1!!, registers.getSW(i.reg1!!).toFloat())
|
registers.setFloat(i.fpReg1!!, registers.getSW(i.reg1!!).toDouble())
|
||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2356,7 +2356,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
randomGenerator = Random(((seed1.toUInt() shl 16) or seed2.toUInt()).toInt())
|
randomGenerator = Random(((seed1.toUInt() shl 16) or seed2.toUInt()).toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun randomSeedFloat(seed: Float) {
|
fun randomSeedFloat(seed: Double) {
|
||||||
randomGeneratorFloats = Random(seed.toBits())
|
randomGeneratorFloats = Random(seed.toBits())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2366,7 +2366,7 @@ internal fun Stack<UByte>.pushw(value: UShort) {
|
|||||||
push((value.toInt() ushr 8).toUByte())
|
push((value.toInt() ushr 8).toUByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Stack<UByte>.pushf(value: Float) {
|
internal fun Stack<UByte>.pushf(value: Double) {
|
||||||
// push float; lsb first, msb last
|
// push float; lsb first, msb last
|
||||||
var bits = value.toBits()
|
var bits = value.toBits()
|
||||||
push(bits.toUByte())
|
push(bits.toUByte())
|
||||||
@@ -2376,6 +2376,14 @@ internal fun Stack<UByte>.pushf(value: Float) {
|
|||||||
push(bits.toUByte())
|
push(bits.toUByte())
|
||||||
bits = bits ushr 8
|
bits = bits ushr 8
|
||||||
push(bits.toUByte())
|
push(bits.toUByte())
|
||||||
|
bits = bits ushr 8
|
||||||
|
push(bits.toUByte())
|
||||||
|
bits = bits ushr 8
|
||||||
|
push(bits.toUByte())
|
||||||
|
bits = bits ushr 8
|
||||||
|
push(bits.toUByte())
|
||||||
|
bits = bits ushr 8
|
||||||
|
push(bits.toUByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Stack<UByte>.popw(): UShort {
|
internal fun Stack<UByte>.popw(): UShort {
|
||||||
@@ -2384,14 +2392,25 @@ internal fun Stack<UByte>.popw(): UShort {
|
|||||||
return ((msb.toInt() shl 8) + lsb.toInt()).toUShort()
|
return ((msb.toInt() shl 8) + lsb.toInt()).toUShort()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Stack<UByte>.popf(): Float {
|
internal fun Stack<UByte>.popf(): Double {
|
||||||
// pop float; lsb is on bottom, msb on top
|
// pop float; lsb is on bottom, msb on top
|
||||||
val b0 = pop()
|
val b0 = pop().toLong()
|
||||||
val b1 = pop()
|
val b1 = pop().toLong()
|
||||||
val b2 = pop()
|
val b2 = pop().toLong()
|
||||||
val b3 = pop()
|
val b3 = pop().toLong()
|
||||||
val bits = b3 + 256u*b2 + 65536u*b1 + 16777216u*b0
|
val b4 = pop().toLong()
|
||||||
return Float.fromBits(bits.toInt())
|
val b5 = pop().toLong()
|
||||||
|
val b6 = pop().toLong()
|
||||||
|
val b7 = pop().toLong()
|
||||||
|
val bits = b7 +
|
||||||
|
(1L shl 8)*b6 +
|
||||||
|
(1L shl 16)*b5 +
|
||||||
|
(1L shl 24)*b4
|
||||||
|
(1L shl 32)*b3
|
||||||
|
(1L shl 40)*b2
|
||||||
|
(1L shl 48)*b1
|
||||||
|
(1L shl 56)*b0
|
||||||
|
return Double.fromBits(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
// probably called via reflection
|
// probably called via reflection
|
||||||
|
@@ -217,7 +217,7 @@ class VmProgramLoader {
|
|||||||
addr += 2
|
addr += 2
|
||||||
}
|
}
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
memory.setFloat(addr, 0.0f)
|
memory.setFloat(addr, 0.0)
|
||||||
addr += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
addr += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||||
}
|
}
|
||||||
in SplitWordArrayTypes -> {
|
in SplitWordArrayTypes -> {
|
||||||
@@ -238,7 +238,7 @@ class VmProgramLoader {
|
|||||||
DataType.BYTE -> memory.setSB(addr, it.toInt().toByte())
|
DataType.BYTE -> memory.setSB(addr, it.toInt().toByte())
|
||||||
DataType.UWORD -> memory.setUW(addr, it.toInt().toUShort())
|
DataType.UWORD -> memory.setUW(addr, it.toInt().toUShort())
|
||||||
DataType.WORD -> memory.setSW(addr, it.toInt().toShort())
|
DataType.WORD -> memory.setSW(addr, it.toInt().toShort())
|
||||||
DataType.FLOAT -> memory.setFloat(addr, it.toFloat())
|
DataType.FLOAT -> memory.setFloat(addr, it)
|
||||||
else -> throw IRParseException("invalid dt")
|
else -> throw IRParseException("invalid dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +314,7 @@ class VmProgramLoader {
|
|||||||
|
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
for (elt in iElts) {
|
for (elt in iElts) {
|
||||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toFloat()
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toDouble()
|
||||||
memory.setFloat(address, value)
|
memory.setFloat(address, value)
|
||||||
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||||
}
|
}
|
||||||
@@ -378,7 +378,7 @@ class VmProgramLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toFloat()
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toDouble()
|
||||||
repeat(variable.length!!) {
|
repeat(variable.length!!) {
|
||||||
memory.setFloat(address, value)
|
memory.setFloat(address, value)
|
||||||
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||||
|
@@ -48,10 +48,10 @@ class TestMemory: FunSpec({
|
|||||||
test("32 bits float access") {
|
test("32 bits float access") {
|
||||||
val mem = Memory()
|
val mem = Memory()
|
||||||
mem.getFloat(1000) shouldNotBe 0.0
|
mem.getFloat(1000) shouldNotBe 0.0
|
||||||
mem.setFloat(1000, 0.0f)
|
mem.setFloat(1000, 0.0)
|
||||||
mem.getFloat(1000) shouldBe 0.0f
|
mem.getFloat(1000) shouldBe 0.0
|
||||||
mem.setFloat(1000, -9.876543f)
|
mem.setFloat(1000, -9.876543)
|
||||||
mem.getFloat(1000) shouldBe -9.876543f
|
mem.getFloat(1000) shouldBe -9.876543
|
||||||
}
|
}
|
||||||
|
|
||||||
test("setstring and getstring") {
|
test("setstring and getstring") {
|
||||||
|
@@ -128,6 +128,6 @@ class TestVm: FunSpec( {
|
|||||||
c64machine.getFloatAsmBytes(Math.PI) shouldBe "\$82, \$49, \$0f, \$da, \$a2"
|
c64machine.getFloatAsmBytes(Math.PI) shouldBe "\$82, \$49, \$0f, \$da, \$a2"
|
||||||
|
|
||||||
val vm = VirtualMachineDefinition()
|
val vm = VirtualMachineDefinition()
|
||||||
vm.getFloatAsmBytes(Math.PI) shouldBe "\$40, \$49, \$0f, \$db"
|
vm.getFloatAsmBytes(Math.PI) shouldBe "\$40, \$09, \$21, \$fb, \$54, \$44, \$2d, \$18"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user