diff --git a/compiler/res/prog8lib/c64/floats.asm b/compiler/res/prog8lib/c64/floats.asm index 7da8915a1..45ffe745d 100644 --- a/compiler/res/prog8lib/c64/floats.asm +++ b/compiler/res/prog8lib/c64/floats.asm @@ -55,6 +55,59 @@ w2float .proc jmp ub2float._fac_to_mem .pend + +cast_from_uw .proc + ; -- uword in A/Y into float var at (P8ZP_SCRATCH_W2) + stx P8ZP_SCRATCH_REG + jsr GIVUAYFAY + jmp ub2float._fac_to_mem + .pend + + +cast_from_w .proc + ; -- word in A/Y into float var at (P8ZP_SCRATCH_W2) + stx P8ZP_SCRATCH_REG + jsr GIVAYFAY + jmp ub2float._fac_to_mem + .pend + + +cast_from_ub .proc + ; -- ubyte in Y into float var at (P8ZP_SCRATCH_W2) + stx P8ZP_SCRATCH_REG + jsr FREADUY + jmp ub2float._fac_to_mem + .pend + + +cast_from_b .proc + ; -- byte in A into float var at (P8ZP_SCRATCH_W2) + stx P8ZP_SCRATCH_REG + jsr FREADSA + jmp ub2float._fac_to_mem + .pend + +cast_as_uw_into_ya .proc ; also used for float 2 ub + ; -- cast float at A/Y to uword into Y/A + stx P8ZP_SCRATCH_REG + jsr MOVFM + jsr GETADR ; into Y/A + ldx P8ZP_SCRATCH_REG + rts + .pend + +cast_as_w_into_ay .proc ; also used for float 2 b + ; -- cast float at A/Y to word into A/Y + stx P8ZP_SCRATCH_REG + jsr MOVFM + jsr AYINT + ldy $64 + lda $65 + ldx P8ZP_SCRATCH_REG + rts + .pend + + stack_b2float .proc ; -- b2float operating on the stack inx diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index e66e567b0..43ab63342 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -255,6 +255,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } when(value) { + is IdentifierReference -> { + if(target.kind==TargetStorageKind.VARIABLE) { + val sourceDt = value.inferType(program).typeOrElse(DataType.STRUCT) + if (sourceDt != DataType.STRUCT) + return assignTypeCastedIdentifier(target.asmVarname, targetDt, asmgen.asmVariableName(value), sourceDt, origAssign.source.expression!!) + } + } is PrefixExpression -> {} is BinaryExpression -> {} is ArrayIndexedExpression -> {} @@ -264,7 +271,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen else -> { // TODO optimize the others further? if(this.asmgen.options.slowCodegenWarnings) - println("warning: slow stack evaluation used for typecast: into $targetDt at ${value.position}") + println("warning: slow stack evaluation used for typecast: $value into $targetDt at ${value.position}") } } @@ -273,6 +280,125 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen assignStackValue(target) } + private fun assignTypeCastedIdentifier(targetAsmVarName: String, targetDt: DataType, + sourceAsmVarName: String, sourceDt: DataType, + origExpr: Expression) { + if(sourceDt == targetDt) + throw AssemblyError("typecast to identical value") + + // also see: ExpressionAsmGen, fun translateExpression(typecast: TypecastExpression) + when(sourceDt) { + DataType.UBYTE -> { + when(targetDt) { + DataType.UBYTE, DataType.BYTE -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName") + } + DataType.UWORD, DataType.WORD -> { + if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | stz $targetAsmVarName+1") + else + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda #0 | sta $targetAsmVarName+1") + } + DataType.FLOAT -> { + asmgen.out(""" + lda #<$targetAsmVarName + ldy #>$targetAsmVarName + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + ldy $sourceAsmVarName + jsr floats.cast_from_ub""") + } + else -> throw AssemblyError("weird type") + } + } + DataType.BYTE -> { + when(targetDt) { + DataType.UBYTE, DataType.BYTE -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName") + } + DataType.UWORD, DataType.WORD -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName") + asmgen.signExtendVariableLsb(targetAsmVarName, DataType.BYTE) + } + DataType.FLOAT -> { + asmgen.out(""" + lda #<$targetAsmVarName + ldy #>$targetAsmVarName + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda $sourceAsmVarName + jsr floats.cast_from_b""") + } + else -> throw AssemblyError("weird type") + } + } + DataType.UWORD -> { + when(targetDt) { + DataType.BYTE, DataType.UBYTE -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName") + } + DataType.WORD, DataType.UWORD -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1") + } + DataType.FLOAT -> { + asmgen.out(""" + lda #<$targetAsmVarName + ldy #>$targetAsmVarName + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda $sourceAsmVarName + ldy $sourceAsmVarName+1 + jsr floats.cast_from_uw""") + } + else -> throw AssemblyError("weird type") + } + } + DataType.WORD -> { + when(targetDt) { + DataType.BYTE, DataType.UBYTE -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName") + } + DataType.WORD, DataType.UWORD -> { + asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1") + } + DataType.FLOAT -> { + asmgen.out(""" + lda #<$targetAsmVarName + ldy #>$targetAsmVarName + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda $sourceAsmVarName + ldy $sourceAsmVarName+1 + jsr floats.cast_from_w""") + } + else -> throw AssemblyError("weird type") + } + } + DataType.FLOAT -> { + asmgen.out(""" + lda #<$targetAsmVarName + ldy #>$targetAsmVarName + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda #<$sourceAsmVarName + ldy #>$sourceAsmVarName""") + when(targetDt) { + DataType.UBYTE -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName") + DataType.BYTE -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName") + DataType.UWORD -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1") + DataType.WORD -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName | sty $targetAsmVarName+1") + else -> throw AssemblyError("weird type") + } + } + DataType.STR -> { + if (targetDt != DataType.UWORD && targetDt == DataType.STR) + throw AssemblyError("cannot typecast a string into another incompatitble type") + } + else -> throw AssemblyError("weird type") + } + } + + private fun assignStackValue(target: AsmAssignTarget) { when(target.kind) { TargetStorageKind.VARIABLE -> { diff --git a/examples/test.p8 b/examples/test.p8 index 11780cb14..286da1f67 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,16 +6,15 @@ main { sub start() { - uword uw = %1111111110000001 - uword uw2 = %000111100001110 ubyte ub = 30 + byte bb = -30 + float f1 - uword addr = $c000 - - @(addr) = 0 - @(addr) ++ - @(addr) += 2*(ub+3) - txt.print_uw(@(addr)) + f1 = ub + floats.print_f(f1) + txt.chrout('\n') + f1 = bb + floats.print_f(f1) txt.chrout('\n') testX()