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_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_structalloc" to FSignature(true, BaseDataType.UWORD),
"abs" to FSignature(true, null, FParam("value", *NumericDatatypes)),
"abs__byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE)),
"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?) {
if(discardResult)
throw AssemblyError("should not discard result of struct allocation at $fcall")
if(fcall.args.isEmpty())
TODO("struct alloc in BSS")
else
TODO("static struct alloc with values")
val struct = fcall.type.subType!!
// ... 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
val slabname = PtIdentifier("????TODO-STRUCTINSTANCENAME????", DataType.UWORD, fcall.position) // TODO STRUCTNAME
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 {
VARIABLE,
VARIABLE, // non-pointer variable
ARRAY,
MEMORY,
REGISTER,
POINTER,
VOID // assign nothing - used in multi-value assigns for void placeholders
POINTER, // wherever the pointer variable points to
VOID // assign nothing - used in multi-value assigns for void placeholders
}
internal enum class SourceStorageKind {

View File

@@ -3541,7 +3541,7 @@ $endLabel""")
}
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}"
}
if(target.datatype.isFloat)

View File

@@ -1,5 +1,6 @@
package prog8.codegen.cpu6502.assignment
import prog8.code.StStruct
import prog8.code.ast.IPtSubroutine
import prog8.code.ast.PtIdentifier
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) {
@@ -126,7 +173,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
loadIndirectByte(zpPtrVar)
asmgen.assignRegister(RegisterOrPair.A, target)
}
else if(value.type.isWord) {
else if(value.type.isWord || value.type.isPointer) {
loadIndirectWord(zpPtrVar)
asmgen.assignRegister(RegisterOrPair.AY, target)
}

View File

@@ -1,60 +1,26 @@
%import textio
%import floats
%option no_sysinit
%zeropage basicsafe
main {
^^bool bptr = 30000
^^bool bptr2
^^ubyte ubptr = 30100
^^ubyte ubptr2
^^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
struct Node {
uword value
bool flag
^^Node next
}
sub start() {
bptr^^ = bv
ubptr^^ = ubv
wptr^^ = uwv
fptr^^ = fv
^^Node nptr = 30000
^^Node nptr2 = Node()
^^Node nptr3 = Node(9999, true, 12345)
bv = bptr^^
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.print_bool(nptr2.flag)
txt.spc()
txt.print_ub(ubptr2^^)
txt.print_bool(nptr3.flag)
txt.spc()
txt.print_uw(wptr2^^)
txt.print_uw(nptr2.next)
txt.spc()
txt.print_f(fptr2^^)
txt.nl()
txt.print_uw(nptr3.next)
}
}