mirror of
https://github.com/irmen/prog8.git
synced 2025-02-04 02:30:19 +00:00
it's now possible to use symbols that are the same name as 6502 instructions
because these are now prefixed internally before generating assembly.
This commit is contained in:
parent
10760a53a8
commit
f470576822
@ -18,7 +18,6 @@ interface IMachineDefinition {
|
||||
val PROGRAM_LOAD_ADDRESS : UInt
|
||||
var GOLDEN: UIntRange
|
||||
|
||||
val opcodeNames: Set<String>
|
||||
var zeropage: Zeropage
|
||||
val cpu: CpuType
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package prog8.code.target.atari
|
||||
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.c64.normal6502instructions
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
@ -61,6 +60,4 @@ class AtariMachineDefinition: IMachineDefinition {
|
||||
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||
zeropage = AtariZeropage(compilerOptions)
|
||||
}
|
||||
|
||||
override val opcodeNames = normal6502instructions
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package prog8.code.target.c128
|
||||
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.c64.normal6502instructions
|
||||
import prog8.code.target.cbm.Mflpt5
|
||||
import java.nio.file.Path
|
||||
|
||||
@ -51,6 +50,4 @@ class C128MachineDefinition: IMachineDefinition {
|
||||
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||
zeropage = C128Zeropage(compilerOptions)
|
||||
}
|
||||
|
||||
override val opcodeNames = normal6502instructions
|
||||
}
|
||||
|
@ -60,18 +60,4 @@ class C64MachineDefinition: IMachineDefinition {
|
||||
zeropage = C64Zeropage(compilerOptions)
|
||||
}
|
||||
|
||||
override val opcodeNames = normal6502instructions
|
||||
}
|
||||
|
||||
|
||||
// 6502 opcodes (including aliases and illegal opcodes), these cannot be used as variable or label names
|
||||
internal val normal6502instructions = setOf(
|
||||
"adc", "ahx", "alr", "anc", "and", "ane", "arr", "asl", "asr", "axs", "bcc", "bcs",
|
||||
"beq", "bge", "bit", "blt", "bmi", "bne", "bpl", "brk", "bvc", "bvs", "clc",
|
||||
"cld", "cli", "clv", "cmp", "cpx", "cpy", "dcm", "dcp", "dec", "dex", "dey",
|
||||
"eor", "gcc", "gcs", "geq", "gge", "glt", "gmi", "gne", "gpl", "gvc", "gvs",
|
||||
"inc", "ins", "inx", "iny", "isb", "isc", "jam", "jmp", "jsr", "lae", "las",
|
||||
"lax", "lda", "lds", "ldx", "ldy", "lsr", "lxa", "nop", "ora", "pha", "php",
|
||||
"pla", "plp", "rla", "rol", "ror", "rra", "rti", "rts", "sax", "sbc", "sbx",
|
||||
"sec", "sed", "sei", "sha", "shl", "shr", "shs", "shx", "shy", "slo", "sre",
|
||||
"sta", "stx", "sty", "tas", "tax", "tay", "tsx", "txa", "txs", "tya", "xaa")
|
@ -61,18 +61,4 @@ class CX16MachineDefinition: IMachineDefinition {
|
||||
zeropage = CX16Zeropage(compilerOptions)
|
||||
}
|
||||
|
||||
// 65c02 opcodes, these cannot be used as variable or label names
|
||||
override val opcodeNames = setOf("adc", "and", "asl", "bcc", "bcs",
|
||||
"beq", "bge", "bit", "blt", "bmi", "bne", "bpl", "brk", "bvc", "bvs", "clc",
|
||||
"cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey",
|
||||
"eor", "gcc", "gcs", "geq", "gge", "glt", "gmi", "gne", "gpl", "gvc", "gvs",
|
||||
"inc", "inx", "iny", "jmp", "jsr",
|
||||
"lda", "ldx", "ldy", "lsr", "nop", "ora", "pha", "php",
|
||||
"pla", "plp", "rol", "ror", "rti", "rts", "sbc",
|
||||
"sec", "sed", "sei",
|
||||
"sta", "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya",
|
||||
"bra", "phx", "phy", "plx", "ply", "stz", "trb", "tsb", "bbr", "bbs",
|
||||
"rmb", "smb", "stp", "wai")
|
||||
|
||||
|
||||
}
|
||||
|
@ -49,8 +49,6 @@ class VirtualMachineDefinition: IMachineDefinition {
|
||||
override fun isIOAddress(address: UInt): Boolean = false
|
||||
|
||||
override fun initializeZeropage(compilerOptions: CompilationOptions) {}
|
||||
|
||||
override val opcodeNames = emptySet<String>()
|
||||
}
|
||||
|
||||
interface IVirtualMachineRunner {
|
||||
|
@ -0,0 +1,49 @@
|
||||
package prog8.compiler.astprocessing
|
||||
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Label
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
class AsmInstructionNamesFinder(val target: ICompilationTarget): IAstVisitor {
|
||||
|
||||
val blocks = mutableSetOf<Block>()
|
||||
val variables = mutableSetOf<VarDecl>()
|
||||
val labels = mutableSetOf<Label>()
|
||||
val subroutines = mutableSetOf<Subroutine>()
|
||||
|
||||
private fun isPossibleInstructionName(name: String) = name.length==3 && name.all { it.isLetter() }
|
||||
|
||||
fun foundAny(): Boolean = blocks.isNotEmpty() || variables.isNotEmpty() || subroutines.isNotEmpty() || labels.isNotEmpty()
|
||||
|
||||
override fun visit(block: Block) {
|
||||
if(target.name!=VMTarget.NAME && !block.isInLibrary && isPossibleInstructionName(block.name)) {
|
||||
blocks += block
|
||||
}
|
||||
super.visit(block)
|
||||
}
|
||||
|
||||
override fun visit(decl: VarDecl) {
|
||||
if(target.name!=VMTarget.NAME && !decl.definingModule.isLibrary && isPossibleInstructionName(decl.name)) {
|
||||
variables += decl
|
||||
}
|
||||
super.visit(decl)
|
||||
}
|
||||
|
||||
override fun visit(label: Label) {
|
||||
if(target.name!=VMTarget.NAME && !label.definingModule.isLibrary && isPossibleInstructionName(label.name)) {
|
||||
labels += label
|
||||
}
|
||||
super.visit(label)
|
||||
}
|
||||
|
||||
override fun visit(subroutine: Subroutine) {
|
||||
if(target.name!=VMTarget.NAME && !subroutine.definingModule.isLibrary && isPossibleInstructionName(subroutine.name)) {
|
||||
subroutines += subroutine
|
||||
}
|
||||
super.visit(subroutine)
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package prog8.compiler.astprocessing
|
||||
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
|
||||
class AsmInstructionNamesReplacer(
|
||||
val blocks: Set<Block>,
|
||||
val subroutines: Set<Subroutine>,
|
||||
val variables: Set<VarDecl>,
|
||||
val labels: Set<Label>): AstWalker() {
|
||||
|
||||
override fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> {
|
||||
val newName = identifier.nameInSource.map { ident ->
|
||||
if(ident.length==3 && !identifier.definingModule.isLibrary) {
|
||||
val blockTarget = blocks.firstOrNull { it.name==ident }
|
||||
val subTarget = subroutines.firstOrNull {it.name==ident }
|
||||
val varTarget = variables.firstOrNull { it.name==ident }
|
||||
val labelTarget = labels.firstOrNull { it.name==ident}
|
||||
|
||||
if(blockTarget!=null || subTarget!=null || varTarget!=null || labelTarget!=null) {
|
||||
"p8p_$ident"
|
||||
} else
|
||||
ident
|
||||
} else
|
||||
ident
|
||||
}
|
||||
|
||||
return if(newName!=identifier.nameInSource)
|
||||
listOf(IAstModification.ReplaceNode(identifier, IdentifierReference(newName, identifier.position), parent))
|
||||
else
|
||||
noModifications
|
||||
}
|
||||
|
||||
override fun after(label: Label, parent: Node): Iterable<IAstModification> {
|
||||
return if(label in labels)
|
||||
listOf(IAstModification.ReplaceNode(label, Label("p8p_${label.name}", label.position), parent))
|
||||
else
|
||||
noModifications
|
||||
}
|
||||
|
||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||
return if(block in blocks)
|
||||
listOf(IAstModification.ReplaceNode(block, Block("p8p_${block.name}", block.address, block.statements, block.isInLibrary, block.position), parent))
|
||||
else
|
||||
noModifications
|
||||
}
|
||||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
return if(decl in variables)
|
||||
listOf(IAstModification.ReplaceNode(decl, decl.renamed("p8p_${decl.name}"), parent))
|
||||
else
|
||||
noModifications
|
||||
}
|
||||
|
||||
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
||||
val parameters = subroutine.parameters.map {
|
||||
if(it.name.length==3 && it.name.all { it.isLetter() } && !it.definingModule.isLibrary)
|
||||
SubroutineParameter("p8p_${it.name}", it.type, it.position) else it
|
||||
}
|
||||
|
||||
// TODO for all decls in the subroutine, update their subroutineParameter if something changed
|
||||
|
||||
val newName = if(subroutine in subroutines) "p8p_${subroutine.name}" else subroutine.name
|
||||
|
||||
return if(newName!=subroutine.name || parameters.map{ it.name} != subroutine.parameters.map {it.name})
|
||||
listOf(IAstModification.ReplaceNode(subroutine,
|
||||
Subroutine(newName, parameters.toMutableList(), subroutine.returntypes,
|
||||
subroutine.asmParameterRegisters, subroutine.asmReturnvaluesRegisters, subroutine.asmClobbers, subroutine.asmAddress, subroutine.isAsmSubroutine,
|
||||
subroutine.inline, subroutine.statements, subroutine.position), parent))
|
||||
else
|
||||
noModifications
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,7 @@ import prog8.ast.statements.VarDeclOrigin
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
|
||||
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
@ -26,6 +27,21 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
|
||||
val boolRemover = BoolRemover(this)
|
||||
boolRemover.visit(this)
|
||||
boolRemover.applyModifications()
|
||||
|
||||
if(compilerOptions.compTarget.name!=VMTarget.NAME) {
|
||||
val finder = AsmInstructionNamesFinder(compilerOptions.compTarget)
|
||||
finder.visit(this)
|
||||
if(finder.foundAny()) {
|
||||
val replacer = AsmInstructionNamesReplacer(
|
||||
finder.blocks,
|
||||
finder.subroutines,
|
||||
finder.variables,
|
||||
finder.labels)
|
||||
replacer.visit(this)
|
||||
replacer.applyModifications()
|
||||
}
|
||||
}
|
||||
|
||||
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
|
||||
fixer.visit(this)
|
||||
while (errors.noErrors() && fixer.applyModifications() > 0) {
|
||||
|
@ -29,9 +29,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
}
|
||||
|
||||
override fun visit(block: Block) {
|
||||
if(block.name in compTarget.machine.opcodeNames)
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position)
|
||||
|
||||
val existing = blocks[block.name]
|
||||
if(existing!=null) {
|
||||
if(block.isInLibrary)
|
||||
@ -51,9 +48,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
if(decl.name in BuiltinFunctions)
|
||||
errors.err("builtin function cannot be redefined", decl.position)
|
||||
|
||||
if(decl.name in compTarget.machine.opcodeNames)
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
|
||||
|
||||
val existingInSameScope = decl.definingScope.lookup(listOf(decl.name))
|
||||
if(existingInSameScope!=null && existingInSameScope!==decl)
|
||||
nameError(decl.name, decl.position, existingInSameScope)
|
||||
@ -75,9 +69,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
}
|
||||
|
||||
override fun visit(subroutine: Subroutine) {
|
||||
if(subroutine.name in compTarget.machine.opcodeNames) {
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position)
|
||||
} else if(subroutine.name in BuiltinFunctions) {
|
||||
if(subroutine.name in BuiltinFunctions) {
|
||||
// the builtin functions can't be redefined
|
||||
errors.err("builtin function cannot be redefined", subroutine.position)
|
||||
} else {
|
||||
@ -121,9 +113,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
}
|
||||
|
||||
override fun visit(label: Label) {
|
||||
if(label.name in compTarget.machine.opcodeNames)
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
|
||||
|
||||
if(label.name in BuiltinFunctions) {
|
||||
errors.err("builtin function cannot be redefined", label.position)
|
||||
} else {
|
||||
|
@ -40,7 +40,7 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
|
||||
strLits[0].value shouldBe "main.bar"
|
||||
strLits[1].value shouldBe "foo.bar"
|
||||
strLits[0].definingScope.name shouldBe "main"
|
||||
strLits[1].definingScope.name shouldBe "foo"
|
||||
strLits[1].definingScope.name shouldBe "foobar"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.code.target.c64.C64Zeropage
|
||||
import prog8.codegen.cpu6502.AsmGen
|
||||
import prog8.compiler.astprocessing.SymbolTableMaker
|
||||
@ -173,4 +174,48 @@ main {
|
||||
val result = compileText(C64Target(), false, text, writeAssembly = true)
|
||||
result shouldNotBe null
|
||||
}
|
||||
|
||||
"identifiers can have the names of cpu instructions" {
|
||||
val text="""
|
||||
%import textio
|
||||
|
||||
nop {
|
||||
sub lda(ubyte sec) -> ubyte {
|
||||
asl:
|
||||
ubyte brk = sec
|
||||
sec++
|
||||
brk += sec
|
||||
return brk
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
|
||||
sub ffalse(ubyte arg) -> ubyte {
|
||||
arg++
|
||||
return 0
|
||||
}
|
||||
sub ftrue(ubyte arg) -> ubyte {
|
||||
arg++
|
||||
return 128
|
||||
}
|
||||
|
||||
sub start() {
|
||||
ubyte col = 10
|
||||
ubyte row = 20
|
||||
txt.print_ub(nop.lda(42))
|
||||
txt.nl()
|
||||
txt.print_uw(nop.lda.asl)
|
||||
|
||||
void ffalse(99)
|
||||
void ftrue(99)
|
||||
}
|
||||
}
|
||||
"""
|
||||
val result = compileText(C64Target(), false, text, writeAssembly = true)
|
||||
result shouldNotBe null
|
||||
val result2 = compileText(VMTarget(), false, text, writeAssembly = true)
|
||||
result2 shouldNotBe null
|
||||
|
||||
}
|
||||
})
|
||||
|
2
compiler/test/fixtures/foo_bar.asm
vendored
2
compiler/test/fixtures/foo_bar.asm
vendored
@ -1,2 +1,2 @@
|
||||
bar .text "foo.bar",0
|
||||
barbar .text "foo.bar",0
|
||||
|
||||
|
4
compiler/test/fixtures/foo_bar.p8
vendored
4
compiler/test/fixtures/foo_bar.p8
vendored
@ -1,3 +1,3 @@
|
||||
foo {
|
||||
str bar = "foo.bar"
|
||||
foobar {
|
||||
str barbar = "foo.bar"
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ main {
|
||||
str myBar = "main.bar"
|
||||
sub start() {
|
||||
txt.print(myBar)
|
||||
txt.print(foo.bar)
|
||||
txt.print(foobar.barbar)
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +268,13 @@ class VarDecl(val type: VarDeclType,
|
||||
return copy
|
||||
}
|
||||
|
||||
fun renamed(newName: String): VarDecl {
|
||||
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize, newName, value,
|
||||
isArray, sharedWithAsm, subroutineParameter, position)
|
||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
return copy
|
||||
}
|
||||
|
||||
fun findInitializer(program: Program): Assignment? =
|
||||
(parent as IStatementContainer).statements
|
||||
.asSequence()
|
||||
|
@ -195,17 +195,22 @@ Directives
|
||||
.. data:: %breakpoint
|
||||
|
||||
Level: not at module scope.
|
||||
Defines a debugging breakpoint at this location. See :ref:`debugging`
|
||||
Defines a debugging breakpoint at this location. See :ref:`debugging`
|
||||
|
||||
.. data:: %asm {{ ... }}
|
||||
|
||||
Level: not at module scope.
|
||||
Declares that a piece of *assembly code* is inside the curly braces.
|
||||
This code will be copied as-is into the generated output assembly source file.
|
||||
The assembler syntax used should be for the 3rd party cross assembler tool that Prog8 uses (64tass).
|
||||
Note that the start and end markers are both *double curly braces* to minimize the chance
|
||||
that the assembly code itself contains either of those. If it does contain a ``}}``,
|
||||
it will confuse the parser.
|
||||
Declares that a piece of *assembly code* is inside the curly braces.
|
||||
This code will be copied as-is into the generated output assembly source file.
|
||||
The assembler syntax used should be for the 3rd party cross assembler tool that Prog8 uses (64tass).
|
||||
Note that the start and end markers are both *double curly braces* to minimize the chance
|
||||
that the assembly code itself contains either of those. If it does contain a ``}}``,
|
||||
it will confuse the parser.
|
||||
|
||||
If you use the correct scoping rules you can access symbols from the prog8 program from inside
|
||||
the assembly code. Sometimes you'll have to declare a variable in prog8 with `@shared` if it
|
||||
is only used in such assembly code. For symbols just consisting of 3 letters, prog8 will
|
||||
add a special prefix to them, read more about this in :ref:`three-letter-prefixing`.
|
||||
|
||||
|
||||
Identifiers
|
||||
|
@ -13,6 +13,21 @@ Especially when you're dealing with interrupts or re-entrant routines: don't mod
|
||||
that you not own or else you will break stuff.
|
||||
|
||||
|
||||
.. _three-letter-prefixing:
|
||||
|
||||
Three-letter symbols prefixing in Assembly
|
||||
------------------------------------------
|
||||
|
||||
Symbols consisting of three letters such as "brk" or "tax" will confuse the assembler that
|
||||
thinks these are cpu instructions. It will likely fail to assemble the program correctly.
|
||||
Because of this, prog8 will prefix every 3-letter symbol with "``p8p_``" automatically during compilation.
|
||||
So "tax" will become "p8p_tax" in the resulting assembly code.
|
||||
|
||||
If you're referencing symbols from the prog8 program in hand-written assembly code, you have to take
|
||||
this into account. Either prefix the 3-letter symbols in the assembly with "``p8p_``" as well, or just
|
||||
choose a shorter or longer symbol name in the first place.
|
||||
|
||||
|
||||
Software stack for expression evaluation
|
||||
----------------------------------------
|
||||
|
||||
|
@ -3,8 +3,7 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
|
||||
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
|
||||
- AsmInstructionNamesReplacer: fix the TODO about the params
|
||||
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
||||
- regression test the various projects
|
||||
|
||||
|
152
examples/test.p8
152
examples/test.p8
@ -1,131 +1,37 @@
|
||||
%import textio
|
||||
%zeropage dontuse
|
||||
|
||||
|
||||
; base level code size: $279
|
||||
%import cx16logo
|
||||
|
||||
nop {
|
||||
sub lda(ubyte sec) -> ubyte {
|
||||
asl:
|
||||
ubyte brk = sec
|
||||
sec++
|
||||
brk += sec
|
||||
return brk
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
bool[1] expected = [ true ]
|
||||
uword[1] expectedw = [4242 ]
|
||||
|
||||
sub get() -> bool {
|
||||
ubyte xx
|
||||
xx = 1
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub same() -> bool {
|
||||
ubyte xx
|
||||
xx = 1
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub ffalse(ubyte arg) -> ubyte {
|
||||
arg++
|
||||
return 0
|
||||
}
|
||||
sub ftrue(ubyte arg) -> ubyte {
|
||||
arg++
|
||||
return 128
|
||||
}
|
||||
|
||||
sub getw() -> uword {
|
||||
uword xx=4242
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub samew() -> uword {
|
||||
uword xx=4242
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub differentw() -> uword {
|
||||
uword xx=9999
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub one() -> ubyte {
|
||||
ubyte xx=1
|
||||
%asm {{
|
||||
stz P8ZP_SCRATCH_W1
|
||||
stz P8ZP_SCRATCH_W1+1
|
||||
stz P8ZP_SCRATCH_W2
|
||||
stz P8ZP_SCRATCH_W2+1
|
||||
stz P8ZP_SCRATCH_REG
|
||||
stz P8ZP_SCRATCH_B1
|
||||
}}
|
||||
return xx
|
||||
}
|
||||
sub start() {
|
||||
ubyte col = 10
|
||||
ubyte row = 20
|
||||
cx16logo.logo_at(col, row)
|
||||
txt.setcc(10, 10, 2, 3)
|
||||
txt.print_ub(nop.lda(42))
|
||||
txt.nl()
|
||||
txt.print_uw(nop.lda.asl)
|
||||
|
||||
sub start() {
|
||||
if getw() == samew()
|
||||
txt.print("ok\n")
|
||||
else
|
||||
txt.print("fail\n")
|
||||
|
||||
if samew() == getw()
|
||||
txt.print("ok\n")
|
||||
else
|
||||
txt.print("fail\n")
|
||||
|
||||
if getw() != samew()
|
||||
txt.print("fail\n")
|
||||
else
|
||||
txt.print("ok\n")
|
||||
|
||||
if samew() != getw()
|
||||
txt.print("fail\n")
|
||||
else
|
||||
txt.print("ok\n")
|
||||
|
||||
|
||||
if getw() == differentw()
|
||||
txt.print("fail\n")
|
||||
else
|
||||
txt.print("ok\n")
|
||||
|
||||
if differentw() == getw()
|
||||
txt.print("fail\n")
|
||||
else
|
||||
txt.print("ok\n")
|
||||
|
||||
if getw() != differentw()
|
||||
txt.print("ok\n")
|
||||
else
|
||||
txt.print("fail\n")
|
||||
|
||||
if differentw() != getw()
|
||||
txt.print("ok\n")
|
||||
else
|
||||
txt.print("fail\n")
|
||||
|
||||
}
|
||||
void ffalse(99)
|
||||
void ftrue(99)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user