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)
throw AssemblyError("rpn node type error, expected ${value.type} got ${oper.type}")
if(oper.operator in ComparisonOperators) {
assignRPNComparison(assign, value)
return true
}
if(right is PtExpression) {
if (simpleEqualityExprRPN(value, oper, right, assign.target))
return true
if (simpleLogicalExprRPN(value, oper, right, assign.target))
return true
if (simplePlusOrMinusExprRPN(value, oper, right, assign.target))
return true
if (simpleBitshiftExprRPN(value, oper, right, assign.target))
return true
}
// TODO RPN optimizations for simple cases
// if(oper.operator in ComparisonOperators) {
// assignRPNComparison(assign, value)
// return true
// }
//
// if(right is PtExpression) {
// if (simpleEqualityExprRPN(value, oper, right, assign.target))
// return true
// if (simpleLogicalExprRPN(value, oper, right, assign.target))
// return true
// if (simplePlusOrMinusExprRPN(value, oper, right, assign.target))
// return true
// if (simpleBitshiftExprRPN(value, oper, right, assign.target))
// return true
// }
val asmExtra = asmgen.subroutineExtra(scope)
val evalVars = mutableMapOf (
@ -437,30 +438,16 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val resultVarname = evalVarName(it.type, asmExtra.rpnDepth)
asmExtra.rpnDepth++
symbolTable.resetCachedFlat()
if(it.operator in ComparisonOperators) {
require(it.type == DataType.UBYTE)
if(leftvar!=resultVarname) {
val scopeName = (scope as PtNamedNode).scopedName
val comparison = PtRpn(DataType.UBYTE, assign.position)
comparison.addRpnNode(PtIdentifier("$scopeName.$leftvar", it.leftType, value.position))
comparison.addRpnNode(PtIdentifier("$scopeName.$rightvar", it.rightType, value.position))
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 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)
}
is PtExpression -> {
val varname = evalVarName(it.type, asmExtra.rpnDepth)
@ -499,406 +486,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
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 {
if(expr.operator in ComparisonOperators) {
if(expr.right.asConstInteger() == 0) {

View File

@ -35,16 +35,22 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun augmentedAssignExpr(assign: AsmAugmentedAssignment) {
val srcValue = assign.source.toAstExpression(assign.target.scope as PtNamedNode)
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}")
}
}
@ -333,6 +339,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"&" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"|" -> asmgen.out(" ora 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")
}
asmgen.storeAIntoZpPointerVar(sourceName)
@ -369,6 +381,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"&" -> asmgen.out(" and $otherName")
"|" -> asmgen.out(" ora $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")
}
asmgen.storeAIntoZpPointerVar(sourceName)
@ -437,6 +455,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" eor #$value")
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")
}
}
@ -531,6 +555,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0
+ 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")
}
}
@ -607,6 +635,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0
+ 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")
}
}
@ -697,6 +729,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+ lda #0
+ 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")
}
}
@ -732,6 +768,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" eor $name | sta $name")
}
// 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 -> {
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")
}
// 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 -> {
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")
}
}
"==" -> 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")
}
}
@ -1211,6 +1265,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
"|" -> asmgen.out(" lda $otherName | ora $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")
}
}
@ -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 | 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")
"==" -> 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")
}
}
@ -1469,6 +1535,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
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")
}
}
@ -1518,6 +1590,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY)
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")
}
}
@ -1557,6 +1635,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
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")
}
asmgen.out("""
@ -1615,6 +1699,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
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")
}
// store Fac1 back into memory
@ -1677,6 +1767,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
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")
}
// store Fac1 back into memory

View File

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

View File

@ -1,54 +1,9 @@
%import textio
%import floats
%zeropage basicsafe
main {
const uword width = 256
const uword height = 240
const ubyte max_iter = 16 ; 32 actually looks pretty nice but takes longer
sub start() {
void cx16.screen_mode($80, false)
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)
}
}
sub start() {
ubyte x
ubyte y
if x<y
x++
;x = x+(x<y)+1
}
}