diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 03e15f52f..fbe0687c7 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -451,66 +451,49 @@ internal class AstChecker(private val program: Program, } } - val regCounts = mutableMapOf().withDefault { 0 } - val statusflagCounts = mutableMapOf().withDefault { 0 } + val regsUsed = mutableListOf() + val statusflagUsed = mutableListOf() fun countRegisters(from: Iterable) { - regCounts.clear() - statusflagCounts.clear() + regsUsed.clear() + statusflagUsed.clear() for(p in from) { when(p.registerOrPair) { - RegisterOrPair.A -> regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1 - RegisterOrPair.X -> regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1 - RegisterOrPair.Y -> regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1 + null -> { + if (p.statusflag != null) + statusflagUsed += p.statusflag!! + } RegisterOrPair.AX -> { - regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1 - regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1 + regsUsed += RegisterOrPair.A + regsUsed += RegisterOrPair.X } RegisterOrPair.AY -> { - regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1 - regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1 + regsUsed += RegisterOrPair.A + regsUsed += RegisterOrPair.Y } RegisterOrPair.XY -> { - regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1 - regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1 - } - RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> { /* no sensible way to count this */ } - RegisterOrPair.R0, - RegisterOrPair.R1, - RegisterOrPair.R2, - RegisterOrPair.R3, - RegisterOrPair.R4, - RegisterOrPair.R5, - RegisterOrPair.R6, - RegisterOrPair.R7, - RegisterOrPair.R8, - RegisterOrPair.R9, - RegisterOrPair.R10, - RegisterOrPair.R11, - RegisterOrPair.R12, - RegisterOrPair.R13, - RegisterOrPair.R14, - RegisterOrPair.R15 -> { /* no sensible way to count this */ } - null -> { - val statusf = p.statusflag - if (statusf != null) - statusflagCounts[statusf] = statusflagCounts.getValue(statusf) + 1 + regsUsed += RegisterOrPair.X + regsUsed += RegisterOrPair.Y } + else -> regsUsed += p.registerOrPair!! } } } countRegisters(subroutine.asmParameterRegisters) - if(regCounts.any{it.value>1}) + if(regsUsed.size != regsUsed.toSet().size) err("a register is used multiple times in the parameters") - if(statusflagCounts.any{it.value>1}) + if(statusflagUsed.size != statusflagUsed.toSet().size) err("a status flag is used multiple times in the parameters") + countRegisters(subroutine.asmReturnvaluesRegisters) - if(regCounts.any{it.value>1}) + if(regsUsed.size != regsUsed.toSet().size) err("a register is used multiple times in the return values") - if(statusflagCounts.any{it.value>1}) + if(statusflagUsed.size != statusflagUsed.toSet().size) err("a status flag is used multiple times in the return values") - if(subroutine.asmClobbers.intersect(regCounts.keys).isNotEmpty()) - err("a return register is also in the clobber list") + for(reg in subroutine.asmClobbers) { + if(regsUsed.contains(RegisterOrPair.fromCpuRegister(reg))) + err("a return register is also in the clobber list") + } if(subroutine.statements.any{it !is InlineAssembly}) err("asmsub can only contain inline assembly (%asm)") diff --git a/examples/test.p8 b/examples/test.p8 index c8038ce8e..8def12622 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,31 +3,34 @@ main { sub start() { - const long foo2 = $123456 - cx16.r0 = $ffff - cx16.r1 = $ea31 - txt.print_uwbin(cx16.r1 << 7, true) - txt.nl() - txt.print_uwhex(cx16.r0 ^ cx16.r1, true) - txt.nl() - txt.print_ubhex(^cx16.r0, true) - txt.spc() - txt.print_uwhex(< ubyte @X { + %asm {{ + rts + }} } }