really fix byte-word sign extension for function args as expression

This commit is contained in:
Irmen de Jong 2020-10-11 03:02:58 +02:00
parent 9e54e11113
commit 73524e01a6
7 changed files with 83 additions and 26 deletions

View File

@ -39,16 +39,20 @@ enum class DataType {
infix fun isAssignableTo(targetTypes: Set<DataType>) = targetTypes.any { this isAssignableTo it } infix fun isAssignableTo(targetTypes: Set<DataType>) = targetTypes.any { this isAssignableTo it }
infix fun largerThan(other: DataType) = infix fun largerThan(other: DataType) =
when(this) { when {
in ByteDatatypes -> false this == other -> false
in WordDatatypes -> other in ByteDatatypes this in ByteDatatypes -> false
this in WordDatatypes -> other in ByteDatatypes
this==STR && other==UWORD || this==UWORD && other==STR -> false
else -> true else -> true
} }
infix fun equalsSize(other: DataType) = infix fun equalsSize(other: DataType) =
when(this) { when {
in ByteDatatypes -> other in ByteDatatypes this == other -> true
in WordDatatypes -> other in WordDatatypes this in ByteDatatypes -> other in ByteDatatypes
this in WordDatatypes -> other in WordDatatypes
this==STR && other==UWORD || this==UWORD && other==STR -> true
else -> false else -> false
} }

View File

@ -611,7 +611,7 @@ $endLabel""")
private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) { private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) {
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, stmt.loopVarDt(program).typeOrElse(DataType.STRUCT), stmt.definingSubroutine(), variable=stmt.loopVar) val target = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, stmt.loopVarDt(program).typeOrElse(DataType.STRUCT), stmt.definingSubroutine(), variable=stmt.loopVar)
val src = AsmAssignSource.fromAstSource(range.from, program).adjustDataTypeToTarget(target) val src = AsmAssignSource.fromAstSource(range.from, program).adjustSignedUnsigned(target)
val assign = AsmAssignment(src, target, false, range.position) val assign = AsmAssignment(src, target, false, range.position)
asmgen.translateNormalAssignment(assign) asmgen.translateNormalAssignment(assign)
} }

View File

@ -159,7 +159,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val identifier = IdentifierReference(scopedParamVar, sub.position) val identifier = IdentifierReference(scopedParamVar, sub.position)
identifier.linkParents(value.parent) identifier.linkParents(value.parent)
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, parameter.value.type, sub, variable = identifier) val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, parameter.value.type, sub, variable = identifier)
val source = AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(tgt) val source = AsmAssignSource.fromAstSource(value, program).adjustSignedUnsigned(tgt)
val asgn = AsmAssignment(source, tgt, false, Position.DUMMY) val asgn = AsmAssignment(source, tgt, false, Position.DUMMY)
asmgen.translateNormalAssignment(asgn) asmgen.translateNormalAssignment(asgn)
} }
@ -179,7 +179,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val stack = paramRegister.stack val stack = paramRegister.stack
val requiredDt = parameter.value.type val requiredDt = parameter.value.type
if(requiredDt!=valueDt) { if(requiredDt!=valueDt) {
if(valueDt.largerThan(requiredDt)) if(valueDt largerThan requiredDt)
throw AssemblyError("can only convert byte values to word param types") throw AssemblyError("can only convert byte values to word param types")
} }
when { when {
@ -233,22 +233,30 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
else -> { else -> {
// via register or register pair // via register or register pair
val target = AsmAssignTarget.fromRegisters(register!!, sub, program, asmgen) val target = AsmAssignTarget.fromRegisters(register!!, sub, program, asmgen)
if(requiredDt largerThan valueDt) {
// TODO we need to sign extend the source, do this via stack (slow)
println("warning: slow stack evaluation used for sign-extend: into $requiredDt at ${value.position}")
asmgen.translateExpression(value)
asmgen.signExtendStackLsb(valueDt)
val src = AsmAssignSource(SourceStorageKind.STACK, program, valueDt)
asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY))
}
else {
val src = if(valueDt in PassByReferenceDatatypes) { val src = if(valueDt in PassByReferenceDatatypes) {
if(value is IdentifierReference) { if(value is IdentifierReference) {
val addr = AddressOf(value, Position.DUMMY) val addr = AddressOf(value, Position.DUMMY)
AsmAssignSource.fromAstSource(addr, program).adjustDataTypeToTarget(target) AsmAssignSource.fromAstSource(addr, program).adjustSignedUnsigned(target)
} else { } else {
AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(target) AsmAssignSource.fromAstSource(value, program).adjustSignedUnsigned(target)
} }
} else { } else {
AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(target) AsmAssignSource.fromAstSource(value, program).adjustSignedUnsigned(target)
} }
// the following routine knows about converting byte to word if required:
asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY)) asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY))
} }
} }
} }
}
private fun isArgumentTypeCompatible(argType: DataType, paramType: DataType): Boolean { private fun isArgumentTypeCompatible(argType: DataType, paramType: DataType): Boolean {
if(argType isAssignableTo paramType) if(argType isAssignableTo paramType)

View File

@ -165,7 +165,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
fun withAdjustedDt(newType: DataType) = fun withAdjustedDt(newType: DataType) =
AsmAssignSource(kind, program, newType, variable, array, memory, register, number, expression) AsmAssignSource(kind, program, newType, variable, array, memory, register, number, expression)
fun adjustDataTypeToTarget(target: AsmAssignTarget): AsmAssignSource { fun adjustSignedUnsigned(target: AsmAssignTarget): AsmAssignSource {
// allow some signed/unsigned relaxations // allow some signed/unsigned relaxations
if(target.datatype!=datatype) { if(target.datatype!=datatype) {
if(target.datatype in ByteDatatypes && datatype in ByteDatatypes) { if(target.datatype in ByteDatatypes && datatype in ByteDatatypes) {

View File

@ -18,7 +18,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
fun translate(assignment: Assignment) { fun translate(assignment: Assignment) {
val target = AsmAssignTarget.fromAstAssignment(assignment, program, asmgen) val target = AsmAssignTarget.fromAstAssignment(assignment, program, asmgen)
val source = AsmAssignSource.fromAstSource(assignment.value, program).adjustDataTypeToTarget(target) val source = AsmAssignSource.fromAstSource(assignment.value, program).adjustSignedUnsigned(target)
val assign = AsmAssignment(source, target, assignment.isAugmentable, assignment.position) val assign = AsmAssignment(source, target, assignment.isAugmentable, assignment.position)
target.origAssign = assign target.origAssign = assign

View File

@ -7,6 +7,25 @@ main {
sub start() { sub start() {
print_10s(1)
txt.chrout('\n')
print_10s(123)
txt.chrout('\n')
print_10s(54321)
txt.chrout('\n')
txt.chrout('\n')
ubyte ww
ww=1
print_10s(ww)
txt.chrout('\n')
ww=123
print_10s(ww)
txt.chrout('\n')
ww=255
print_10s(ww)
txt.chrout('\n')
txt.print("\nCommands are:\n"+ txt.print("\nCommands are:\n"+
"buy jump inf cash\n" + "buy jump inf cash\n" +
"sell teleport market hold\n" + "sell teleport market hold\n" +
@ -30,6 +49,32 @@ main {
} }
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
%asm {{
jsr conv.uword2decimal
lda conv.uword2decimal.decTenThousands
cmp #'0'
beq +
jsr c64.CHROUT
+ lda conv.uword2decimal.decThousands
cmp #'0'
beq +
jsr c64.CHROUT
+ lda conv.uword2decimal.decHundreds
cmp #'0'
beq +
jsr c64.CHROUT
+ lda conv.uword2decimal.decTens
jsr c64.CHROUT
lda #'.'
jsr c64.CHROUT
lda conv.uword2decimal.decOnes
jsr c64.CHROUT
rts
}}
}
asmsub testX() { asmsub testX() {
%asm {{ %asm {{
stx _saveX stx _saveX

View File

@ -181,7 +181,7 @@ market {
ubyte ci ubyte ci
txt.print(" COMMODITY / PRICE / AVAIL / IN HOLD\n") txt.print(" COMMODITY / PRICE / AVAIL / IN HOLD\n")
for ci in 0 to len(names)-1 { for ci in 0 to len(names)-1 {
util.print_right(12, names[ci]) util.print_right(13, names[ci])
txt.print(" ") txt.print(" ")
util.print_10s(current_price[ci]) util.print_10s(current_price[ci])
txt.print(" ") txt.print(" ")