mirror of
https://github.com/irmen/prog8.git
synced 2025-10-25 05:18:38 +00:00
working on 6502 pointer dereferencing
This commit is contained in:
@@ -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)),
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user