added peek() and peekw() builtin functions

This commit is contained in:
Irmen de Jong 2021-02-13 22:38:39 +01:00
parent 4fff150c7b
commit cc0f19653e
10 changed files with 59 additions and 20 deletions

View File

@ -1071,3 +1071,18 @@ sign_extend_AY_byte .proc
pla
rts
.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

View File

@ -2,6 +2,8 @@ package prog8.compiler.astprocessing
import prog8.ast.INameScope
import prog8.ast.Node
import prog8.ast.expressions.DirectMemoryRead
import prog8.ast.expressions.FunctionCall
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.TypecastExpression
import prog8.ast.statements.AnonymousScope
@ -43,4 +45,14 @@ internal class VariousCleanups: AstWalker() {
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
}
}

View File

@ -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("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("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("rndw" , false, emptyList(), DataType.UWORD),
FSignature("rndf" , false, emptyList(), DataType.FLOAT),

View File

@ -56,6 +56,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
"sort" -> funcSort(fcall)
"reverse" -> funcReverse(fcall)
"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}")
}
}
@ -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?) {
if(resultToStack) {
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb

View File

@ -413,10 +413,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
outputlni("}}")
}
override fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder) {
output(builtinFunctionStatementPlaceholder.name)
}
override fun visit(whenStatement: WhenStatement) {
output("when ")
whenStatement.condition.accept(this)

View File

@ -34,8 +34,8 @@ sealed class Statement : Node {
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : Statement() {
override var parent: Node = ParentSentinel
override fun linkParents(parent: Node) {}
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node")
override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node")
override fun definingScope(): INameScope = BuiltinFunctionScopePlaceholder
override fun replaceChildNode(node: Node, replacement: Node) {
replacement.parent = this

View File

@ -84,7 +84,6 @@ abstract class AstWalker {
open fun before(block: Block, 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(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, 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(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
@ -395,11 +394,6 @@ abstract class AstWalker {
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) {
track(before(nopStatement, parent), nopStatement, parent)
track(after(nopStatement, parent), nopStatement, parent)

View File

@ -158,9 +158,6 @@ interface IAstVisitor {
fun visit(inlineAssembly: InlineAssembly) {
}
fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder) {
}
fun visit(nopStatement: NopStatement) {
}

View File

@ -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
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()
returns a pseudo-random byte from 0..255

View File

@ -10,16 +10,16 @@ main {
@(ptr) = $34
@(ptr+1) = $ea
txt.print_ubhex(@(ptr), 1)
txt.print_ubhex(@(ptr+1), 1)
txt.print_ubhex(peek(ptr), 1)
txt.print_ubhex(peek(ptr+1), 1)
txt.nl()
uword ww = mkword(@(ptr+1), @(ptr)) ; TODO FIX
uword ww = peekw(ptr)
txt.print_uwhex(ww,1)
txt.nl()
ubyte low = @(ptr)
ubyte high = @(ptr+1)
ubyte low = peek(ptr)
ubyte high = peek(ptr+1)
ww = mkword(high, low)
txt.print_uwhex(ww,1)
txt.nl()