check that block address leaves room for program startup logic

This commit is contained in:
Irmen de Jong 2024-10-03 21:16:11 +02:00
parent 51279a98b3
commit d1ddf05e38
5 changed files with 49 additions and 51 deletions

View File

@ -1238,11 +1238,10 @@ sub search_x16edit() -> ubyte {
str @shared signature = petscii:"x16edit" str @shared signature = petscii:"x16edit"
for cx16.r1L in 31 downto 0 { for cx16.r1L in 31 downto 0 {
cx16.rombank(cx16.r1L) cx16.rombank(cx16.r1L)
cx16.r2 = $fff0
%asm {{ %asm {{
ldy #0 ldy #0
- lda signature,y - lda signature,y
cmp (cx16.r2),y cmp $fff0,y
bne + bne +
iny iny
cpy #7 cpy #7

View File

@ -107,14 +107,14 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
) )
} }
determineProgramLoadAddress(program, compilationOptions, args.errors)
args.errors.report()
postprocessAst(program, args.errors, compilationOptions) postprocessAst(program, args.errors, compilationOptions)
args.errors.report()
// println("*********** COMPILER AST BEFORE ASSEMBLYGEN *************") // println("*********** COMPILER AST BEFORE ASSEMBLYGEN *************")
// printProgram(program) // printProgram(program)
determineProgramLoadAddress(program, compilationOptions, args.errors)
args.errors.report()
if (args.writeAssembly) { if (args.writeAssembly) {
// re-initialize memory areas with final compilationOptions // re-initialize memory areas with final compilationOptions

View File

@ -280,8 +280,13 @@ internal class AstChecker(private val program: Program,
errors.err("identifiers cannot start with an underscore", block.position) errors.err("identifiers cannot start with an underscore", block.position)
val addr = block.address val addr = block.address
if(addr!=null && addr>65535u) { if (addr!=null) {
errors.err("block memory address must be valid integer 0..\$ffff", block.position) if (addr > 65535u)
errors.err("block address must be valid integer 0..\$ffff", block.position)
if(compilerOptions.loadAddress!=0u) {
if (addr < compilerOptions.loadAddress + 20u)
errors.err("block address must be at least program load address + 20 (to allow for startup logic)", block.position)
}
} }
for (statement in block.statements) { for (statement in block.statements) {

View File

@ -384,6 +384,32 @@ main {
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
} }
test("block start address must be greater than program load address") {
val src = """
%output raw
%launcher none
%address ${'$'}2000
main $2000 {
sub start() {
sys.clear_carry()
}
}
otherblock ${'$'}2013 {
%option force_output
}
thirdblock ${'$'}2014 {
%option force_output
}"""
val errors = ErrorReporterForTests()
compileText(C64Target(), false, src, writeAssembly = false, errors = errors) shouldBe null
errors.errors.size shouldBe 2
errors.errors[0] shouldContain "6:1: block address must be at least program load address + 20"
errors.errors[1] shouldContain "12:1: block address must be at least program load address + 20"
}
test("for loops with just 1 iteration") { test("for loops with just 1 iteration") {
val src=""" val src="""
main { main {

View File

@ -1,50 +1,18 @@
%zeropage basicsafe ; EXAMPLE external command source code
%launcher none
%option no_sysinit %option no_sysinit
%zeropage basicsafe
%encoding iso
%import textio
%address $4000
main {
sub func() -> ubyte {
cx16.r0++
return cx16.r0L
}
sub start() { main $4030 {
bool[256] @shared cells %option force_output
word starw
byte bb
uword uw
ubyte ub
starw = (240-64 as word) + func() sub start() {
txt.print("external command\n")
for starw in 50 downto 10 { sys.exit(0)
cx16.r0++
}
for starw in cx16.r0L downto 10 {
cx16.r0++
}
for ub in 0 to len(cells)-1 {
cx16.r0++
}
for ub in cx16.r0L to len(cells)-1 {
cx16.r0++
}
for bb in 50 downto 10 {
cx16.r0++
}
for bb in cx16.r0sL downto 10 {
cx16.r0++
}
for starw in 500 downto 10 {
cx16.r0++
}
for uw in 50 downto 10 {
cx16.r0++
}
for uw in 500 downto 10 {
cx16.r0++
}
} }
} }