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.LITERALNUMBER -> inplacemodificationLongWithLiteralval(target.asmVarname, operator, value.number!!.number.toInt())
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(target.asmVarname, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(target.asmVarname, operator, value.asmVarname)
|
||||||
SourceStorageKind.EXPRESSION -> inplacemodificationLongWithExpression(target.asmVarname, operator, value.expression!!)
|
SourceStorageKind.EXPRESSION -> inplacemodificationLongWithExpression(target.asmVarname, operator, value.expression!!)
|
||||||
SourceStorageKind.REGISTER -> TODO("32 bits register inplace modification? ${target.position}")
|
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(target.asmVarname, operator, regName(value))
|
||||||
SourceStorageKind.ARRAY -> TODO("inplace modify long with array ${target.position}")
|
SourceStorageKind.ARRAY -> TODO("inplace modify long with array value ${target.position}")
|
||||||
SourceStorageKind.MEMORY -> TODO("memread into long ${target.position}")
|
SourceStorageKind.MEMORY -> TODO("inplace modify long with memread value ${target.position}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.datatype.isFloat -> {
|
target.datatype.isFloat -> {
|
||||||
@@ -124,7 +124,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.number!!.number)
|
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.number!!.number)
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(target.asmVarname, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(target.asmVarname, operator, value.asmVarname)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(target.asmVarname, operator, regName(value))
|
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.ARRAY -> inplacemodificationFloatWithValue(target.asmVarname, operator, value.array!!)
|
||||||
SourceStorageKind.EXPRESSION -> {
|
SourceStorageKind.EXPRESSION -> {
|
||||||
if(value.expression is PtTypeCast) {
|
if(value.expression is PtTypeCast) {
|
||||||
@@ -164,18 +164,18 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
is PtIdentifier -> {
|
is PtIdentifier -> {
|
||||||
val pointer = memory.address as PtIdentifier
|
val pointer = memory.address as PtIdentifier
|
||||||
when(value.kind) {
|
when(value.kind) {
|
||||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt())
|
SourceStorageKind.LITERALBOOLEAN -> ptrgen.inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt())
|
||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt())
|
SourceStorageKind.LITERALNUMBER -> ptrgen.inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt())
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> ptrgen.inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationBytePointerWithVariable(pointer, operator, regName(value))
|
SourceStorageKind.REGISTER -> ptrgen.inplacemodificationBytePointerWithVariable(pointer, operator, regName(value))
|
||||||
SourceStorageKind.MEMORY -> TODO("memread into pointer ${target.position}")
|
SourceStorageKind.MEMORY -> ptrgen. inplacemodificationBytePointerWithValue(pointer, operator, value.memory!!)
|
||||||
SourceStorageKind.ARRAY -> inplacemodificationBytePointerWithValue(pointer, operator, value.array!!)
|
SourceStorageKind.ARRAY -> ptrgen.inplacemodificationBytePointerWithValue(pointer, operator, value.array!!)
|
||||||
SourceStorageKind.EXPRESSION -> {
|
SourceStorageKind.EXPRESSION -> {
|
||||||
if(value.expression is PtTypeCast) {
|
if(value.expression is PtTypeCast) {
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
||||||
inplacemodificationBytePointerWithValue(pointer, operator, value.expression)
|
ptrgen.inplacemodificationBytePointerWithValue(pointer, operator, value.expression)
|
||||||
} else {
|
} 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.LITERALNUMBER -> inplacemodificationLongWithLiteralval(targetVarName, operator, value.number!!.number.toInt())
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(targetVarName, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(targetVarName, operator, value.asmVarname)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(targetVarName, operator, regName(value))
|
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(targetVarName, operator, regName(value))
|
||||||
SourceStorageKind.MEMORY -> TODO("inplace long modifiication ${target.position}")
|
SourceStorageKind.MEMORY -> TODO("inplace long modifiication with memread value ${target.position}")
|
||||||
SourceStorageKind.ARRAY -> TODO("inplace long modifiication ${target.position}")
|
SourceStorageKind.ARRAY -> TODO("inplace long modifiication with array value ${target.position}")
|
||||||
SourceStorageKind.EXPRESSION -> {
|
SourceStorageKind.EXPRESSION -> {
|
||||||
if(value.expression is PtTypeCast) {
|
if(value.expression is PtTypeCast) {
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
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.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number)
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value))
|
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.ARRAY -> inplacemodificationFloatWithValue(targetVarName, operator, value.array!!)
|
||||||
SourceStorageKind.EXPRESSION -> {
|
SourceStorageKind.EXPRESSION -> {
|
||||||
if(value.expression is PtTypeCast) {
|
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.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number)
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
|
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value))
|
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.ARRAY -> inplacemodificationFloatWithValue(tempvar, operator, value.array!!)
|
||||||
SourceStorageKind.EXPRESSION -> {
|
SourceStorageKind.EXPRESSION -> {
|
||||||
if(value.expression is PtTypeCast) {
|
if(value.expression is PtTypeCast) {
|
||||||
@@ -1406,188 +1406,6 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
return false
|
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) {
|
private fun inplacemodificationByteWithValue(name: String, dt: DataType, operator: String, value: PtExpression) {
|
||||||
require(dt.isByteOrBool)
|
require(dt.isByteOrBool)
|
||||||
if(!value.isSimple()) {
|
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}")
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordMul(target, value)
|
target.dt.isByte -> TODO("inplaceByteMul(target, value) ${target.position}")
|
||||||
else if(target.dt.isFloat) inplaceFloatAddOrMul(target, "FMULT", value)
|
target.dt.isWord -> inplaceWordMul(target, value)
|
||||||
else if(target.dt.isLong) TODO("inplace long mul ${target.position}")
|
target.dt.isFloat -> inplaceFloatAddOrMul(target, "FMULT", value)
|
||||||
else throw AssemblyError("weird dt ${target.position}")
|
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}")
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordDiv(target, value)
|
target.dt.isByte -> TODO("inplaceByteDiv(target, value) ${target.position}")
|
||||||
else if(target.dt.isFloat) inplaceFloatSubOrDiv(target, "FDIV", value)
|
target.dt.isWord -> inplaceWordDiv(target, value)
|
||||||
else if(target.dt.isLong) TODO("inplace long div ${target.position}")
|
target.dt.isFloat -> inplaceFloatSubOrDiv(target, "FDIV", value)
|
||||||
else throw AssemblyError("weird dt ${target.position}")
|
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)
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordShiftLeft(target, value)
|
target.dt.isByte -> inplaceByteShiftLeft(target, value)
|
||||||
else if(target.dt.isLong) inplaceLongShiftLeft(target, value)
|
target.dt.isWord -> inplaceWordShiftLeft(target, value)
|
||||||
else throw AssemblyError("weird dt ${target.position}")
|
target.dt.isLong -> inplaceLongShiftLeft(target, value)
|
||||||
|
else -> throw AssemblyError("weird dt ${target.position}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
">>" -> {
|
">>" -> {
|
||||||
if(target.dt.isByte) inplaceByteShiftRight(target, value)
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordShiftRight(target, value)
|
target.dt.isByte -> inplaceByteShiftRight(target, value)
|
||||||
else if(target.dt.isLong) inplaceLongShiftRight(target, value)
|
target.dt.isWord -> inplaceWordShiftRight(target, value)
|
||||||
else throw AssemblyError("weird dt ${target.position}")
|
target.dt.isLong -> inplaceLongShiftRight(target, value)
|
||||||
|
else -> throw AssemblyError("weird dt ${target.position}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"&", "and" -> {
|
"&", "and" -> {
|
||||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
// 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)
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordAnd(target, value)
|
target.dt.isByteOrBool -> inplaceByteAnd(target, value)
|
||||||
else if(target.dt.isLong) inplaceLongAnd(target, value)
|
target.dt.isWord -> inplaceWordAnd(target, value)
|
||||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
target.dt.isLong -> inplaceLongAnd(target, value)
|
||||||
|
else -> throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"|", "or" -> {
|
"|", "or" -> {
|
||||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
// 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)
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordOr(target, value)
|
target.dt.isByteOrBool -> inplaceByteOr(target, value)
|
||||||
else if(target.dt.isLong) inplaceLongOr(target, value)
|
target.dt.isWord -> inplaceWordOr(target, value)
|
||||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
target.dt.isLong -> inplaceLongOr(target, value)
|
||||||
|
else -> throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"^", "xor" -> {
|
"^", "xor" -> {
|
||||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
// 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)
|
when {
|
||||||
else if(target.dt.isWord) inplaceWordXor(target, value)
|
target.dt.isByteOrBool -> inplaceByteXor(target, value)
|
||||||
else if(target.dt.isLong) inplaceLongXor(target, value)
|
target.dt.isWord -> inplaceWordXor(target, value)
|
||||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
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")
|
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""")
|
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> {
|
internal fun operatorDereference(binExpr: PtBinaryExpression): Triple<String, UByte, DataType> {
|
||||||
// the only case we support here is: a.b.c[i] . value
|
// 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: 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)
|
- 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
|
- 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)
|
- 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
|
- 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)
|
- 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