created direct-on-memory ++/-- and augmented assignemnts.

This commit is contained in:
Irmen de Jong 2018-12-31 02:25:45 +01:00
parent aeb963673a
commit c07bd8a4a8
6 changed files with 69 additions and 19 deletions

View File

@ -4,11 +4,22 @@
sub start() { sub start() {
ubyte[63] balloonsprite = [ 0,127,0,1,255,192,3,255,224,3,231,224, A+=5
7,217,240,7,223,240,7,217,240,3,231,224,
3,255,224,3,255,224,2,255,160,1,127,64, ; @todo if-else if should compile ?:
1,62,64,0,156,128,0,156,128,0,73,0,0,73,0, ; if A>100
0,62,0,0,62,0,0,62,0,0,28,0 ] ; Y=2
; else if A>20
; Y=3
; @($d020) = 5
@($d020)++
@($d021)--
; @($d020)=(@$d020)+5
@($d020)+=5
; @($d021)=(@$d021)-5
@($d021)-=5
} }
} }

View File

@ -391,7 +391,6 @@ class AstChecker(private val namespace: INameScope,
if(memAddr!=null) { if(memAddr!=null) {
if(memAddr<0 || memAddr>=65536) if(memAddr<0 || memAddr>=65536)
checkResult.add(ExpressionError("address out of range", target.position)) checkResult.add(ExpressionError("address out of range", target.position))
return assignment
} }
if(target.identifier!=null) { if(target.identifier!=null) {
@ -436,6 +435,16 @@ class AstChecker(private val namespace: INameScope,
target.register != null -> RegisterExpr(target.register, target.position) target.register != null -> RegisterExpr(target.register, target.position)
target.identifier != null -> target.identifier target.identifier != null -> target.identifier
target.arrayindexed != null -> target.arrayindexed target.arrayindexed != null -> target.arrayindexed
target.memAddressExpression != null -> {
// @addr += 4 --> @addr = @addr +4
// TODO: make it so that it follows the others
val memRead = DirectMemoryExpression(target.memAddressExpression!!, target.position)
val expression = BinaryExpression(memRead, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position)
expression.linkParents(assignment.parent)
val assignment2 = Assignment(listOf(target), null, expression, assignment.position)
assignment2.linkParents(assignment.parent)
return assignment2
}
else -> throw FatalAstException("strange assignment") else -> throw FatalAstException("strange assignment")
} }
@ -818,6 +827,8 @@ class AstChecker(private val namespace: INameScope,
if(dt !in NumericDatatypes && dt !in ArrayDatatypes) if(dt !in NumericDatatypes && dt !in ArrayDatatypes)
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position)) checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
} }
} else if(postIncrDecr.target.memAddressExpression != null) {
// a memory location can always be ++/--
} }
return super.process(postIncrDecr) return super.process(postIncrDecr)
} }

View File

@ -1273,7 +1273,18 @@ private class StatementTranslator(private val prog: IntermediateProgram,
"--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname) "--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
} }
} }
else -> throw CompilerException("very strange postincrdecr") stmt.target.memAddressExpression != null -> {
val address = stmt.target.memAddressExpression!!.constValue(namespace, heap)?.asIntegerValue
if(address!=null) {
when(stmt.operator) {
"++" -> prog.instr(Opcode.INC_MEMORY, Value(DataType.UWORD, address))
"--" -> prog.instr(Opcode.DEC_MEMORY, Value(DataType.UWORD, address))
}
} else {
TODO("memory ++/-- ${stmt.target.memAddressExpression}")
}
}
else -> throw CompilerException("very strange postincrdecr ${stmt.target}")
} }
} }
@ -1357,6 +1368,9 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
assignTarget.register != null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = assignTarget.register.toString()) assignTarget.register != null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = assignTarget.register.toString())
assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, false) assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, false)
assignTarget.memAddressExpression != null -> {
TODO("translate aug assign on memory address $stmt")
}
} }
translateAugAssignOperator(stmt.aug_op, stmt.value.resultingDatatype(namespace, heap)) translateAugAssignOperator(stmt.aug_op, stmt.value.resultingDatatype(namespace, heap))
@ -1496,7 +1510,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
} }
private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) { private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) { // @todo: not used in practice? (all augassigns are converted to normal assigns)
if(valueDt==null) if(valueDt==null)
throw CompilerException("value datatype not known") throw CompilerException("value datatype not known")
val validDt = setOf(DataType.UBYTE, DataType.UWORD, DataType.FLOAT) val validDt = setOf(DataType.UBYTE, DataType.UWORD, DataType.FLOAT)

View File

@ -164,6 +164,8 @@ enum class Opcode {
DEC_VAR_W, DEC_VAR_W,
DEC_VAR_UW, DEC_VAR_UW,
DEC_VAR_F, DEC_VAR_F,
INC_MEMORY,
DEC_MEMORY,
// comparisons // comparisons
// @todo the comparisons push the result back on the stack. Optimize this to work with just processor flags? This does mean you can no longer use a logical boolean result as a byte 0/1 value ? // @todo the comparisons push the result back on the stack. Optimize this to work with just processor flags? This does mean you can no longer use a logical boolean result as a byte 0/1 value ?

View File

@ -655,6 +655,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
jsr prog8_lib.dec_var_f jsr prog8_lib.dec_var_f
""" """
} }
Opcode.INC_MEMORY -> " inc ${hexVal(ins)}"
Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}"
Opcode.NEG_B -> " jsr prog8_lib.neg_b" Opcode.NEG_B -> " jsr prog8_lib.neg_b"
Opcode.NEG_W -> " jsr prog8_lib.neg_w" Opcode.NEG_W -> " jsr prog8_lib.neg_w"
Opcode.NEG_F -> " jsr prog8_lib.neg_f" Opcode.NEG_F -> " jsr prog8_lib.neg_f"

View File

@ -968,6 +968,16 @@ class StackVm(private var traceOutputFile: String?) {
val array = heap.get(variable.heapId) val array = heap.get(variable.heapId)
array.array!![index].dec() array.array!![index].dec()
} }
Opcode.INC_MEMORY -> {
val address = evalstack.pop()
checkDt(address, DataType.UWORD)
TODO("inc_memory $address")
}
Opcode.DEC_MEMORY -> {
val address = evalstack.pop()
checkDt(address, DataType.UWORD)
TODO("dec_memory $address")
}
Opcode.MSB -> { Opcode.MSB -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD) checkDt(v, DataType.UWORD, DataType.WORD)