working on 6502 pointer dereferencing

This commit is contained in:
Irmen de Jong
2025-08-04 02:30:34 +02:00
parent 83ec437e8a
commit 6bd7752bac
6 changed files with 77 additions and 57 deletions

View File

@@ -96,6 +96,7 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
"prog8_lib_stringcompare" to FSignature(true, BaseDataType.BYTE, FParam("str1", BaseDataType.STR), FParam("str2", BaseDataType.STR)), "prog8_lib_stringcompare" to FSignature(true, BaseDataType.BYTE, FParam("str1", BaseDataType.STR), FParam("str2", BaseDataType.STR)),
"prog8_lib_square_byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)), "prog8_lib_square_byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)),
"prog8_lib_square_word" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD, BaseDataType.UWORD)), "prog8_lib_square_word" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD, BaseDataType.UWORD)),
"prog8_lib_structalloc" to FSignature(true, BaseDataType.UWORD),
"abs" to FSignature(true, null, FParam("value", *NumericDatatypes)), "abs" to FSignature(true, null, FParam("value", *NumericDatatypes)),
"abs__byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE)), "abs__byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE)),
"abs__word" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD)), "abs__word" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD)),

View File

@@ -397,10 +397,16 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
private fun funcStructAlloc(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultRegister: RegisterOrPair?) { private fun funcStructAlloc(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultRegister: RegisterOrPair?) {
if(discardResult) if(discardResult)
throw AssemblyError("should not discard result of struct allocation at $fcall") throw AssemblyError("should not discard result of struct allocation at $fcall")
if(fcall.args.isEmpty()) val struct = fcall.type.subType!!
TODO("struct alloc in BSS") // ... don't need to pay attention to args here because struct instance is put together elsewhere we just have to get a pointer to it
else val slabname = PtIdentifier("????TODO-STRUCTINSTANCENAME????", DataType.UWORD, fcall.position) // TODO STRUCTNAME
TODO("static struct alloc with values") val addressOf = PtAddressOf(fcall.type, true, fcall.position)
addressOf.add(slabname)
addressOf.parent = fcall
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, fcall.type, expression = addressOf)
val target = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, null, asmgen)
val assign = AsmAssignment(src, listOf(target), program.memsizer, fcall.position)
asmgen.translateNormalAssignment(assign, fcall.definingISub())
} }

View File

@@ -6,12 +6,12 @@ import prog8.codegen.cpu6502.AsmGen6502Internal
internal enum class TargetStorageKind { internal enum class TargetStorageKind {
VARIABLE, VARIABLE, // non-pointer variable
ARRAY, ARRAY,
MEMORY, MEMORY,
REGISTER, REGISTER,
POINTER, POINTER, // wherever the pointer variable points to
VOID // assign nothing - used in multi-value assigns for void placeholders VOID // assign nothing - used in multi-value assigns for void placeholders
} }
internal enum class SourceStorageKind { internal enum class SourceStorageKind {

View File

@@ -3541,7 +3541,7 @@ $endLabel""")
} }
internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
require(target.datatype.isNumeric || target.datatype.isPassByRef) { require(target.datatype.isNumeric || target.datatype.isPassByRef || target.datatype.isPointer) {
"assign target must be word type ${target.position}" "assign target must be word type ${target.position}"
} }
if(target.datatype.isFloat) if(target.datatype.isFloat)

View File

@@ -1,5 +1,6 @@
package prog8.codegen.cpu6502.assignment package prog8.codegen.cpu6502.assignment
import prog8.code.StStruct
import prog8.code.ast.IPtSubroutine import prog8.code.ast.IPtSubroutine
import prog8.code.ast.PtIdentifier import prog8.code.ast.PtIdentifier
import prog8.code.ast.PtPointerDeref import prog8.code.ast.PtPointerDeref
@@ -114,10 +115,56 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
} }
} }
TODO("deref pointer chain ${pointer.position}") // walk pointer chain, calculate pointer address using P8ZP_SCRATCH_W1
asmgen.assignExpressionToVariable(pointer.startpointer, "P8ZP_SCRATCH_W1", DataType.UWORD)
// TODO: do we have to look at derefLast ? fun addFieldOffset(fieldoffset: UInt) {
if(fieldoffset==0u)
return
require(fieldoffset<=0xffu)
asmgen.out("""
lda P8ZP_SCRATCH_W1
clc
adc #$fieldoffset
sta P8ZP_SCRATCH_W1
bcc +
inc P8ZP_SCRATCH_W1+1
+""")
}
fun updatePointer() {
asmgen.out("""
ldy #0
lda (P8ZP_SCRATCH_W1),y
tax
iny
lda (P8ZP_SCRATCH_W1),y
sta P8ZP_SCRATCH_W1+1
stx P8ZP_SCRATCH_W1""")
}
// traverse deref chain
var struct: StStruct? = null
if(pointer.startpointer.type.subType!=null)
struct = pointer.startpointer.type.subType as StStruct
for(deref in pointer.chain.dropLast(1)) {
val fieldinfo = struct!!.getField(deref, asmgen.program.memsizer)
val fieldoffset = fieldinfo.second
struct = fieldinfo.first.subType as StStruct
// get new pointer from field (P8ZP_SCRATCH_W1 += fieldoffset, read pointer from new location)
addFieldOffset(fieldoffset)
updatePointer()
}
val field = pointer.chain.last()
val fieldinfo = struct!!.getField(field, asmgen.program.memsizer)
addFieldOffset(fieldinfo.second)
if(pointer.derefLast) {
require(fieldinfo.first.isPointer)
updatePointer()
}
return "P8ZP_SCRATCH_W1"
} }
internal fun assignPointerDerefExpression(target: AsmAssignTarget, value: PtPointerDeref) { internal fun assignPointerDerefExpression(target: AsmAssignTarget, value: PtPointerDeref) {
@@ -126,7 +173,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
loadIndirectByte(zpPtrVar) loadIndirectByte(zpPtrVar)
asmgen.assignRegister(RegisterOrPair.A, target) asmgen.assignRegister(RegisterOrPair.A, target)
} }
else if(value.type.isWord) { else if(value.type.isWord || value.type.isPointer) {
loadIndirectWord(zpPtrVar) loadIndirectWord(zpPtrVar)
asmgen.assignRegister(RegisterOrPair.AY, target) asmgen.assignRegister(RegisterOrPair.AY, target)
} }

View File

@@ -1,60 +1,26 @@
%import textio %import textio
%import floats
%option no_sysinit %option no_sysinit
%zeropage basicsafe %zeropage basicsafe
main { main {
^^bool bptr = 30000 struct Node {
^^bool bptr2 uword value
^^ubyte ubptr = 30100 bool flag
^^ubyte ubptr2 ^^Node next
^^uword wptr = 30200 }
^^uword wptr2
^^float fptr = 30300
^^float fptr2
bool @shared bv = true
ubyte @shared ubv = 123
uword @shared uwv = 44444
float @shared fv = 3.1415927
sub start() { sub start() {
bptr^^ = bv ^^Node nptr = 30000
ubptr^^ = ubv ^^Node nptr2 = Node()
wptr^^ = uwv ^^Node nptr3 = Node(9999, true, 12345)
fptr^^ = fv
bv = bptr^^ txt.print_bool(nptr2.flag)
ubv = ubptr^^
uwv = wptr^^
fv = fptr^^
bv = bptr^^ or bv
ubv = ubptr^^ + 1
uwv = wptr^^ + 1
fv = fptr^^ + 1.1
bptr = fptr as ^^bool
bptr^^ = bptr^^ xor bv
ubptr^^ += 10
wptr^^ += 1000
fptr^^ += 1.1
bptr2 = bptr
ubptr2 = ubptr
wptr2 = wptr
fptr2 = fptr
txt.print_bool(bptr2^^)
txt.spc() txt.spc()
txt.print_ub(ubptr2^^) txt.print_bool(nptr3.flag)
txt.spc() txt.spc()
txt.print_uw(wptr2^^) txt.print_uw(nptr2.next)
txt.spc() txt.spc()
txt.print_f(fptr2^^) txt.print_uw(nptr3.next)
txt.nl()
} }
} }