vm: implementing more fp instructions

This commit is contained in:
Irmen de Jong 2022-05-02 20:16:45 +02:00
parent fa357a450b
commit 86cc2f1075
8 changed files with 259 additions and 115 deletions

View File

@ -380,10 +380,22 @@ class CodeGen(internal val program: PtProgram,
return code return code
} }
internal fun multiplyByConstFloat(fpReg: Int, factor: Float): VmCodeChunk {
val code = VmCodeChunk()
if(factor==1f)
return code
if(factor==0f) {
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = 0f)
} else {
val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = fpReg, fpReg3 = factorReg)
}
return code
}
internal val powersOfTwo = (0..16).map { 2.0.pow(it.toDouble()).toInt() } internal val powersOfTwo = (0..16).map { 2.0.pow(it.toDouble()).toInt() }
internal fun multiplyByConst(dt: VmDataType, reg: Int, factor: Int): VmCodeChunk { internal fun multiplyByConst(dt: VmDataType, reg: Int, factor: Int): VmCodeChunk {
// TODO support floating-point factors
val code = VmCodeChunk() val code = VmCodeChunk()
if(factor==1) if(factor==1)
return code return code

View File

@ -62,7 +62,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
is PtTypeCast -> code += translate(expr, resultRegister) is PtTypeCast -> code += translate(expr, resultRegister)
is PtPrefix -> code += translate(expr, resultRegister) is PtPrefix -> code += translate(expr, resultRegister)
is PtArrayIndexer -> code += translate(expr, resultRegister) is PtArrayIndexer -> code += translate(expr, resultRegister)
is PtBinaryExpression -> code += translate(expr, resultRegister) is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister) is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister)
is PtFunctionCall -> code += translate(expr, resultRegister, resultFpRegister) is PtFunctionCall -> code += translate(expr, resultRegister, resultFpRegister)
is PtContainmentCheck -> code += translate(expr, resultRegister, resultFpRegister) is PtContainmentCheck -> code += translate(expr, resultRegister, resultFpRegister)
@ -269,13 +269,13 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code return code
} }
private fun translate(binExpr: PtBinaryExpression, resultRegister: Int): VmCodeChunk { private fun translate(binExpr: PtBinaryExpression, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val vmDt = codeGen.vmType(binExpr.left.type) val vmDt = codeGen.vmType(binExpr.left.type)
val signed = binExpr.left.type in SignedDatatypes val signed = binExpr.left.type in SignedDatatypes
return when(binExpr.operator) { return when(binExpr.operator) {
"+" -> operatorPlus(binExpr, vmDt, resultRegister) "+" -> operatorPlus(binExpr, vmDt, resultRegister)
"-" -> operatorMinus(binExpr, vmDt, resultRegister) "-" -> operatorMinus(binExpr, vmDt, resultRegister)
"*" -> operatorMultiply(binExpr, vmDt, resultRegister) "*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister )
"/" -> operatorDivide(binExpr, vmDt, resultRegister) "/" -> operatorDivide(binExpr, vmDt, resultRegister)
"%" -> operatorModulo(binExpr, vmDt, resultRegister) "%" -> operatorModulo(binExpr, vmDt, resultRegister)
"|", "or" -> operatorOr(binExpr, vmDt, resultRegister) "|", "or" -> operatorOr(binExpr, vmDt, resultRegister)
@ -398,6 +398,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
} }
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
if(vmDt==VmDataType.FLOAT)
throw IllegalArgumentException("floating-point modulo not supported")
val code = VmCodeChunk() val code = VmCodeChunk()
val leftResultReg = codeGen.vmRegisters.nextFree() val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
@ -410,74 +412,104 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
val constFactorRight = binExpr.right as? PtNumber val constFactorRight = binExpr.right as? PtNumber
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { if(vmDt==VmDataType.FLOAT) {
code += translateExpression(binExpr.left, resultRegister, -1) TODO("div float")
val factor = constFactorRight.number.toInt()
code += codeGen.divideByConst(vmDt, resultRegister, factor)
} else { } else {
val leftResultReg = codeGen.vmRegisters.nextFree() if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
val rightResultReg = codeGen.vmRegisters.nextFree() code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.left, leftResultReg, -1) val factor = constFactorRight.number.toInt()
code += translateExpression(binExpr.right, rightResultReg, -1) code += codeGen.divideByConst(vmDt, resultRegister, factor)
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) } else {
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
} }
return code return code
} }
private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
val constFactorLeft = binExpr.left as? PtNumber val constFactorLeft = binExpr.left as? PtNumber
val constFactorRight = binExpr.right as? PtNumber val constFactorRight = binExpr.right as? PtNumber
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) { if(vmDt==VmDataType.FLOAT) {
code += translateExpression(binExpr.right, resultRegister, -1) if(constFactorLeft!=null) {
val factor = constFactorLeft.number.toInt() code += translateExpression(binExpr.right, -1, resultFpRegister)
code += codeGen.multiplyByConst(vmDt, resultRegister, factor) val factor = constFactorLeft.number.toFloat()
} else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { code += codeGen.multiplyByConstFloat(resultFpRegister, factor)
code += translateExpression(binExpr.left, resultRegister, -1) } else if(constFactorRight!=null) {
val factor = constFactorRight.number.toInt() code += translateExpression(binExpr.left, -1, resultFpRegister)
code += codeGen.multiplyByConst(vmDt, resultRegister, factor) val factor = constFactorRight.number.toFloat()
code += codeGen.multiplyByConstFloat(resultFpRegister, factor)
} else {
val leftResultFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftResultFpReg)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, reg2=leftResultFpReg, reg3=rightResultFpReg)
}
} else { } else {
val leftResultReg = codeGen.vmRegisters.nextFree() if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
val rightResultReg = codeGen.vmRegisters.nextFree() code += translateExpression(binExpr.right, resultRegister, -1)
code += translateExpression(binExpr.left, leftResultReg, -1) val factor = constFactorLeft.number.toInt()
code += translateExpression(binExpr.right, rightResultReg, -1) code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) } else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
code += translateExpression(binExpr.left, resultRegister, -1)
val factor = constFactorRight.number.toInt()
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
} else {
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
} }
return code return code
} }
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
if((binExpr.right as? PtNumber)?.number==1.0) { if(vmDt==VmDataType.FLOAT) {
code += translateExpression(binExpr.left, resultRegister, -1) TODO("minus float")
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister) } else {
} if((binExpr.right as? PtNumber)?.number==1.0) {
else { code += translateExpression(binExpr.left, resultRegister, -1)
val leftResultReg = codeGen.vmRegisters.nextFree() code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
val rightResultReg = codeGen.vmRegisters.nextFree() }
code += translateExpression(binExpr.left, leftResultReg, -1) else {
code += translateExpression(binExpr.right, rightResultReg, -1) val leftResultReg = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
} }
return code return code
} }
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
if((binExpr.left as? PtNumber)?.number==1.0) { if(vmDt==VmDataType.FLOAT) {
code += translateExpression(binExpr.right, resultRegister, -1) TODO("plus float")
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister) } else {
} if((binExpr.left as? PtNumber)?.number==1.0) {
else if((binExpr.right as? PtNumber)?.number==1.0) { code += translateExpression(binExpr.right, resultRegister, -1)
code += translateExpression(binExpr.left, resultRegister, -1) code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister) }
} else if((binExpr.right as? PtNumber)?.number==1.0) {
else { code += translateExpression(binExpr.left, resultRegister, -1)
val leftResultReg = codeGen.vmRegisters.nextFree() code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
val rightResultReg = codeGen.vmRegisters.nextFree() }
code += translateExpression(binExpr.left, leftResultReg, -1) else {
code += translateExpression(binExpr.right, rightResultReg, -1) val leftResultReg = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
} }
return code return code
} }

View File

@ -184,47 +184,76 @@ sub str2ubyte(str string) -> ubyte {
; -- returns in A the unsigned byte value of the string number argument in AY ; -- returns in A the unsigned byte value of the string number argument in AY
; the number may NOT be preceded by a + sign and may NOT contain spaces ; the number may NOT be preceded by a + sign and may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
; TODO return str2uword(string) as ubyte
return 0
} }
sub str2byte(str string) -> byte { sub str2byte(str string) -> byte {
; -- returns in A the signed byte value of the string number argument in AY ; -- returns in A the signed byte value of the string number argument in AY
; the number may be preceded by a + or - sign but may NOT contain spaces ; the number may be preceded by a + or - sign but may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
; TODO return str2word(string) as byte
return 0
} }
sub str2uword(str string) -> uword { sub str2uword(str string) -> uword {
; -- returns the unsigned word value of the string number argument in AY ; -- returns the unsigned word value of the string number argument in AY
; the number may NOT be preceded by a + sign and may NOT contain spaces ; the number may NOT be preceded by a + sign and may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
; TODO %asm {{
return 0 loadm.w r0, {conv.str2uword.string}
syscall 11
return
}}
} }
sub str2word(str string) -> word { sub str2word(str string) -> word {
; -- returns the signed word value of the string number argument in AY ; -- returns the signed word value of the string number argument in AY
; the number may be preceded by a + or - sign but may NOT contain spaces ; the number may be preceded by a + or - sign but may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
; TODO %asm {{
return 0 loadm.w r0, {conv.str2word.string}
syscall 12
return
}}
} }
sub hex2uword(str string) -> uword { sub hex2uword(str string) -> uword {
; -- hexadecimal string (with or without '$') to uword. ; -- hexadecimal string (with or without '$') to uword.
; string may be in petscii or c64-screencode encoding.
; stops parsing at the first character that's not a hex digit (except leading $) ; stops parsing at the first character that's not a hex digit (except leading $)
; TODO ; TODO fix this result
return 0 uword result
ubyte char
if @(string)=='$'
string++
repeat {
char = @(string)
if char==0
return result
result <<= 4
if char>='0' and char<='9'
result |= char-'0'
else
result |= char-'a'+10
string++
}
} }
sub bin2uword(str string) -> uword { sub bin2uword(str string) -> uword {
; -- binary string (with or without '%') to uword. ; -- binary string (with or without '%') to uword.
; stops parsing at the first character that's not a 0 or 1. (except leading %) ; stops parsing at the first character that's not a 0 or 1. (except leading %)
; TODO ; TODO fix this result
return 0 uword result
ubyte char
if @(string)=='%'
string++
repeat {
char = @(string)
if char==0
return result
result <<= 1
if char=='1'
result |= 1
string++
}
} }
} }

View File

@ -19,17 +19,15 @@ sub print_f(float value) {
} }
sub pow(float value, float power) -> float { sub pow(float value, float power) -> float {
; TODO fpow.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.pow.value} loadm.f fr0,{floats.pow.value}
loadm.f fr1,{floats.pow.power} loadm.f fr1,{floats.pow.power}
fpow.f fr0,fr0 fpow.f fr0,fr0,fr1
return return
}} }}
} }
sub fabs(float value) -> float { sub fabs(float value) -> float {
; TODO fabs.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.fabs.value} loadm.f fr0,{floats.fabs.value}
fabs.f fr0,fr0 fabs.f fr0,fr0
@ -38,7 +36,6 @@ sub fabs(float value) -> float {
} }
sub sin(float angle) -> float { sub sin(float angle) -> float {
; TODO fsin.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.sin.angle} loadm.f fr0,{floats.sin.angle}
fsin.f fr0,fr0 fsin.f fr0,fr0
@ -47,7 +44,6 @@ sub sin(float angle) -> float {
} }
sub cos(float angle) -> float { sub cos(float angle) -> float {
; TODO fcos.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.cos.angle} loadm.f fr0,{floats.cos.angle}
fcos.f fr0,fr0 fcos.f fr0,fr0
@ -56,7 +52,6 @@ sub cos(float angle) -> float {
} }
sub tan(float value) -> float { sub tan(float value) -> float {
; TODO ftan.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.tan.value} loadm.f fr0,{floats.tan.value}
ftan.f fr0,fr0 ftan.f fr0,fr0
@ -65,7 +60,6 @@ sub tan(float value) -> float {
} }
sub atan(float value) -> float { sub atan(float value) -> float {
; TODO fatan.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.atan.value} loadm.f fr0,{floats.atan.value}
fatan.f fr0,fr0 fatan.f fr0,fr0
@ -74,7 +68,6 @@ sub atan(float value) -> float {
} }
sub ln(float value) -> float { sub ln(float value) -> float {
; TODO fln.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.ln.value} loadm.f fr0,{floats.ln.value}
fln.f fr0,fr0 fln.f fr0,fr0
@ -83,16 +76,14 @@ sub ln(float value) -> float {
} }
sub log2(float value) -> float { sub log2(float value) -> float {
; TODO flog2.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.log2.value} loadm.f fr0,{floats.log2.value}
flog2.f fr0,fr0 flog.f fr0,fr0
return return
}} }}
} }
sub sqrt(float value) -> float { sub sqrt(float value) -> float {
; TODO fsqrt.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.sqrt.value} loadm.f fr0,{floats.sqrt.value}
fsqrt.f fr0,fr0 fsqrt.f fr0,fr0
@ -111,7 +102,6 @@ sub deg(float angle) -> float {
} }
sub round(float value) -> float { sub round(float value) -> float {
; TODO fround.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.round.value} loadm.f fr0,{floats.round.value}
fround.f fr0,fr0 fround.f fr0,fr0
@ -120,7 +110,6 @@ sub round(float value) -> float {
} }
sub floor(float value) -> float { sub floor(float value) -> float {
; TODO ffloor.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.floor.value} loadm.f fr0,{floats.floor.value}
ffloor.f fr0,fr0 ffloor.f fr0,fr0
@ -130,7 +119,6 @@ sub floor(float value) -> float {
sub ceil(float value) -> float { sub ceil(float value) -> float {
; -- ceil: tr = int(f); if tr==f -> return else return tr+1 ; -- ceil: tr = int(f); if tr==f -> return else return tr+1
; TODO fceil.f instruction
%asm {{ %asm {{
loadm.f fr0,{floats.ceil.value} loadm.f fr0,{floats.ceil.value}
fceil.f fr0,fr0 fceil.f fr0,fr0
@ -139,9 +127,8 @@ sub ceil(float value) -> float {
} }
sub rndf() -> float { sub rndf() -> float {
; TODO frnd.f instruction
%asm {{ %asm {{
frnd.f fr0 rnd.f fr0
return return
}} }}
} }

View File

@ -3,8 +3,12 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- vm: fix fp reg out of bounds - vm: fix if @(string)=='$' string++ not working on ea31
- vm: implement missing floating point functions - vm: fix conv hex2uword and bin2uword
- vm: implement float div, minus, plus
- vm: implement float type casts to integer types
- vm: implement float any, all, reverse, sort
- vm: fix test fp calc result being 0
- vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly? - vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly?
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls. - pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type - allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type

View File

@ -8,15 +8,61 @@
main { main {
sub start() { sub start() {
float fl = 500.0
txt.print("rad 180 = ") ubyte ub = conv.str2ubyte("234")
floats.print_f(floats.rad(180.0)) txt.print_ub(ub)
txt.print("rad 360 = ") txt.nl()
floats.print_f(floats.rad(360.0)) byte sb = conv.str2byte("-123")
txt.print("deg 2 = ") txt.print_b(sb)
floats.print_f(floats.deg(2.0)) txt.nl()
txt.print("deg pi = ") uword uw = conv.str2uword("54321")
floats.print_f(floats.deg(floats.PI)) txt.print_uw(uw)
txt.nl()
word sw = conv.str2word("-12345")
txt.print_w(sw)
txt.nl()
txt.nl()
; TODO fix hex2uword and bin2uword
uw = conv.hex2uword("0")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("1")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("a")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("0")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("1")
txt.print_uw(uw)
txt.nl()
txt.nl()
uw = conv.hex2uword("$ea31")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("ea31")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("%100000111011101")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("100000111011101")
txt.print_uw(uw)
txt.nl()
; float fl = 500.0
; txt.print("rad 180 = ")
; floats.print_f(floats.rad(180.0))
; txt.print("rad 360 = ")
; floats.print_f(floats.rad(360.0))
; txt.print("deg 2 = ")
; floats.print_f(floats.deg(2.0))
; txt.print("deg pi = ")
; floats.print_f(floats.deg(floats.PI))
sys.exit(42) sys.exit(42)
; floats.print_f(-42.42) ; floats.print_f(-42.42)
; float f1 = 1.2345 ; float f1 = 1.2345
@ -58,21 +104,21 @@ main {
; "deg", "round", "floor", "ceil", "rndf" ; "deg", "round", "floor", "ceil", "rndf"
; a "pixelshader": ; a "pixelshader":
sys.gfx_enable(0) ; enable lo res screen ; sys.gfx_enable(0) ; enable lo res screen
ubyte shifter ; ubyte shifter
;
repeat { ; repeat {
uword xx ; uword xx
uword yy = 0 ; uword yy = 0
repeat 240 { ; repeat 240 {
xx = 0 ; xx = 0
repeat 320 { ; repeat 320 {
sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte) ; sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte)
xx++ ; xx++
} ; }
yy++ ; yy++
} ; }
shifter+=4 ; shifter+=4
} ; }
} }
} }

View File

@ -18,8 +18,6 @@ a few fp conversion instructions to
*only* LOAD AND STORE instructions have a possible memory operand, all other instructions use only registers or immediate value. *only* LOAD AND STORE instructions have a possible memory operand, all other instructions use only registers or immediate value.
TODO all floating point arithmethic functions as fp-instructions.
LOAD/STORE LOAD/STORE
---------- ----------
All have type b or w or f. All have type b or w or f.
@ -130,8 +128,8 @@ rol reg1 - rotate reg1 left by 1bits, not us
roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit
FLOATING POINT CONVERSIONS FLOATING POINT CONVERSIONS AND FUNCTIONS
-------------------------- ----------------------------------------
ffromub fpreg1, reg1 - fpreg1 = reg1 from usigned byte ffromub fpreg1, reg1 - fpreg1 = reg1 from usigned byte
ffromsb fpreg1, reg1 - fpreg1 = reg1 from signed byte ffromsb fpreg1, reg1 - fpreg1 = reg1 from signed byte
ffromuw fpreg1, reg1 - fpreg1 = reg1 from unsigned word ffromuw fpreg1, reg1 - fpreg1 = reg1 from unsigned word
@ -140,6 +138,8 @@ ftoub reg1, fpreg1 - reg1 = fpreg1 as unsigned byte
ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte
ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word
ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word
fpow fpreg1, fpreg2, fpreg3 - fpreg1 = fpreg2 to the power of fpreg3
fabs fpreg1, fpreg2 - fpreg1 = abs(fpreg2)
MISC MISC
@ -248,6 +248,18 @@ enum class Opcode {
FTOSB, FTOSB,
FTOUW, FTOUW,
FTOSW, FTOSW,
FPOW,
FABS,
FSIN,
FCOS,
FTAN,
FATAN,
FLN,
FLOG,
FSQRT,
FROUND,
FFLOOR,
FCEIL,
CLC, CLC,
SEC, SEC,
@ -512,6 +524,18 @@ val instructionFormats = mutableMapOf(
Opcode.FTOSB to InstructionFormat.from("F,r1,fr1"), Opcode.FTOSB to InstructionFormat.from("F,r1,fr1"),
Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"), Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"),
Opcode.FTOSW to InstructionFormat.from("F,r1,fr1"), Opcode.FTOSW to InstructionFormat.from("F,r1,fr1"),
Opcode.FPOW to InstructionFormat.from("F,fr1,fr2,fr3"),
Opcode.FABS to InstructionFormat.from("F,fr1,fr2"),
Opcode.FSIN to InstructionFormat.from("F,fr1,fr2"),
Opcode.FCOS to InstructionFormat.from("F,fr1,fr2"),
Opcode.FTAN to InstructionFormat.from("F,fr1,fr2"),
Opcode.FATAN to InstructionFormat.from("F,fr1,fr2"),
Opcode.FLN to InstructionFormat.from("F,fr1,fr2"),
Opcode.FLOG to InstructionFormat.from("F,fr1,fr2"),
Opcode.FSQRT to InstructionFormat.from("F,fr1,fr2"),
Opcode.FROUND to InstructionFormat.from("F,fr1,fr2"),
Opcode.FFLOOR to InstructionFormat.from("F,fr1,fr2"),
Opcode.FCEIL to InstructionFormat.from("F,fr1,fr2"),
Opcode.MSIG to InstructionFormat.from("BW,r1,r2"), Opcode.MSIG to InstructionFormat.from("BW,r1,r2"),
Opcode.PUSH to InstructionFormat.from("BW,r1"), Opcode.PUSH to InstructionFormat.from("BW,r1"),

View File

@ -16,8 +16,8 @@ SYSCALLS:
8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480 8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
9 = gfx_clear ; clear graphics window with shade in r0.b 9 = gfx_clear ; clear graphics window with shade in r0.b
10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness
11 = <unused 1> 11 = decimal string to word (unsigned)
12 = <unused 2> 12 = decimal string to word (signed)
13 = wait ; wait certain amount of jiffies (1/60 sec) 13 = wait ; wait certain amount of jiffies (1/60 sec)
14 = waitvsync ; wait on vsync 14 = waitvsync ; wait on vsync
15 = sort_ubyte array 15 = sort_ubyte array
@ -55,8 +55,8 @@ enum class Syscall {
GFX_ENABLE, GFX_ENABLE,
GFX_CLEAR, GFX_CLEAR,
GFX_PLOT, GFX_PLOT,
UNUSED_1, STR_TO_UWORD,
UNUSED_2, STR_TO_WORD,
WAIT, WAIT,
WAITVSYNC, WAITVSYNC,
SORT_UBYTE, SORT_UBYTE,
@ -301,6 +301,16 @@ object SysCalls {
val value = vm.registers.getFloat(0) val value = vm.registers.getFloat(0)
print(value) print(value)
} }
Syscall.STR_TO_UWORD -> {
val stringAddr = vm.registers.getUW(0)
val string = vm.memory.getString(stringAddr.toInt())
vm.registers.setUW(0, string.toUShort())
}
Syscall.STR_TO_WORD -> {
val stringAddr = vm.registers.getUW(0)
val string = vm.memory.getString(stringAddr.toInt())
vm.registers.setSW(0, string.toShort())
}
else -> TODO("syscall ${call.name}") else -> TODO("syscall ${call.name}")
} }
} }