mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
tweak pointer access, fix and optimize reading memory from a label as pointer
This commit is contained in:
parent
478e2b4ebd
commit
0ffebc25d0
@ -1164,12 +1164,13 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
|
||||
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression, allowNegativeIndex: Boolean=false): Pair<PtExpression, PtExpression>? {
|
||||
if (pointerOffsetExpr !is PtBinaryExpression) return null
|
||||
val operator = pointerOffsetExpr.operator
|
||||
val left = pointerOffsetExpr.left
|
||||
val right = pointerOffsetExpr.right
|
||||
if (operator != "+") return null
|
||||
if (operator != "+" && (operator != "-" || !allowNegativeIndex))
|
||||
return null
|
||||
val leftDt = left.type
|
||||
val rightDt = right.type
|
||||
if(leftDt.isUnsignedWord && rightDt.isUnsignedByte)
|
||||
@ -1212,70 +1213,166 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
if(addressExpr.operator=="+") {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr)
|
||||
if(ptrAndIndex!=null) {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr, false)
|
||||
if (ptrAndIndex == null) return false
|
||||
|
||||
if(write) {
|
||||
|
||||
// WRITING TO pointer + offset
|
||||
|
||||
val addrOf = ptrAndIndex.first as? PtAddressOf
|
||||
val constOffset = (ptrAndIndex.second as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && constOffset!=null) {
|
||||
if(addrOf.isFromArrayElement) {
|
||||
TODO("address-of array element $addrOf")
|
||||
} else {
|
||||
out(" sta ${asmSymbolName(addrOf.identifier)}+${constOffset}")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
val target = if(pointervar==null) null else symbolTable.lookup(pointervar.name)!!.astNode
|
||||
when(target) {
|
||||
is PtLabel -> {
|
||||
if(pointervar!=null && isZpVar(pointervar)) {
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA) out(" pha")
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (${asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.first) || evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA) out(" pha")
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda ${asmSymbolName(pointervar!!)},y")
|
||||
return true
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
pushCpuStack(BaseDataType.UBYTE, ptrAndIndex.second)
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
restoreRegisterStack(CpuRegister.Y, true)
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
is IPtVariable, null -> {
|
||||
if(write) {
|
||||
if(pointervar!=null && isZpVar(pointervar)) {
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA)
|
||||
out(" pha")
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA)
|
||||
out(" pla")
|
||||
out(" sta (${asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.first) || evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA)
|
||||
out(" pha")
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA)
|
||||
out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
pushCpuStack(BaseDataType.UBYTE, ptrAndIndex.second)
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
restoreRegisterStack(CpuRegister.Y, true)
|
||||
if(saveA)
|
||||
out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// READING FROM pointer + offset
|
||||
|
||||
val addrOf = ptrAndIndex.first as? PtAddressOf
|
||||
val constOffset = (ptrAndIndex.second as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && constOffset!=null) {
|
||||
if(addrOf.isFromArrayElement) {
|
||||
TODO("address-of array element $addrOf")
|
||||
} else {
|
||||
out(" lda ${asmSymbolName(addrOf.identifier)}+${constOffset}")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
val targetVariable = if(pointervar==null) null else symbolTable.lookup(pointervar.name)!!.astNode
|
||||
when(targetVariable) {
|
||||
is PtLabel -> {
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda ${asmSymbolName(pointervar!!)},y")
|
||||
return true
|
||||
}
|
||||
is IPtVariable, null -> {
|
||||
if(pointervar!=null && isZpVar(pointervar)) {
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda (${asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
if(pointervar!=null && isZpVar(pointervar)) {
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda (${asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
pushCpuStack(BaseDataType.UBYTE, ptrAndIndex.second)
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
restoreRegisterStack(CpuRegister.Y, false)
|
||||
out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
pushCpuStack(BaseDataType.UBYTE, ptrAndIndex.second)
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
restoreRegisterStack(CpuRegister.Y, false)
|
||||
out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> throw AssemblyError("invalid pointervar $pointervar")
|
||||
}
|
||||
}
|
||||
|
||||
else if(addressExpr.operator=="-") {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr, true)
|
||||
if (ptrAndIndex == null) return false
|
||||
|
||||
if(write) {
|
||||
|
||||
// WRITING TO pointer - offset
|
||||
|
||||
val addrOf = ptrAndIndex.first as? PtAddressOf
|
||||
val constOffset = (ptrAndIndex.second as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && constOffset!=null) {
|
||||
if(addrOf.isFromArrayElement) {
|
||||
TODO("address-of array element $addrOf")
|
||||
} else {
|
||||
out(" sta ${asmSymbolName(addrOf.identifier)}-${constOffset}")
|
||||
return true
|
||||
}
|
||||
else -> throw AssemblyError("invalid pointervar $pointervar")
|
||||
}
|
||||
|
||||
if(constOffset!=null) {
|
||||
println("MEMWRITE POINTER - $constOffset ${addressExpr.position}") // TODO
|
||||
/*
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
if(pointervar!=null && isZpVar(pointervar)) {
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA) out(" pha")
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (${asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.first) || evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA) out(" pha")
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
pushCpuStack(BaseDataType.UBYTE, ptrAndIndex.second)
|
||||
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
restoreRegisterStack(CpuRegister.Y, true)
|
||||
if(saveA) out(" pla")
|
||||
out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
return true
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
// READING FROM pointer - offset
|
||||
|
||||
val addrOf = ptrAndIndex.first as? PtAddressOf
|
||||
val constOffset = (ptrAndIndex.second as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && constOffset!=null) {
|
||||
if(addrOf.isFromArrayElement) {
|
||||
TODO("address-of array element $addrOf")
|
||||
} else {
|
||||
out(" lda ${asmSymbolName(addrOf.identifier)}-${constOffset}")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if(constOffset!=null) {
|
||||
println("MEMREAD POINTER - $constOffset ${addressExpr.position}") // TODO
|
||||
// TODO optimize more cases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -306,38 +306,29 @@ internal class AssignmentAsmGen(
|
||||
}
|
||||
}
|
||||
}
|
||||
SourceStorageKind.MEMORY -> {
|
||||
val value = assign.source.memory!!
|
||||
when (value.address) {
|
||||
is PtNumber -> {
|
||||
val address = (value.address as PtNumber).number.toUInt()
|
||||
assignMemoryByte(assign.target, address, null)
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
assignMemoryByte(assign.target, null, value.address as PtIdentifier)
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
val addrExpr = value.address as PtBinaryExpression
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||
assignRegisterByte(assign.target, CpuRegister.A, false, true)
|
||||
} else {
|
||||
assignByteFromAddressExpression(value.address, assign.target)
|
||||
}
|
||||
}
|
||||
else -> assignByteFromAddressExpression(value.address, assign.target)
|
||||
}
|
||||
}
|
||||
SourceStorageKind.EXPRESSION -> {
|
||||
assignExpression(assign, scope)
|
||||
}
|
||||
SourceStorageKind.REGISTER -> {
|
||||
asmgen.assignRegister(assign.source.register!!, assign.target)
|
||||
}
|
||||
SourceStorageKind.MEMORY -> assignByteFromAddressExpression(assign.source.memory!!.address, assign.target)
|
||||
SourceStorageKind.EXPRESSION -> assignExpression(assign, scope)
|
||||
SourceStorageKind.REGISTER -> asmgen.assignRegister(assign.source.register!!, assign.target)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignByteFromAddressExpression(address: PtExpression, target: AsmAssignTarget) {
|
||||
if(address is PtBinaryExpression) {
|
||||
|
||||
if (address is PtNumber) {
|
||||
val address = address.number.toUInt()
|
||||
assignMemoryByte(target, address, null)
|
||||
return
|
||||
}
|
||||
else if (address is PtIdentifier) {
|
||||
assignMemoryByte(target, null, address)
|
||||
return
|
||||
}
|
||||
else if (address is PtBinaryExpression) {
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(address, false)) {
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
return
|
||||
}
|
||||
|
||||
if(address.operator=="+" && address.right.type.isUnsignedWord) {
|
||||
if (address.left is PtIdentifier) {
|
||||
// use (zp),Y instead of explicitly calculating the full zp pointer value
|
||||
@ -376,9 +367,11 @@ internal class AssignmentAsmGen(
|
||||
}
|
||||
}
|
||||
// else if(address.operator=="-") {
|
||||
// // does this ever occur? we could optimize it too, but it seems like a pathological case
|
||||
// // TODO does this ever occur? we could optimize it too, but it seems like a pathological case
|
||||
// }
|
||||
}
|
||||
|
||||
// fallback assignmen through temporary pointer var
|
||||
assignExpressionToVariable(address, "P8ZP_SCRATCH_W2", DataType.forDt(BaseDataType.UWORD))
|
||||
asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2", false)
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
@ -4010,18 +4003,6 @@ $endLabel""")
|
||||
asmgen.storeAIntoPointerVar(addressExpr)
|
||||
}
|
||||
addressExpr is PtBinaryExpression -> {
|
||||
if(addressExpr.operator=="+" || addressExpr.operator=="-") {
|
||||
val addrOf = addressExpr.left as? PtAddressOf
|
||||
val offset = (addressExpr.right as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && offset!=null) {
|
||||
if(addrOf.isFromArrayElement) {
|
||||
TODO("address-of array element $addrOf")
|
||||
} else {
|
||||
asmgen.out(" sta ${asmgen.asmSymbolName(addrOf.identifier)}${addressExpr.operator}${offset}")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true))
|
||||
storeViaExprEval()
|
||||
}
|
||||
|
@ -169,10 +169,14 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
else -> {
|
||||
if(memory.address is PtBinaryExpression && tryOptimizedMemoryInplace(memory.address as PtBinaryExpression, operator, value))
|
||||
return
|
||||
// slower method to calculate and use the pointer to access the memory with:
|
||||
asmgen.assignExpressionToRegister(memory.address, RegisterOrPair.AY, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.A, true)
|
||||
asmgen.saveRegisterStack(CpuRegister.Y, true)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_in_AY_into_A")
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_in_AY_into_A_65c02")
|
||||
else
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_in_AY_into_A")
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> {
|
||||
inplacemodificationRegisterAwithVariable(operator, "#${value.boolean!!.asInt()}", false)
|
||||
@ -212,7 +216,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
asmgen.out(" jsr prog8_lib.write_byte_X_to_address_in_AY")
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
asmgen.out(" jsr prog8_lib.write_byte_X_to_address_in_AY_65c02")
|
||||
else
|
||||
asmgen.out(" jsr prog8_lib.write_byte_X_to_address_in_AY")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,13 @@ read_byte_from_address_in_AY_into_A .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
read_byte_from_address_in_AY_into_A_65c02 .proc
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
lda (P8ZP_SCRATCH_W2)
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
write_byte_X_to_address_in_AY .proc
|
||||
sta P8ZP_SCRATCH_W2
|
||||
@ -41,6 +48,14 @@ write_byte_X_to_address_in_AY .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
write_byte_X_to_address_in_AY_65c02 .proc
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
txa
|
||||
sta (P8ZP_SCRATCH_W2)
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
reg_less_uw .proc
|
||||
; AY < P8ZP_SCRATCH_W2?
|
||||
|
@ -265,7 +265,7 @@ _after:
|
||||
override fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||
// for word variables:
|
||||
// @(&var) --> lsb(var)
|
||||
// @(&var+1) --> msb(var)
|
||||
// @(&var+1) --> msb(var) NOTE: ONLY WHEN VAR IS AN ACTUAL WORD VARIABLE (POINTER)
|
||||
|
||||
val addrOf = memread.addressExpression as? AddressOf
|
||||
if(addrOf?.arrayIndex!=null)
|
||||
@ -279,8 +279,11 @@ _after:
|
||||
val addressOf = expr.left as? AddressOf
|
||||
val offset = (expr.right as? NumericLiteral)?.number?.toInt()
|
||||
if(addressOf!=null && offset==1) {
|
||||
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), memread.position), mutableListOf(addressOf.identifier), memread.position)
|
||||
return listOf(IAstModification.ReplaceNode(memread, msb, parent))
|
||||
val variable = addressOf.identifier.targetVarDecl(program)
|
||||
if(variable!=null && variable.datatype.isWord) {
|
||||
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), memread.position), mutableListOf(addressOf.identifier), memread.position)
|
||||
return listOf(IAstModification.ReplaceNode(memread, msb, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- optimize @(cell_ptr-offset) to use DEC pointer_msb ; LDY #255 ; INC pointer_msb instead. See tryOptimizedPointerAccessWithA()
|
||||
|
||||
|
||||
- add paypal donation button as well?
|
||||
- announce prog8 on the 6502.org site?
|
||||
|
||||
@ -83,7 +86,6 @@ Optimizations
|
||||
- if magicwall_enabled and (jiffy_counter & 3 == 1) sounds.magicwall() -> generates shortcut jump to another jump, why not immediately after the if
|
||||
- explode(x, y+1) pushes x on the stack and pops it, could simply load it in reverse order and not use the stack.normal
|
||||
- return mkword(attrs[cx16.r2L], object[cx16.r2L]) same as the explode() above
|
||||
- @(cell_ptr-1) = objects.amoeba uses temp zp pointer, also when cell_ptr is zp already?
|
||||
- x = y + z more efficient if rewritten to x=y; x+=z ?
|
||||
- return peekw(table+64+pos*2) .... or rather .. return <complex expression> -> can this be optimized by using a temporary variable and chop up the expression?
|
||||
likewise cx16.r0 = (gfx_lores.WIDTH-bmx.width)/2 + (gfx_lores.HEIGHT-bmx.height)/2*gfx_lores.WIDTH a lot of register juggling
|
||||
|
@ -1,23 +1,46 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
%zeropage kernalsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
word @shared dx
|
||||
uword @shared udx
|
||||
dx++
|
||||
udx++
|
||||
dx = -5000
|
||||
if abs(dx) < 9999
|
||||
txt.print("yes1")
|
||||
else
|
||||
txt.print("no2")
|
||||
ubyte[] array = [11,22,33,44,55,66,77,88,99]
|
||||
uword @shared ptr = &array[5]
|
||||
ubyte @shared offset
|
||||
|
||||
|
||||
cx16.r0L = @(&start + 1)
|
||||
cx16.r1L = @(&start - 1)
|
||||
@(&start+1) = 99
|
||||
@(&start-1) = 99
|
||||
|
||||
; @(ptr+1) = cx16.r0L
|
||||
; @(ptr+2) = cx16.r0L
|
||||
; @(ptr+offset) = cx16.r0L
|
||||
; @(ptr-1) = cx16.r0L
|
||||
; @(ptr-2) = cx16.r0L
|
||||
; @(ptr-offset) = cx16.r0L
|
||||
|
||||
|
||||
; cx16.r0L = @(ptr+1)
|
||||
; cx16.r1L = @(ptr+2)
|
||||
; cx16.r2L = @(ptr+offset)
|
||||
; cx16.r3L = @(ptr-1)
|
||||
; cx16.r4L = @(ptr-2)
|
||||
; cx16.r5L = @(ptr-offset)
|
||||
|
||||
|
||||
|
||||
; %asm {{
|
||||
; dec p8v_ptr+1
|
||||
; ldy #255
|
||||
; lda (p8v_ptr),y
|
||||
; inc p8v_ptr+1
|
||||
; sta cx16.r0L
|
||||
; }}
|
||||
|
||||
repeat {
|
||||
}
|
||||
|
||||
dx = -15000
|
||||
if abs(dx) < 9999
|
||||
txt.print("yes2")
|
||||
else
|
||||
txt.print("no2")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user