mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
optimization in + or - assignment to word array
This commit is contained in:
parent
c36afd872e
commit
77fa2e2722
@ -996,6 +996,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private fun assignOptimizedComparisonBytes(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
val signed = expr.left.type == DataType.BYTE || expr.right.type == DataType.BYTE
|
||||
|
||||
// TODO no need to use a temporary variable if the right expression is a literal number or a variable name (or register name)
|
||||
|
||||
when(expr.operator) {
|
||||
"==" -> {
|
||||
asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1")
|
||||
|
@ -320,44 +320,69 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
||||
return
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y)
|
||||
if(target.array.splitWords) {
|
||||
asmgen.out(" lda ${target.array.variable.name}_lsb,y | sta P8ZP_SCRATCH_W1")
|
||||
asmgen.out(" lda ${target.array.variable.name}_msb,y | sta P8ZP_SCRATCH_W1+1")
|
||||
} else {
|
||||
asmgen.out(" lda ${target.array.variable.name},y | sta P8ZP_SCRATCH_W1")
|
||||
asmgen.out(" lda ${target.array.variable.name}+1,y | sta P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
||||
if(target.array.splitWords) {
|
||||
asmgen.out(" lda ${target.array.variable.name}_lsb,y")
|
||||
asmgen.out(" ldx ${target.array.variable.name}_msb,y")
|
||||
} else {
|
||||
asmgen.out(" lda ${target.array.variable.name},y")
|
||||
asmgen.out(" ldx ${target.array.variable.name}+1,y")
|
||||
}
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
// TODO optimize the stuff below to not use temp variables??
|
||||
inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, value.number!!.number.toInt())
|
||||
val number = value.number!!.number.toInt()
|
||||
if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, number)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
}
|
||||
SourceStorageKind.VARIABLE -> {
|
||||
// TODO optimize the stuff below to not use temp variables??
|
||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, value.asmVarname, value.datatype)
|
||||
if(!inplacemodificationRegisterAXwithVariable(
|
||||
operator,
|
||||
value.asmVarname,
|
||||
value.datatype
|
||||
)) {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, value.asmVarname, value.datatype)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
}
|
||||
SourceStorageKind.REGISTER -> {
|
||||
// TODO optimize the stuff below to not use temp variables??
|
||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, regName(value), value.datatype)
|
||||
if(!inplacemodificationRegisterAXwithVariable(
|
||||
operator,
|
||||
regName(value),
|
||||
value.datatype
|
||||
)) {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, regName(value), value.datatype)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
}
|
||||
SourceStorageKind.MEMORY -> {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithMemread("P8ZP_SCRATCH_W1", target.datatype, operator, value.memory!!)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
SourceStorageKind.ARRAY -> {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.array!!)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
SourceStorageKind.MEMORY -> inplacemodificationWordWithMemread("P8ZP_SCRATCH_W1", target.datatype, operator, value.memory!!)
|
||||
SourceStorageKind.ARRAY -> inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.array!!)
|
||||
SourceStorageKind.EXPRESSION -> {
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||
if(value.expression is PtTypeCast)
|
||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression)
|
||||
else
|
||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression!!)
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||
}
|
||||
}
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||
if(target.array.splitWords) {
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | sta ${target.array.variable.name}_lsb,y")
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1+1 | sta ${target.array.variable.name}_msb,y")
|
||||
} else {
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | sta ${target.array.variable.name},y")
|
||||
asmgen.out(" lda P8ZP_SCRATCH_W1+1 | sta ${target.array.variable.name}+1,y")
|
||||
}
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||
if(target.array.splitWords)
|
||||
asmgen.out(" sta ${target.array.variable.name}_lsb,y | txa | sta ${target.array.variable.name}_msb,y")
|
||||
else
|
||||
asmgen.out(" sta ${target.array.variable.name},y | txa | sta ${target.array.variable.name}+1,y")
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.FLOAT, CpuRegister.A)
|
||||
@ -412,6 +437,110 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplacemodificationRegisterAXwithVariable(operator: String, variable: String, varDt: DataType): Boolean {
|
||||
// note: we only optimize addition and subtraction, and these are the same for unsigned or signed.
|
||||
when(operator) {
|
||||
"+" -> {
|
||||
return if(varDt in WordDatatypes) {
|
||||
asmgen.out("""
|
||||
clc
|
||||
adc $variable
|
||||
pha
|
||||
txa
|
||||
adc $variable+1
|
||||
tax
|
||||
pla""")
|
||||
true
|
||||
} else {
|
||||
asmgen.out("""
|
||||
ldy $variable
|
||||
bpl +
|
||||
dex ; sign extend
|
||||
+ clc
|
||||
adc $variable
|
||||
bcc +
|
||||
inx
|
||||
+""")
|
||||
true
|
||||
}
|
||||
}
|
||||
"-" -> {
|
||||
return if(varDt in WordDatatypes) {
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc $variable
|
||||
pha
|
||||
txa
|
||||
sbc $variable+1
|
||||
tax
|
||||
pla""")
|
||||
true
|
||||
} else {
|
||||
asmgen.out("""
|
||||
ldy $variable
|
||||
bpl +
|
||||
inx ; sign extend
|
||||
+ sec
|
||||
sbc $variable
|
||||
bcs +
|
||||
dex
|
||||
+""")
|
||||
true
|
||||
}
|
||||
}
|
||||
else -> return false // TODO optimize more operators, such as the bitwise logical ones? Might need to know if signed
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplacemodificationRegisterAXwithLiteralval(operator: String, number: Int): Boolean {
|
||||
// note: we only optimize addition and subtraction, and these are the same for unsigned or signed.
|
||||
when(operator) {
|
||||
"+" -> {
|
||||
return if(number in -128..255) {
|
||||
asmgen.out("""
|
||||
clc
|
||||
adc #$number
|
||||
bcc +
|
||||
inx
|
||||
+""")
|
||||
true
|
||||
} else {
|
||||
asmgen.out("""
|
||||
clc
|
||||
adc #<$number
|
||||
pha
|
||||
txa
|
||||
adc #>$number
|
||||
tax
|
||||
pla""")
|
||||
true
|
||||
}
|
||||
}
|
||||
"-" -> {
|
||||
return if(number in -128..255) {
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc #$number
|
||||
bcs +
|
||||
dex
|
||||
+""")
|
||||
true
|
||||
} else {
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc #<$number
|
||||
pha
|
||||
txa
|
||||
sbc #>$number
|
||||
tax
|
||||
pla""")
|
||||
true
|
||||
}
|
||||
}
|
||||
else -> return false // TODO optimize more operators, such as the bitwise logical ones? Might need to know if signed
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryInplaceModifyWithRemovedRedundantCast(value: PtTypeCast, target: AsmAssignTarget, operator: String): Boolean {
|
||||
if (target.datatype == value.type) {
|
||||
val childDt = value.value.type
|
||||
@ -579,7 +708,6 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun inplacemodificationByteVariableWithValue(name: String, dt: DataType, operator: String, value: PtExpression) {
|
||||
// TODO optimize the stuff below to not use temp variables??
|
||||
val tmpVar = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG"
|
||||
asmgen.assignExpressionToVariable(value, tmpVar, value.type)
|
||||
asmgen.out(" lda $name")
|
||||
@ -1932,21 +2060,21 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
sta $name+1""")
|
||||
}
|
||||
"*" -> {
|
||||
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// value is (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// TODO use an optimized word * byte multiplication routine?
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.signExtendAYlsb(valueDt)
|
||||
multiplyVarByWordInAY()
|
||||
}
|
||||
"/" -> {
|
||||
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// value is (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// TODO use an optimized word / byte divmod routine?
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.signExtendAYlsb(valueDt)
|
||||
divideVarByWordInAY()
|
||||
}
|
||||
"%" -> {
|
||||
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// value is (u) byte value, sign extend that and proceed with regular 16 bit operation
|
||||
// TODO use an optimized word / byte divmod routine?
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.signExtendAYlsb(valueDt)
|
||||
|
@ -1,8 +1,8 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- try to reduce the number of uses of temp variables for example in array[idx] -= amount see AugmentableAssignmentAsmGen
|
||||
- investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... / - investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||
- try to reduce the number of temp variables in comparison expressions like if a>4 or a<2 .... See assignOptimizedComparisonBytes().
|
||||
- investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||
|
||||
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
||||
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!
|
||||
|
@ -3,16 +3,16 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
uword[4] array = [1,2,3,4]
|
||||
ubyte index = 2
|
||||
ubyte a = 1
|
||||
|
||||
cx16.r0 = 99
|
||||
array[index] += 12345
|
||||
array[index] += cx16.r0
|
||||
array[index] += index
|
||||
txt.print_uw(array[index]) ; prints 12449
|
||||
if a>4 or a<2 {
|
||||
a++
|
||||
}
|
||||
|
||||
; code size = $0249
|
||||
if a>=2 and a<4 {
|
||||
a++
|
||||
}
|
||||
|
||||
txt.print_ub(a) ; 3
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user