mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
Get rid of any() and all() builtin functions.
Replaced by regular subroutines in the anyall module.
This commit is contained in:
parent
b10a8e728f
commit
484677b4b1
@ -67,7 +67,7 @@ What does Prog8 provide?
|
||||
- conditional branches
|
||||
- ``when`` statement to provide a concise jump table alternative to if/elseif chains
|
||||
- ``in`` expression for concise and efficient multi-value/containment check
|
||||
- many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``sort`` and ``reverse``
|
||||
- several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
||||
- various powerful built-in libraries to do I/O, number conversions, graphics and more
|
||||
- convenience abstractions for low level aspects such as ZeroPage handling, program startup, explicit memory addresses
|
||||
- inline assembly allows you to have full control when every cycle or byte matters
|
||||
|
@ -97,8 +97,6 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
"divmod" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("divisor", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("quotient", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("remainder", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
"divmod__ubyte" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE)), FParam("divisor", arrayOf(DataType.UBYTE)), FParam("quotient", arrayOf(DataType.UBYTE)), FParam("remainder", arrayOf(DataType.UBYTE))), null),
|
||||
"divmod__uword" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UWORD)), FParam("divisor", arrayOf(DataType.UWORD)), FParam("quotient", arrayOf(DataType.UWORD)), FParam("remainder", arrayOf(DataType.UWORD))), null),
|
||||
"any" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL),
|
||||
"all" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL),
|
||||
"lsb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE),
|
||||
"msb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE),
|
||||
"mkword" to FSignature(true, listOf(FParam("msb", arrayOf(DataType.UBYTE)), FParam("lsb", arrayOf(DataType.UBYTE))), DataType.UWORD),
|
||||
|
@ -33,7 +33,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultRegister)
|
||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultRegister)
|
||||
"abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultRegister, sscope)
|
||||
"any", "all" -> funcAnyAll(fcall, resultRegister, sscope)
|
||||
"sgn" -> funcSgn(fcall, resultRegister, sscope)
|
||||
"sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(fcall, resultRegister, sscope)
|
||||
"divmod__ubyte" -> funcDivmod(fcall)
|
||||
@ -726,63 +725,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true, true)
|
||||
}
|
||||
|
||||
private fun funcAnyAll(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||
val dt = fcall.args.single().type
|
||||
val array = fcall.args[0] as PtIdentifier
|
||||
when (dt) {
|
||||
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> {
|
||||
outputAddressAndLengthOfArray(array)
|
||||
asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A")
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
outputAddressAndLengthOfArray(array)
|
||||
asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
outputAddressAndLengthOfArray(array)
|
||||
asmgen.out(" jsr floats.func_${fcall.name}_f_into_A")
|
||||
}
|
||||
in SplitWordArrayTypes -> {
|
||||
val numElements = (asmgen.symbolTable.lookup(array.name) as StStaticVariable).length
|
||||
when(fcall.name) {
|
||||
"any" -> {
|
||||
// any(lsb-array) or any(msb-array)
|
||||
val arrayName = asmgen.asmVariableName(array)
|
||||
asmgen.out("""
|
||||
lda #<${arrayName}_lsb
|
||||
ldy #>${arrayName}_lsb
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda #$numElements
|
||||
""")
|
||||
asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A")
|
||||
asmgen.out(" bne +") // shortcircuit
|
||||
asmgen.out("""
|
||||
pha
|
||||
lda #<${arrayName}_msb
|
||||
ldy #>${arrayName}_msb
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda #$numElements
|
||||
""")
|
||||
asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A")
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_REG
|
||||
pla
|
||||
ora P8ZP_SCRATCH_REG
|
||||
+""")
|
||||
}
|
||||
"all" -> {
|
||||
TODO("split words all")
|
||||
}
|
||||
else -> throw AssemblyError("weird call")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type $dt")
|
||||
}
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes, true)
|
||||
}
|
||||
|
||||
private fun funcAbs(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||
translateArguments(fcall, scope)
|
||||
val dt = fcall.args.single().type
|
||||
|
@ -9,8 +9,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
fun translate(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
return when(call.name) {
|
||||
"any" -> funcAny(call)
|
||||
"all" -> funcAll(call)
|
||||
"abs__byte", "abs__word", "abs__float" -> funcAbs(call)
|
||||
"cmp" -> funcCmp(call)
|
||||
"sgn" -> funcSgn(call)
|
||||
@ -202,79 +200,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return ExpressionCodeResult(result, dt, leftTr.resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcAny(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val arrayLength = codeGen.symbolTable.getLength(arrayName.name)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val lengthReg = codeGen.registers.nextFree()
|
||||
|
||||
if(arrayName.type in SplitWordArrayTypes) {
|
||||
// any(lsb-array) or any(msb-array)
|
||||
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null)
|
||||
val trLsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_lsb", DataType.ARRAY_UB, call.position))
|
||||
addToResult(result, trLsb, trLsb.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null)
|
||||
result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trLsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trLsb.resultReg)
|
||||
val shortcircuitLabel = codeGen.createLabelName()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = trLsb.resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = shortcircuitLabel)
|
||||
it += IRInstruction(Opcode.PREPARECALL, immediate = 2)
|
||||
}
|
||||
val trMsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_msb", DataType.ARRAY_UB, call.position))
|
||||
addToResult(result, trMsb, trMsb.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null)
|
||||
result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trMsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trMsb.resultReg)
|
||||
addInstr(result, IRInstruction(Opcode.ORR, IRDataType.BYTE, reg1=trLsb.resultReg, reg2=trMsb.resultReg), null)
|
||||
result += IRCodeChunk(shortcircuitLabel, null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, trLsb.resultReg, -1)
|
||||
}
|
||||
|
||||
val syscall =
|
||||
when (arrayName.type) {
|
||||
DataType.ARRAY_UB,
|
||||
DataType.ARRAY_B -> IMSyscall.ANY_BYTE
|
||||
DataType.ARRAY_UW,
|
||||
DataType.ARRAY_W -> IMSyscall.ANY_WORD
|
||||
DataType.ARRAY_F -> IMSyscall.ANY_FLOAT
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null)
|
||||
val tr = exprGen.translateExpression(arrayName)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength!! and 255), null)
|
||||
result += codeGen.makeSyscall(syscall, listOf(IRDataType.WORD to tr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to tr.resultReg)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcAll(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val arrayLength = codeGen.symbolTable.getLength(arrayName.name)
|
||||
|
||||
if(arrayName.type in SplitWordArrayTypes) {
|
||||
// this is a bit complicated to calculate.... have to check all recombined (lsb,msb) words for $0000
|
||||
TODO("all(split words $arrayName)")
|
||||
}
|
||||
|
||||
val syscall =
|
||||
when(arrayName.type) {
|
||||
DataType.ARRAY_UB,
|
||||
DataType.ARRAY_B -> IMSyscall.ALL_BYTE
|
||||
DataType.ARRAY_UW,
|
||||
DataType.ARRAY_W -> IMSyscall.ALL_WORD
|
||||
DataType.ARRAY_F -> IMSyscall.ALL_FLOAT
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null)
|
||||
val tr = exprGen.translateExpression(arrayName)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val lengthReg = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength!! and 255), null)
|
||||
result += codeGen.makeSyscall(syscall, listOf(IRDataType.WORD to tr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to tr.resultReg)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcAbs(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val sourceDt = call.args.single().type
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
|
81
compiler/res/prog8lib/anyall.p8
Normal file
81
compiler/res/prog8lib/anyall.p8
Normal file
@ -0,0 +1,81 @@
|
||||
; any() and all() checks on arrays/memory buffers
|
||||
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
anyall {
|
||||
sub any(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if any byte in the array is not zero.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
for cx16.r0L in 0 to lsb(num_elements)-1 {
|
||||
if cx16.r1[cx16.r0L]!=0
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
repeat num_elements {
|
||||
if @(cx16.r1)!=0
|
||||
return true
|
||||
cx16.r1++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
sub all(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if all bytes in the array are not zero.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
for cx16.r0L in 0 to lsb(num_elements)-1 {
|
||||
if cx16.r1[cx16.r0L]==0
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
repeat num_elements {
|
||||
if @(cx16.r1)==0
|
||||
return false
|
||||
cx16.r1++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
sub anyw(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if any word in the array is not zero.
|
||||
; doesn't work on @split arrays.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
repeat lsb(num_elements) {
|
||||
if peekw(cx16.r1)!=0
|
||||
return true
|
||||
cx16.r1+=2
|
||||
}
|
||||
return false
|
||||
}
|
||||
repeat num_elements {
|
||||
if peekw(cx16.r1)!=0
|
||||
return true
|
||||
cx16.r1+=2
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
sub allw(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if all words in the array are not zero.
|
||||
; doesn't work on @split arrays.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
repeat lsb(num_elements) {
|
||||
if peekw(cx16.r1)==0
|
||||
return false
|
||||
cx16.r1+=2
|
||||
}
|
||||
return true
|
||||
}
|
||||
repeat num_elements {
|
||||
if peekw(cx16.r1)==0
|
||||
return false
|
||||
cx16.r1+=2
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
; experimental buffer data structures
|
||||
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
smallringbuffer {
|
||||
; -- A ringbuffer (FIFO queue) that occupies a single page in memory, containing 255 bytes maximum.
|
||||
; You can store and retrieve words too.
|
||||
|
@ -16,26 +16,6 @@ a_times_5 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_any_f_into_A .proc
|
||||
jsr a_times_5
|
||||
jmp prog8_lib.func_any_b_into_A
|
||||
.pend
|
||||
|
||||
func_all_f_into_A .proc
|
||||
jsr a_times_5
|
||||
jmp prog8_lib.func_all_b_into_A
|
||||
.pend
|
||||
|
||||
func_any_f_stack .proc
|
||||
jsr a_times_5
|
||||
jmp prog8_lib.func_any_b_stack
|
||||
.pend
|
||||
|
||||
func_all_f_stack .proc
|
||||
jsr a_times_5
|
||||
jmp prog8_lib.func_all_b_stack
|
||||
.pend
|
||||
|
||||
func_abs_f_into_FAC1 .proc
|
||||
jsr MOVFM
|
||||
jmp ABS
|
||||
|
@ -1,60 +1,5 @@
|
||||
; ---- builtin functions
|
||||
|
||||
|
||||
func_any_b_into_A .proc
|
||||
; -- any(array), array in P8ZP_SCRATCH_W1, num bytes in A
|
||||
sta _cmp_mod+1 ; self-modifying code
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
bne _got_any
|
||||
iny
|
||||
_cmp_mod cpy #255 ; modified
|
||||
bne -
|
||||
lda #0
|
||||
rts
|
||||
_got_any lda #1
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
func_all_b_into_A .proc
|
||||
; -- all(array), array in P8ZP_SCRATCH_W1, num bytes in A
|
||||
sta _cmp_mod+1 ; self-modifying code
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq _got_not_all
|
||||
iny
|
||||
_cmp_mod cpy #255 ; modified
|
||||
bne -
|
||||
lda #1
|
||||
_got_not_all rts
|
||||
.pend
|
||||
|
||||
func_any_w_into_A .proc
|
||||
asl a
|
||||
jmp func_any_b_into_A
|
||||
.pend
|
||||
|
||||
func_all_w_into_A .proc
|
||||
; -- all(warray), array in P8ZP_SCRATCH_W1, num bytes in A
|
||||
asl a ; times 2 because of word
|
||||
sta _cmp_mod+1 ; self-modifying code
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
bne +
|
||||
iny
|
||||
lda (P8ZP_SCRATCH_W1),y
|
||||
bne ++
|
||||
lda #0
|
||||
rts
|
||||
+ iny
|
||||
+ iny
|
||||
_cmp_mod cpy #255 ; modified
|
||||
bne -
|
||||
lda #1
|
||||
rts
|
||||
.pend
|
||||
|
||||
abs_b_into_A .proc
|
||||
; -- A = abs(A)
|
||||
cmp #0
|
||||
|
@ -11,7 +11,7 @@ diskio {
|
||||
%ir {{
|
||||
loadm.w r65534,diskio.load.filenameptr
|
||||
loadm.w r65535,diskio.load.address_override
|
||||
syscall 61 (): r0.b
|
||||
syscall 48 (): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
@ -157,7 +157,7 @@ diskio {
|
||||
loadm.w r65533,diskio.save.filenameptr
|
||||
loadm.w r65534,diskio.save.start_address
|
||||
loadm.w r65535,diskio.save.savesize
|
||||
syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
|
||||
syscall 45 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
@ -169,7 +169,7 @@ diskio {
|
||||
loadm.w r65533,diskio.save.filenameptr
|
||||
loadm.w r65534,diskio.save.start_address
|
||||
loadm.w r65535,diskio.save.savesize
|
||||
syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
|
||||
syscall 45 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
@ -184,7 +184,7 @@ diskio {
|
||||
%ir {{
|
||||
loadm.w r65534,diskio.load.filenameptr
|
||||
loadm.w r65535,diskio.load.address_override
|
||||
syscall 56 (r65534.w, r65535.w): r0.w
|
||||
syscall 43 (r65534.w, r65535.w): r0.w
|
||||
returnr.w r0
|
||||
}}
|
||||
}
|
||||
@ -196,7 +196,7 @@ diskio {
|
||||
%ir {{
|
||||
loadm.w r65534,diskio.load_raw.filenameptr
|
||||
loadm.w r65535,diskio.load_raw.start_address
|
||||
syscall 57 (r65534.w, r65535.w): r0.w
|
||||
syscall 44 (r65534.w, r65535.w): r0.w
|
||||
returnr.w r0
|
||||
}}
|
||||
}
|
||||
@ -205,7 +205,7 @@ diskio {
|
||||
; -- delete a file on the drive
|
||||
%ir {{
|
||||
loadm.w r65535,diskio.delete.filenameptr
|
||||
syscall 59 (r65535.w)
|
||||
syscall 46 (r65535.w)
|
||||
}}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ diskio {
|
||||
%ir {{
|
||||
loadm.w r65534,diskio.rename.oldfileptr
|
||||
loadm.w r65535,diskio.rename.newfileptr
|
||||
syscall 60 (r65534.w, r65535.w)
|
||||
syscall 47 (r65534.w, r65535.w)
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ sub print(float value) {
|
||||
; ---- prints the floating point value (without a newline and no leading spaces).
|
||||
%ir {{
|
||||
loadm.f fr65535,floats.print.value
|
||||
syscall 25 (fr65535.f)
|
||||
syscall 15 (fr65535.f)
|
||||
return
|
||||
}}
|
||||
}
|
||||
@ -24,7 +24,7 @@ sub tostr(float value) -> str {
|
||||
%ir {{
|
||||
load.w r65535,floats.tostr.buffer
|
||||
loadm.f fr65535,floats.tostr.value
|
||||
syscall 47 (r65535.w, fr65535.f)
|
||||
syscall 34 (r65535.w, fr65535.f)
|
||||
load.w r0,floats.tostr.buffer
|
||||
returnr.w r0
|
||||
}}
|
||||
@ -34,7 +34,7 @@ sub parse(str value) -> float {
|
||||
; -- parse a string value of a number to float
|
||||
%ir {{
|
||||
loadm.w r65535,floats.parse.value
|
||||
syscall 45 (r65535.w): fr0.f
|
||||
syscall 32 (r65535.w): fr0.f
|
||||
returnr.f fr0
|
||||
}}
|
||||
}
|
||||
@ -147,7 +147,7 @@ sub ceil(float value) -> float {
|
||||
|
||||
sub rnd() -> float {
|
||||
%ir {{
|
||||
syscall 35 () : fr0.f
|
||||
syscall 22 () : fr0.f
|
||||
returnr.f fr0
|
||||
}}
|
||||
}
|
||||
@ -155,7 +155,7 @@ sub rnd() -> float {
|
||||
sub rndseed(float seed) {
|
||||
%ir {{
|
||||
loadm.f fr65535,floats.rndseed.seed
|
||||
syscall 32 (fr65535.f)
|
||||
syscall 19 (fr65535.f)
|
||||
return
|
||||
}}
|
||||
}
|
||||
|
@ -164,14 +164,14 @@ math {
|
||||
|
||||
sub rnd() -> ubyte {
|
||||
%ir {{
|
||||
syscall 33 (): r0.b
|
||||
syscall 20 (): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
||||
sub rndw() -> uword {
|
||||
%ir {{
|
||||
syscall 34 (): r0.w
|
||||
syscall 21 (): r0.w
|
||||
returnr.w r0
|
||||
}}
|
||||
}
|
||||
@ -199,7 +199,7 @@ math {
|
||||
%ir {{
|
||||
loadm.w r65534,math.rndseed.seed1
|
||||
loadm.w r65535,math.rndseed.seed2
|
||||
syscall 31 (r65534.w, r65535.w)
|
||||
syscall 19 (r65534.w, r65535.w)
|
||||
return
|
||||
}}
|
||||
}
|
||||
@ -280,7 +280,7 @@ math {
|
||||
loadm.b r65533,math.atan2.y1
|
||||
loadm.b r65534,math.atan2.x2
|
||||
loadm.b r65535,math.atan2.y2
|
||||
syscall 44 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b
|
||||
syscall 31 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
@ -294,7 +294,7 @@ math {
|
||||
; - not all multiplications in the source code result in an actual multiplication call:
|
||||
; some simpler multiplications will be optimized away into faster routines. These will not set the upper 16 bits at all!
|
||||
%ir {{
|
||||
syscall 46 (): r0.w
|
||||
syscall 33 (): r0.w
|
||||
returnr.w r0
|
||||
}}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ string {
|
||||
%ir {{
|
||||
loadm.w r65534,string.copy.source
|
||||
loadm.w r65535,string.copy.target
|
||||
syscall 52 (r65534.w, r65535.w): r0.b
|
||||
syscall 39 (r65534.w, r65535.w): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
@ -103,7 +103,7 @@ string {
|
||||
%ir {{
|
||||
loadm.w r65534,string.compare.st1
|
||||
loadm.w r65535,string.compare.st2
|
||||
syscall 29 (r65534.w, r65535.w) : r0.b
|
||||
syscall 16 (r65534.w, r65535.w) : r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ sys {
|
||||
%ir {{
|
||||
loadm.w r65534,sys.internal_stringcopy.source
|
||||
loadm.w r65535,sys.internal_stringcopy.tgt
|
||||
syscall 52 (r65534.w, r65535.w): r0.b
|
||||
syscall 39 (r65534.w, r65535.w): r0.b
|
||||
}}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ sys {
|
||||
loadm.w r65533,sys.memcopy.source
|
||||
loadm.w r65534,sys.memcopy.tgt
|
||||
loadm.w r65535,sys.memcopy.count
|
||||
syscall 49 (r65533.w, r65534.w, r65535.w)
|
||||
syscall 36 (r65533.w, r65534.w, r65535.w)
|
||||
}}
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ sys {
|
||||
loadm.w r65533,sys.memset.mem
|
||||
loadm.w r65534,sys.memset.numbytes
|
||||
loadm.b r65535,sys.memset.value
|
||||
syscall 50 (r65533.w, r65534.w, r65535.b)
|
||||
syscall 37 (r65533.w, r65534.w, r65535.b)
|
||||
}}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ sys {
|
||||
loadm.w r65533,sys.memsetw.mem
|
||||
loadm.w r65534,sys.memsetw.numwords
|
||||
loadm.w r65535,sys.memsetw.value
|
||||
syscall 51 (r65533.w, r65534.w, r65535.w)
|
||||
syscall 38 (r65533.w, r65534.w, r65535.w)
|
||||
}}
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ sys {
|
||||
%ir {{
|
||||
loadm.w r65534,sys.gfx_getpixel.xx
|
||||
loadm.w r65535,sys.gfx_getpixel.yy
|
||||
syscall 30 (r65534.w, r65535.w): r0.b
|
||||
syscall 17 (r65534.w, r65535.w): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ txt {
|
||||
|
||||
sub width() -> ubyte {
|
||||
%ir {{
|
||||
syscall 62 (): r0.w
|
||||
syscall 49 (): r0.w
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
||||
sub height() -> ubyte {
|
||||
%ir {{
|
||||
syscall 62 (): r0.w
|
||||
syscall 49 (): r0.w
|
||||
msig.b r1,r0
|
||||
returnr.b r1
|
||||
}}
|
||||
|
@ -19,8 +19,6 @@ internal val constEvaluatorsForBuiltinFuncs: Map<String, ConstExpressionCaller>
|
||||
"sqrt__ubyte" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, false) { sqrt(it.toDouble()) } },
|
||||
"sqrt__uword" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, false) { sqrt(it.toDouble()) } },
|
||||
"sqrt__float" to { a, p, prg -> oneFloatArgOutputFloat(a, p, prg) { sqrt(it) } },
|
||||
"any" to { a, p, prg -> collectionArgBoolResult(a, p, prg) { array->array.any { it!=0.0 } } },
|
||||
"all" to { a, p, prg -> collectionArgBoolResult(a, p, prg) { array->array.all { it!=0.0 } } },
|
||||
"lsb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 255).toDouble() } },
|
||||
"msb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 8 and 255).toDouble()} },
|
||||
"mkword" to ::builtinMkword,
|
||||
|
@ -20,23 +20,6 @@ import prog8tests.helpers.compileText
|
||||
import kotlin.io.path.readText
|
||||
|
||||
class TestCompilerVirtual: FunSpec({
|
||||
test("compile virtual: any all builtin funcs") {
|
||||
val src = """
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
uword[] words = [1111,2222,0,4444,3333]
|
||||
bool result = all(words)
|
||||
cx16.r0++
|
||||
result = any(words)
|
||||
}
|
||||
}"""
|
||||
val target = VMTarget()
|
||||
val result = compileText(target, true, src, writeAssembly = true)!!
|
||||
val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir")
|
||||
VmRunner().runProgram(virtfile.readText())
|
||||
}
|
||||
|
||||
test("compile virtual: array with pointers") {
|
||||
val src = """
|
||||
main {
|
||||
|
@ -85,7 +85,7 @@ Features
|
||||
- Conditional branches for status flags that map 1:1 to processor branch instructions for optimal efficiency
|
||||
- ``when`` statement to avoid if-else chains
|
||||
- ``in`` expression for concise and efficient multi-value/containment test
|
||||
- Several powerful built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
||||
- Several specialized built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
||||
- Variable data types include signed and unsigned bytes and words, arrays, strings.
|
||||
- Various powerful built-in libraries to do I/O, number conversions, graphics and more
|
||||
- Floating point math is supported on select compiler targets.
|
||||
|
@ -73,12 +73,6 @@ divmod (dividend, divisor, quotient, remainder)
|
||||
Array operations
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
any (x)
|
||||
true if any of the values in the array value x is 'true' (not zero), else false.
|
||||
|
||||
all (x)
|
||||
true if all of the values in the array value x are 'true' (not zero), else false.
|
||||
|
||||
len (x)
|
||||
Number of values in the array value x, or the number of characters in a string (excluding the 0-byte).
|
||||
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte. See sizeof().
|
||||
@ -369,6 +363,25 @@ sys (part of syslib)
|
||||
Low-level function that should normally not be used.
|
||||
|
||||
|
||||
anyall
|
||||
------
|
||||
Routines to check if any or all values in an array or memory buffer are not zero.
|
||||
|
||||
``any (arrayptr, num_elements)``
|
||||
true if any of the byte values in the array is not zero, else false.
|
||||
|
||||
``all (arrayptr, num_elements)``
|
||||
true if all of the byte values in the array are not zero, else false.
|
||||
|
||||
``anyw (arrayptr, num_elements)``
|
||||
true if any of the word values in the array is not zero, else false.
|
||||
Doesn't work on split arrays.
|
||||
|
||||
``allw (arrayptr, num_elements)``
|
||||
true if all of the word values in the array are not zero, else false.
|
||||
Doesn't work on split arrays.
|
||||
|
||||
|
||||
conv
|
||||
----
|
||||
Routines to convert strings to numbers or vice versa.
|
||||
|
@ -1,8 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
Get rid of any() and all() as builtin functions? Replace them with regular subroutines in buffer.p8 for example?
|
||||
|
||||
See open issues on github.
|
||||
|
||||
IR: add SEC and CLC instructions in place of call to sys.set_carry() and sys.clear_carry(). (check more inline sub calls that should be a single instruction?)
|
||||
|
@ -1,20 +1,66 @@
|
||||
|
||||
%import textio
|
||||
%import buffers
|
||||
%zeropage basicsafe
|
||||
%import anyall
|
||||
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
byte[256] barray
|
||||
word[128] warray
|
||||
uword large_barray=memory("bytes", 1000, 0)
|
||||
uword large_warray=memory("words", 1000, 0)
|
||||
|
||||
sub check() {
|
||||
txt.print_bool(anyall.all(barray, 256))
|
||||
txt.spc()
|
||||
txt.print_bool(anyall.any(barray, 256))
|
||||
txt.nl()
|
||||
txt.print_bool(anyall.allw(warray, 128))
|
||||
txt.spc()
|
||||
txt.print_bool(anyall.anyw(warray, 128))
|
||||
txt.nl()
|
||||
txt.print_bool(anyall.all(large_barray, 1000))
|
||||
txt.spc()
|
||||
txt.print_bool(anyall.any(large_barray, 1000))
|
||||
txt.nl()
|
||||
txt.print_bool(anyall.allw(large_warray, 500))
|
||||
txt.spc()
|
||||
txt.print_bool(anyall.anyw(large_warray, 500))
|
||||
txt.nl()
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
sub start() {
|
||||
smallringbuffer.init()
|
||||
sys.memset(large_barray, 1000, 0)
|
||||
sys.memset(large_warray, 1000, 0)
|
||||
|
||||
smallringbuffer.put(123)
|
||||
txt.print_ub(smallringbuffer.get())
|
||||
txt.nl()
|
||||
check()
|
||||
barray[250] = 99
|
||||
warray[100] = $0100
|
||||
large_barray[900] = 99
|
||||
large_warray[900] = 99
|
||||
check()
|
||||
sys.memset(barray, 255, 1)
|
||||
sys.memset(warray, 254, 1)
|
||||
sys.memset(large_barray, 999, 1)
|
||||
sys.memset(large_warray, 998, 1)
|
||||
check()
|
||||
barray[255]=1
|
||||
warray[127]=1
|
||||
@(large_barray+999)=1
|
||||
@(large_warray+999)=1
|
||||
check()
|
||||
repeat {}
|
||||
|
||||
smallringbuffer.putw(12345)
|
||||
txt.print_uw(smallringbuffer.getw())
|
||||
txt.nl()
|
||||
; smallringbuffer.init()
|
||||
;
|
||||
; smallringbuffer.put(123)
|
||||
; txt.print_ub(smallringbuffer.get())
|
||||
; txt.nl()
|
||||
;
|
||||
; smallringbuffer.putw(12345)
|
||||
; txt.print_uw(smallringbuffer.getw())
|
||||
; txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,19 +5,6 @@ package prog8.intermediate
|
||||
// Note that in the VM these are translated into whatever the corresponding Syscall number in the VM is.
|
||||
|
||||
enum class IMSyscall(val number: Int) {
|
||||
SORT_UBYTE(0x1000),
|
||||
SORT_BYTE(0x1001),
|
||||
SORT_UWORD(0x1002),
|
||||
SORT_WORD(0x1003),
|
||||
ANY_BYTE(0x1004),
|
||||
ANY_WORD(0x1005),
|
||||
ANY_FLOAT(0x1006),
|
||||
ALL_BYTE(0x1007),
|
||||
ALL_WORD(0x1008),
|
||||
ALL_FLOAT(0x1009),
|
||||
REVERSE_BYTES(0x100a),
|
||||
REVERSE_WORDS(0x100b),
|
||||
REVERSE_FLOATS(0x100c),
|
||||
COMPARE_STRINGS(0x100d),
|
||||
STRING_CONTAINS(0x100e),
|
||||
BYTEARRAY_CONTAINS(0x100f),
|
||||
|
@ -14,7 +14,7 @@
|
||||
<keywords keywords="&;->;@;and;as;asmsub;break;clobbers;continue;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%option;%output;%zeropage;%zpallowed;%zpreserved;atascii:;cp437:;default:;iso16:;iso5:;iso:;petscii:;sc:" />
|
||||
<keywords3 keywords="@nozp;@requirezp;@shared;@split;@zp;bool;byte;const;float;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;all;any;call;callfar;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
<keywords4 keywords="abs;call;callfar;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
|
@ -27,7 +27,7 @@
|
||||
<Keywords name="Keywords1">void const
str
byte ubyte bool
word uword
float
zp shared split requirezp nozp</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%ir
%asmbinary
%asminclude
%breakpoint
%encoding
%import
%launcher
%option
%output
%zeropage
%zpreserved
%zpallowed</Keywords>
|
||||
<Keywords name="Keywords3">inline sub asmsub romsub
clobbers
asm
if
when else
if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z
for in step do while repeat unroll
break continue return goto</Keywords>
|
||||
<Keywords name="Keywords4">abs all any call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
<Keywords name="Keywords4">abs call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
||||
<Keywords name="Keywords6"></Keywords>
|
||||
<Keywords name="Keywords7"></Keywords>
|
||||
|
@ -10,7 +10,7 @@
|
||||
syn keyword prog8BuiltInFunc sgn sqrtw
|
||||
|
||||
" Array functions
|
||||
syn keyword prog8BuiltInFunc any all len
|
||||
syn keyword prog8BuiltInFunc len
|
||||
|
||||
" Miscellaneous functions
|
||||
syn keyword prog8BuiltInFunc cmp divmod lsb msb mkword min max peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex
|
||||
|
@ -25,54 +25,41 @@ SYSCALLS:
|
||||
12 = decimal string to word (signed)
|
||||
13 = wait ; wait certain amount of jiffies (1/60 sec)
|
||||
14 = waitvsync ; wait on vsync
|
||||
15 = sort_ubyte array
|
||||
16 = sort_byte array
|
||||
17 = sort_uword array
|
||||
18 = sort_word array
|
||||
19 = any_byte array
|
||||
20 = any_word array
|
||||
21 = any_float array
|
||||
22 = all_byte array
|
||||
23 = all_word array
|
||||
24 = all_float array
|
||||
25 = print_f (floating point value in fp reg 0)
|
||||
26 = reverse_bytes array
|
||||
27 = reverse_words array
|
||||
28 = reverse_floats array
|
||||
29 = compare strings
|
||||
30 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w
|
||||
31 = rndseed
|
||||
32 = rndfseed
|
||||
33 = RND
|
||||
34 = RNDW
|
||||
35 = RNDF
|
||||
36 = STRING_CONTAINS
|
||||
37 = BYTEARRAY_CONTAINS
|
||||
38 = WORDARRAY_CONTAINS
|
||||
39 = CLAMP_BYTE
|
||||
40 = CLAMP_UBYTE
|
||||
41 = CLAMP_WORD
|
||||
42 = CLAMP_UWORD
|
||||
43 = CLAMP_FLOAT
|
||||
44 = ATAN
|
||||
45 = str to float
|
||||
46 = MUL16_LAST_UPPER
|
||||
47 = float to str
|
||||
48 = FLOATARRAY_CONTAINS
|
||||
49 = memcopy
|
||||
50 = memset
|
||||
51 = memsetw
|
||||
52 = stringcopy
|
||||
53 = ARRAYCOPY_SPLITW_TO_NORMAL
|
||||
54 = ARRAYCOPY_NORMAL_TO_SPLITW
|
||||
55 = memcopy_small
|
||||
56 = load
|
||||
57 = load_raw
|
||||
58 = save
|
||||
59 = delete
|
||||
60 = rename
|
||||
61 = directory
|
||||
62 = getconsolesize
|
||||
15 = print_f (floating point value in fp reg 0)
|
||||
16 = compare strings
|
||||
17 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w
|
||||
18 = rndseed
|
||||
19 = rndfseed
|
||||
20 = RND
|
||||
21 = RNDW
|
||||
22 = RNDF
|
||||
23 = STRING_CONTAINS
|
||||
24 = BYTEARRAY_CONTAINS
|
||||
25 = WORDARRAY_CONTAINS
|
||||
26 = CLAMP_BYTE
|
||||
27 = CLAMP_UBYTE
|
||||
28 = CLAMP_WORD
|
||||
29 = CLAMP_UWORD
|
||||
30 = CLAMP_FLOAT
|
||||
31 = ATAN
|
||||
32 = str to float
|
||||
33 = MUL16_LAST_UPPER
|
||||
34 = float to str
|
||||
35 = FLOATARRAY_CONTAINS
|
||||
36 = memcopy
|
||||
37 = memset
|
||||
38 = memsetw
|
||||
39 = stringcopy
|
||||
40 = ARRAYCOPY_SPLITW_TO_NORMAL
|
||||
41 = ARRAYCOPY_NORMAL_TO_SPLITW
|
||||
42 = memcopy_small
|
||||
43 = load
|
||||
44 = load_raw
|
||||
45 = save
|
||||
46 = delete
|
||||
47 = rename
|
||||
48 = directory
|
||||
49 = getconsolesize
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -91,20 +78,7 @@ enum class Syscall {
|
||||
STR_TO_WORD,
|
||||
WAIT,
|
||||
WAITVSYNC,
|
||||
SORT_UBYTE,
|
||||
SORT_BYTE,
|
||||
SORT_UWORD,
|
||||
SORT_WORD,
|
||||
ANY_BYTE,
|
||||
ANY_WORD,
|
||||
ANY_FLOAT,
|
||||
ALL_BYTE,
|
||||
ALL_WORD,
|
||||
ALL_FLOAT,
|
||||
PRINT_F,
|
||||
REVERSE_BYTES,
|
||||
REVERSE_WORDS,
|
||||
REVERSE_FLOATS,
|
||||
COMPARE_STRINGS,
|
||||
GFX_GETPIXEL,
|
||||
RNDSEED,
|
||||
@ -243,149 +217,6 @@ object SysCalls {
|
||||
Thread.sleep(time.toLong() * 1000/60)
|
||||
}
|
||||
Syscall.WAITVSYNC -> vm.waitvsync()
|
||||
Syscall.SORT_UBYTE -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_BYTE -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getSB(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setSB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_UWORD -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_WORD -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getSW(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setSW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_BYTES -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.reversed()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_WORDS -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.reversed()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_FLOATS -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map {
|
||||
vm.memory.getFloat(it)
|
||||
}.reversed()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setFloat(address+index*4, value)
|
||||
}
|
||||
}
|
||||
Syscall.ANY_BYTE -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + if(length==0) 256 else length
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-1, 1)
|
||||
if(addresses.any { vm.memory.getUB(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.ANY_WORD -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + if(length==0) 256*2 else length*2
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-2, 2)
|
||||
if(addresses.any { vm.memory.getUW(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.ANY_FLOAT -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + (if(length==0) 256*vm.machinedef.FLOAT_MEM_SIZE else length*vm.machinedef.FLOAT_MEM_SIZE)
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-vm.machinedef.FLOAT_MEM_SIZE, 4)
|
||||
if(addresses.any { vm.memory.getFloat(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.ALL_BYTE -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + if(length==0) 256 else length
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-1, 1)
|
||||
if(addresses.all { vm.memory.getUB(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.ALL_WORD -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + if(length==0) 256*2 else length*2
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-2, 2)
|
||||
if(addresses.all { vm.memory.getUW(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.ALL_FLOAT -> {
|
||||
val (addressV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
val address = (addressV as UShort).toInt()
|
||||
val length = (lengthV as UByte).toInt()
|
||||
val endAddressExcl = address + (if(length==0) 256*vm.machinedef.FLOAT_MEM_SIZE else length*vm.machinedef.FLOAT_MEM_SIZE)
|
||||
val addresses = IntProgression.fromClosedRange(address, endAddressExcl-vm.machinedef.FLOAT_MEM_SIZE, 4)
|
||||
if(addresses.all { vm.memory.getFloat(it).toInt()!=0 })
|
||||
returnValue(callspec.returns.single(), 1, vm)
|
||||
else
|
||||
returnValue(callspec.returns.single(), 0, vm)
|
||||
}
|
||||
Syscall.PRINT_F -> {
|
||||
val value = getArgValues(callspec.arguments, vm).single() as Double
|
||||
if(value.toInt().toDouble()==value)
|
||||
|
@ -103,19 +103,6 @@ class VmProgramLoader {
|
||||
if(ins.opcode == Opcode.SYSCALL) {
|
||||
// convert IR Syscall to VM Syscall
|
||||
val vmSyscall = when(ins.immediate!!) {
|
||||
IMSyscall.SORT_UBYTE.number -> Syscall.SORT_UBYTE
|
||||
IMSyscall.SORT_BYTE.number -> Syscall.SORT_BYTE
|
||||
IMSyscall.SORT_UWORD.number -> Syscall.SORT_UWORD
|
||||
IMSyscall.SORT_WORD.number -> Syscall.SORT_WORD
|
||||
IMSyscall.ANY_BYTE.number -> Syscall.ANY_BYTE
|
||||
IMSyscall.ANY_WORD.number -> Syscall.ANY_WORD
|
||||
IMSyscall.ANY_FLOAT.number -> Syscall.ANY_FLOAT
|
||||
IMSyscall.ALL_BYTE.number -> Syscall.ALL_BYTE
|
||||
IMSyscall.ALL_WORD.number -> Syscall.ALL_WORD
|
||||
IMSyscall.ALL_FLOAT.number -> Syscall.ALL_FLOAT
|
||||
IMSyscall.REVERSE_BYTES.number -> Syscall.REVERSE_BYTES
|
||||
IMSyscall.REVERSE_WORDS.number -> Syscall.REVERSE_WORDS
|
||||
IMSyscall.REVERSE_FLOATS.number -> Syscall.REVERSE_FLOATS
|
||||
IMSyscall.COMPARE_STRINGS.number -> Syscall.COMPARE_STRINGS
|
||||
IMSyscall.STRING_CONTAINS.number -> Syscall.STRING_CONTAINS
|
||||
IMSyscall.BYTEARRAY_CONTAINS.number -> Syscall.BYTEARRAY_CONTAINS
|
||||
|
Loading…
Reference in New Issue
Block a user