From 01ac5f29dbe5f8f42a8cc492297933834e35a372 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 11 Oct 2020 01:35:38 +0200 Subject: [PATCH] fix byte-word sign extension for function args as expression --- .../target/c64/codegen/FunctionCallAsmGen.kt | 10 ++++++ .../codegen/assignment/AssignmentAsmGen.kt | 8 +++-- examples/test.p8 | 32 +++++++++---------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt index db7d0752b..5ff1340fd 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt @@ -177,13 +177,22 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg val statusflag = paramRegister.statusflag val register = paramRegister.registerOrPair val stack = paramRegister.stack + val requiredDt = parameter.value.type + if(requiredDt!=valueDt) { + if(valueDt.largerThan(requiredDt)) + throw AssemblyError("can only convert byte values to word param types") + } when { stack -> { // push arg onto the stack // note: argument order is reversed (first argument will be deepest on the stack) asmgen.translateExpression(value) + if(requiredDt!=valueDt) + asmgen.signExtendStackLsb(valueDt) } statusflag!=null -> { + if(requiredDt!=valueDt) + throw AssemblyError("for statusflag, byte value is required") if (statusflag == Statusflag.Pc) { // this param needs to be set last, right before the jsr // for now, this is already enforced on the subroutine definition by the Ast Checker @@ -235,6 +244,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(target) } + // the following routine knows about converting byte to word if required: asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY)) } } 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 c918861e0..46cfe9e4f 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -34,7 +34,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen SourceStorageKind.LITERALNUMBER -> { // simple case: assign a constant number val num = assign.source.number!!.number - when (assign.source.datatype) { + when (assign.target.datatype) { DataType.UBYTE, DataType.BYTE -> assignConstantByte(assign.target, num.toShort()) DataType.UWORD, DataType.WORD -> assignConstantWord(assign.target, num.toInt()) DataType.FLOAT -> assignConstantFloat(assign.target, num.toDouble()) @@ -44,7 +44,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen SourceStorageKind.VARIABLE -> { // simple case: assign from another variable val variable = assign.source.variable!! - when (assign.source.datatype) { + when (assign.target.datatype) { DataType.UBYTE, DataType.BYTE -> assignVariableByte(assign.target, variable) DataType.UWORD, DataType.WORD -> assignVariableWord(assign.target, variable) DataType.FLOAT -> assignVariableFloat(assign.target, variable) @@ -143,12 +143,16 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } else { // regular subroutine, return values are (for now) always done via the stack... TODO optimize this asmgen.translateExpression(value) + if(assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) + asmgen.signExtendStackLsb(assign.source.datatype) assignStackValue(assign.target) } } else -> { // everything else just evaluate via the stack. asmgen.translateExpression(value) + if(assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) + asmgen.signExtendStackLsb(assign.source.datatype) assignStackValue(assign.target) } } diff --git a/examples/test.p8 b/examples/test.p8 index d6537eff7..245a4baec 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -13,28 +13,26 @@ main { ; "sell teleport market hold\n" + ; "fuel galhyp local quit\n") - str name = "irmen de jong" - uword strptr = &name - - - txt.print_ub(strlen("1234")) - txt.chrout('\n') - txt.print_ub(strlen(name)) - txt.chrout('\n') - txt.print_uwhex(strptr, 1) - txt.chrout('\n') - txt.print(strptr) - txt.chrout('\n') - txt.print_ub(strlen(strptr)) - txt.chrout('\n') +; str name = "irmen de jong" +; uword strptr = &name +; +; +; txt.print_ub(strlen("1234")) +; txt.chrout('\n') +; txt.print_ub(strlen(name)) +; txt.chrout('\n') +; txt.print_uwhex(strptr, 1) +; txt.chrout('\n') +; txt.print(strptr) +; txt.chrout('\n') +; txt.print_ub(strlen(strptr)) +; txt.chrout('\n') ubyte q for q in 0 to 255 { txt.print_ub(q) txt.chrout(' ') - ;txt.print_uw(q*4) ; TODO fix -; txt.chrout(' ') - txt.print_uw(q*$0004) ; TODO fix + txt.print_uw(q*5) ; TODO fix txt.chrout('\n') }