mirror of
https://github.com/irmen/prog8.git
synced 2025-10-25 05:18:38 +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 ""
|
||||
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 -> {
|
||||
val indexer = fcall.args[0] as PtArrayIndexer
|
||||
val elementSize: Int
|
||||
|
||||
@@ -808,11 +808,11 @@ _jump jmp (${target.asmLabel})
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||
asmgen.out(" cpy #0")
|
||||
} else {
|
||||
var varname = asmgen.asmVariableName(value.identifier)
|
||||
if(value.identifier.type.isSplitWordArray) {
|
||||
TODO("address of split word array")
|
||||
} else {
|
||||
asmgen.out(" lda #>${asmgen.asmVariableName(value.identifier)}")
|
||||
varname += if(value.isMsbForSplitArray) "_msb" else "_lsb"
|
||||
}
|
||||
asmgen.out(" lda #>$varname")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@@ -1607,13 +1607,13 @@ _jump jmp (${target.asmLabel})
|
||||
if(left.isFromArrayElement)
|
||||
fallbackTranslateForSimpleCondition(stmt)
|
||||
else {
|
||||
if(left.identifier.type.isSplitWordArray) {
|
||||
TODO("address of split word array")
|
||||
val varname = if(left.identifier.type.isSplitWordArray) {
|
||||
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||
val varname = left.identifier.name
|
||||
translateAYNotEquals("#<$varname", "#>$varname")
|
||||
left.identifier.name
|
||||
}
|
||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||
translateAYNotEquals("#<$varname", "#>$varname")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@@ -1659,13 +1659,13 @@ _jump jmp (${target.asmLabel})
|
||||
if(left.isFromArrayElement)
|
||||
fallbackTranslateForSimpleCondition(stmt)
|
||||
else {
|
||||
if(left.identifier.type.isSplitWordArray) {
|
||||
TODO("address of split word array")
|
||||
val varname = if(left.identifier.type.isSplitWordArray) {
|
||||
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||
val varname = left.identifier.name
|
||||
translateAYEquals("#<$varname", "#>$varname")
|
||||
left.identifier.name
|
||||
}
|
||||
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||
translateAYEquals("#<$varname", "#>$varname")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
||||
@@ -1341,13 +1341,12 @@ internal class AssignmentAsmGen(
|
||||
|
||||
when (right) {
|
||||
is PtAddressOf -> {
|
||||
val symbol = asmgen.asmVariableName(right.identifier)
|
||||
var symbol = asmgen.asmVariableName(right.identifier)
|
||||
if(right.isFromArrayElement) {
|
||||
TODO("address-of array element $symbol at ${right.position}")
|
||||
} else {
|
||||
if(right.identifier.type.isSplitWordArray) {
|
||||
TODO("address of split word array")
|
||||
return true
|
||||
symbol = if(right.isMsbForSplitArray) symbol+"_msb" else symbol+"_lsb"
|
||||
}
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt.isSigned)
|
||||
if(expr.operator=="+")
|
||||
@@ -2579,7 +2578,8 @@ $endLabel""")
|
||||
|
||||
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
|
||||
if(arrayIndexExpr!=null) {
|
||||
require(arrayDt?.isSplitWordArray!=true)
|
||||
if(arrayDt?.isSplitWordArray==true)
|
||||
TODO("address of element of a split word array")
|
||||
val constIndex = arrayIndexExpr.asConstInteger()
|
||||
if(constIndex!=null) {
|
||||
if (arrayDt?.isUnsignedWord==true) {
|
||||
@@ -2930,14 +2930,12 @@ $endLabel""")
|
||||
storeRegisterAInMemoryAddress(target.memory!!)
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
if(target.array!!.splitWords)
|
||||
TODO("assign into split words ${target.position}")
|
||||
if (target.constArrayIndexValue!=null) {
|
||||
val scaledIdx = program.memsizer.memorySize(target.datatype, target.constArrayIndexValue!!.toInt())
|
||||
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
|
||||
}
|
||||
else {
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, CpuRegister.Y)
|
||||
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
|
||||
}
|
||||
}
|
||||
@@ -2979,19 +2977,33 @@ $endLabel""")
|
||||
""")
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
if(wordtarget.array!!.splitWords)
|
||||
TODO("assign byte into split words ${wordtarget.position}")
|
||||
if (wordtarget.constArrayIndexValue!=null) {
|
||||
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
|
||||
asmgen.out(" lda $sourceName")
|
||||
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||
asmgen.out(" sta ${wordtarget.asmVarname}+$scaledIdx | sty ${wordtarget.asmVarname}+$scaledIdx+1")
|
||||
if(wordtarget.array!!.splitWords) {
|
||||
// signed byte, we must sign-extend
|
||||
if (wordtarget.constArrayIndexValue!=null) {
|
||||
val scaledIdx = wordtarget.constArrayIndexValue!!
|
||||
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_lsb+$scaledIdx")
|
||||
asmgen.signExtendAYlsb(BaseDataType.BYTE)
|
||||
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 {
|
||||
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")
|
||||
if (wordtarget.constArrayIndexValue != null) {
|
||||
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
|
||||
asmgen.out(" lda $sourceName")
|
||||
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 -> {
|
||||
@@ -3700,8 +3712,7 @@ $endLabel""")
|
||||
storeRegisterAInMemoryAddress(target.memory!!)
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
if(target.array!!.splitWords)
|
||||
TODO("assign into split words ${target.position}")
|
||||
require(!target.array!!.splitWords)
|
||||
if (target.constArrayIndexValue!=null) {
|
||||
val indexValue = target.constArrayIndexValue!!
|
||||
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
|
||||
} 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? {
|
||||
|
||||
@@ -133,7 +133,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val resultRegister = codeGen.registers.nextFree()
|
||||
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)
|
||||
val indexTr2 = translateExpression(expr.arrayIndexExpr!!)
|
||||
addToResult(result, indexTr2, indexTr2.resultReg, -1)
|
||||
|
||||
@@ -703,7 +703,12 @@ internal class AstChecker(private val program: Program,
|
||||
if (variable!=null) {
|
||||
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -1467,18 +1472,18 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
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") {
|
||||
val firstArg = functionCallStatement.args[0]
|
||||
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__")) {
|
||||
val thirdArg = functionCallStatement.args[2]
|
||||
val fourthArg = functionCallStatement.args[3]
|
||||
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)
|
||||
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 {
|
||||
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)
|
||||
|
||||
@@ -10,6 +10,9 @@ TODO
|
||||
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?
|
||||
- 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)
|
||||
- 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>'?
|
||||
- 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
|
||||
@@ -47,6 +49,8 @@ Future Things and Ideas
|
||||
|
||||
IR/VM
|
||||
-----
|
||||
- fix TODO("IR rol/ror on split words array")
|
||||
- fix "<< in array" / ">> in array"
|
||||
- implement missing operators in AssignmentGen (array shifts etc)
|
||||
- support %align on code chunks
|
||||
- fix call() return value handling
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
&ubyte mmvar = $2000
|
||||
uword[2] array1
|
||||
|
||||
txt.print_ub(@($2000))
|
||||
array1[1] = $0122
|
||||
txt.print_uwhex(array1[1], true)
|
||||
txt.nl()
|
||||
@($2000) = 123
|
||||
txt.print_ub(@($2000))
|
||||
rol(array1[1])
|
||||
txt.print_uwhex(array1[1], true)
|
||||
txt.nl()
|
||||
|
||||
mmvar = 42
|
||||
txt.print_ub(@($2000))
|
||||
sys.set_carry()
|
||||
ror(array1[1])
|
||||
txt.print_uwhex(array1[1], true)
|
||||
txt.nl()
|
||||
|
||||
cx16.r0 = 123
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user