From 0ab0f02e758b1c5f9f19a9dcaa4e4b6abf328e66 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 9 Jan 2019 00:25:02 +0100 Subject: [PATCH] optimized stuff --- compiler/prog8lib/c64flt.p8 | 38 ++---- compiler/prog8lib/c64lib.p8 | 4 + compiler/prog8lib/prog8lib.p8 | 112 +++++++++--------- compiler/src/prog8/ast/AstChecker.kt | 6 +- compiler/src/prog8/compiler/Compiler.kt | 25 ++++ .../src/prog8/compiler/intermediate/Opcode.kt | 1 + .../src/prog8/compiler/target/c64/AsmGen.kt | 28 ++++- compiler/src/prog8/stackvm/StackVm.kt | 9 +- examples/sprites.p8 | 23 ++-- examples/test.p8 | 60 ++-------- examples/wizzine.p8 | 23 +--- 11 files changed, 152 insertions(+), 177 deletions(-) diff --git a/compiler/prog8lib/c64flt.p8 b/compiler/prog8lib/c64flt.p8 index 0ceec3086..035ab49b9 100644 --- a/compiler/prog8lib/c64flt.p8 +++ b/compiler/prog8lib/c64flt.p8 @@ -9,7 +9,6 @@ ~ c64flt { ; ---- this block contains C-64 floating point related functions ---- - ; @todo enable float-checkin astchecker.process(decl: VarDecl) again const float PI = 3.141592653589793 const float TWOPI = 6.283185307179586 @@ -192,54 +191,31 @@ asmsub GETADRAY () -> clobbers(X) -> (uword @ AY) { }} } -sub print_f (float value) { +asmsub print_f (float value @ AY) -> clobbers(A, Y) -> () { ; ---- prints the floating point value (without a newline) using basic rom routines. - ; clobbers no registers. - ; @todo version that takes A/Y pointer to float instead %asm {{ - pha - tya - pha - txa - pha - lda #print_f_value + stx c64.SCRATCH_ZPREGX jsr c64flt.MOVFM ; load float into fac1 jsr c64flt.FOUT ; fac1 to string in A/Y jsr c64.STROUT ; print string in A/Y - pla - tax - pla - tay - pla + ldx c64.SCRATCH_ZPREGX rts }} } -sub print_fln (float value) { +asmsub print_fln (float value @ AY) -> clobbers(A, Y) -> () { ; ---- prints the floating point value (with a newline at the end) using basic rom routines - ; clobbers no registers. - ; @todo version that takes A/Y pointer to float instead %asm {{ - pha - tya - pha - txa - pha - lda #print_fln_value + stx c64.SCRATCH_ZPREGX jsr c64flt.MOVFM ; load float into fac1 jsr c64flt.FPRINTLN ; print fac1 with newline - pla - tax - pla - tay - pla + ldx c64.SCRATCH_ZPREGX rts }} } + ; --- low level floating point assembly routines %asm {{ ub2float .proc diff --git a/compiler/prog8lib/c64lib.p8 b/compiler/prog8lib/c64lib.p8 index b77c76131..8de5f1ba9 100644 --- a/compiler/prog8lib/c64lib.p8 +++ b/compiler/prog8lib/c64lib.p8 @@ -42,6 +42,7 @@ memory ubyte SPRPTR5 = 2045 memory ubyte SPRPTR6 = 2046 memory ubyte SPRPTR7 = 2047 + memory ubyte[8] SPRPTR = 2040 ; ---- VIC-II registers ---- @@ -62,6 +63,7 @@ memory ubyte SP6Y = $d00d memory ubyte SP7X = $d00e memory ubyte SP7Y = $d00f + memory ubyte[16] SPXY = $d000 memory ubyte MSIGX = $d010 memory ubyte SCROLY = $d011 @@ -95,6 +97,8 @@ memory ubyte SP5COL = $d02c memory ubyte SP6COL = $d02d memory ubyte SP7COL = $d02e + memory ubyte[8] SPCOL = $d027 + ; ---- end of VIC-II registers ---- diff --git a/compiler/prog8lib/prog8lib.p8 b/compiler/prog8lib/prog8lib.p8 index 4e2673d72..6c2390499 100644 --- a/compiler/prog8lib/prog8lib.p8 +++ b/compiler/prog8lib/prog8lib.p8 @@ -42,7 +42,7 @@ pop_index_times_5 .proc adc c64.SCRATCH_ZPB1 ; A*=5 rts .pend - + neg_b .proc lda c64.ESTACK_LO+1,x eor #255 @@ -51,7 +51,7 @@ neg_b .proc sta c64.ESTACK_LO+1,x rts .pend - + neg_w .proc sec lda #0 @@ -62,7 +62,7 @@ neg_w .proc sta c64.ESTACK_HI+1,x rts .pend - + inv_word .proc lda c64.ESTACK_LO+1,x eor #255 @@ -82,7 +82,7 @@ not_byte .proc + sta c64.ESTACK_LO+1,x rts .pend - + not_word .proc lda c64.ESTACK_LO + 1,x ora c64.ESTACK_HI + 1,x @@ -94,14 +94,14 @@ not_word .proc sta c64.ESTACK_HI + 1,x rts .pend - + abs_b .proc ; -- push abs(byte) on stack (as byte) lda c64.ESTACK_LO+1,x bmi neg_b rts .pend - + abs_w .proc ; -- push abs(word) on stack (as word) lda c64.ESTACK_HI+1,x @@ -121,7 +121,7 @@ add_w .proc sta c64.ESTACK_HI+1,x rts .pend - + sub_w .proc ; -- push word-word inx @@ -144,7 +144,7 @@ mul_byte .proc sta c64.ESTACK_LO+1,x rts .pend - + mul_word .proc inx lda c64.ESTACK_LO,x @@ -162,7 +162,7 @@ mul_word .proc sta c64.ESTACK_HI+1,x rts .pend - + idiv_b .proc ; signed division: use unsigned division and fix sign of result afterwards inx @@ -194,7 +194,7 @@ idiv_b .proc rts _remainder .byte 0 .pend - + idiv_ub .proc inx ldy c64.ESTACK_LO,x @@ -204,7 +204,7 @@ idiv_ub .proc sta c64.ESTACK_LO+1,x rts .pend - + idiv_w .proc ; signed division: use unsigned division and fix sign of result afterwards lda c64.ESTACK_HI+2,x @@ -232,7 +232,7 @@ idiv_w .proc jmp neg_w ; negate result + rts .pend - + idiv_uw .proc inx lda c64.ESTACK_LO+1,x @@ -256,7 +256,7 @@ remainder_ub .proc sta c64.ESTACK_LO+1,x rts .pend - + remainder_uw .proc inx lda c64.ESTACK_LO+1,x @@ -272,7 +272,7 @@ remainder_uw .proc sta c64.ESTACK_HI+1,x rts .pend - + equal_w .proc ; -- are the two words on the stack identical? lda c64.ESTACK_LO+1,x @@ -292,7 +292,7 @@ notequal_b .proc sta c64.ESTACK_LO+1,x rts .pend - + notequal_w .proc ; -- are the two words on the stack different? inx @@ -306,14 +306,14 @@ notequal_w .proc sta c64.ESTACK_LO+1,x rts .pend - + less_ub .proc lda c64.ESTACK_LO+2,x cmp c64.ESTACK_LO+1,x bcc equal_b._equal_b_true bcs equal_b._equal_b_false .pend - + less_b .proc ; see http://www.6502.org/tutorials/compare_beyond.html lda c64.ESTACK_LO+2,x @@ -364,10 +364,10 @@ lesseq_ub .proc lda c64.ESTACK_LO+2,x cmp c64.ESTACK_LO+1,x bcc equal_b._equal_b_true - beq equal_b._equal_b_true ; @todo optimize by flipping comparison + beq equal_b._equal_b_true ; @todo optimize by flipping comparison? bcs equal_b._equal_b_false .pend - + lesseq_b .proc ; see http://www.6502.org/tutorials/compare_beyond.html lda c64.ESTACK_LO+2,x @@ -389,7 +389,7 @@ lesseq_uw .proc bcs equal_b._equal_b_true bcc equal_b._equal_b_false .pend - + lesseq_w .proc lda c64.ESTACK_LO+1,x cmp c64.ESTACK_LO+2,x @@ -408,7 +408,7 @@ greater_ub .proc bcs equal_b._equal_b_true ; @todo optimize by flipping comparison? bcc equal_b._equal_b_false .pend - + greater_b .proc ; see http://www.6502.org/tutorials/compare_beyond.html lda c64.ESTACK_LO+2,x @@ -441,14 +441,14 @@ greater_w .proc + bmi equal_b._equal_b_true bpl equal_b._equal_b_false .pend - + greatereq_ub .proc lda c64.ESTACK_LO+2,x cmp c64.ESTACK_LO+1,x bcs equal_b._equal_b_true bcc equal_b._equal_b_false .pend - + greatereq_b .proc ; see http://www.6502.org/tutorials/compare_beyond.html lda c64.ESTACK_LO+2,x @@ -482,7 +482,7 @@ greatereq_w .proc bmi equal_b._equal_b_false .pend - + func_sin8 .proc ldy c64.ESTACK_LO+1,x lda _sinecos8,y @@ -511,7 +511,7 @@ _ := 32767 * sin(range(256+64) * rad(360.0/256.0)) _sinecos8lo .byte <_ _sinecos8hi .byte >_ .pend - + func_sin16u .proc ldy c64.ESTACK_LO+1,x lda _sinecos8ulo,y @@ -531,7 +531,7 @@ func_cos8 .proc sta c64.ESTACK_LO+1,x rts .pend - + func_cos8u .proc ldy c64.ESTACK_LO+1,x lda func_sin8u._sinecos8u+64,y @@ -556,8 +556,8 @@ func_cos16u .proc sta c64.ESTACK_HI+1,x rts .pend - - + + peek_address .proc ; -- peek address on stack into c64.SCRATCH_ZPWORD1 lda c64.ESTACK_LO+1,x @@ -585,7 +585,7 @@ _got_any lda #1 sta c64.ESTACK_LO+1,x rts .pend - + func_any_w .proc inx lda c64.ESTACK_LO,x ; array size @@ -611,7 +611,7 @@ _got_not_all lda #0 sta c64.ESTACK_LO+1,x rts .pend - + func_all_w .proc inx lda c64.ESTACK_LO,x ; array size @@ -634,7 +634,7 @@ _cmp_mod cpy #255 ; modified sta c64.ESTACK_LO+1,x rts .pend - + func_max_ub .proc jsr pop_array_and_lengthmin1Y lda #0 @@ -651,7 +651,7 @@ func_max_ub .proc dex rts .pend - + func_max_b .proc jsr pop_array_and_lengthmin1Y lda #-128 @@ -661,7 +661,7 @@ func_max_b .proc sbc c64.SCRATCH_ZPB1 bvc + eor #$80 -+ bmi + ++ bmi + lda (c64.SCRATCH_ZPWORD1),y sta c64.SCRATCH_ZPB1 + dey @@ -672,7 +672,7 @@ func_max_b .proc dex rts .pend - + func_max_uw .proc lda #0 sta _result_maxuw @@ -708,7 +708,7 @@ _lesseq dey rts _result_maxuw .word 0 .pend - + func_max_w .proc lda #$00 sta _result_maxw @@ -745,7 +745,7 @@ _lesseq dey rts _result_maxw .word 0 .pend - + func_sum_b .proc jsr pop_array_and_lengthmin1Y @@ -770,7 +770,7 @@ _loop lda (c64.SCRATCH_ZPWORD1),y dex rts .pend - + func_sum_ub .proc jsr pop_array_and_lengthmin1Y lda #0 @@ -818,7 +818,7 @@ func_sum_w .proc jmp func_sum_uw .pend - + pop_array_and_lengthmin1Y .proc inx ldy c64.ESTACK_LO,x @@ -830,7 +830,7 @@ pop_array_and_lengthmin1Y .proc inx rts .pend - + func_min_ub .proc jsr pop_array_and_lengthmin1Y lda #255 @@ -847,8 +847,8 @@ func_min_ub .proc dex rts .pend - - + + func_min_b .proc jsr pop_array_and_lengthmin1Y lda #127 @@ -858,7 +858,7 @@ func_min_b .proc sbc c64.SCRATCH_ZPB1 bvc + eor #$80 -+ bpl + ++ bpl + lda (c64.SCRATCH_ZPWORD1),y sta c64.SCRATCH_ZPB1 + dey @@ -869,7 +869,7 @@ func_min_b .proc dex rts .pend - + func_min_uw .proc lda #$ff sta _result_minuw @@ -905,7 +905,7 @@ _gtequ dey rts _result_minuw .word 0 .pend - + func_min_w .proc lda #$ff sta _result_minw @@ -942,7 +942,7 @@ _gtequ dey rts _result_minw .word 0 .pend - + func_len_str .proc ; -- push length of 0-terminated string on stack @@ -956,7 +956,7 @@ func_len_str .proc sta c64.ESTACK_LO+1,x rts .pend - + func_len_strp .proc ; -- push length of pascal-string on stack jsr peek_address @@ -973,7 +973,7 @@ func_rnd .proc dex rts .pend - + func_rndw .proc ; -- put a random uword on the estack jsr math.randword @@ -983,8 +983,8 @@ func_rndw .proc dex rts .pend - - + + func_memcopy .proc ; clobbers A,Y inx stx c64.SCRATCH_ZPREGX @@ -1004,7 +1004,7 @@ func_memcopy .proc ; clobbers A,Y inx rts .pend - + }} } @@ -1088,7 +1088,7 @@ mult16 lda #$00 rts multiply_words_result .byte 0,0,0,0 - + }} } @@ -1138,7 +1138,7 @@ result = dividend ;save memory by reusing divident to store the result ldx #16 ;repeat for each bit: ... - asl dividend ;dividend lb & hb*2, msb -> Carry - rol dividend+1 + rol dividend+1 rol remainder ;remainder lb & hb * 2 + msb from carry rol remainder+1 lda remainder @@ -1150,23 +1150,23 @@ result = dividend ;save memory by reusing divident to store the result bcc + ;if carry=0 then divisor didn't fit in yet sta remainder+1 ;else save substraction result as new remainder, - sty remainder + sty remainder inc result ;and INCrement result cause divisor fit in 1 times + dex bne - - + lda result ldy result+1 ldx c64.SCRATCH_ZPREGX rts -_divisor .word 0 +_divisor .word 0 }} } asmsub randseed (uword seed @ AY) -> clobbers(A, Y) -> () { ; ---- reset the random seeds for the byte and word random generators - ; default starting values are: A=$2c Y=$9e + ; default starting values are: A=$2c Y=$9e %asm {{ sta randword._seed sty randword._seed+1 diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index a52c15260..2fbdc9284 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -272,7 +272,8 @@ class AstChecker(private val namespace: INameScope, err("parameter '${param.first.name}' should be (u)byte") } else if(param.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) { - if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD && param.first.type !in StringDatatypes && param.first.type !in ArrayDatatypes) + if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD + && param.first.type !in StringDatatypes && param.first.type !in ArrayDatatypes && param.first.type != DataType.FLOAT) err("parameter '${param.first.name}' should be (u)word/address") } else if(param.second.statusflag!=null) { @@ -286,7 +287,8 @@ class AstChecker(private val namespace: INameScope, err("return value #${ret.first.index + 1} should be (u)byte") } else if(ret.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) { - if (ret.first.value != DataType.UWORD && ret.first.value != DataType.WORD && ret.first.value !in StringDatatypes && ret.first.value !in ArrayDatatypes) + if (ret.first.value != DataType.UWORD && ret.first.value != DataType.WORD + && ret.first.value !in StringDatatypes && ret.first.value !in ArrayDatatypes && ret.first.value != DataType.FLOAT) err("return value #${ret.first.index + 1} should be (u)word/address") } else if(ret.second.statusflag!=null) { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index ee5b52428..318f6dbd8 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -967,6 +967,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? prog.instr(Opcode.POP_REGAX_WORD) } + DataType.FLOAT -> { + pushFloatAddress(arg.first) + prog.instr(Opcode.POP_REGAX_WORD) + } else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition") } } @@ -993,6 +997,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? prog.instr(Opcode.POP_REGAY_WORD) } + DataType.FLOAT -> { + pushFloatAddress(arg.first) + prog.instr(Opcode.POP_REGAY_WORD) + } else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition") } } @@ -1023,6 +1031,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? prog.instr(Opcode.POP_REGXY_WORD) } + DataType.FLOAT -> { + pushFloatAddress(arg.first) + prog.instr(Opcode.POP_REGXY_WORD) + } else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition") } } @@ -1485,6 +1497,19 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } + private fun pushFloatAddress(value: IExpression) { + when (value) { + is LiteralValue -> { + prog.instr(Opcode.PUSH_ADDR_FLOAT, Value(value.type, value.floatvalue!!)) + } + is IdentifierReference -> { + val vardecl = value.targetStatement(namespace) as VarDecl + prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname) + } + else -> throw CompilerException("literal float value or float variable expected") + } + } + private fun translateMultiReturnAssignment(stmt: Assignment) { val targetStmt = (stmt.value as? FunctionCall)?.target?.targetStatement(namespace) if(targetStmt is Subroutine && targetStmt.isAsmSubroutine) { diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index b2569da8a..7f7201aa9 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -19,6 +19,7 @@ enum class Opcode { PUSH_REGAY_WORD, // push registers A/Y as a 16-bit word PUSH_REGXY_WORD, // push registers X/Y as a 16-bit word PUSH_ADDR_STR, // push the address of the string value (literal) + PUSH_ADDR_FLOAT, // push the address of the float value (literal) PUSH_ADDR_HEAPVAR, // push the address of the variable that's on the heap (string or array) // popping values off the (evaluation) stack, possibly storing them in another location diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 8d96906c5..77e5bf0ce 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -536,6 +536,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.PUSH_ADDR_HEAPVAR -> { " lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex" } + Opcode.PUSH_ADDR_FLOAT -> { + val varname = getFloatConst(ins.arg!!) + " lda #<$varname | sta ${ESTACK_LO.toHex()},x | lda #>$varname | sta ${ESTACK_HI.toHex()},x | dex" + } Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGAY_WORD -> { @@ -570,9 +574,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.WRITE_INDEXED_VAR_BYTE -> { """ inx - lda ${ESTACK_LO.toHex()},x - inx ldy ${ESTACK_LO.toHex()},x + inx + lda ${ESTACK_LO.toHex()},x sta ${ins.callLabel},y """ } @@ -701,6 +705,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } Opcode.INC_MEMORY -> " inc ${hexVal(ins)}" Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}" + Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | inc ${ins.callLabel},x | pla | tax" + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | dec ${ins.callLabel},x | pla | tax" + Opcode.NEG_B -> " jsr prog8_lib.neg_b" Opcode.NEG_W -> " jsr prog8_lib.neg_w" Opcode.NEG_F -> " jsr c64flt.neg_f" @@ -1034,10 +1041,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX inc $variable,x | tax", 10) Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX dec $variable,x | tax", 10) Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w") - Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw") + Opcode.INC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord inc $variable,x | bne + | inc $variable+1,x |+ $restoreX", 10) Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f") Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w") - Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw") + Opcode.DEC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord lda $variable,x | bne + | dec $variable+1,x |+ | dec $variable,x $restoreX", 10) Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f") else -> null @@ -2915,6 +2922,19 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment -> " ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " }, + // set a register pair to a certain memory address (of a floating point value) + AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGAX_WORD)) { segment -> + val varname=getFloatConst(segment[0].arg!!) + " lda #<$varname | ldx #>$varname " + }, + AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGAY_WORD)) { segment -> + val varname=getFloatConst(segment[0].arg!!) + " lda #<$varname | ldy #>$varname " + }, + AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGXY_WORD)) { segment -> + val varname=getFloatConst(segment[0].arg!!) + " ldx #<$varname | ldy #>$varname " + }, // set a register pair to a certain memory address (of a literal string value) AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGAX_WORD)) { segment -> TODO("$segment") diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index d5530be91..25ca00b9e 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -1443,13 +1443,18 @@ class StackVm(private var traceOutputFile: String?) { val heapId = variables[ins.callLabel]!!.heapId if(heapId<0) throw VmExecutionException("expected variable on heap") - evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable + evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable (this is taken care of properly in the assembly code generator) } Opcode.PUSH_ADDR_STR -> { val heapId = ins.arg!!.heapId if(heapId<0) throw VmExecutionException("expected string to be on heap") - evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string + evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string (this is taken care of properly in the assembly code generator) + } + Opcode.PUSH_ADDR_FLOAT -> { + val floatvalue = ins.arg!! + checkDt(floatvalue, DataType.FLOAT) + evalstack.push(Value(DataType.UWORD, floatvalue.numericValue().toInt() and 65535)) // push the "address" of the floating point value (this is taken care of properly in the assembly code generator) } Opcode.CAST_UB_TO_B -> typecast(DataType.UBYTE, DataType.BYTE) Opcode.CAST_W_TO_B -> typecast(DataType.WORD, DataType.BYTE) diff --git a/examples/sprites.p8 b/examples/sprites.p8 index 6409e7a98..2e2d7c1b3 100644 --- a/examples/sprites.p8 +++ b/examples/sprites.p8 @@ -39,19 +39,10 @@ c64.STROUT("balloon sprites!\n") c64.STROUT("...we are all floating...\n") - const uword sprite_address_ptr = $0a00 // 64 - c64.SPRPTR0 = sprite_address_ptr - c64.SPRPTR1 = sprite_address_ptr - c64.SPRPTR2 = sprite_address_ptr - c64.SPRPTR3 = sprite_address_ptr - c64.SPRPTR4 = sprite_address_ptr - c64.SPRPTR5 = sprite_address_ptr - c64.SPRPTR6 = sprite_address_ptr - c64.SPRPTR7 = sprite_address_ptr - for ubyte i in 0 to 7 { - @(SP0X+i*2) = 50+25*i - @(SP0Y+i*2) = rnd() + c64.SPRPTR[i] = $0a00 // 64 + c64.SPXY[i*2] = 50+25*i + c64.SPXY[i*2+1] = rnd() } c64.SPENA = 255 ; enable all sprites @@ -63,15 +54,17 @@ ~ irq { sub irq() { c64.EXTCOL-- + ; float up & wobble horizontally for ubyte i in 0 to 14 step 2 { - @(main.SP0Y+i)-- + c64.SPXY[i+1]-- ubyte r = rnd() if r>200 - @(main.SP0X+i)++ + c64.SPXY[i]++ else if r<40 - @(main.SP0X+i)-- + c64.SPXY[i]-- } + c64.EXTCOL++ } diff --git a/examples/test.p8 b/examples/test.p8 index ded0ff1fc..9bac7bbf2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,60 +1,20 @@ %import c64utils +%import c64flt ~ main { sub start() { - ubyte ub=20 - ubyte ub2 - byte b =-10 - byte b2 - uword uw = 2000 - uword uw2 - word w = -222 - word w2 +; @todo create word function ;c64.SPXY[i] = (rnd() as uword) * 256 + (50+25*i) +; @todo more efficient +1/-1 additions in expressions - A>>=1 - A>>=3 - A<<=1 - A<<=3 - lsr(A) - lsl(A) + float f1 = c64flt.TWOPI - ub2 = ub>>1 - ub2 = ub>>2 - ub2 = ub<<1 - ub2 = ub<<2 - b2 = b>>1 - b2 = b>>2 - b2 = b<<1 - b2 = b<<2 - uw2 = uw>>1 - uw2 = uw>>2 - uw2 = uw<<1 - uw2 = uw<<2 - w2 = w>>1 - w2 = w>>2 - w2 = w<<1 - w2 = w<<2 - - lsr(ub) - lsr(b) - lsr(uw) - lsr(w) - lsl(ub) - lsl(b) - lsl(uw) - lsl(w) - rol(ub) - rol(uw) - rol2(ub) - rol2(uw) - ror(ub) - ror(uw) - ror2(ub) - ror2(uw) - - ;c64scr.print_ub(X) - ;c64.CHROUT('\n') + c64flt.print_fln(3.1415) + c64flt.print_fln(f1) + f1 = 3.1415 + f1 = 3.1415 + f1 = 3.1415 + f1 = 3.1415 } } diff --git a/examples/wizzine.p8 b/examples/wizzine.p8 index 9f82dd8cc..d1920218a 100644 --- a/examples/wizzine.p8 +++ b/examples/wizzine.p8 @@ -33,16 +33,9 @@ sub start() { - const uword sprite_address_ptr = $0a00 // 64 - c64.SPRPTR0 = sprite_address_ptr - c64.SPRPTR1 = sprite_address_ptr - c64.SPRPTR2 = sprite_address_ptr - c64.SPRPTR3 = sprite_address_ptr - c64.SPRPTR4 = sprite_address_ptr - c64.SPRPTR5 = sprite_address_ptr - c64.SPRPTR6 = sprite_address_ptr - c64.SPRPTR7 = sprite_address_ptr - + for ubyte i in 0 to 7 { + c64.SPRPTR[i] = $0a00//64 + } c64.SPENA = 255 ; enable all sprites c64utils.set_rasterirq(260) ; enable animation } @@ -54,21 +47,17 @@ ubyte angle=0 sub irq() { - const uword SP0X = $d000 - const uword SP0Y = $d001 - c64.EXTCOL-- angle++ c64.MSIGX=0 - ubyte i=14 + ubyte i=14 nextsprite: ; @todo should be a for loop from 14 to 0 step -2 but this causes a value out of range error at the moment uword x = sin8u(angle*2-i*8) as uword + 50 ubyte y = cos8u(angle*3-i*8) // 2 + 70 - @(SP0X+i) = lsb(x) - @(SP0Y+i) = y - + c64.SPXY[i] = lsb(x) + c64.SPXY[i+1] = y lsl(c64.MSIGX) if msb(x) c64.MSIGX++ i-=2