working on doing comparison codegen differently

This commit is contained in:
Irmen de Jong 2023-03-22 20:05:44 +01:00
parent c8b2c8ae50
commit 04832f052a
4 changed files with 142 additions and 502 deletions

View File

@ -368,21 +368,22 @@ internal class AssignmentAsmGen(private val program: PtProgram,
if(oper.type != value.type) if(oper.type != value.type)
throw AssemblyError("rpn node type error, expected ${value.type} got ${oper.type}") throw AssemblyError("rpn node type error, expected ${value.type} got ${oper.type}")
if(oper.operator in ComparisonOperators) { // TODO RPN optimizations for simple cases
assignRPNComparison(assign, value) // if(oper.operator in ComparisonOperators) {
return true // assignRPNComparison(assign, value)
} // return true
// }
if(right is PtExpression) { //
if (simpleEqualityExprRPN(value, oper, right, assign.target)) // if(right is PtExpression) {
return true // if (simpleEqualityExprRPN(value, oper, right, assign.target))
if (simpleLogicalExprRPN(value, oper, right, assign.target)) // return true
return true // if (simpleLogicalExprRPN(value, oper, right, assign.target))
if (simplePlusOrMinusExprRPN(value, oper, right, assign.target)) // return true
return true // if (simplePlusOrMinusExprRPN(value, oper, right, assign.target))
if (simpleBitshiftExprRPN(value, oper, right, assign.target)) // return true
return true // if (simpleBitshiftExprRPN(value, oper, right, assign.target))
} // return true
// }
val asmExtra = asmgen.subroutineExtra(scope) val asmExtra = asmgen.subroutineExtra(scope)
val evalVars = mutableMapOf ( val evalVars = mutableMapOf (
@ -437,30 +438,16 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val resultVarname = evalVarName(it.type, asmExtra.rpnDepth) val resultVarname = evalVarName(it.type, asmExtra.rpnDepth)
asmExtra.rpnDepth++ asmExtra.rpnDepth++
symbolTable.resetCachedFlat() symbolTable.resetCachedFlat()
if(it.operator in ComparisonOperators) { if(leftvar!=resultVarname) {
require(it.type == DataType.UBYTE)
val scopeName = (scope as PtNamedNode).scopedName val scopeName = (scope as PtNamedNode).scopedName
val comparison = PtRpn(DataType.UBYTE, assign.position) val leftVarPt = PtIdentifier("$scopeName.$leftvar", it.leftType, it.position)
comparison.addRpnNode(PtIdentifier("$scopeName.$leftvar", it.leftType, value.position)) leftVarPt.parent=scope
comparison.addRpnNode(PtIdentifier("$scopeName.$rightvar", it.rightType, value.position)) assignExpressionToVariable(leftVarPt, resultVarname, it.type)
comparison.addRpnNode(PtRpnOperator(it.operator, it.type, it.leftType, it.rightType, it.position))
comparison.parent = scope
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UBYTE, expression = comparison)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UBYTE, scope, assign.position, variableAsmName = resultVarname)
val normalAssign = AsmAssignment(src, target, program.memsizer, assign.position)
assignRPNComparison(normalAssign, comparison)
} else {
if(leftvar!=resultVarname) {
val scopeName = (scope as PtNamedNode).scopedName
val leftVarPt = PtIdentifier("$scopeName.$leftvar", it.leftType, it.position)
leftVarPt.parent=scope
assignExpressionToVariable(leftVarPt, resultVarname, it.type)
}
val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, it.rightType, variableAsmName = rightvar)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, it.type, scope, assign.position, variableAsmName = resultVarname)
val augAssign = AsmAugmentedAssignment(src, it.operator+"=", target, program.memsizer, assign.position)
augmentableAsmGen.translate(augAssign, scope)
} }
val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, it.rightType, variableAsmName = rightvar)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, it.type, scope, assign.position, variableAsmName = resultVarname)
val augAssign = AsmAugmentedAssignment(src, it.operator+":=", target, program.memsizer, assign.position)
augmentableAsmGen.translate(augAssign, scope)
} }
is PtExpression -> { is PtExpression -> {
val varname = evalVarName(it.type, asmExtra.rpnDepth) val varname = evalVarName(it.type, asmExtra.rpnDepth)
@ -499,406 +486,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
return true return true
} }
private fun simpleLogicalExprRPN(expr: PtRpn, oper: PtRpnOperator, right: PtExpression, target: AsmAssignTarget): Boolean {
fun simpleLogicalBytesExpr(left: PtExpression, operand: String) {
// both left and right expression operands are simple.
if (right is PtNumber || right is PtIdentifier)
assignLogicalWithSimpleRightOperandByte(target, left, operand, right)
else if (left is PtNumber || left is PtIdentifier)
assignLogicalWithSimpleRightOperandByte(target, right, operand, left)
else {
assignExpressionToRegister(left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
asmgen.restoreRegisterStack(CpuRegister.A, false)
when (operand) {
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
else -> throw AssemblyError("invalid operator")
}
assignRegisterByte(target, CpuRegister.A)
}
}
fun simpleLogicalWordsExpr(left: PtExpression, operand: String) {
// both left and right expression operands are simple.
if (right is PtNumber || right is PtIdentifier)
assignLogicalWithSimpleRightOperandWord(target, left, operand, right)
else if (left is PtNumber || left is PtIdentifier)
assignLogicalWithSimpleRightOperandWord(target, right, operand, left)
else {
assignExpressionToRegister(left, RegisterOrPair.AY, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false)
assignExpressionToVariable(right, "P8ZP_SCRATCH_W1", DataType.UWORD)
when (operand) {
"&", "and" -> asmgen.out(" pla | and P8ZP_SCRATCH_W1+1 | tay | pla | and P8ZP_SCRATCH_W1")
"|", "or" -> asmgen.out(" pla | ora P8ZP_SCRATCH_W1+1 | tay | pla | ora P8ZP_SCRATCH_W1")
"^", "xor" -> asmgen.out(" pla | eor P8ZP_SCRATCH_W1+1 | tay | pla | eor P8ZP_SCRATCH_W1")
else -> throw AssemblyError("invalid operator")
}
assignRegisterpairWord(target, RegisterOrPair.AY)
}
}
if(oper.operator in setOf("&", "|", "^", "and", "or", "xor")) {
if (oper.leftType in ByteDatatypes && right.type in ByteDatatypes) {
if (right.isSimple()) {
val left = expr.truncateLastOperator()
simpleLogicalBytesExpr(left, oper.operator)
return true
}
}
if (oper.leftType in WordDatatypes && right.type in WordDatatypes) {
if (right.isSimple()) {
val left = expr.truncateLastOperator()
simpleLogicalWordsExpr(left, oper.operator)
return true
}
}
}
return false
}
private fun simpleEqualityExprRPN(expr: PtRpn, oper: PtRpnOperator, right: PtExpression, target: AsmAssignTarget): Boolean {
if(oper.operator!="==" && oper.operator!="!=")
return false
// expression datatype is BOOL (ubyte) but operands can be anything
if(oper.leftType in ByteDatatypes && oper.rightType in ByteDatatypes && right.isSimple()) { // TODO && left.isSimple??
val left = expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
asmgen.restoreRegisterStack(CpuRegister.A, false)
if(oper.operator=="==") {
asmgen.out("""
cmp P8ZP_SCRATCH_B1
bne +
lda #1
bne ++
+ lda #0
+""")
} else {
asmgen.out("""
cmp P8ZP_SCRATCH_B1
beq +
lda #1
bne ++
+ lda #0
+""")
}
assignRegisterByte(target, CpuRegister.A)
return true
} else if(oper.leftType in WordDatatypes && oper.rightType in WordDatatypes && right.isSimple()) { // TODO && left.isSimple?
val left = expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false)
assignExpressionToVariable(right, "P8ZP_SCRATCH_W1", DataType.UWORD)
asmgen.restoreRegisterStack(CpuRegister.Y, false)
asmgen.restoreRegisterStack(CpuRegister.A, false)
if(oper.operator=="==") {
asmgen.out("""
cmp P8ZP_SCRATCH_W1
bne +
cpy P8ZP_SCRATCH_W1+1
bne +
lda #1
bne ++
+ lda #0
+""")
} else {
asmgen.out("""
cmp P8ZP_SCRATCH_W1
bne +
cpy P8ZP_SCRATCH_W1+1
bne +
lda #0
bne ++
+ lda #1
+""")
}
assignRegisterByte(target, CpuRegister.A)
return true
}
return false
}
private fun simplePlusOrMinusExprRPN(expr: PtRpn, oper: PtRpnOperator, right: PtExpression, target: AsmAssignTarget): Boolean {
if(oper.operator!="+" && oper.operator!="!-")
return false
val dt = target.datatype
if(dt in ByteDatatypes) {
when (right) {
is PtIdentifier -> {
val left=expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
val symname = asmgen.asmVariableName(right)
if(oper.operator=="+")
asmgen.out(" clc | adc $symname")
else
asmgen.out(" sec | sbc $symname")
assignRegisterByte(target, CpuRegister.A)
return true
}
is PtNumber -> {
val left=expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
if(oper.operator=="+")
asmgen.out(" clc | adc #${right.number.toHex()}")
else
asmgen.out(" sec | sbc #${right.number.toHex()}")
assignRegisterByte(target, CpuRegister.A)
return true
}
else -> return false
}
} else if(dt in WordDatatypes) {
when (right) {
is PtAddressOf -> {
val left=expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
val symbol = asmgen.asmVariableName(right.identifier)
if(oper.operator=="+")
asmgen.out("""
clc
adc #<$symbol
pha
tya
adc #>$symbol
tay
pla""")
else
asmgen.out("""
sec
sbc #<$symbol
pha
tya
sbc #>$symbol
tay
pla""")
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
is PtIdentifier -> {
val left=expr.truncateLastOperator()
val symname = asmgen.asmVariableName(right)
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(oper.operator=="+")
asmgen.out("""
clc
adc $symname
pha
tya
adc $symname+1
tay
pla""")
else
asmgen.out("""
sec
sbc $symname
pha
tya
sbc $symname+1
tay
pla""")
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
is PtNumber -> {
val left=expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(oper.operator=="+") {
asmgen.out("""
clc
adc #<${right.number.toHex()}
pha
tya
adc #>${right.number.toHex()}
tay
pla""")
} else if(oper.operator=="-") {
asmgen.out("""
sec
sbc #<${right.number.toHex()}
pha
tya
sbc #>${right.number.toHex()}
tay
pla""")
}
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
is PtTypeCast -> {
val castedValue = right.value
if(right.type in WordDatatypes && castedValue.type in ByteDatatypes) {
if(castedValue is PtIdentifier) {
val castedSymname = asmgen.asmVariableName(castedValue)
val left=expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(oper.operator=="+")
asmgen.out("""
clc
adc $castedSymname
bcc +
iny
+""")
else
asmgen.out("""
sec
sbc $castedSymname
bcs +
dey
+""")
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
}
}
else -> return false
}
}
return false
}
private fun simpleBitshiftExprRPN(expr: PtRpn, oper: PtRpnOperator, right: PtExpression, target: AsmAssignTarget): Boolean {
if(oper.operator!="<<" && oper.operator!=">>")
return false
val shifts = right.asConstInteger()
if(shifts==null || shifts !in 0..7 || oper.leftType !in IntegerDatatypes)
return false
if(oper.leftType in ByteDatatypes) {
val signed = oper.leftType == DataType.BYTE
val left = expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.A, signed)
if(oper.operator=="<<") {
repeat(shifts) {
asmgen.out(" asl a")
}
} else {
if(signed && shifts>0) {
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
} else {
repeat(shifts) {
asmgen.out(" lsr a")
}
}
}
assignRegisterByte(target, CpuRegister.A)
return true
} else if(oper.leftType in WordDatatypes) {
val signed = oper.leftType == DataType.WORD
if(oper.operator=="<<") {
val left = expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, signed)
if(shifts>0) {
asmgen.out(" sty P8ZP_SCRATCH_B1")
repeat(shifts) {
asmgen.out(" asl a | rol P8ZP_SCRATCH_B1")
}
asmgen.out(" ldy P8ZP_SCRATCH_B1")
}
} else {
if(signed) {
return false // TODO("shift AY >> $shifts signed")
} else {
val left = expr.truncateLastOperator()
assignExpressionToRegister(left, RegisterOrPair.AY, false)
if(shifts>0) {
asmgen.out(" sty P8ZP_SCRATCH_B1")
repeat(shifts) {
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a")
}
asmgen.out(" ldy P8ZP_SCRATCH_B1")
}
}
}
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
return false
}
private fun assignRPNComparison(assign: AsmAssignment, comparison: PtRpn) {
val (leftRpn, oper, right) = comparison.finalOperation()
val constRight = (right as PtExpression).asConstInteger()
if(constRight == 0) {
if(oper.operator == "==" || oper.operator == "!=") {
when(assign.target.datatype) {
in ByteDatatypes -> {
if(attemptAssignToByteCompareZeroRPN(comparison, assign))
return
}
in WordDatatypes -> {
assignConstantWord(assign.target, 0)
if(attemptAssignToByteCompareZeroRPN(comparison, assign))
return
}
else -> {
// do nothing, this is handled by a type cast.
}
}
}
}
val left: PtExpression = if(comparison.children.size>3 || leftRpn !is PtExpression)
comparison.truncateLastOperator()
else
leftRpn
val leftNum = left as? PtNumber
val rightNum = right as? PtNumber
val jumpIfFalseLabel = asmgen.makeLabel("cmp")
if(assign.target.isSameAs(left)) {
// In-place comparison Target = Target <compare> Right
val targetDt = assign.target.datatype
val tempVar = asmgen.getTempVarName(assign.target.datatype)
val tempTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, targetDt, comparison.definingISub(), comparison.position, variableAsmName = tempVar)
when (assign.target.datatype) {
in ByteDatatypes -> assignConstantByte(tempTarget, 0)
in WordDatatypes -> assignConstantWord(tempTarget, 0)
DataType.FLOAT -> assignConstantFloat(tempTarget, 0.0)
else -> throw AssemblyError("invalid dt")
}
asmgen.testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftNum, rightNum)
when (assign.target.datatype) {
in ByteDatatypes -> assignConstantByte(tempTarget, 1)
in WordDatatypes -> assignConstantWord(tempTarget, 1)
DataType.FLOAT -> assignConstantFloat(tempTarget, 1.0)
else -> throw AssemblyError("invalid dt")
}
asmgen.out(jumpIfFalseLabel)
val tempLeft = PtIdentifier(tempVar, targetDt, comparison.position)
tempLeft.parent=comparison
asmgen.assignExpressionTo(tempLeft, assign.target)
} else {
// Normal comparison Target = Left <compare> Right
when (assign.target.datatype) {
in ByteDatatypes -> assignConstantByte(assign.target, 0)
in WordDatatypes -> assignConstantWord(assign.target, 0)
DataType.FLOAT -> assignConstantFloat(assign.target, 0.0)
else -> throw AssemblyError("invalid dt")
}
asmgen.testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftNum, rightNum)
when (assign.target.datatype) {
in ByteDatatypes -> assignConstantByte(assign.target, 1)
in WordDatatypes -> assignConstantWord(assign.target, 1)
DataType.FLOAT -> assignConstantFloat(assign.target, 1.0)
else -> throw AssemblyError("invalid dt")
}
asmgen.out(jumpIfFalseLabel)
}
}
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
if(expr.operator in ComparisonOperators) { if(expr.operator in ComparisonOperators) {
if(expr.right.asConstInteger() == 0) { if(expr.right.asConstInteger() == 0) {

View File

@ -35,16 +35,22 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun augmentedAssignExpr(assign: AsmAugmentedAssignment) { private fun augmentedAssignExpr(assign: AsmAugmentedAssignment) {
val srcValue = assign.source.toAstExpression(assign.target.scope as PtNamedNode) val srcValue = assign.source.toAstExpression(assign.target.scope as PtNamedNode)
when (assign.operator) { when (assign.operator) {
"+=" -> inplaceModification(assign.target, "+", srcValue) "+=", "+:=" -> inplaceModification(assign.target, "+", srcValue)
"-=" -> inplaceModification(assign.target, "-", srcValue) "-=", "-:=" -> inplaceModification(assign.target, "-", srcValue)
"*=" -> inplaceModification(assign.target, "*", srcValue) "*=", "*:=" -> inplaceModification(assign.target, "*", srcValue)
"/=" -> inplaceModification(assign.target, "/", srcValue) "/=", "/:=" -> inplaceModification(assign.target, "/", srcValue)
"|=" -> inplaceModification(assign.target, "|", srcValue) "|=", "|:=" -> inplaceModification(assign.target, "|", srcValue)
"&=" -> inplaceModification(assign.target, "&", srcValue) "&=", "&:=" -> inplaceModification(assign.target, "&", srcValue)
"^=" -> inplaceModification(assign.target, "^", srcValue) "^=", "^:=" -> inplaceModification(assign.target, "^", srcValue)
"<<=" -> inplaceModification(assign.target, "<<", srcValue) "<<=", "<<:=" -> inplaceModification(assign.target, "<<", srcValue)
">>=" -> inplaceModification(assign.target, ">>", srcValue) ">>=", ">>:=" -> inplaceModification(assign.target, ">>", srcValue)
"%=" -> inplaceModification(assign.target, "%", srcValue) "%=", "%:=" -> inplaceModification(assign.target, "%", srcValue)
"==:=" -> inplaceModification(assign.target, "==", srcValue)
"!=:=" -> inplaceModification(assign.target, "!=", srcValue)
"<:=" -> inplaceModification(assign.target, "<", srcValue)
">:=" -> inplaceModification(assign.target, ">", srcValue)
"<=:=" -> inplaceModification(assign.target, "<=", srcValue)
">=:=" -> inplaceModification(assign.target, ">=", srcValue)
else -> throw AssemblyError("invalid augmented assign operator ${assign.operator}") else -> throw AssemblyError("invalid augmented assign operator ${assign.operator}")
} }
} }
@ -333,6 +339,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"&" -> asmgen.out(" and P8ZP_SCRATCH_B1") "&" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"|" -> asmgen.out(" ora P8ZP_SCRATCH_B1") "|" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
"^" -> asmgen.out(" eor P8ZP_SCRATCH_B1") "^" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
"==" -> TODO("byte-value-to-pointer ==")
"!=" -> TODO("byte-value-to-pointer !=")
"<" -> TODO("byte-value-to-pointer <")
"<=" -> TODO("byte-value-to-pointer <=")
">" -> TODO("byte-value-to-pointer >")
">=" -> TODO("byte-value-to-pointer >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
asmgen.storeAIntoZpPointerVar(sourceName) asmgen.storeAIntoZpPointerVar(sourceName)
@ -369,6 +381,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"&" -> asmgen.out(" and $otherName") "&" -> asmgen.out(" and $otherName")
"|" -> asmgen.out(" ora $otherName") "|" -> asmgen.out(" ora $otherName")
"^" -> asmgen.out(" eor $otherName") "^" -> asmgen.out(" eor $otherName")
"==" -> TODO("byte-var-to-pointer ==")
"!=" -> TODO("byte-var-to-pointer !=")
"<" -> TODO("byte-var-to-pointer <")
"<=" -> TODO("byte-var-to-pointer <=")
">" -> TODO("byte-var-to-pointer >")
">=" -> TODO("byte-var-to-pointer >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
asmgen.storeAIntoZpPointerVar(sourceName) asmgen.storeAIntoZpPointerVar(sourceName)
@ -437,6 +455,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" eor #$value") asmgen.out(" eor #$value")
asmgen.storeAIntoZpPointerVar(sourceName) asmgen.storeAIntoZpPointerVar(sourceName)
} }
"==" -> TODO("byte-litval-to-pointer ==")
"!=" -> TODO("byte-litval-to-pointer !=")
"<" -> TODO("byte-litval-to-pointer <")
"<=" -> TODO("byte-litval-to-pointer <=")
">" -> TODO("byte-litval-to-pointer >")
">=" -> TODO("byte-litval-to-pointer >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -531,6 +555,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0 + lda #0
+ sta $name""") + sta $name""")
} }
"<" -> TODO("byte-value-to-var <")
"<=" -> TODO("byte-value-to-var <=")
">" -> TODO("byte-value-to-var >")
">=" -> TODO("byte-value-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -607,6 +635,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0 + lda #0
+ sta $name""") + sta $name""")
} }
"<" -> TODO("byte-var-to-var <")
"<=" -> TODO("byte-var-to-var <=")
">" -> TODO("byte-var-to-var >")
">=" -> TODO("byte-var-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -697,6 +729,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0 + lda #0
+ sta $name""") + sta $name""")
} }
"<" -> TODO("byte-litval-to-var <")
"<=" -> TODO("byte-litval-to-var <=")
">" -> TODO("byte-litval-to-var >")
">=" -> TODO("byte-litval-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -732,6 +768,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" eor $name | sta $name") asmgen.out(" eor $name | sta $name")
} }
// TODO: tuned code for more operators // TODO: tuned code for more operators
"==" -> TODO("byte-memread-to-var ==")
"!=" -> TODO("byte-memread-to-var !=")
"<" -> TODO("byte-memread-to-var <")
"<=" -> TODO("byte-memread-to-var <=")
">" -> TODO("byte-memread-to-var >")
">=" -> TODO("byte-memread-to-var >=")
else -> { else -> {
inplaceModification_byte_value_to_variable(name, dt, operator, memread) inplaceModification_byte_value_to_variable(name, dt, operator, memread)
} }
@ -781,6 +823,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" eor $name | sta $name") asmgen.out(" eor $name | sta $name")
} }
// TODO: tuned code for more operators // TODO: tuned code for more operators
"==" -> TODO("word-memread-to-var ==")
"!=" -> TODO("word-memread-to-var !=")
"<" -> TODO("word-memread-to-var <")
"<=" -> TODO("word-memread-to-var <=")
">" -> TODO("word-memread-to-var >")
">=" -> TODO("word-memread-to-var >=")
else -> { else -> {
inplaceModification_word_value_to_variable(name, dt, operator, memread) inplaceModification_word_value_to_variable(name, dt, operator, memread)
} }
@ -1045,6 +1093,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
else -> asmgen.out(" lda $name | eor #<$value | sta $name | lda $name+1 | eor #>$value | sta $name+1") else -> asmgen.out(" lda $name | eor #<$value | sta $name | lda $name+1 | eor #>$value | sta $name+1")
} }
} }
"==" -> TODO("word-litval-to-var ==")
"!=" -> TODO("word-litval-to-var !=")
"<" -> TODO("word-litval-to-var <")
"<=" -> TODO("word-litval-to-var <=")
">" -> TODO("word-litval-to-var >")
">=" -> TODO("word-litval-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -1211,6 +1265,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
} }
"|" -> asmgen.out(" lda $otherName | ora $name | sta $name") "|" -> asmgen.out(" lda $otherName | ora $name | sta $name")
"^" -> asmgen.out(" lda $otherName | eor $name | sta $name") "^" -> asmgen.out(" lda $otherName | eor $name | sta $name")
"==" -> TODO("word-bytevar-to-var ==")
"!=" -> TODO("word-bytevar-to-var !=")
"<" -> TODO("word-bytevar-to-var <")
"<=" -> TODO("word-bytevar-to-var <=")
">" -> TODO("word-bytevar-to-var >")
">=" -> TODO("word-bytevar-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -1285,6 +1345,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1") "&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1") "|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
"^" -> asmgen.out(" lda $name | eor $otherName | sta $name | lda $name+1 | eor $otherName+1 | sta $name+1") "^" -> asmgen.out(" lda $name | eor $otherName | sta $name | lda $name+1 | eor $otherName+1 | sta $name+1")
"==" -> TODO("word-var-to-var ==")
"!=" -> TODO("word-var-to-var !=")
"<" -> TODO("word-var-to-var <")
"<=" -> TODO("word-var-to-var <=")
">" -> TODO("word-var-to-var >")
">=" -> TODO("word-var-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -1469,6 +1535,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(value, RegisterOrPair.A) asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
asmgen.out(" eor $name | sta $name") asmgen.out(" eor $name | sta $name")
} }
"==" -> TODO("word-bytevalue-to-var ==")
"!=" -> TODO("word-bytevalue-to-var !=")
"<" -> TODO("word-bytevalue-to-var <")
"<=" -> TODO("word-bytevalue-to-var <=")
">" -> TODO("word-bytevalue-to-var >")
">=" -> TODO("word-bytevalue-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -1518,6 +1590,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY) asmgen.assignExpressionToRegister(value, RegisterOrPair.AY)
asmgen.out(" eor $name | sta $name | tya | eor $name+1 | sta $name+1") asmgen.out(" eor $name | sta $name | tya | eor $name+1 | sta $name+1")
} }
"==" -> TODO("word-value-to-var ==")
"!=" -> TODO("word-value-to-var !=")
"<" -> TODO("word-value-to-var <")
"<=" -> TODO("word-value-to-var <=")
">" -> TODO("word-value-to-var >")
">=" -> TODO("word-value-to-var >=")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -1557,6 +1635,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
jsr floats.FDIV jsr floats.FDIV
""") """)
} }
"==" -> TODO("float-value-to-var ==")
"!=" -> TODO("float-value-to-var !=")
"<" -> TODO("float-value-to-var <")
"<=" -> TODO("float-value-to-var <=")
">" -> TODO("float-value-to-var >")
">=" -> TODO("float-value-to-var >=")
else -> throw AssemblyError("invalid operator for in-place float modification $operator") else -> throw AssemblyError("invalid operator for in-place float modification $operator")
} }
asmgen.out(""" asmgen.out("""
@ -1615,6 +1699,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
jsr floats.FDIV jsr floats.FDIV
""") """)
} }
"==" -> TODO("float-var-to-var ==")
"!=" -> TODO("float-var-to-var !=")
"<" -> TODO("float-var-to-var <")
"<=" -> TODO("float-var-to-var <=")
">" -> TODO("float-var-to-var >")
">=" -> TODO("float-var-to-var >=")
else -> throw AssemblyError("invalid operator for in-place float modification $operator") else -> throw AssemblyError("invalid operator for in-place float modification $operator")
} }
// store Fac1 back into memory // store Fac1 back into memory
@ -1677,6 +1767,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
jsr floats.FDIV jsr floats.FDIV
""") """)
} }
"==" -> TODO("float-litval-to-var ==")
"!=" -> TODO("float-litval-to-var !=")
"<" -> TODO("float-litval-to-var <")
"<=" -> TODO("float-litval-to-var <=")
">" -> TODO("float-litval-to-var >")
">=" -> TODO("float-litval-to-var >=")
else -> throw AssemblyError("invalid operator for in-place float modification $operator") else -> throw AssemblyError("invalid operator for in-place float modification $operator")
} }
// store Fac1 back into memory // store Fac1 back into memory

View File

@ -6,9 +6,11 @@ import prog8.ast.Program
import prog8.ast.base.AstException import prog8.ast.base.AstException
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.expressions.NumericLiteral import prog8.ast.expressions.NumericLiteral
import prog8.ast.printProgram
import prog8.ast.statements.Directive import prog8.ast.statements.Directive
import prog8.code.SymbolTableMaker import prog8.code.SymbolTableMaker
import prog8.code.ast.PtProgram import prog8.code.ast.PtProgram
import prog8.code.ast.printAst
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.* import prog8.code.target.*
import prog8.codegen.vm.VmCodeGen import prog8.codegen.vm.VmCodeGen
@ -117,10 +119,10 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
args.errors.report() args.errors.report()
val intermediateAst = IntermediateAstMaker(program, compilationOptions).transform() val intermediateAst = IntermediateAstMaker(program, compilationOptions).transform()
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************") println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
// printProgram(program) printProgram(program)
// println("*********** AST RIGHT BEFORE ASM GENERATION *************") println("*********** AST RIGHT BEFORE ASM GENERATION *************")
// printAst(intermediateAst, true, ::println) printAst(intermediateAst, true, ::println)
if(!createAssemblyAndAssemble(intermediateAst, args.errors, compilationOptions)) { if(!createAssemblyAndAssemble(intermediateAst, args.errors, compilationOptions)) {
System.err.println("Error in codegeneration or assembler") System.err.println("Error in codegeneration or assembler")

View File

@ -1,54 +1,9 @@
%import textio
%import floats
%zeropage basicsafe
main { main {
const uword width = 256 sub start() {
const uword height = 240 ubyte x
const ubyte max_iter = 16 ; 32 actually looks pretty nice but takes longer ubyte y
if x<y
sub start() { x++
void cx16.screen_mode($80, false) ;x = x+(x<y)+1
cx16.r0=0
cx16.FB_init()
mandel()
}
sub mandel() {
const float XL=-2.200
const float XU=0.800
const float YL=-1.300
const float YU=1.300
float dx = (XU-XL)/width
float dy = (YU-YL)/height
ubyte pixelx
ubyte pixely
for pixely in 0 to height-1 {
float yy = YL+dy*(pixely as float)
cx16.FB_cursor_position(0, pixely)
for pixelx in 0 to width-1 {
float xx = XL+dx*(pixelx as float)
float xsquared = 0.0
float ysquared = 0.0
float x = 0.0
float y = 0.0
ubyte iter = 0
while xsquared+ysquared<4.0 {
y = x*y*2.0 + yy
x = xsquared - ysquared + xx
xsquared = x*x
ysquared = y*y
iter++
if iter>16
break
}
cx16.FB_set_pixel(iter)
}
}
} }
} }