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 largerThan(other: DataType) =
when(this) {
in ByteDatatypes -> false
in WordDatatypes -> other in ByteDatatypes
when {
this == other -> false
this in ByteDatatypes -> false
this in WordDatatypes -> other in ByteDatatypes
this==STR && other==UWORD || this==UWORD && other==STR -> false
else -> true
}
infix fun equalsSize(other: DataType) =
when(this) {
in ByteDatatypes -> other in ByteDatatypes
in WordDatatypes -> other in WordDatatypes
when {
this == other -> true
this in ByteDatatypes -> other in ByteDatatypes
this in WordDatatypes -> other in WordDatatypes
this==STR && other==UWORD || this==UWORD && other==STR -> true
else -> false
}

View File

@ -611,7 +611,7 @@ $endLabel""")
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 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)
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)
identifier.linkParents(value.parent)
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)
asmgen.translateNormalAssignment(asgn)
}
@ -179,7 +179,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val stack = paramRegister.stack
val requiredDt = parameter.value.type
if(requiredDt!=valueDt) {
if(valueDt.largerThan(requiredDt))
if(valueDt largerThan requiredDt)
throw AssemblyError("can only convert byte values to word param types")
}
when {
@ -233,19 +233,27 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
else -> {
// via register or register pair
val target = AsmAssignTarget.fromRegisters(register!!, sub, program, asmgen)
val src = if(valueDt in PassByReferenceDatatypes) {
if(value is IdentifierReference) {
val addr = AddressOf(value, Position.DUMMY)
AsmAssignSource.fromAstSource(addr, program).adjustDataTypeToTarget(target)
} else {
AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(target)
}
} else {
AsmAssignSource.fromAstSource(value, program).adjustDataTypeToTarget(target)
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) {
if(value is IdentifierReference) {
val addr = AddressOf(value, Position.DUMMY)
AsmAssignSource.fromAstSource(addr, program).adjustSignedUnsigned(target)
} else {
AsmAssignSource.fromAstSource(value, program).adjustSignedUnsigned(target)
}
} else {
AsmAssignSource.fromAstSource(value, program).adjustSignedUnsigned(target)
}
asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY))
}
// the following routine knows about converting byte to word if required:
asmgen.translateNormalAssignment(AsmAssignment(src, target, false, Position.DUMMY))
}
}
}

View File

@ -165,7 +165,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
fun withAdjustedDt(newType: DataType) =
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
if(target.datatype!=datatype) {
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) {
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)
target.origAssign = assign

View File

@ -7,6 +7,25 @@ main {
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"+
"buy jump inf cash\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() {
%asm {{
stx _saveX

View File

@ -179,10 +179,10 @@ market {
sub display() {
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 {
util.print_right(12, names[ci])
txt.print(" ")
util.print_right(13, names[ci])
txt.print(" ")
util.print_10s(current_price[ci])
txt.print(" ")
txt.print_ub(current_quantity[ci])