mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 06:16:15 +00:00
fix the missing cases in certain expressions that need the address of a split word array
This commit is contained in:
@@ -644,32 +644,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
val varname = asmgen.asmVariableName(fcall.args[0] as PtIdentifier) + if(msb) "+1" else ""
|
val varname = asmgen.asmVariableName(fcall.args[0] as PtIdentifier) + if(msb) "+1" else ""
|
||||||
target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, variableAsmName = varname)
|
target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, variableAsmName = varname)
|
||||||
}
|
}
|
||||||
is PtNumber -> {
|
|
||||||
val num = (fcall.args[0] as PtNumber).number + if(msb) 1 else 0
|
|
||||||
val mem = PtMemoryByte(fcall.position)
|
|
||||||
mem.add(PtNumber(BaseDataType.UBYTE, num, fcall.position))
|
|
||||||
target = AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, memory = mem)
|
|
||||||
}
|
|
||||||
is PtAddressOf -> {
|
|
||||||
val addrof = fcall.args[0] as PtAddressOf
|
|
||||||
if(addrof.identifier.type.isSplitWordArray) {
|
|
||||||
TODO("address of split word array")
|
|
||||||
} else {
|
|
||||||
val mem = PtMemoryByte(fcall.position)
|
|
||||||
if(addrof.isFromArrayElement)
|
|
||||||
TODO("address-of arrayelement")
|
|
||||||
if(msb) {
|
|
||||||
val address = PtBinaryExpression("+", DataType.forDt(BaseDataType.UWORD), addrof.position)
|
|
||||||
address.add(addrof)
|
|
||||||
address.add(PtNumber(address.type.base, 1.0, addrof.position))
|
|
||||||
mem.add(address)
|
|
||||||
} else {
|
|
||||||
mem.add(addrof)
|
|
||||||
}
|
|
||||||
target = AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, memory = mem)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
is PtArrayIndexer -> {
|
is PtArrayIndexer -> {
|
||||||
val indexer = fcall.args[0] as PtArrayIndexer
|
val indexer = fcall.args[0] as PtArrayIndexer
|
||||||
val elementSize: Int
|
val elementSize: Int
|
||||||
|
|||||||
@@ -808,11 +808,11 @@ _jump jmp (${target.asmLabel})
|
|||||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||||
asmgen.out(" cpy #0")
|
asmgen.out(" cpy #0")
|
||||||
} else {
|
} else {
|
||||||
|
var varname = asmgen.asmVariableName(value.identifier)
|
||||||
if(value.identifier.type.isSplitWordArray) {
|
if(value.identifier.type.isSplitWordArray) {
|
||||||
TODO("address of split word array")
|
varname += if(value.isMsbForSplitArray) "_msb" else "_lsb"
|
||||||
} else {
|
|
||||||
asmgen.out(" lda #>${asmgen.asmVariableName(value.identifier)}")
|
|
||||||
}
|
}
|
||||||
|
asmgen.out(" lda #>$varname")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -1607,13 +1607,13 @@ _jump jmp (${target.asmLabel})
|
|||||||
if(left.isFromArrayElement)
|
if(left.isFromArrayElement)
|
||||||
fallbackTranslateForSimpleCondition(stmt)
|
fallbackTranslateForSimpleCondition(stmt)
|
||||||
else {
|
else {
|
||||||
if(left.identifier.type.isSplitWordArray) {
|
val varname = if(left.identifier.type.isSplitWordArray) {
|
||||||
TODO("address of split word array")
|
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
|
||||||
} else {
|
} else {
|
||||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
left.identifier.name
|
||||||
val varname = left.identifier.name
|
|
||||||
translateAYNotEquals("#<$varname", "#>$varname")
|
|
||||||
}
|
}
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
translateAYNotEquals("#<$varname", "#>$varname")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -1659,13 +1659,13 @@ _jump jmp (${target.asmLabel})
|
|||||||
if(left.isFromArrayElement)
|
if(left.isFromArrayElement)
|
||||||
fallbackTranslateForSimpleCondition(stmt)
|
fallbackTranslateForSimpleCondition(stmt)
|
||||||
else {
|
else {
|
||||||
if(left.identifier.type.isSplitWordArray) {
|
val varname = if(left.identifier.type.isSplitWordArray) {
|
||||||
TODO("address of split word array")
|
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
|
||||||
} else {
|
} else {
|
||||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
left.identifier.name
|
||||||
val varname = left.identifier.name
|
|
||||||
translateAYEquals("#<$varname", "#>$varname")
|
|
||||||
}
|
}
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
translateAYEquals("#<$varname", "#>$varname")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -1341,13 +1341,12 @@ internal class AssignmentAsmGen(
|
|||||||
|
|
||||||
when (right) {
|
when (right) {
|
||||||
is PtAddressOf -> {
|
is PtAddressOf -> {
|
||||||
val symbol = asmgen.asmVariableName(right.identifier)
|
var symbol = asmgen.asmVariableName(right.identifier)
|
||||||
if(right.isFromArrayElement) {
|
if(right.isFromArrayElement) {
|
||||||
TODO("address-of array element $symbol at ${right.position}")
|
TODO("address-of array element $symbol at ${right.position}")
|
||||||
} else {
|
} else {
|
||||||
if(right.identifier.type.isSplitWordArray) {
|
if(right.identifier.type.isSplitWordArray) {
|
||||||
TODO("address of split word array")
|
symbol = if(right.isMsbForSplitArray) symbol+"_msb" else symbol+"_lsb"
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt.isSigned)
|
assignExpressionToRegister(left, RegisterOrPair.AY, dt.isSigned)
|
||||||
if(expr.operator=="+")
|
if(expr.operator=="+")
|
||||||
@@ -2579,7 +2578,8 @@ $endLabel""")
|
|||||||
|
|
||||||
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
|
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
|
||||||
if(arrayIndexExpr!=null) {
|
if(arrayIndexExpr!=null) {
|
||||||
require(arrayDt?.isSplitWordArray!=true)
|
if(arrayDt?.isSplitWordArray==true)
|
||||||
|
TODO("address of element of a split word array")
|
||||||
val constIndex = arrayIndexExpr.asConstInteger()
|
val constIndex = arrayIndexExpr.asConstInteger()
|
||||||
if(constIndex!=null) {
|
if(constIndex!=null) {
|
||||||
if (arrayDt?.isUnsignedWord==true) {
|
if (arrayDt?.isUnsignedWord==true) {
|
||||||
@@ -2930,14 +2930,12 @@ $endLabel""")
|
|||||||
storeRegisterAInMemoryAddress(target.memory!!)
|
storeRegisterAInMemoryAddress(target.memory!!)
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
if(target.array!!.splitWords)
|
|
||||||
TODO("assign into split words ${target.position}")
|
|
||||||
if (target.constArrayIndexValue!=null) {
|
if (target.constArrayIndexValue!=null) {
|
||||||
val scaledIdx = program.memsizer.memorySize(target.datatype, target.constArrayIndexValue!!.toInt())
|
val scaledIdx = program.memsizer.memorySize(target.datatype, target.constArrayIndexValue!!.toInt())
|
||||||
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
|
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, CpuRegister.Y)
|
||||||
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
|
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2979,19 +2977,33 @@ $endLabel""")
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
if(wordtarget.array!!.splitWords)
|
if(wordtarget.array!!.splitWords) {
|
||||||
TODO("assign byte into split words ${wordtarget.position}")
|
// signed byte, we must sign-extend
|
||||||
if (wordtarget.constArrayIndexValue!=null) {
|
if (wordtarget.constArrayIndexValue!=null) {
|
||||||
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
|
val scaledIdx = wordtarget.constArrayIndexValue!!
|
||||||
asmgen.out(" lda $sourceName")
|
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_lsb+$scaledIdx")
|
||||||
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||||
asmgen.out(" sta ${wordtarget.asmVarname}+$scaledIdx | sty ${wordtarget.asmVarname}+$scaledIdx+1")
|
asmgen.out(" sty ${wordtarget.asmVarname}_msb+$scaledIdx")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
|
||||||
|
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_msb,x")
|
||||||
|
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||||
|
asmgen.out(" tya | sta ${wordtarget.asmVarname}_msb,x")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
|
if (wordtarget.constArrayIndexValue != null) {
|
||||||
asmgen.out(" lda $sourceName")
|
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
|
||||||
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
asmgen.out(" lda $sourceName")
|
||||||
asmgen.out(" sta ${wordtarget.asmVarname},x | inx | tya | sta ${wordtarget.asmVarname},x")
|
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||||
|
asmgen.out(" sta ${wordtarget.asmVarname}+$scaledIdx | sty ${wordtarget.asmVarname}+$scaledIdx+1")
|
||||||
|
} else {
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
|
||||||
|
asmgen.out(" lda $sourceName")
|
||||||
|
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||||
|
asmgen.out(" sta ${wordtarget.asmVarname},x | inx | tya | sta ${wordtarget.asmVarname},x")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.REGISTER -> {
|
TargetStorageKind.REGISTER -> {
|
||||||
@@ -3700,8 +3712,7 @@ $endLabel""")
|
|||||||
storeRegisterAInMemoryAddress(target.memory!!)
|
storeRegisterAInMemoryAddress(target.memory!!)
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
if(target.array!!.splitWords)
|
require(!target.array!!.splitWords)
|
||||||
TODO("assign into split words ${target.position}")
|
|
||||||
if (target.constArrayIndexValue!=null) {
|
if (target.constArrayIndexValue!=null) {
|
||||||
val indexValue = target.constArrayIndexValue!!
|
val indexValue = target.constArrayIndexValue!!
|
||||||
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue")
|
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue")
|
||||||
|
|||||||
@@ -904,10 +904,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
return null // TODO("inplace split word array +")
|
return null // TODO("inplace split word array -")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null // TODO("inplace split word array +")
|
return null // TODO("inplace split word array -")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun operatorPlusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
|
private fun operatorPlusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val resultRegister = codeGen.registers.nextFree()
|
val resultRegister = codeGen.registers.nextFree()
|
||||||
if(expr.isFromArrayElement) {
|
if(expr.isFromArrayElement) {
|
||||||
require(!expr.identifier.type.isSplitWordArray)
|
if(expr.identifier.type.isSplitWordArray)
|
||||||
|
TODO("address of element of a split word array")
|
||||||
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol), null)
|
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol), null)
|
||||||
val indexTr2 = translateExpression(expr.arrayIndexExpr!!)
|
val indexTr2 = translateExpression(expr.arrayIndexExpr!!)
|
||||||
addToResult(result, indexTr2, indexTr2.resultReg, -1)
|
addToResult(result, indexTr2, indexTr2.resultReg, -1)
|
||||||
|
|||||||
@@ -703,7 +703,12 @@ internal class AstChecker(private val program: Program,
|
|||||||
if (variable!=null) {
|
if (variable!=null) {
|
||||||
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
|
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
|
||||||
errors.err("invalid pointer-of operand type",addressOf.position)
|
errors.err("invalid pointer-of operand type",addressOf.position)
|
||||||
|
|
||||||
|
if(addressOf.arrayIndex!=null && variable.datatype.isSplitWordArray) {
|
||||||
|
errors.err("cannot take the adress of a word element that is in a split-word array", addressOf.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.visit(addressOf)
|
super.visit(addressOf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1467,18 +1472,18 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
|
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
|
||||||
// in-place modification, can't be done on literals
|
// in-place modification, can be done on specific types of arguments only (variables, array elements)
|
||||||
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
|
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
|
||||||
val firstArg = functionCallStatement.args[0]
|
val firstArg = functionCallStatement.args[0]
|
||||||
if(firstArg !is IdentifierReference && firstArg !is ArrayIndexedExpression)
|
if(firstArg !is IdentifierReference && firstArg !is ArrayIndexedExpression)
|
||||||
errors.err("invalid argument to a in-place modifying function", firstArg.position)
|
errors.err("this function can only act on an identifier or array element", firstArg.position)
|
||||||
} else if(funcName[0]=="divmod" || funcName[0].startsWith("divmod__")) {
|
} else if(funcName[0]=="divmod" || funcName[0].startsWith("divmod__")) {
|
||||||
val thirdArg = functionCallStatement.args[2]
|
val thirdArg = functionCallStatement.args[2]
|
||||||
val fourthArg = functionCallStatement.args[3]
|
val fourthArg = functionCallStatement.args[3]
|
||||||
if(thirdArg !is IdentifierReference && thirdArg !is ArrayIndexedExpression)
|
if(thirdArg !is IdentifierReference && thirdArg !is ArrayIndexedExpression)
|
||||||
errors.err("invalid argument to a in-place modifying function", thirdArg.position)
|
errors.err("this function can only act on an identifier or array element", thirdArg.position)
|
||||||
if(fourthArg !is IdentifierReference && fourthArg !is ArrayIndexedExpression)
|
if(fourthArg !is IdentifierReference && fourthArg !is ArrayIndexedExpression)
|
||||||
errors.err("invalid argument to a in-place modifying function", fourthArg.position)
|
errors.err("this function can only act on an identifier or array element", fourthArg.position)
|
||||||
} else {
|
} else {
|
||||||
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead })
|
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead })
|
||||||
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ TODO
|
|||||||
Future Things and Ideas
|
Future Things and Ideas
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- support &, &< and &> on array elements from split word arrays too not just the array as a whole (to get rid of the error "&< is only valid on array variables"
|
||||||
|
and "cannot take the adress of a word element that is in a split-word array" and the TODOS "address of element of a split word array")
|
||||||
|
- fix leftover asmgen split word array todo's
|
||||||
- Kotlin: can we use inline value classes in certain spots?
|
- Kotlin: can we use inline value classes in certain spots?
|
||||||
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||||
|
|
||||||
@@ -28,7 +31,6 @@ Future Things and Ideas
|
|||||||
|
|
||||||
- Allow normal subroutines to return multiple values as well (just as asmsubs already can)
|
- Allow normal subroutines to return multiple values as well (just as asmsubs already can)
|
||||||
- Change scoping rules for qualified symbols so that they don't always start from the root but behave like other programming languages (look in local scope first)
|
- Change scoping rules for qualified symbols so that they don't always start from the root but behave like other programming languages (look in local scope first)
|
||||||
- Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array")
|
|
||||||
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
|
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
|
||||||
- Improve register load order in subroutine call args assignments:
|
- Improve register load order in subroutine call args assignments:
|
||||||
in certain situations (need examples!), the "wrong" order of evaluation of function call arguments is done which results
|
in certain situations (need examples!), the "wrong" order of evaluation of function call arguments is done which results
|
||||||
@@ -47,6 +49,8 @@ Future Things and Ideas
|
|||||||
|
|
||||||
IR/VM
|
IR/VM
|
||||||
-----
|
-----
|
||||||
|
- fix TODO("IR rol/ror on split words array")
|
||||||
|
- fix "<< in array" / ">> in array"
|
||||||
- implement missing operators in AssignmentGen (array shifts etc)
|
- implement missing operators in AssignmentGen (array shifts etc)
|
||||||
- support %align on code chunks
|
- support %align on code chunks
|
||||||
- fix call() return value handling
|
- fix call() return value handling
|
||||||
|
|||||||
@@ -5,18 +5,17 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
&ubyte mmvar = $2000
|
uword[2] array1
|
||||||
|
|
||||||
txt.print_ub(@($2000))
|
array1[1] = $0122
|
||||||
|
txt.print_uwhex(array1[1], true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
@($2000) = 123
|
rol(array1[1])
|
||||||
txt.print_ub(@($2000))
|
txt.print_uwhex(array1[1], true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
sys.set_carry()
|
||||||
mmvar = 42
|
ror(array1[1])
|
||||||
txt.print_ub(@($2000))
|
txt.print_uwhex(array1[1], true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
cx16.r0 = 123
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user