mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
working on doing comparison codegen differently
This commit is contained in:
parent
c8b2c8ae50
commit
04832f052a
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user