mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
6502 asmgen
This commit is contained in:
parent
10d12f73d6
commit
6b52ba9397
@ -142,11 +142,12 @@ private fun PtVariable.prefix(st: SymbolTable): PtVariable {
|
||||
return this
|
||||
|
||||
val arrayValue = value as? PtArray
|
||||
return if(arrayValue!=null && arrayValue.children.any { it !is PtNumber} ) {
|
||||
return if(arrayValue!=null && arrayValue.children.any { it !is PtNumber && it !is PtBool } ) {
|
||||
val newValue = PtArray(arrayValue.type, arrayValue.position)
|
||||
arrayValue.children.forEach { elt ->
|
||||
when(elt) {
|
||||
is PtIdentifier -> newValue.add(elt.prefix(arrayValue, st))
|
||||
is PtBool -> newValue.add(elt)
|
||||
is PtNumber -> newValue.add(elt)
|
||||
is PtAddressOf -> {
|
||||
if(elt.definingBlock()?.options?.noSymbolPrefixing==true)
|
||||
@ -624,7 +625,7 @@ class AsmGen6502Internal (
|
||||
}
|
||||
|
||||
when (expr.type) {
|
||||
in ByteDatatypes -> {
|
||||
in ByteDatatypesWithBoolean -> {
|
||||
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false)
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
@ -691,7 +692,7 @@ class AsmGen6502Internal (
|
||||
|
||||
internal fun assignExpressionTo(value: PtExpression, target: AsmAssignTarget) {
|
||||
when (target.datatype) {
|
||||
in ByteDatatypes -> {
|
||||
in ByteDatatypesWithBoolean -> {
|
||||
if (value.asConstInteger()==0) {
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
@ -805,7 +806,7 @@ class AsmGen6502Internal (
|
||||
}
|
||||
when(stmt.condition.type) {
|
||||
in WordDatatypes -> translateWordEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label)
|
||||
in ByteDatatypes -> translateByteEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label)
|
||||
in ByteDatatypesWithBoolean -> translateByteEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label)
|
||||
else -> throw AssemblyError("weird condition dt")
|
||||
}
|
||||
} else {
|
||||
@ -813,7 +814,7 @@ class AsmGen6502Internal (
|
||||
val endLabel = makeLabel("if_end")
|
||||
when(stmt.condition.type) {
|
||||
in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel)
|
||||
in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel)
|
||||
in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel)
|
||||
else -> throw AssemblyError("weird condition dt")
|
||||
}
|
||||
translate(stmt.ifScope)
|
||||
@ -825,7 +826,7 @@ class AsmGen6502Internal (
|
||||
val endLabel = makeLabel("if_end")
|
||||
when(stmt.condition.type) {
|
||||
in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel)
|
||||
in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel)
|
||||
in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel)
|
||||
else -> throw AssemblyError("weird condition dt")
|
||||
}
|
||||
translate(stmt.ifScope)
|
||||
@ -839,7 +840,7 @@ class AsmGen6502Internal (
|
||||
|
||||
private fun requireComparisonExpression(condition: PtExpression) {
|
||||
if (!(condition is PtBinaryExpression && condition.operator in ComparisonOperators))
|
||||
throw AssemblyError("expected boolean comparison expression $condition")
|
||||
throw AssemblyError("expected boolean comparison expression")
|
||||
}
|
||||
|
||||
private fun translate(stmt: PtRepeatLoop) {
|
||||
@ -1118,7 +1119,7 @@ $repeatLabel""")
|
||||
val sub = ret.definingSub()!!
|
||||
val returnReg = sub.returnRegister()!!
|
||||
when (sub.returntype) {
|
||||
in NumericDatatypes -> {
|
||||
in NumericDatatypes, DataType.BOOL -> {
|
||||
assignExpressionToRegister(returnvalue, returnReg.registerOrPair!!)
|
||||
}
|
||||
else -> {
|
||||
@ -1256,6 +1257,7 @@ $repeatLabel""")
|
||||
return when(expr) {
|
||||
is PtIdentifier -> false
|
||||
is PtNumber -> false
|
||||
is PtBool -> false
|
||||
is PtMemoryByte -> expr.address !is PtIdentifier && expr.address !is PtNumber
|
||||
is PtTypeCast -> evalBytevalueWillClobberA(expr.value)
|
||||
else -> true
|
||||
@ -1344,7 +1346,7 @@ $repeatLabel""")
|
||||
|
||||
// invert the comparison, so we can reuse the JumpIfFalse code generation routines
|
||||
val invertedComparisonOperator = invertedComparisonOperator(expr.operator)
|
||||
?: throw AssemblyError("can't invert comparison $expr")
|
||||
?: throw AssemblyError("can't invert comparison ${expr.operator} $expr")
|
||||
|
||||
val left = expr.left
|
||||
val right = expr.right
|
||||
@ -1383,7 +1385,7 @@ $repeatLabel""")
|
||||
jumpIfFalseLabel: String
|
||||
) {
|
||||
val dt = left.type
|
||||
if(dt in IntegerDatatypes && left is PtIdentifier)
|
||||
if(dt in IntegerDatatypesWithBoolean && left is PtIdentifier)
|
||||
return testVariableZeroOrJumpElsewhere(left, dt, operator, jumpIfFalseLabel)
|
||||
|
||||
when(dt) {
|
||||
@ -1543,7 +1545,7 @@ $repeatLabel""")
|
||||
when (operator) {
|
||||
"==" -> {
|
||||
when (dt) {
|
||||
in ByteDatatypes -> translateByteEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
in ByteDatatypesWithBoolean -> translateByteEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
in WordDatatypes -> translateWordEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
DataType.FLOAT -> translateFloatEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
DataType.STR -> translateStringEqualsOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel)
|
||||
@ -1552,7 +1554,7 @@ $repeatLabel""")
|
||||
}
|
||||
"!=" -> {
|
||||
when (dt) {
|
||||
in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
DataType.FLOAT -> translateFloatNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||
DataType.STR -> translateStringNotEqualsOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel)
|
||||
@ -2547,6 +2549,7 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
when (right) {
|
||||
is PtBool -> TODO("word equals for bool operand")
|
||||
is PtNumber -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY)
|
||||
val number = right.number.toHex()
|
||||
@ -2635,6 +2638,7 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
when (right) {
|
||||
is PtBool -> TODO("word not equals for bool operand")
|
||||
is PtNumber -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY)
|
||||
val number = right.number.toHex()
|
||||
@ -2669,6 +2673,7 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
TODO("word not equals boolean in special case?")
|
||||
if(left.isSimple()) {
|
||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY)
|
||||
@ -2983,6 +2988,7 @@ $repeatLabel""")
|
||||
|
||||
private fun wordJumpForSimpleLeftOperand(left: PtExpression, right: PtExpression, code: (String, String)->Unit): Boolean {
|
||||
when (left) {
|
||||
is PtBool -> TODO("word jump for bool operand")
|
||||
is PtNumber -> {
|
||||
assignExpressionToRegister(right, RegisterOrPair.AY)
|
||||
val number = left.number.toHex()
|
||||
@ -3010,32 +3016,44 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
private fun byteJumpForSimpleRightOperand(left: PtExpression, right: PtExpression, code: (String)->Unit): Boolean {
|
||||
if(right is PtNumber) {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code("#${right.number.toHex()}")
|
||||
return true
|
||||
}
|
||||
if(right is PtIdentifier) {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code(asmVariableName(right))
|
||||
return true
|
||||
}
|
||||
var memread = right as? PtMemoryByte
|
||||
if(memread==null && right is PtTypeCast)
|
||||
memread = right.value as? PtMemoryByte
|
||||
if(memread!=null) {
|
||||
val address = memread.address as? PtNumber
|
||||
if(address!=null) {
|
||||
when (right) {
|
||||
is PtBool -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code(address.number.toHex())
|
||||
code("#${right.asInt()} ; TODO can we get rid of this cmp when dealing with booleans?") // TODO can we get rid of the cmp when dealing with booleans?
|
||||
return true
|
||||
}
|
||||
is PtNumber -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code("#${right.number.toHex()}")
|
||||
return true
|
||||
}
|
||||
|
||||
is PtIdentifier -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code(asmVariableName(right))
|
||||
return true
|
||||
}
|
||||
|
||||
else -> {
|
||||
var memread = right as? PtMemoryByte
|
||||
if (memread == null && right is PtTypeCast)
|
||||
memread = right.value as? PtMemoryByte
|
||||
if (memread != null) {
|
||||
val address = memread.address as? PtNumber
|
||||
if (address != null) {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A)
|
||||
code(address.number.toHex())
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun wordJumpForSimpleRightOperands(left: PtExpression, right: PtExpression, code: (String, String)->Unit): Boolean {
|
||||
when (right) {
|
||||
is PtBool -> TODO("word jump for bool operand")
|
||||
is PtNumber -> {
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY)
|
||||
val number = right.number.toHex()
|
||||
@ -3077,7 +3095,7 @@ $repeatLabel""")
|
||||
out(" lda P8ZP_SCRATCH_REG")
|
||||
}
|
||||
else {
|
||||
if (parameter.type in ByteDatatypes) {
|
||||
if (parameter.type in ByteDatatypesWithBoolean) {
|
||||
if (isTargetCpu(CpuType.CPU65c02)) {
|
||||
when (reg.registerOrPair) {
|
||||
RegisterOrPair.A -> out(" pla")
|
||||
@ -3135,7 +3153,7 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
internal fun popCpuStack(dt: DataType) {
|
||||
if (dt in ByteDatatypes) {
|
||||
if (dt in ByteDatatypesWithBoolean) {
|
||||
out(" pla")
|
||||
} else if (dt in WordDatatypes) {
|
||||
if (isTargetCpu(CpuType.CPU65c02))
|
||||
@ -3149,7 +3167,7 @@ $repeatLabel""")
|
||||
|
||||
internal fun pushCpuStack(dt: DataType, value: PtExpression) {
|
||||
val signed = value.type.oneOf(DataType.BYTE, DataType.WORD)
|
||||
if(dt in ByteDatatypes) {
|
||||
if(dt in ByteDatatypesWithBoolean) {
|
||||
assignExpressionToRegister(value, RegisterOrPair.A, signed)
|
||||
out(" pha")
|
||||
} else if(dt in WordDatatypes) {
|
||||
@ -3176,7 +3194,7 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
internal fun needAsaveForExpr(arg: PtExpression): Boolean =
|
||||
arg !is PtNumber && arg !is PtIdentifier && (arg !is PtMemoryByte || !arg.isSimple())
|
||||
arg !is PtNumber && arg !is PtBool && arg !is PtIdentifier && (arg !is PtMemoryByte || !arg.isSimple())
|
||||
|
||||
private val subroutineExtrasCache = mutableMapOf<IPtSubroutine, SubroutineExtraAsmInfo>()
|
||||
|
||||
|
@ -315,6 +315,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A)
|
||||
asmgen.out(" cmp #${arg2.number.toInt()}")
|
||||
}
|
||||
is PtBool -> {
|
||||
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A)
|
||||
asmgen.out(" cmp #${arg2.asInt()}")
|
||||
}
|
||||
is PtMemoryByte -> {
|
||||
if(arg2.address is PtNumber) {
|
||||
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A)
|
||||
@ -343,6 +347,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
cmp ${asmgen.asmVariableName(arg2)}
|
||||
+""")
|
||||
}
|
||||
is PtBool -> TODO("word compare against bool")
|
||||
is PtNumber -> {
|
||||
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.AY)
|
||||
asmgen.out("""
|
||||
|
@ -359,7 +359,7 @@ $loopLabel lda ${65535.toHex()} ; modified
|
||||
bne $loopLabel
|
||||
$endLabel""")
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_BOOL -> {
|
||||
val indexVar = asmgen.makeLabel("for_index")
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
|
@ -16,8 +16,8 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
}
|
||||
|
||||
internal fun optimizeIntArgsViaRegisters(sub: PtSub) =
|
||||
(sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypes)
|
||||
|| (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypes && sub.parameters[1].type in ByteDatatypes)
|
||||
(sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypesWithBoolean)
|
||||
|| (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypesWithBoolean && sub.parameters[1].type in ByteDatatypesWithBoolean)
|
||||
|
||||
internal fun translateFunctionCall(call: PtFunctionCall) {
|
||||
// Output only the code to set up the parameters and perform the actual call
|
||||
@ -84,6 +84,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
is PtMachineRegister -> false
|
||||
is PtMemoryByte -> return usesOtherRegistersWhileEvaluating(arg.address)
|
||||
is PtNumber -> false
|
||||
is PtBool -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
@ -152,7 +153,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
}
|
||||
if (statusflag!=null) {
|
||||
if(requiredDt!=value.type)
|
||||
throw AssemblyError("for statusflag, byte value is required")
|
||||
throw AssemblyError("for statusflag, byte or bool value is required")
|
||||
if (statusflag == Statusflag.Pc) {
|
||||
// this boolean param needs to be set last, right before the jsr
|
||||
// for now, this is already enforced on the subroutine definition by the Ast Checker
|
||||
@ -161,6 +162,9 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
val carrySet = value.number.toInt() != 0
|
||||
asmgen.out(if(carrySet) " sec" else " clc")
|
||||
}
|
||||
is PtBool -> {
|
||||
asmgen.out(if(value.value) " sec" else " clc")
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val sourceName = asmgen.asmVariableName(value)
|
||||
// note: cannot use X register here to store A because it might be used for other arguments
|
||||
|
@ -404,7 +404,7 @@ internal class ProgramAndVarsGen(
|
||||
if(sub.parameters.size==1) {
|
||||
val dt = sub.parameters[0].type
|
||||
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, dt, sub, sub.parameters[0].position, variableAsmName = sub.parameters[0].name)
|
||||
if(dt in ByteDatatypes)
|
||||
if(dt in ByteDatatypesWithBoolean)
|
||||
asmgen.assignRegister(RegisterOrPair.A, target)
|
||||
else
|
||||
asmgen.assignRegister(RegisterOrPair.AY, target)
|
||||
@ -604,7 +604,7 @@ internal class ProgramAndVarsGen(
|
||||
|
||||
private fun uninitializedVariable2asm(variable: StStaticVariable) {
|
||||
when (variable.dt) {
|
||||
DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ?")
|
||||
DataType.BOOL, DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ?")
|
||||
DataType.BYTE -> asmgen.out("${variable.name}\t.char ?")
|
||||
DataType.UWORD -> asmgen.out("${variable.name}\t.word ?")
|
||||
DataType.WORD -> asmgen.out("${variable.name}\t.sint ?")
|
||||
@ -634,6 +634,7 @@ internal class ProgramAndVarsGen(
|
||||
} else 0
|
||||
|
||||
when (variable.dt) {
|
||||
DataType.BOOL -> TODO("bool var to asm")
|
||||
DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
||||
DataType.BYTE -> asmgen.out("${variable.name}\t.char $initialValue")
|
||||
DataType.UWORD -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
||||
@ -658,7 +659,7 @@ internal class ProgramAndVarsGen(
|
||||
|
||||
private fun arrayVariable2asm(varname: String, dt: DataType, value: StArray?, orNumberOfZeros: Int?) {
|
||||
when(dt) {
|
||||
DataType.ARRAY_UB -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_BOOL -> {
|
||||
val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros)
|
||||
if (data.size <= 16)
|
||||
asmgen.out("$varname\t.byte ${data.joinToString()}")
|
||||
@ -763,6 +764,16 @@ internal class ProgramAndVarsGen(
|
||||
private fun makeArrayFillDataUnsigned(dt: DataType, value: StArray?, orNumberOfZeros: Int?): List<String> {
|
||||
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
|
||||
return when (dt) {
|
||||
DataType.ARRAY_BOOL ->
|
||||
// byte array can never contain pointer-to types, so treat values as all integers
|
||||
array.map {
|
||||
if(it.boolean!=null)
|
||||
if(it.boolean==true) "1" else "0"
|
||||
else {
|
||||
val number = it.number!!
|
||||
if(number==0.0) "0" else "1"
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UB ->
|
||||
// byte array can never contain pointer-to types, so treat values as all integers
|
||||
array.map {
|
||||
|
@ -18,8 +18,8 @@ internal class AnyExprAsmGen(
|
||||
) {
|
||||
fun assignAnyExpressionUsingStack(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when(expr.type) {
|
||||
in ByteDatatypes -> {
|
||||
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes)
|
||||
in ByteDatatypesWithBoolean -> {
|
||||
if(expr.left.type in ByteDatatypesWithBoolean && expr.right.type in ByteDatatypesWithBoolean)
|
||||
return assignByteBinExpr(expr, assign)
|
||||
if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||
require(expr.operator in ComparisonOperators)
|
||||
|
@ -14,6 +14,7 @@ internal enum class TargetStorageKind {
|
||||
}
|
||||
|
||||
internal enum class SourceStorageKind {
|
||||
LITERALBOOLEAN,
|
||||
LITERALNUMBER,
|
||||
VARIABLE,
|
||||
ARRAY,
|
||||
@ -133,6 +134,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
val memory: PtMemoryByte? = null,
|
||||
val register: RegisterOrPair? = null,
|
||||
val number: PtNumber? = null,
|
||||
val boolean: PtBool? = null,
|
||||
val expression: PtExpression? = null
|
||||
)
|
||||
{
|
||||
@ -147,6 +149,9 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
val cv = value as? PtNumber
|
||||
if(cv!=null)
|
||||
return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv)
|
||||
val bv = value as? PtBool
|
||||
if(bv!=null)
|
||||
return AsmAssignSource(SourceStorageKind.LITERALBOOLEAN, program, asmgen, DataType.BOOL, boolean = bv)
|
||||
|
||||
return when(value) {
|
||||
// checked above: is PtNumber -> throw AssemblyError("should have been constant value")
|
||||
@ -194,7 +199,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
// allow some signed/unsigned relaxations
|
||||
|
||||
fun withAdjustedDt(newType: DataType) =
|
||||
AsmAssignSource(kind, program, asmgen, newType, variableAsmName, array, memory, register, number, expression)
|
||||
AsmAssignSource(kind, program, asmgen, newType, variableAsmName, array, memory, register, number, boolean, expression)
|
||||
|
||||
if(target.datatype!=datatype) {
|
||||
if(target.datatype in ByteDatatypes && datatype in ByteDatatypes) {
|
||||
|
@ -33,6 +33,16 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
|
||||
fun translateNormalAssignment(assign: AsmAssignment, scope: IPtSubroutine?) {
|
||||
when(assign.source.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> {
|
||||
// simple case: assign a constant number
|
||||
val num = assign.source.boolean!!.asInt()
|
||||
when (assign.target.datatype) {
|
||||
DataType.BOOL, DataType.UBYTE, DataType.BYTE -> assignConstantByte(assign.target, num)
|
||||
DataType.UWORD, DataType.WORD -> assignConstantWord(assign.target, num)
|
||||
DataType.FLOAT -> assignConstantFloat(assign.target, num.toDouble())
|
||||
else -> throw AssemblyError("weird numval type")
|
||||
}
|
||||
}
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
// simple case: assign a constant number
|
||||
val num = assign.source.number!!.number
|
||||
|
@ -18,13 +18,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
val a2 = AsmAssignment(assign.source, assign.target, assign.memsizer, assign.position)
|
||||
assignmentAsmGen.inplaceNegate(a2, false, scope)
|
||||
}
|
||||
"~" -> {
|
||||
"~", "not" -> {
|
||||
val a2 = AsmAssignment(assign.source, assign.target, assign.memsizer, assign.position)
|
||||
assignmentAsmGen.inplaceInvert(a2, scope)
|
||||
}
|
||||
"+" -> { /* is a nop */ }
|
||||
else -> {
|
||||
require(assign.operator in ComparisonOperators || assign.operator.length>=2) { "invalid aug assign operator ${assign.operator}" }
|
||||
augmentedAssignExpr(assign)
|
||||
}
|
||||
}
|
||||
@ -64,11 +63,15 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
|
||||
fun regName(v: AsmAssignSource) = "cx16.${v.register!!.name.lowercase()}"
|
||||
|
||||
if(value.kind==SourceStorageKind.LITERALBOOLEAN)
|
||||
TODO("inplace modification literalboolean")
|
||||
|
||||
when (target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
when (target.datatype) {
|
||||
in ByteDatatypes -> {
|
||||
in ByteDatatypesWithBoolean -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(target.asmVarname, target.datatype, operator, value.boolean!!.asInt())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(target.asmVarname, target.datatype, operator, value.number!!.number.toInt())
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(target.asmVarname, target.datatype, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(target.asmVarname, target.datatype, operator, regName(value))
|
||||
@ -87,6 +90,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
in WordDatatypes -> {
|
||||
val block = target.origAstTarget?.definingBlock()
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationWordWithLiteralval(target.asmVarname, target.datatype, operator, value.boolean!!.asInt(), block)
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(target.asmVarname, target.datatype, operator, value.number!!.number.toInt(), block)
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(target.asmVarname, target.datatype, operator, value.asmVarname, value.datatype, block)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(target.asmVarname, target.datatype, operator, regName(value), value.datatype, block)
|
||||
@ -105,6 +109,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.boolean!!.asInt().toDouble())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.number!!.number)
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(target.asmVarname, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(target.asmVarname, operator, regName(value))
|
||||
@ -129,6 +134,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
is PtNumber -> {
|
||||
val addr = (memory.address as PtNumber).number.toInt()
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(addr.toHex(), DataType.UBYTE, operator, value.boolean!!.asInt())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(addr.toHex(), DataType.UBYTE, operator, value.number!!.number.toInt())
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(addr.toHex(), DataType.UBYTE, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(addr.toHex(), DataType.UBYTE, operator, regName(value))
|
||||
@ -147,6 +153,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
is PtIdentifier -> {
|
||||
val pointer = memory.address as PtIdentifier
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt())
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationBytePointerWithVariable(pointer, operator, regName(value))
|
||||
@ -170,6 +177,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
asmgen.saveRegisterStack(CpuRegister.Y, true)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_in_AY_into_A")
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> {
|
||||
inplacemodificationRegisterAwithVariable(operator, "#${value.boolean!!.asInt()}", false)
|
||||
asmgen.out(" tax")
|
||||
}
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", false)
|
||||
asmgen.out(" tax")
|
||||
@ -231,6 +242,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
when (target.datatype) {
|
||||
in ByteDatatypes -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.boolean!!.asInt())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt())
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value))
|
||||
@ -250,6 +262,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
in WordDatatypes -> {
|
||||
val block = target.origAstTarget?.definingBlock()
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.boolean!!.asInt(), block)
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt(), block)
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, value.asmVarname, value.datatype, block)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, regName(value), value.datatype, block)
|
||||
@ -268,6 +281,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
|
||||
DataType.FLOAT -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.boolean!!.asInt().toDouble())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number)
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value))
|
||||
@ -304,6 +318,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
||||
asmgen.out(" lda ${target.array.variable.name},y")
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> {
|
||||
inplacemodificationRegisterAwithVariable(operator, "#${value.boolean!!.asInt()}", target.datatype in SignedDatatypes)
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||
}
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", target.datatype in SignedDatatypes)
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||
@ -363,6 +381,14 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
val block = target.origAstTarget?.definingBlock()
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> {
|
||||
val number = value.boolean!!.asInt()
|
||||
if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, number, block)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
}
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
val number = value.number!!.number.toInt()
|
||||
if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) {
|
||||
@ -446,6 +472,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
|
||||
// calculate on tempvar
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.boolean!!.asInt().toDouble())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number)
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value))
|
||||
@ -953,7 +980,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
+ lda #1
|
||||
+""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a pointer?
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?
|
||||
"<", "<=", ">", ">=" -> TODO("byte-var-to-pointer comparisons")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
@ -1058,7 +1085,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
+""")
|
||||
asmgen.storeAIntoZpPointerVar(sourceName, false)
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a pointer?:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?:
|
||||
"<", "<=", ">", ">=" -> TODO("byte-litval-to-pointer comparisons")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
@ -2400,7 +2427,7 @@ $shortcutLabel:""")
|
||||
lda #0
|
||||
sta $name+1""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a word var?:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a word var?:
|
||||
"<", "<=", ">", ">=" -> TODO("word-bytevar-to-var comparisons")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
@ -2827,7 +2854,7 @@ $shortcutLabel:""")
|
||||
lda #0
|
||||
sta $name+1""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a word var?:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a word var?:
|
||||
"<", "<=", ">", ">=" -> TODO("word-bytevalue-to-var comparisons")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
@ -2907,7 +2934,7 @@ $shortcutLabel:""")
|
||||
lda #0
|
||||
sta $name+1""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a word var?:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a word var?:
|
||||
"<", "<=", ">", ">=" -> TODO("word-value-to-var comparisons")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
@ -2947,7 +2974,7 @@ $shortcutLabel:""")
|
||||
jsr floats.FDIV
|
||||
""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a float var:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a float var:
|
||||
"==" -> TODO("float-value-to-var comparison ==")
|
||||
"!=" -> TODO("float-value-to-var comparison !=")
|
||||
"<", "<=", ">", ">=" -> TODO("float-value-to-var comparisons")
|
||||
@ -3003,7 +3030,7 @@ $shortcutLabel:""")
|
||||
jsr floats.FDIV
|
||||
""")
|
||||
}
|
||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a float var:
|
||||
// pretty uncommon, who's going to assign a comparison boolean expression to a float var:
|
||||
"==" -> {
|
||||
asmgen.out("""
|
||||
lda #<$name
|
||||
|
@ -1,8 +1,8 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
while not cx16.mouse_pos() should give error
|
||||
|
||||
merge last 2 codegen files from booleans-tryout branch: AssignmentAsmGen, ExpressionGen (everything else was merged)
|
||||
|
||||
ConstantFoldingOptimizer (after merging master):
|
||||
after(numLiteral..) : check that cast to/from BOOL is not done??
|
||||
@ -29,6 +29,7 @@ ok . type error for bool[3] derp = 99 and also for init value [1,0,1]
|
||||
ok . while booleanvar==42 and do..until booleanvar==42 should give type error
|
||||
ok . while not <integervar> should give type error
|
||||
ok . while not <integer functioncall> should give type error
|
||||
ok . while not cx16.mouse_pos() should give condition type error
|
||||
ok . while boolean should produce identical code as while integer!=0
|
||||
ok . while not boolvar -> can we get rid of the cmp? (6502 only?)
|
||||
ok . if someint==0 / ==1 should stil produce good asm same as what it used to be with if not someint/if someint
|
||||
|
Loading…
Reference in New Issue
Block a user