mirror of
https://github.com/irmen/prog8.git
synced 2024-10-19 22:24:17 +00:00
added peek() and peekw() builtin functions
This commit is contained in:
parent
4fff150c7b
commit
cc0f19653e
@ -1071,3 +1071,18 @@ sign_extend_AY_byte .proc
|
|||||||
pla
|
pla
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
peekw .proc
|
||||||
|
; -- read the word value on the address in AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
ldy #0
|
||||||
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
|
pha
|
||||||
|
iny
|
||||||
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
|
tay
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
@ -2,6 +2,8 @@ package prog8.compiler.astprocessing
|
|||||||
|
|
||||||
import prog8.ast.INameScope
|
import prog8.ast.INameScope
|
||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
|
import prog8.ast.expressions.DirectMemoryRead
|
||||||
|
import prog8.ast.expressions.FunctionCall
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.expressions.TypecastExpression
|
import prog8.ast.expressions.TypecastExpression
|
||||||
import prog8.ast.statements.AnonymousScope
|
import prog8.ast.statements.AnonymousScope
|
||||||
@ -43,4 +45,14 @@ internal class VariousCleanups: AstWalker() {
|
|||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
||||||
|
if(functionCall.target.nameInSource==listOf("peek")) {
|
||||||
|
// peek is synonymous with @
|
||||||
|
val memread = DirectMemoryRead(functionCall.args.single(), functionCall.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(functionCall, memread, parent))
|
||||||
|
}
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,8 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||||||
FSignature("lsb" , true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x and 255 } },
|
FSignature("lsb" , true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x and 255 } },
|
||||||
FSignature("msb" , true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x ushr 8 and 255} },
|
FSignature("msb" , true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x ushr 8 and 255} },
|
||||||
FSignature("mkword" , true, listOf(FParam("msb", setOf(DataType.UBYTE)), FParam("lsb", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinMkword),
|
FSignature("mkword" , true, listOf(FParam("msb", setOf(DataType.UBYTE)), FParam("lsb", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinMkword),
|
||||||
|
FSignature("peek" , true, listOf(FParam("address", setOf(DataType.UWORD))), DataType.UBYTE),
|
||||||
|
FSignature("peekw" , true, listOf(FParam("address", setOf(DataType.UWORD))), DataType.UWORD),
|
||||||
FSignature("rnd" , false, emptyList(), DataType.UBYTE),
|
FSignature("rnd" , false, emptyList(), DataType.UBYTE),
|
||||||
FSignature("rndw" , false, emptyList(), DataType.UWORD),
|
FSignature("rndw" , false, emptyList(), DataType.UWORD),
|
||||||
FSignature("rndf" , false, emptyList(), DataType.FLOAT),
|
FSignature("rndf" , false, emptyList(), DataType.FLOAT),
|
||||||
|
@ -56,6 +56,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
"sort" -> funcSort(fcall)
|
"sort" -> funcSort(fcall)
|
||||||
"reverse" -> funcReverse(fcall)
|
"reverse" -> funcReverse(fcall)
|
||||||
"memory" -> funcMemory(fcall, discardResult, resultToStack, resultRegister)
|
"memory" -> funcMemory(fcall, discardResult, resultToStack, resultRegister)
|
||||||
|
"peekw" -> funcPeekW(fcall, resultToStack, resultRegister)
|
||||||
|
"peek" -> throw AssemblyError("peek() should have been replaced by @()")
|
||||||
else -> TODO("missing asmgen for builtin func ${func.name}")
|
else -> TODO("missing asmgen for builtin func ${func.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -958,6 +960,22 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun funcPeekW(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||||
|
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||||
|
asmgen.out(" jsr prog8_lib.peekw")
|
||||||
|
if(resultToStack){
|
||||||
|
asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
||||||
|
} else {
|
||||||
|
when(resultRegister ?: RegisterOrPair.AY) {
|
||||||
|
RegisterOrPair.AY -> {}
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" sty P8ZP_SCRATCH_REG | ldx P8ZP_SCRATCH_REG")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" tax")
|
||||||
|
in Cx16VirtualRegisters -> asmgen.out(" sta cx16.${resultRegister.toString().toLowerCase()} | sty cx16.${resultRegister.toString().toLowerCase()}+1")
|
||||||
|
else -> throw AssemblyError("invalid reg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun funcMkword(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
private fun funcMkword(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
|
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
|
||||||
|
@ -413,10 +413,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||||||
outputlni("}}")
|
outputlni("}}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder) {
|
|
||||||
output(builtinFunctionStatementPlaceholder.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visit(whenStatement: WhenStatement) {
|
override fun visit(whenStatement: WhenStatement) {
|
||||||
output("when ")
|
output("when ")
|
||||||
whenStatement.condition.accept(this)
|
whenStatement.condition.accept(this)
|
||||||
|
@ -34,8 +34,8 @@ sealed class Statement : Node {
|
|||||||
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : Statement() {
|
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : Statement() {
|
||||||
override var parent: Node = ParentSentinel
|
override var parent: Node = ParentSentinel
|
||||||
override fun linkParents(parent: Node) {}
|
override fun linkParents(parent: Node) {}
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node")
|
||||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node")
|
||||||
override fun definingScope(): INameScope = BuiltinFunctionScopePlaceholder
|
override fun definingScope(): INameScope = BuiltinFunctionScopePlaceholder
|
||||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||||
replacement.parent = this
|
replacement.parent = this
|
||||||
|
@ -84,7 +84,6 @@ abstract class AstWalker {
|
|||||||
open fun before(block: Block, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(block: Block, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = emptyList()
|
|
||||||
open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
@ -395,11 +394,6 @@ abstract class AstWalker {
|
|||||||
track(after(inlineAssembly, parent), inlineAssembly, parent)
|
track(after(inlineAssembly, parent), inlineAssembly, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node) {
|
|
||||||
track(before(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
|
|
||||||
track(after(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun visit(nopStatement: NopStatement, parent: Node) {
|
fun visit(nopStatement: NopStatement, parent: Node) {
|
||||||
track(before(nopStatement, parent), nopStatement, parent)
|
track(before(nopStatement, parent), nopStatement, parent)
|
||||||
track(after(nopStatement, parent), nopStatement, parent)
|
track(after(nopStatement, parent), nopStatement, parent)
|
||||||
|
@ -158,9 +158,6 @@ interface IAstVisitor {
|
|||||||
fun visit(inlineAssembly: InlineAssembly) {
|
fun visit(inlineAssembly: InlineAssembly) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun visit(nopStatement: NopStatement) {
|
fun visit(nopStatement: NopStatement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,6 +803,11 @@ mkword(msb, lsb)
|
|||||||
Don't get confused by how the system actually stores this 16-bit word value in memory (which is
|
Don't get confused by how the system actually stores this 16-bit word value in memory (which is
|
||||||
in little-endian format, so lsb first then msb)
|
in little-endian format, so lsb first then msb)
|
||||||
|
|
||||||
|
peek(address)
|
||||||
|
same as @(address) - reads the byte at the given address in memory.
|
||||||
|
|
||||||
|
peekw(address)
|
||||||
|
reads the word value at the given address in memory. Word is assumed to be stored in usual lsb/msb byte order.
|
||||||
|
|
||||||
rnd()
|
rnd()
|
||||||
returns a pseudo-random byte from 0..255
|
returns a pseudo-random byte from 0..255
|
||||||
|
@ -10,16 +10,16 @@ main {
|
|||||||
@(ptr) = $34
|
@(ptr) = $34
|
||||||
@(ptr+1) = $ea
|
@(ptr+1) = $ea
|
||||||
|
|
||||||
txt.print_ubhex(@(ptr), 1)
|
txt.print_ubhex(peek(ptr), 1)
|
||||||
txt.print_ubhex(@(ptr+1), 1)
|
txt.print_ubhex(peek(ptr+1), 1)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
uword ww = mkword(@(ptr+1), @(ptr)) ; TODO FIX
|
uword ww = peekw(ptr)
|
||||||
txt.print_uwhex(ww,1)
|
txt.print_uwhex(ww,1)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
ubyte low = @(ptr)
|
ubyte low = peek(ptr)
|
||||||
ubyte high = @(ptr+1)
|
ubyte high = peek(ptr+1)
|
||||||
ww = mkword(high, low)
|
ww = mkword(high, low)
|
||||||
txt.print_uwhex(ww,1)
|
txt.print_uwhex(ww,1)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
Loading…
Reference in New Issue
Block a user