This commit is contained in:
Irmen de Jong 2022-04-13 20:43:07 +02:00
parent ab1766a559
commit bf7f4bba7b
6 changed files with 112 additions and 57 deletions

View File

@ -1575,8 +1575,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
private fun outputAddressAndLenghtOfArray(arg: Expression) {
// address in P8ZP_SCRATCH_W1, number of elements in A
arg as IdentifierReference
val arrayVar = arg.targetVarDecl(program)!!
if(!arrayVar.isArray)
throw AssemblyError("length of non-array requested")
val size = arrayVar.arraysize!!.constIndex()!!
val identifierName = asmgen.asmVariableName(arg)
val size = arg.targetVarDecl(program)!!.arraysize!!.constIndex()!!
asmgen.out("""
lda #<$identifierName
ldy #>$identifierName

View File

@ -12,11 +12,13 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
fun translate(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
return when(call.name) {
"cmp" -> TODO("cmp() can't be used on vm because no processor status bits implemented")
"max" -> TODO()
"max" -> funcMax(call, resultRegister)
"min" -> TODO()
"sum" -> TODO()
"abs" -> TODO()
"any" -> TODO()
"all" -> TODO()
"abs" -> TODO("abs once we can compare plus minus")
"cmp" -> TODO("cmp() can't be used on vm because no processor status bits implemented")
"sgn" -> funcSgn(call, resultRegister)
"sin" -> TODO("floats not yet implemented")
"cos" -> TODO("floats not yet implemented")
@ -31,8 +33,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
"round" -> TODO("floats not yet implemented")
"floor" -> TODO("floats not yet implemented")
"ceil" -> TODO("floats not yet implemented")
"any" -> TODO()
"all" -> TODO()
"pop" -> funcPop(call)
"popw" -> funcPopw(call)
"push" -> funcPush(call)
@ -59,8 +59,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
"pokew" -> funcPokeW(call)
"pokemon" -> VmCodeChunk()
"mkword" -> funcMkword(call, resultRegister)
"sin8u" -> funcSin8u(call, resultRegister)
"cos8u" -> funcCos8u(call, resultRegister)
"sort" -> funcSort(call)
"reverse" -> funcReverse(call)
"swap" -> funcSwap(call)
@ -72,6 +70,25 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
}
}
private fun funcMax(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
val arrayName = (call.args.single() as PtIdentifier).targetName
val array = codeGen.symbolTable.flat.getValue(arrayName) as StStaticVariable
when (array.dt) {
DataType.ARRAY_UW, DataType.ARRAY_W -> {
TODO("max word array")
}
DataType.STR -> {
TODO("max string")
}
else -> {
TODO("max byte array")
}
}
return code
}
private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args.single(), 0)
@ -164,24 +181,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
return code
}
private fun funcCos8u(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], 0)
code += VmCodeInstruction(Opcode.SYSCALL, value=Syscall.COS8U.ordinal)
if(resultRegister!=0)
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
return code
}
private fun funcSin8u(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], 0)
code += VmCodeInstruction(Opcode.SYSCALL, value=Syscall.SIN8U.ordinal)
if(resultRegister!=0)
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
return code
}
private fun funcMkword(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val msbReg = codeGen.vmRegisters.nextFree()
val lsbReg = codeGen.vmRegisters.nextFree()

View File

@ -214,6 +214,67 @@ math
Low level math routines. You should not normally have to bother with this directly.
The compiler needs it to implement most of the math operations in your programs.
However there's a bunch of integer trig functions in here too that use lookup tables
to quickly calculate sine and cosines. Usually a custom lookup table is the way to go if your
application needs this, but perhaps the provided ones can be of service too:
sin8u(x)
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
sin8(x)
Fast 8-bit byte sine of angle 0..255, result is in range -127..127
sin16u(x)
Fast 16-bit uword sine of angle 0..255, result is in range 0..65535
sin16(x)
Fast 16-bit word sine of angle 0..255, result is in range -32767..32767
sinr8u(x)
Fast 8-bit ubyte sine of angle 0..179 (each is a 2 degree step), result is in range 0..255
Angles 180..255 will yield a garbage result!
sinr8(x)
Fast 8-bit byte sine of angle 0..179 (each is a 2 degree step), result is in range -127..127
Angles 180..255 will yield a garbage result!
sinr16u(x)
Fast 16-bit uword sine of angle 0..179 (each is a 2 degree step), result is in range 0..65535
Angles 180..255 will yield a garbage result!
sinr16(x)
Fast 16-bit word sine of angle 0..179 (each is a 2 degree step), result is in range -32767..32767
Angles 180..255 will yield a garbage result!
cos8u(x)
Fast 8-bit ubyte cosine of angle 0..255, result is in range 0..255
cos8(x)
Fast 8-bit byte cosine of angle 0..255, result is in range -127..127
cos16u(x)
Fast 16-bit uword cosine of angle 0..255, result is in range 0..65535
cos16(x)
Fast 16-bit word cosine of angle 0..255, result is in range -32767..32767
cosr8u(x)
Fast 8-bit ubyte cosine of angle 0..179 (each is a 2 degree step), result is in range 0..255
Angles 180..255 will yield a garbage result!
cosr8(x)
Fast 8-bit byte cosine of angle 0..179 (each is a 2 degree step), result is in range -127..127
Angles 180..255 will yield a garbage result!
cosr16u(x)
Fast 16-bit uword cosine of angle 0..179 (each is a 2 degree step), result is in range 0..65535
Angles 180..255 will yield a garbage result!
cosr16(x)
Fast 16-bit word cosine of angle 0..179 (each is a 2 degree step), result is in range -32767..32767
Angles 180..255 will yield a garbage result!
cx16logo
--------

View File

@ -3,8 +3,9 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm: add support for all builtin functions
- min/max/any/all should give error when string arg is given instead of array
- can't use abs() etc in pipe expression because return type depends on argument type
- vm: add support for all builtin functions
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type

View File

@ -7,14 +7,21 @@
main {
sub start() {
word zz = 0
txt.print_b(sgn(zz))
word[] values = [1111, -222, -9999, 88, 20222, 0, 0, 1111]
word[] values2 = [0,0,0,0,0,1,0,0,0]
txt.print_w(max("abcde"))
txt.nl()
zz = -100
txt.print_b(sgn(zz))
txt.print_w(max(values))
txt.nl()
zz = 9999
txt.print_b(sgn(zz))
txt.print_w(min(values))
txt.nl()
txt.print_w(sum(values))
txt.nl()
txt.print_ub(any(values))
txt.nl()
txt.print_ub(any(values2))
txt.nl()
txt.print_ub(all(values))
txt.nl()
; uword other = $fe4a

View File

@ -21,14 +21,12 @@ SYSCALLS:
12 = rndw ; random WORD
13 = wait ; wait certain amount of jiffies (1/60 sec)
14 = waitvsync ; wait on vsync
15 = sin8u
16 = cos8u
17 = sort_ubyte array
18 = sort_byte array
19 = sort_uword array
20 = sort_word array
21 = reverse_bytes array
22 = reverse_words array
15 = sort_ubyte array
16 = sort_byte array
17 = sort_uword array
18 = sort_word array
19 = reverse_bytes array
20 = reverse_words array
*/
enum class Syscall {
@ -47,14 +45,12 @@ enum class Syscall {
RNDW,
WAIT,
WAITVSYNC,
SIN8U,
COS8U,
SORT_UBYTE,
SORT_BYTE,
SORT_UWORD,
SORT_WORD,
REVERSE_BYTES,
REVERSE_WORDS
REVERSE_BYTES, // TODO not as syscall
REVERSE_WORDS // TODO not as syscall
}
object SysCalls {
@ -112,18 +108,6 @@ object SysCalls {
Thread.sleep(millis)
}
Syscall.WAITVSYNC -> vm.waitvsync()
Syscall.SIN8U -> {
val arg = vm.registers.getUB(0).toDouble()
val rad = arg /256.0 * 2.0 * PI
val answer = truncate(128.0 + 127.5 * sin(rad))
vm.registers.setUB(0, answer.toUInt().toUByte())
}
Syscall.COS8U -> {
val arg = vm.registers.getUB(0).toDouble()
val rad = arg /256.0 * 2.0 * PI
val answer = truncate(128.0 + 127.5 * cos(rad))
vm.registers.setUB(0, answer.toUInt().toUByte())
}
Syscall.SORT_UBYTE -> {
val address = vm.registers.getUW(0).toInt()
val length = vm.registers.getUB(1).toInt()