mirror of
https://github.com/irmen/prog8.git
synced 2025-02-20 18:29:06 +00:00
tweak
This commit is contained in:
parent
80113f9208
commit
59f8b91e25
@ -1 +1 @@
|
|||||||
1.52
|
1.53-dev
|
||||||
|
@ -21,37 +21,39 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
is NumericLiteralValue -> translateExpression(expression)
|
is NumericLiteralValue -> translateExpression(expression)
|
||||||
is RegisterExpr -> translateExpression(expression)
|
is RegisterExpr -> translateExpression(expression)
|
||||||
is IdentifierReference -> translateExpression(expression)
|
is IdentifierReference -> translateExpression(expression)
|
||||||
is FunctionCall -> {
|
is FunctionCall -> translateExpression(expression)
|
||||||
val functionName = expression.target.nameInSource.last()
|
|
||||||
val builtinFunc = BuiltinFunctions[functionName]
|
|
||||||
if(builtinFunc!=null) {
|
|
||||||
asmgen.translateFunctioncallExpression(expression, builtinFunc)
|
|
||||||
} else {
|
|
||||||
asmgen.translateFunctionCall(expression)
|
|
||||||
val sub = expression.target.targetSubroutine(program.namespace)!!
|
|
||||||
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
|
|
||||||
for((_, reg) in returns) {
|
|
||||||
if(!reg.stack) {
|
|
||||||
// result value in cpu or status registers, put it on the stack
|
|
||||||
if(reg.registerOrPair!=null) {
|
|
||||||
when(reg.registerOrPair) {
|
|
||||||
RegisterOrPair.A -> asmgen.out(" sta ${MachineDefinition.ESTACK_LO_HEX},x | dex")
|
|
||||||
RegisterOrPair.Y -> asmgen.out(" tya | sta ${MachineDefinition.ESTACK_LO_HEX},x | dex")
|
|
||||||
RegisterOrPair.AY -> asmgen.out(" sta ${MachineDefinition.ESTACK_LO_HEX},x | tya | sta ${MachineDefinition.ESTACK_HI_HEX},x | dex")
|
|
||||||
RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't push X register - use a variable")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// return value from a statusregister is not put on the stack, it should be acted on via a conditional branch such as if_cc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ArrayLiteralValue, is StringLiteralValue -> TODO("string/array/struct assignment?")
|
is ArrayLiteralValue, is StringLiteralValue -> TODO("string/array/struct assignment?")
|
||||||
is StructLiteralValue -> throw AssemblyError("struct literal value assignment should have been flattened")
|
is StructLiteralValue -> throw AssemblyError("struct literal value assignment should have been flattened")
|
||||||
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values")
|
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun translateExpression(expression: FunctionCall) {
|
||||||
|
val functionName = expression.target.nameInSource.last()
|
||||||
|
val builtinFunc = BuiltinFunctions[functionName]
|
||||||
|
if (builtinFunc != null) {
|
||||||
|
asmgen.translateFunctioncallExpression(expression, builtinFunc)
|
||||||
|
} else {
|
||||||
|
asmgen.translateFunctionCall(expression)
|
||||||
|
val sub = expression.target.targetSubroutine(program.namespace)!!
|
||||||
|
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
|
||||||
|
for ((_, reg) in returns) {
|
||||||
|
if (!reg.stack) {
|
||||||
|
// result value in cpu or status registers, put it on the stack
|
||||||
|
if (reg.registerOrPair != null) {
|
||||||
|
when (reg.registerOrPair) {
|
||||||
|
RegisterOrPair.A -> asmgen.out(" sta ${MachineDefinition.ESTACK_LO_HEX},x | dex")
|
||||||
|
RegisterOrPair.Y -> asmgen.out(" tya | sta ${MachineDefinition.ESTACK_LO_HEX},x | dex")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" sta ${MachineDefinition.ESTACK_LO_HEX},x | tya | sta ${MachineDefinition.ESTACK_HI_HEX},x | dex")
|
||||||
|
RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't push X register - use a variable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return value from a statusregister is not put on the stack, it should be acted on via a conditional branch such as if_cc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun translateExpression(expr: TypecastExpression) {
|
private fun translateExpression(expr: TypecastExpression) {
|
||||||
translateExpression(expr.expression)
|
translateExpression(expr.expression)
|
||||||
when(expr.expression.inferType(program).typeOrElse(DataType.STRUCT)) {
|
when(expr.expression.inferType(program).typeOrElse(DataType.STRUCT)) {
|
||||||
@ -175,7 +177,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
|
|
||||||
private val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)
|
private val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)
|
||||||
private val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40)
|
private val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40)
|
||||||
private val powerOfTwos = setOf(0,1,2,4,8,16,32,64,128,256)
|
private val powersOfTwo = setOf(0,1,2,4,8,16,32,64,128,256)
|
||||||
|
|
||||||
private fun translateExpression(expr: BinaryExpression) {
|
private fun translateExpression(expr: BinaryExpression) {
|
||||||
val leftIDt = expr.left.inferType(program)
|
val leftIDt = expr.left.inferType(program)
|
||||||
@ -215,7 +217,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
if(value!=null) {
|
if(value!=null) {
|
||||||
if(rightDt in IntegerDatatypes) {
|
if(rightDt in IntegerDatatypes) {
|
||||||
val amount = value.number.toInt()
|
val amount = value.number.toInt()
|
||||||
if(amount in powerOfTwos)
|
if(amount in powersOfTwo)
|
||||||
printWarning("${expr.right.position} multiplication by power of 2 should have been optimized into a left shift instruction: $amount")
|
printWarning("${expr.right.position} multiplication by power of 2 should have been optimized into a left shift instruction: $amount")
|
||||||
when(rightDt) {
|
when(rightDt) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
@ -312,7 +314,6 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun translatePushFromArray(arrayExpr: ArrayIndexedExpression) {
|
private fun translatePushFromArray(arrayExpr: ArrayIndexedExpression) {
|
||||||
// assume *reading* from an array
|
// assume *reading* from an array
|
||||||
val index = arrayExpr.arrayspec.index
|
val index = arrayExpr.arrayspec.index
|
||||||
|
@ -608,8 +608,8 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val powersOfTwo = (1 .. 16).map { (2.0).pow(it) }
|
private val powersOfTwo = (1 .. 16).map { (2.0).pow(it) }.toSet()
|
||||||
private val negativePowersOfTwo = powersOfTwo.map { -it }
|
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
|
||||||
|
|
||||||
private fun optimizeDivision(expr: BinaryExpression, leftVal: NumericLiteralValue?, rightVal: NumericLiteralValue?): Expression {
|
private fun optimizeDivision(expr: BinaryExpression, leftVal: NumericLiteralValue?, rightVal: NumericLiteralValue?): Expression {
|
||||||
if(leftVal==null && rightVal==null)
|
if(leftVal==null && rightVal==null)
|
||||||
@ -712,7 +712,7 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
|
|||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.left
|
return expr.left
|
||||||
}
|
}
|
||||||
2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 2048.0, 4096.0, 8192.0, 16384.0, 32768.0, 65536.0 -> {
|
in powersOfTwo -> {
|
||||||
if(leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) {
|
if(leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) {
|
||||||
// times a power of two => shift left
|
// times a power of two => shift left
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -720,7 +720,7 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
|
|||||||
return BinaryExpression(expr.left, "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
return BinaryExpression(expr.left, "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-2.0, -4.0, -8.0, -16.0, -32.0, -64.0, -128.0, -256.0, -512.0, -1024.0, -2048.0, -4096.0, -8192.0, -16384.0, -32768.0, -65536.0 -> {
|
in negativePowersOfTwo -> {
|
||||||
if(leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) {
|
if(leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) {
|
||||||
// times a negative power of two => negate, then shift left
|
// times a negative power of two => negate, then shift left
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
%import c64lib
|
%import c64lib
|
||||||
%import c64utils
|
%import c64utils
|
||||||
|
|
||||||
; TODO: some optimizer breaks this.. runs fine without optimization
|
|
||||||
|
|
||||||
spritedata $2000 {
|
spritedata $2000 {
|
||||||
; this memory block contains the sprite data
|
; this memory block contains the sprite data
|
||||||
; it must start on an address aligned to 64 bytes.
|
; it must start on an address aligned to 64 bytes.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
|
|
||||||
; TODO complete codegeneration for all lines in this
|
; TODO complete asm code generation for all lines in this
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user