mirror of
https://github.com/irmen/prog8.git
synced 2024-11-05 10:05:00 +00:00
added containment check of float arrays
This commit is contained in:
parent
41de8caa13
commit
0a356ba73a
@ -1940,7 +1940,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
TODO("containment check of floats")
|
||||
assignExpressionToRegister(containment.element, RegisterOrPair.FAC1, true)
|
||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
|
||||
asmgen.out(" ldy #$numElements")
|
||||
asmgen.out(" jsr floats.containment_floatarray")
|
||||
}
|
||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
|
||||
|
@ -565,7 +565,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
private fun funcLsb(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
return exprGen.translateExpression(call.args.single())
|
||||
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
|
||||
// TODO to be more strict, maybe we *should* introduce a new result register that is of type .b?
|
||||
// ....To be more strict, maybe we should introduce a new result register that is of type .b?
|
||||
}
|
||||
|
||||
private fun funcMsb(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
|
@ -154,7 +154,19 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
result += codeGen.makeSyscall(IMSyscall.WORDARRAY_CONTAINS, listOf(IRDataType.WORD to elementTr.resultReg, IRDataType.WORD to iterableTr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to elementTr.resultReg)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, elementTr.resultReg, -1)
|
||||
}
|
||||
DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported")
|
||||
DataType.ARRAY_F -> {
|
||||
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 3), null)
|
||||
val elementTr = translateExpression(check.element)
|
||||
addToResult(result, elementTr, -1, elementTr.resultFpReg)
|
||||
val iterableTr = translateExpression(check.iterable)
|
||||
addToResult(result, iterableTr, iterableTr.resultReg, -1)
|
||||
val lengthReg = codeGen.registers.nextFree()
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
val iterableLength = codeGen.symbolTable.getLength(check.iterable.name)
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=lengthReg, immediate = iterableLength!!), null)
|
||||
result += codeGen.makeSyscall(IMSyscall.FLOATARRAY_CONTAINS, listOf(IRDataType.FLOAT to elementTr.resultFpReg, IRDataType.WORD to iterableTr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to resultReg)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
}
|
||||
else -> throw AssemblyError("weird iterable dt ${check.iterable.type} for ${check.iterable.name}")
|
||||
}
|
||||
}
|
||||
|
@ -1709,7 +1709,7 @@ class IRCodeGen(
|
||||
is PtLabel -> {
|
||||
irBlock += IRCodeChunk(child.name, null)
|
||||
}
|
||||
else -> TODO("weird child node $child")
|
||||
else -> TODO("weird block child node $child")
|
||||
}
|
||||
}
|
||||
return irBlock
|
||||
|
@ -419,7 +419,6 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
// TODO: detect multiple loads to the same target registers, only keep first (if source is not I/O memory)
|
||||
// TODO: detect multiple stores to the same target, only keep first (if target is not I/O memory)
|
||||
// TODO: detect multiple float ffrom/fto to the same target, only keep first
|
||||
// TODO: detect multiple sequential rnd with same reg1, only keep one
|
||||
// TODO: detect subsequent same xors/nots/negs, remove the pairs completely as they cancel out
|
||||
// TODO: detect multiple same ands, ors; only keep first
|
||||
// TODO: (hard) detect multiple registers being assigned the same value (and not changed) - use only 1 of them
|
||||
|
@ -221,7 +221,7 @@ class IRUnusedCodeRemover(
|
||||
}
|
||||
|
||||
// make sure that chunks that are only used as a prefix of a label, are also marked as linked
|
||||
linkedChunks.forEach { chunk ->
|
||||
linkedChunks.toList().forEach { chunk ->
|
||||
chunk.instructions.forEach {
|
||||
if(it.labelSymbol!=null) {
|
||||
val chunkName = it.labelSymbol!!.substringBeforeLast('.')
|
||||
|
@ -147,3 +147,54 @@ func_sqrt_into_FAC1 .proc
|
||||
jsr MOVFM
|
||||
jmp SQR
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
containment_floatarray .proc
|
||||
; -- check if a value exists in a float array.
|
||||
; parameters: FAC1: value to check, P8ZP_SCRATCH_W1: address of the word array, Y = length of array (>=1).
|
||||
; returns boolean 0/1 in A.
|
||||
sty P8ZP_SCRATCH_REG
|
||||
ldx #<floats.floats_temp_var
|
||||
ldy #>floats.floats_temp_var
|
||||
jsr floats.MOVMF
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
ldy #0
|
||||
- lda floats.floats_temp_var
|
||||
cmp (P8ZP_SCRATCH_W1),y
|
||||
bne _firstmiss
|
||||
iny
|
||||
lda floats.floats_temp_var+1
|
||||
cmp (P8ZP_SCRATCH_W1),y
|
||||
bne _secondmiss
|
||||
iny
|
||||
lda floats.floats_temp_var+2
|
||||
cmp (P8ZP_SCRATCH_W1),y
|
||||
bne _thirdmiss
|
||||
iny
|
||||
lda floats.floats_temp_var+3
|
||||
cmp (P8ZP_SCRATCH_W1),y
|
||||
bne _fourthmiss
|
||||
iny
|
||||
lda floats.floats_temp_var+4
|
||||
cmp (P8ZP_SCRATCH_W1),y
|
||||
bne _fifthmiss
|
||||
lda #1
|
||||
rts
|
||||
|
||||
_firstmiss
|
||||
iny
|
||||
_secondmiss
|
||||
iny
|
||||
_thirdmiss
|
||||
iny
|
||||
_fourthmiss
|
||||
iny
|
||||
_fifthmiss
|
||||
iny
|
||||
dex
|
||||
bne -
|
||||
lda #0
|
||||
rts
|
||||
|
||||
.pend
|
||||
|
@ -708,7 +708,7 @@ gfx2 {
|
||||
while cx16.r12L {
|
||||
pop_stack()
|
||||
xx = x1
|
||||
; TODO: if mode==1 (256c) use vera autodecrement instead of pget(), but code bloat not worth it?
|
||||
; possible speed optimization: if mode==1 (256c) use vera autodecrement instead of pget(), but code bloat not worth it?
|
||||
while xx >= 0 {
|
||||
if pget(xx as uword, yy as uword) != cx16.r11L
|
||||
break
|
||||
@ -726,7 +726,7 @@ gfx2 {
|
||||
|
||||
do {
|
||||
cx16.r9 = xx
|
||||
; TODO: if mode==1 (256c) use vera autoincrement instead of pget(), but code bloat not worth it?
|
||||
; possible speed optimization: if mode==1 (256c) use vera autoincrement instead of pget(), but code bloat not worth it?
|
||||
while xx <= width-1 {
|
||||
if pget(xx as uword, yy as uword) != cx16.r11L
|
||||
break
|
||||
|
@ -454,12 +454,12 @@ skip:
|
||||
; -- select the text charset to use with the text() routine
|
||||
; the charset number is the same as for the cx16.screen_set_charset() ROM function.
|
||||
; 1 = ISO charset, 2 = PETSCII uppercase+graphs, 3= PETSCII uppercase+lowercase.
|
||||
; TODO vm has no bitmap charset
|
||||
; TODO vm bitmap charset
|
||||
}
|
||||
|
||||
sub text(uword @zp xx, uword yy, bool draw, uword sctextptr) {
|
||||
; -- Write some text at the given pixel position. The text string must be in screencode encoding (not petscii!).
|
||||
; You must also have called text_charset() first to select and prepare the character set to use.
|
||||
; TODO vm has no bitmap charset
|
||||
; TODO vm bitmap charset
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
split words sort and reverse
|
||||
split words rol and ror and rol2/ror2
|
||||
split words any and all
|
||||
|
||||
Mark had a compiler crash FatalAstException: invalid dt
|
||||
|
||||
...
|
||||
@ -33,6 +37,7 @@ Compiler:
|
||||
- ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)
|
||||
global initialization values are simply a list of LOAD instructions.
|
||||
Variables replaced include all subroutine parameters! So the only variables that remain as variables are arrays and strings.
|
||||
- ir: fix call() return value handling
|
||||
- ir: add more optimizations in IRPeepholeOptimizer
|
||||
- ir: the @split arrays are currently also split in _lsb/_msb arrays in the IR, and operations take multiple (byte) instructions that may lead to verbose and slow operation and machine code generation down the line.
|
||||
maybe another representation is needed once actual codegeneration is done from the IR...?
|
||||
@ -59,7 +64,7 @@ Optimizations:
|
||||
for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest
|
||||
- various optimizers skip stuff if compTarget.name==VMTarget.NAME. Once 6502-codegen is done from IR code,
|
||||
those checks should probably be removed, or be made permanent
|
||||
|
||||
- optimizeCommonSubExpressions: currently only looks in expressions on a single line, could search across multiple expressions
|
||||
|
||||
STRUCTS again?
|
||||
--------------
|
||||
|
@ -1,12 +1,13 @@
|
||||
%import textio
|
||||
%import sprites
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
float[] fa = [1.1, 2.2, 3.3]
|
||||
float @shared fl = 2.2
|
||||
|
||||
cx16.mouse_config2(1)
|
||||
sprites.set_mousepointer_hand()
|
||||
txt.print_ub(fl in fa)
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,11 @@ enum class IMSyscall(val number: Int) {
|
||||
STRING_CONTAINS(0x100e),
|
||||
BYTEARRAY_CONTAINS(0x100f),
|
||||
WORDARRAY_CONTAINS(0x1010),
|
||||
CLAMP_UBYTE(0x1011),
|
||||
CLAMP_BYTE(0x1012),
|
||||
CLAMP_UWORD(0x1013),
|
||||
CLAMP_WORD(0x1014),
|
||||
CLAMP_FLOAT(0x1015),
|
||||
CALLFAR(0x1016),
|
||||
FLOATARRAY_CONTAINS(0x1011),
|
||||
CLAMP_UBYTE(0x1012),
|
||||
CLAMP_BYTE(0x1013),
|
||||
CLAMP_UWORD(0x1014),
|
||||
CLAMP_WORD(0x1015),
|
||||
CLAMP_FLOAT(0x1016),
|
||||
CALLFAR(0x1017),
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ SYSCALLS:
|
||||
45 = str to float
|
||||
46 = MUL16_LAST_UPPER
|
||||
47 = float to str
|
||||
48 = FLOATARRAY_CONTAINS
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -105,7 +106,8 @@ enum class Syscall {
|
||||
ATAN,
|
||||
STR_TO_FLOAT,
|
||||
MUL16_LAST_UPPER,
|
||||
FLOAT_TO_STR
|
||||
FLOAT_TO_STR,
|
||||
FLOATARRAY_CONTAINS,
|
||||
;
|
||||
|
||||
companion object {
|
||||
@ -456,6 +458,18 @@ object SysCalls {
|
||||
}
|
||||
returnValue(callspec.returns!!, 0u, vm)
|
||||
}
|
||||
Syscall.FLOATARRAY_CONTAINS -> {
|
||||
val (value, arrayV, lengthV) = getArgValues(callspec.arguments, vm)
|
||||
var length = lengthV as UByte
|
||||
var array = (arrayV as UShort).toInt()
|
||||
while(length>0u) {
|
||||
if(vm.memory.getFloat(array)==value)
|
||||
return returnValue(callspec.returns!!, 1u, vm)
|
||||
array += vm.machinedef.FLOAT_MEM_SIZE
|
||||
length--
|
||||
}
|
||||
returnValue(callspec.returns!!, 0u, vm)
|
||||
}
|
||||
Syscall.CLAMP_BYTE -> {
|
||||
val (valueU, minimumU, maximumU) = getArgValues(callspec.arguments, vm)
|
||||
val value = (valueU as UByte).toByte().toInt()
|
||||
|
@ -2,6 +2,7 @@ package prog8.vm
|
||||
|
||||
import prog8.code.core.toHex
|
||||
import prog8.code.target.virtual.IVirtualMachineRunner
|
||||
import prog8.code.target.virtual.VirtualMachineDefinition
|
||||
import prog8.intermediate.*
|
||||
import java.awt.Color
|
||||
import java.awt.Toolkit
|
||||
@ -34,6 +35,7 @@ class BreakpointException(val pcChunk: IRCodeChunk, val pcIndex: Int): Exception
|
||||
class VirtualMachine(irProgram: IRProgram) {
|
||||
class CallSiteContext(val returnChunk: IRCodeChunk, val returnIndex: Int, val fcallSpec: FunctionCallArgs)
|
||||
val memory = Memory()
|
||||
val machinedef = VirtualMachineDefinition()
|
||||
val program: List<IRCodeChunk>
|
||||
val registers = Registers()
|
||||
val callStack = Stack<CallSiteContext>()
|
||||
|
@ -119,6 +119,7 @@ class VmProgramLoader {
|
||||
IMSyscall.STRING_CONTAINS.number -> Syscall.STRING_CONTAINS
|
||||
IMSyscall.BYTEARRAY_CONTAINS.number -> Syscall.BYTEARRAY_CONTAINS
|
||||
IMSyscall.WORDARRAY_CONTAINS.number -> Syscall.WORDARRAY_CONTAINS
|
||||
IMSyscall.FLOATARRAY_CONTAINS.number -> Syscall.FLOATARRAY_CONTAINS
|
||||
IMSyscall.CLAMP_BYTE.number -> Syscall.CLAMP_BYTE
|
||||
IMSyscall.CLAMP_UBYTE.number -> Syscall.CLAMP_UBYTE
|
||||
IMSyscall.CLAMP_WORD.number -> Syscall.CLAMP_WORD
|
||||
|
Loading…
Reference in New Issue
Block a user