more efficient code for inc/dec on arrays

This commit is contained in:
Irmen de Jong 2018-12-26 15:47:23 +01:00
parent 8adbcb7a26
commit c58b862b34
5 changed files with 105 additions and 32 deletions

View File

@ -22,27 +22,20 @@
sub start() {
c64scr.print(" X=")
c64scr.print_ub(X)
c64.CHROUT('\n')
; c64scr.print(" X=")
; c64scr.print_ub(X)
; c64.CHROUT('\n')
c64scr.print(" X=")
c64scr.print_ub(X)
c64.CHROUT('\n')
ubyte[256] screenarray
ubyte index = 2
screenarray[1]--
screenarray[index]--
; c64scr.print(" X=")
; c64scr.print_ub(X)
; c64.CHROUT('\n')
}
}
~ irq {
sub irq() {
memory ubyte[256] screenarray = $0400
memory ubyte firstscreenchar = $0400
screenarray[0]++ ; @todo incorrect code generated?
firstscreenchar++ ; ... this is okay
c64.EXTCOL++
}
}

View File

@ -342,6 +342,28 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun opcodeIncArrayindexedVar(dt: DataType): Opcode {
return when(dt) {
DataType.ARRAY_UB -> Opcode.INC_INDEXED_VAR_UB
DataType.ARRAY_B -> Opcode.INC_INDEXED_VAR_B
DataType.ARRAY_UW -> Opcode.INC_INDEXED_VAR_UW
DataType.ARRAY_W -> Opcode.INC_INDEXED_VAR_W
DataType.ARRAY_F -> Opcode.INC_INDEXED_VAR_FLOAT
else -> throw CompilerException("can't inc type $dt")
}
}
private fun opcodeDecArrayindexedVar(dt: DataType): Opcode {
return when(dt) {
DataType.ARRAY_UB -> Opcode.DEC_INDEXED_VAR_UB
DataType.ARRAY_B -> Opcode.DEC_INDEXED_VAR_B
DataType.ARRAY_UW -> Opcode.DEC_INDEXED_VAR_UW
DataType.ARRAY_W -> Opcode.DEC_INDEXED_VAR_W
DataType.ARRAY_F -> Opcode.DEC_INDEXED_VAR_FLOAT
else -> throw CompilerException("can't dec type $dt")
}
}
private fun translate(stmt: InlineAssembly) {
prog.instr(Opcode.INLINE_ASSEMBLY, callLabel = stmt.assembly)
}
@ -573,7 +595,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
DataType.ARRAY_B, DataType.ARRAY_W -> {
if(lv.heapId==null)
throw CompilerException("array should have been moved into heap ${lv.position}")
prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId)) // XXX push address of array
}
}
}
@ -634,7 +656,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
DataType.UWORD -> prog.instr(Opcode.PUSH_MEM_UW, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
DataType.WORD -> prog.instr(Opcode.PUSH_MEM_W, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
DataType.FLOAT -> prog.instr(Opcode.PUSH_MEM_FLOAT, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
else -> TODO("invalid datatype for memory variable expression: $target")
else -> throw CompilerException("invalid datatype for memory variable expression: $target")
}
}
}
@ -1213,16 +1235,12 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
stmt.target.arrayindexed!=null -> {
// todo: generate more efficient bytecode for this?
translate(stmt.target.arrayindexed!!, false)
val one = Value(stmt.target.arrayindexed!!.resultingDatatype(namespace, heap)!!, 1)
val opcode = opcodePush(one.type)
prog.instr(opcode, one)
val variable = stmt.target.arrayindexed!!.identifier?.targetStatement(namespace) as VarDecl
translate(stmt.target.arrayindexed!!.arrayspec.x)
when(stmt.operator) {
"++" -> prog.instr(opcodeAdd(one.type))
"--" -> prog.instr(opcodeSub(one.type))
"++" -> prog.instr(opcodeIncArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
"--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
}
translate(stmt.target.arrayindexed!!, true)
}
else -> throw CompilerException("very strange postincrdecr")
}

View File

@ -192,13 +192,23 @@ enum class Opcode {
NOTEQUAL_WORD,
NOTEQUAL_F,
// arrayspec access
// array access and simple manipulations
READ_INDEXED_VAR_BYTE,
READ_INDEXED_VAR_WORD,
READ_INDEXED_VAR_FLOAT,
WRITE_INDEXED_VAR_BYTE,
WRITE_INDEXED_VAR_WORD,
WRITE_INDEXED_VAR_FLOAT,
INC_INDEXED_VAR_B,
INC_INDEXED_VAR_UB,
INC_INDEXED_VAR_W,
INC_INDEXED_VAR_UW,
INC_INDEXED_VAR_FLOAT,
DEC_INDEXED_VAR_B,
DEC_INDEXED_VAR_UB,
DEC_INDEXED_VAR_W,
DEC_INDEXED_VAR_UW,
DEC_INDEXED_VAR_FLOAT,
// branching, without consuming a value from the stack
JUMP,
@ -248,5 +258,9 @@ val opcodesWithVarArgument = setOf(
Opcode.POP_VAR_BYTE, Opcode.POP_VAR_WORD, Opcode.POP_VAR_FLOAT,
Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_ADDR_HEAPVAR,
Opcode.READ_INDEXED_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.READ_INDEXED_VAR_FLOAT,
Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT
Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT,
Opcode.INC_INDEXED_VAR_UB, Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UW,
Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT,
Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UW,
Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_FLOAT
)

View File

@ -808,6 +808,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
}
else if((opcodes[0]==Opcode.PUSH_BYTE && opcodes[1] in setOf(Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB,
Opcode.INC_INDEXED_VAR_UW, Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT,
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_W,
Opcode.DEC_INDEXED_VAR_UW, Opcode.DEC_INDEXED_VAR_FLOAT))) {
val fragment = sameConstantIndexedVarOperation(segment[1].callLabel!!, segment[0].arg!!.integerValue(), segment[1])
if(fragment!=null) {
fragment.segmentSize=2
result.add(fragment)
}
}
else if((opcodes[0]==Opcode.PUSH_VAR_BYTE && opcodes[1] in setOf(Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB,
Opcode.INC_INDEXED_VAR_UW, Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT,
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_W,
Opcode.DEC_INDEXED_VAR_UW, Opcode.DEC_INDEXED_VAR_FLOAT))) {
val fragment = sameIndexedVarOperation(segment[1].callLabel!!, segment[0].callLabel!!, segment[1])
if(fragment!=null) {
fragment.segmentSize=2
result.add(fragment)
}
}
else if((opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[2]==Opcode.POP_MEM_BYTE) ||
(opcodes[0]==Opcode.PUSH_MEM_B && opcodes[2]==Opcode.POP_MEM_BYTE) ||
(opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[2]==Opcode.POP_MEM_WORD) ||
@ -877,6 +897,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.ROR2_BYTE -> AsmFragment(" lda $variable+$index | lsr a | bcc + | ora #\$80 |+ | sta $variable+$index", 10)
Opcode.ROL2_WORD -> AsmFragment(" asl $variable+$index | rol $variable+${index+1} | bcc + | inc $variable+$index |+",20)
Opcode.ROR2_WORD -> AsmFragment(" lsr $variable+${index+1} | ror $variable+$index | bcc + | lda $variable+${index+1} | ora #\$80 | sta $variable+${index+1} |+", 30)
Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" inc $variable+$index", 2)
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" dec $variable+$index", 5)
Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w")
Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw")
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f")
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w")
Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw")
Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f")
else -> null
}
}
@ -921,6 +949,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.ROR2_BYTE -> AsmFragment("$saveX $loadX lda $variable,x | lsr a | bcc + | ora #\$80 |+ | sta $variable,x $restoreX", 10)
Opcode.ROL2_WORD -> AsmFragment(" txa | $loadXWord asl $variable,x | rol $variable+1,x | bcc + | inc $variable,x |+ | tax", 30)
Opcode.ROR2_WORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x | bcc + | lda $variable+1,x | ora #\$80 | sta $variable+1,x |+ $restoreX", 30)
Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX inc $variable,x | tax", 10)
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX dec $variable,x | tax", 10)
Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w")
Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw")
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f")
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w")
Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw")
Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f")
else -> null
}
}
@ -2807,7 +2844,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment ->
" lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
}
)
}

View File

@ -944,6 +944,18 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(variable, DataType.FLOAT)
variables[ins.callLabel] =variable.dec()
}
Opcode.INC_INDEXED_VAR_B,Opcode.INC_INDEXED_VAR_UB,Opcode.INC_INDEXED_VAR_W,Opcode.INC_INDEXED_VAR_UW,Opcode.INC_INDEXED_VAR_FLOAT -> {
val index = evalstack.pop().integerValue()
val variable = getVar(ins.callLabel!!)
val array = heap.get(variable.heapId)
array.array!![index].inc()
}
Opcode.DEC_INDEXED_VAR_B,Opcode.DEC_INDEXED_VAR_UB,Opcode.DEC_INDEXED_VAR_W,Opcode.DEC_INDEXED_VAR_UW,Opcode.DEC_INDEXED_VAR_FLOAT -> {
val index = evalstack.pop().integerValue()
val variable = getVar(ins.callLabel!!)
val array = heap.get(variable.heapId)
array.array!![index].dec()
}
Opcode.MSB -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD)