mirror of
https://github.com/irmen/prog8.git
synced 2025-12-19 20:17:17 +00:00
some more obscure inplace modifications implemented
This commit is contained in:
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user