some more obscure inplace modifications implemented

This commit is contained in:
Irmen de Jong
2025-12-05 20:25:56 +01:00
parent bd272a8567
commit 76c95ba6fa
3 changed files with 255 additions and 229 deletions

View File

@@ -113,9 +113,9 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALNUMBER -> inplacemodificationLongWithLiteralval(target.asmVarname, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(target.asmVarname, operator, value.asmVarname)
SourceStorageKind.EXPRESSION -> inplacemodificationLongWithExpression(target.asmVarname, operator, value.expression!!)
SourceStorageKind.REGISTER -> TODO("32 bits register inplace modification? ${target.position}")
SourceStorageKind.ARRAY -> TODO("inplace modify long with array ${target.position}")
SourceStorageKind.MEMORY -> TODO("memread into long ${target.position}")
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(target.asmVarname, operator, regName(value))
SourceStorageKind.ARRAY -> TODO("inplace modify long with array value ${target.position}")
SourceStorageKind.MEMORY -> TODO("inplace modify long with memread value ${target.position}")
}
}
target.datatype.isFloat -> {
@@ -124,7 +124,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.number!!.number)
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(target.asmVarname, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(target.asmVarname, operator, regName(value))
SourceStorageKind.MEMORY -> TODO("memread into float ${target.position}")
SourceStorageKind.MEMORY -> inplacemodificationFloatWithValue(target.asmVarname, operator, value.memory!!)
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(target.asmVarname, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
@@ -164,18 +164,18 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
is PtIdentifier -> {
val pointer = memory.address as PtIdentifier
when(value.kind) {
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt())
SourceStorageKind.LITERALNUMBER -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationBytePointerWithVariable(pointer, operator, regName(value))
SourceStorageKind.MEMORY -> TODO("memread into pointer ${target.position}")
SourceStorageKind.ARRAY -> inplacemodificationBytePointerWithValue(pointer, operator, value.array!!)
SourceStorageKind.LITERALBOOLEAN -> ptrgen.inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt())
SourceStorageKind.LITERALNUMBER -> ptrgen.inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> ptrgen.inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname)
SourceStorageKind.REGISTER -> ptrgen.inplacemodificationBytePointerWithVariable(pointer, operator, regName(value))
SourceStorageKind.MEMORY -> ptrgen. inplacemodificationBytePointerWithValue(pointer, operator, value.memory!!)
SourceStorageKind.ARRAY -> ptrgen.inplacemodificationBytePointerWithValue(pointer, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
inplacemodificationBytePointerWithValue(pointer, operator, value.expression)
ptrgen.inplacemodificationBytePointerWithValue(pointer, operator, value.expression)
} else {
inplacemodificationBytePointerWithValue(pointer, operator, value.expression!!)
ptrgen.inplacemodificationBytePointerWithValue(pointer, operator, value.expression!!)
}
}
}
@@ -309,8 +309,8 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALNUMBER -> inplacemodificationLongWithLiteralval(targetVarName, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(targetVarName, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(targetVarName, operator, regName(value))
SourceStorageKind.MEMORY -> TODO("inplace long modifiication ${target.position}")
SourceStorageKind.ARRAY -> TODO("inplace long modifiication ${target.position}")
SourceStorageKind.MEMORY -> TODO("inplace long modifiication with memread value ${target.position}")
SourceStorageKind.ARRAY -> TODO("inplace long modifiication with array value ${target.position}")
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
@@ -328,7 +328,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number)
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value))
SourceStorageKind.MEMORY -> TODO("memread into float array ${target.position}")
SourceStorageKind.MEMORY -> inplacemodificationFloatWithValue(targetVarName, operator, value.memory!!)
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(targetVarName, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
@@ -519,7 +519,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number)
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value))
SourceStorageKind.MEMORY -> TODO("memread into float ${target.position}")
SourceStorageKind.MEMORY -> inplacemodificationFloatWithValue(tempvar, operator, value.memory!!)
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(tempvar, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
@@ -1406,188 +1406,6 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
return false
}
private fun inplacemodificationBytePointerWithValue(pointervar: PtIdentifier, operator: String, value: PtExpression) {
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", DataType.UBYTE)
inplacemodificationBytePointerWithVariable(pointervar, operator, "P8ZP_SCRATCH_B1")
}
private fun inplacemodificationBytePointerWithVariable(pointervar: PtIdentifier, operator: String, otherName: String) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
when (operator) {
"+" -> asmgen.out(" clc | adc $otherName")
"-" -> asmgen.out(" sec | sbc $otherName")
"*" -> asmgen.out(" ldy $otherName | jsr prog8_math.multiply_bytes")
"/" -> asmgen.out(" ldy $otherName | jsr prog8_math.divmod_ub_asm | tya")
"%" -> asmgen.out(" ldy $otherName | jsr prog8_math.remainder_ub_asm")
"<<" -> {
asmgen.out("""
ldy $otherName
beq +
- asl a
dey
bne -
+""")
}
">>" -> {
asmgen.out("""
ldy $otherName
beq +
- lsr a
dey
bne -
+""")
}
"&" -> asmgen.out(" and $otherName")
"|" -> asmgen.out(" ora $otherName")
"^" -> asmgen.out(" eor $otherName")
"==" -> {
asmgen.out("""
cmp $otherName
beq +
lda #0
beq ++
+ lda #1
+""")
}
"!=" -> {
asmgen.out("""
cmp $otherName
bne +
lda #0
beq ++
+ lda #1
+""")
}
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?
"<", "<=", ">", ">=" -> TODO("byte-var-to-pointer comparisons ${pointervar.position}")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
private fun inplacemodificationBytePointerWithLiteralval(pointervar: PtIdentifier, operator: String, value: Int) {
// note: this contains special optimized cases because we know the exact value. Don't replace this with another routine.
when (operator) {
"+" -> {
if(value==1) {
if(asmgen.options.romable) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(asmgen.isTargetCpu(CpuType.CPU65C02))
asmgen.out(" inc a")
else
asmgen.out(" clc | adc #1")
asmgen.storeAIntoZpPointerVar(sourceName, false)
} else {
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out($$"+\tinc $ffff\t; modified")
}
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" clc | adc #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"-" -> {
if(value==1) {
if(asmgen.options.romable) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(asmgen.isTargetCpu(CpuType.CPU65C02))
asmgen.out(" dec a")
else
asmgen.out(" sec | sbc #1")
asmgen.storeAIntoZpPointerVar(sourceName, false)
} else {
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out($$"+\tdec $ffff\t; modified")
}
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" sec | sbc #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"*" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value in asmgen.optimizedByteMultiplications)
asmgen.out(" jsr prog8_math.mul_byte_${value}")
else
asmgen.out(" ldy #$value | jsr prog8_math.multiply_bytes")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"/" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0)
throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr prog8_math.divmod_ub_asm | tya")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"%" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0)
throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr prog8_math.remainder_ub_asm")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"<<" -> {
if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" asl a") }
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
">>" -> {
if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" lsr a") }
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"&" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" and #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"|"-> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" ora #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"^" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" eor #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"==" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out("""
cmp #$value
beq +
lda #0
beq ++
+ lda #1
+""")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"!=" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out("""
cmp #$value
bne +
lda #0
beq ++
+ lda #1
+""")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?:
"<", "<=", ">", ">=" -> TODO("byte-litval-to-pointer comparisons ${pointervar.position}")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
}
private fun inplacemodificationByteWithValue(name: String, dt: DataType, operator: String, value: PtExpression) {
require(dt.isByteOrBool)
if(!value.isSimple()) {

View File

@@ -288,52 +288,76 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
}
}
"*" -> {
if(target.dt.isByte) TODO("inplaceByteMul(target, value) ${target.position}")
else if(target.dt.isWord) inplaceWordMul(target, value)
else if(target.dt.isFloat) inplaceFloatAddOrMul(target, "FMULT", value)
else if(target.dt.isLong) TODO("inplace long mul ${target.position}")
else throw AssemblyError("weird dt ${target.position}")
when {
target.dt.isByte -> TODO("inplaceByteMul(target, value) ${target.position}")
target.dt.isWord -> inplaceWordMul(target, value)
target.dt.isFloat -> inplaceFloatAddOrMul(target, "FMULT", value)
target.dt.isLong -> TODO("inplace long mul ${target.position}")
else -> throw AssemblyError("weird dt ${target.position}")
}
}
"/" -> {
if(target.dt.isByte) TODO("inplaceByteDiv(target, value) ${target.position}")
else if(target.dt.isWord) inplaceWordDiv(target, value)
else if(target.dt.isFloat) inplaceFloatSubOrDiv(target, "FDIV", value)
else if(target.dt.isLong) TODO("inplace long div ${target.position}")
else throw AssemblyError("weird dt ${target.position}")
when {
target.dt.isByte -> TODO("inplaceByteDiv(target, value) ${target.position}")
target.dt.isWord -> inplaceWordDiv(target, value)
target.dt.isFloat -> inplaceFloatSubOrDiv(target, "FDIV", value)
target.dt.isLong -> TODO("inplace long div ${target.position}")
else -> throw AssemblyError("weird dt ${target.position}")
}
}
"%" -> {
if(target.dt.isSigned || value.datatype.isSigned)
throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
when {
target.dt.isByte -> TODO("inplace byte pointer mod should have been handled via MEMORY target type ${target.position}")
target.dt.isWord -> TODO("inplace word pointer mod ${target.position}")
//target.dt.isFloat -> TODO("inplace float pointer mod ${target.position}")
//target.dt.isLong -> TODO("inplace long pointer mod ${target.position}")
else -> throw AssemblyError("weird dt ${target.position}")
}
}
"%" -> TODO("inplace ptr % ${target.position}")
"<<" -> {
if(target.dt.isByte) inplaceByteShiftLeft(target, value)
else if(target.dt.isWord) inplaceWordShiftLeft(target, value)
else if(target.dt.isLong) inplaceLongShiftLeft(target, value)
else throw AssemblyError("weird dt ${target.position}")
when {
target.dt.isByte -> inplaceByteShiftLeft(target, value)
target.dt.isWord -> inplaceWordShiftLeft(target, value)
target.dt.isLong -> inplaceLongShiftLeft(target, value)
else -> throw AssemblyError("weird dt ${target.position}")
}
}
">>" -> {
if(target.dt.isByte) inplaceByteShiftRight(target, value)
else if(target.dt.isWord) inplaceWordShiftRight(target, value)
else if(target.dt.isLong) inplaceLongShiftRight(target, value)
else throw AssemblyError("weird dt ${target.position}")
when {
target.dt.isByte -> inplaceByteShiftRight(target, value)
target.dt.isWord -> inplaceWordShiftRight(target, value)
target.dt.isLong -> inplaceLongShiftRight(target, value)
else -> throw AssemblyError("weird dt ${target.position}")
}
}
"&", "and" -> {
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
if(target.dt.isByteOrBool) inplaceByteAnd(target, value)
else if(target.dt.isWord) inplaceWordAnd(target, value)
else if(target.dt.isLong) inplaceLongAnd(target, value)
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
when {
target.dt.isByteOrBool -> inplaceByteAnd(target, value)
target.dt.isWord -> inplaceWordAnd(target, value)
target.dt.isLong -> inplaceLongAnd(target, value)
else -> throw AssemblyError("weird dt ${target.dt} ${target.position}")
}
}
"|", "or" -> {
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
if(target.dt.isByteOrBool) inplaceByteOr(target, value)
else if(target.dt.isWord) inplaceWordOr(target, value)
else if(target.dt.isLong) inplaceLongOr(target, value)
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
when {
target.dt.isByteOrBool -> inplaceByteOr(target, value)
target.dt.isWord -> inplaceWordOr(target, value)
target.dt.isLong -> inplaceLongOr(target, value)
else -> throw AssemblyError("weird dt ${target.dt} ${target.position}")
}
}
"^", "xor" -> {
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
if(target.dt.isByteOrBool) inplaceByteXor(target, value)
else if(target.dt.isWord) inplaceWordXor(target, value)
else if(target.dt.isLong) inplaceLongXor(target, value)
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
when {
target.dt.isByteOrBool -> inplaceByteXor(target, value)
target.dt.isWord -> inplaceWordXor(target, value)
target.dt.isLong -> inplaceLongXor(target, value)
else -> throw AssemblyError("weird dt ${target.dt} ${target.position}")
}
}
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
@@ -501,6 +525,189 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
sta ($ptrVar),y""")
}
internal fun inplacemodificationBytePointerWithValue(pointervar: PtIdentifier, operator: String, value: PtExpression) {
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", DataType.UBYTE)
inplacemodificationBytePointerWithVariable(pointervar, operator, "P8ZP_SCRATCH_B1")
}
internal fun inplacemodificationBytePointerWithVariable(pointervar: PtIdentifier, operator: String, otherName: String) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
when (operator) {
"+" -> asmgen.out(" clc | adc $otherName")
"-" -> asmgen.out(" sec | sbc $otherName")
"*" -> asmgen.out(" ldy $otherName | jsr prog8_math.multiply_bytes")
"/" -> asmgen.out(" ldy $otherName | jsr prog8_math.divmod_ub_asm | tya")
"%" -> asmgen.out(" ldy $otherName | jsr prog8_math.remainder_ub_asm")
"<<" -> {
asmgen.out("""
ldy $otherName
beq +
- asl a
dey
bne -
+""")
}
">>" -> {
asmgen.out("""
ldy $otherName
beq +
- lsr a
dey
bne -
+""")
}
"&" -> asmgen.out(" and $otherName")
"|" -> asmgen.out(" ora $otherName")
"^" -> asmgen.out(" eor $otherName")
"==" -> {
asmgen.out("""
cmp $otherName
beq +
lda #0
beq ++
+ lda #1
+""")
}
"!=" -> {
asmgen.out("""
cmp $otherName
bne +
lda #0
beq ++
+ lda #1
+""")
}
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?
"<", "<=", ">", ">=" -> TODO("byte-var-to-pointer comparisons ${pointervar.position}")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
internal fun inplacemodificationBytePointerWithLiteralval(pointervar: PtIdentifier, operator: String, value: Int) {
// note: this contains special optimized cases because we know the exact value. Don't replace this with another routine.
when (operator) {
"+" -> {
if(value==1) {
if(asmgen.options.romable) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(asmgen.isTargetCpu(CpuType.CPU65C02))
asmgen.out(" inc a")
else
asmgen.out(" clc | adc #1")
asmgen.storeAIntoZpPointerVar(sourceName, false)
} else {
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out($$"+\tinc $ffff\t; modified")
}
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" clc | adc #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"-" -> {
if(value==1) {
if(asmgen.options.romable) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(asmgen.isTargetCpu(CpuType.CPU65C02))
asmgen.out(" dec a")
else
asmgen.out(" sec | sbc #1")
asmgen.storeAIntoZpPointerVar(sourceName, false)
} else {
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out($$"+\tdec $ffff\t; modified")
}
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" sec | sbc #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"*" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value in asmgen.optimizedByteMultiplications)
asmgen.out(" jsr prog8_math.mul_byte_${value}")
else
asmgen.out(" ldy #$value | jsr prog8_math.multiply_bytes")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"/" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0)
throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr prog8_math.divmod_ub_asm | tya")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"%" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0)
throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr prog8_math.remainder_ub_asm")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"<<" -> {
if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" asl a") }
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
">>" -> {
if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" lsr a") }
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
}
"&" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" and #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"|"-> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" ora #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"^" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" eor #$value")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"==" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out("""
cmp #$value
beq +
lda #0
beq ++
+ lda #1
+""")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
"!=" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out("""
cmp #$value
bne +
lda #0
beq ++
+ lda #1
+""")
asmgen.storeAIntoZpPointerVar(sourceName, false)
}
// pretty uncommon, who's going to assign a comparison boolean expression to a pointer?:
"<", "<=", ">", ">=" -> TODO("byte-litval-to-pointer comparisons ${pointervar.position}")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
}
internal fun operatorDereference(binExpr: PtBinaryExpression): Triple<String, UByte, DataType> {
// the only case we support here is: a.b.c[i] . value

View File

@@ -26,6 +26,7 @@ Future Things and Ideas
- struct/ptr: really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
- struct/ptr: (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
- structs: properly fix the symbol name prefix hack in StStruct.sameas(), see github issue 198
- should we have a SourceStorageKind.POINTER? (there is one for TargetStorageKind...)
- array-as-param bug: printf([1111,2,3,-4444]) gives argument type mismatch (param is of type uword), while printf([1111,2,3,4444]) just works fine (passes address of @nosplit array)
- make memory mapped variables support more constant expressions such as: &uword MyHigh = &mylong1+2
- allow memory() to occur in array initializer (maybe needed for 2 dimensional arrays?) i.e. make it a constant (see github issue #192)