Skip to content

Commit

Permalink
added %option romable to enable romable mode, but only generate a bun…
Browse files Browse the repository at this point in the history
…ch of warnings for problematic codegeneration atm
  • Loading branch information
irmen committed Feb 20, 2025
1 parent fb1e89d commit e55ce55
Show file tree
Hide file tree
Showing 21 changed files with 94 additions and 115 deletions.
1 change: 1 addition & 0 deletions codeCore/src/prog8/code/core/CompilationOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class CompilationOptions(val output: OutputType,
val zpAllowed: List<UIntRange>,
val floats: Boolean,
val noSysInit: Boolean,
val romable: Boolean,
val compTarget: ICompilationTarget,
// these are set later, based on command line arguments or options in the source code:
var loadAddress: UInt,
Expand Down
8 changes: 8 additions & 0 deletions codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,14 @@ $repeatLabel""")
}
return null
}

fun romableWarning(problem: String, pos: Position) {
if(options.romable) {
// until the code generation can provide an alternative, we have to report about code generated that is incompatible with ROMable code mode...
errors.warn("problem for ROMable code: $problem", pos)
out(" .warn \"ROMable code selected but incompatible code was generated: $problem\"")
}
}
}

/**
Expand Down
24 changes: 15 additions & 9 deletions codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
jsr $jsrfar
+ .word 0
+ .byte 0""")
asmgen.romableWarning("self-modifying code for jsrfar", fcall.position) // TODO
}

// note that by convention the values in A+Y registers are now the return value of the call.
Expand Down Expand Up @@ -292,6 +293,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
jsr $jsrfar
+ .word 0
+ .byte 0""")
asmgen.romableWarning("self-modifying code for jsrfar", fcall.position) // TODO
}

// note that by convention the values in A+Y registers are now the return value of the call.
Expand Down Expand Up @@ -411,20 +413,20 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
is PtArrayIndexer -> {
asmgen.loadScaledArrayIndexIntoRegister(what, CpuRegister.X)
val varname = asmgen.asmVariableName(what.variable)
asmgen.out(" lda ${varname},x | lsr a | bcc + | ora #\$80 |+ | sta ${varname},x")
asmgen.out(" lda ${varname},x | lsr a | bcc + | ora #$80 |+ | sta ${varname},x")
}
is PtMemoryByte -> {
if (what.address is PtNumber) {
val number = (what.address as PtNumber).number
asmgen.out(" lda ${number.toHex()} | lsr a | bcc + | ora #\$80 |+ | sta ${number.toHex()}")
asmgen.out(" lda ${number.toHex()} | lsr a | bcc + | ora #$80 |+ | sta ${number.toHex()}")
} else {
asmgen.assignExpressionToRegister(what.address, RegisterOrPair.AY)
asmgen.out(" jsr prog8_lib.ror2_mem_ub")
}
}
is PtIdentifier -> {
val variable = asmgen.asmVariableName(what)
asmgen.out(" lda $variable | lsr a | bcc + | ora #\$80 |+ | sta $variable")
asmgen.out(" lda $variable | lsr a | bcc + | ora #$80 |+ | sta $variable")
}
else -> throw AssemblyError("weird type")
}
Expand All @@ -435,13 +437,13 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.loadScaledArrayIndexIntoRegister(what, CpuRegister.X)
val varname = asmgen.asmVariableName(what.variable)
if(what.splitWords)
asmgen.out(" lsr ${varname}_msb,x | ror ${varname}_lsb,x | bcc + | lda ${varname}_msb,x | ora #\$80 | sta ${varname}_msb,x |+ ")
asmgen.out(" lsr ${varname}_msb,x | ror ${varname}_lsb,x | bcc + | lda ${varname}_msb,x | ora #$80 | sta ${varname}_msb,x |+ ")
else
asmgen.out(" lsr ${varname}+1,x | ror ${varname},x | bcc + | lda ${varname}+1,x | ora #\$80 | sta ${varname}+1,x |+ ")
asmgen.out(" lsr ${varname}+1,x | ror ${varname},x | bcc + | lda ${varname}+1,x | ora #$80 | sta ${varname}+1,x |+ ")
}
is PtIdentifier -> {
val variable = asmgen.asmVariableName(what)
asmgen.out(" lsr $variable+1 | ror $variable | bcc + | lda $variable+1 | ora #\$80 | sta $variable+1 |+ ")
asmgen.out(" lsr $variable+1 | ror $variable | bcc + | lda $variable+1 | ora #$80 | sta $variable+1 |+ ")
}
else -> throw AssemblyError("weird type")
}
Expand Down Expand Up @@ -478,6 +480,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out("""
plp
+ ror ${'$'}ffff,x ; modified""")
asmgen.romableWarning("self-modifying code (ror)", fcall.position) // TODO
} else {
if(!what.address.isSimple()) asmgen.out(" php") // save Carry
asmgen.assignExpressionToRegister(what.address, RegisterOrPair.AY)
Expand All @@ -486,6 +489,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
sta (+) + 1
sty (+) + 2
+ ror ${'$'}ffff ; modified""")
asmgen.romableWarning("self-modifying code (ror)", fcall.position) // TODO
}
}
}
Expand Down Expand Up @@ -527,20 +531,20 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
is PtArrayIndexer -> {
asmgen.loadScaledArrayIndexIntoRegister(what, CpuRegister.X)
val varname = asmgen.asmVariableName(what.variable)
asmgen.out(" lda ${varname},x | cmp #\$80 | rol a | sta ${varname},x")
asmgen.out(" lda ${varname},x | cmp #$80 | rol a | sta ${varname},x")
}
is PtMemoryByte -> {
if (what.address is PtNumber) {
val number = (what.address as PtNumber).number
asmgen.out(" lda ${number.toHex()} | cmp #\$80 | rol a | sta ${number.toHex()}")
asmgen.out(" lda ${number.toHex()} | cmp #$80 | rol a | sta ${number.toHex()}")
} else {
asmgen.assignExpressionToRegister(what.address, RegisterOrPair.AY)
asmgen.out(" jsr prog8_lib.rol2_mem_ub")
}
}
is PtIdentifier -> {
val variable = asmgen.asmVariableName(what)
asmgen.out(" lda $variable | cmp #\$80 | rol a | sta $variable")
asmgen.out(" lda $variable | cmp #$80 | rol a | sta $variable")
}
else -> throw AssemblyError("weird type")
}
Expand Down Expand Up @@ -594,6 +598,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out("""
plp
+ rol ${'$'}ffff,x ; modified""")
asmgen.romableWarning("self-modifying code (rol)", fcall.position) // TODO
} else {
if(!what.address.isSimple()) asmgen.out(" php") // save Carry
asmgen.assignExpressionToRegister(what.address, RegisterOrPair.AY)
Expand All @@ -602,6 +607,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
sta (+) + 1
sty (+) + 2
+ rol ${'$'}ffff ; modified""")
asmgen.romableWarning("self-modifying code (rol)", fcall.position) // TODO
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ internal class ForLoopsAsmGen(
$modifiedLabel cmp #0 ; modified
beq $endLabel
$incdec $varname""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
asmgen.jmp(loopLabel)
asmgen.out(endLabel)

Expand Down Expand Up @@ -159,6 +160,7 @@ $modifiedLabel cmp #0 ; modified
$modifiedLabel cmp #0 ; modified
bmi $loopLabel
beq $loopLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
} else {
asmgen.out("""
lda $varname
Expand All @@ -167,6 +169,7 @@ $modifiedLabel cmp #0 ; modified
sta $varname
$modifiedLabel cmp #0 ; modified
bpl $loopLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
}
asmgen.out(endLabel)
}
Expand Down Expand Up @@ -223,6 +226,7 @@ $modifiedLabel cmp #0 ; modified
lda $varname
$modifiedLabel2 cmp #0 ; modified
beq $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
if(stepsize==1) {
asmgen.out("""
+ inc $varname
Expand Down Expand Up @@ -266,6 +270,7 @@ $modifiedLabel2 lda #0 ; modified
bcc $endLabel
bcs $loopLabel
$endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
} else {
asmgen.out("""
lda $varname
Expand All @@ -283,6 +288,7 @@ $modifiedLabel lda #0 ; modified
eor #$80
+ bpl $loopLabel
$endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
}
}
else {
Expand Down Expand Up @@ -313,6 +319,7 @@ $modifiedLabel sbc #0 ; modified
eor #$80
+ bpl $loopLabel
$endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
}
}
else -> throw AssemblyError("range expression can only be byte or word")
Expand Down Expand Up @@ -391,6 +398,7 @@ $endLabel""")
$loopLabel lda ${65535.toHex()} ; modified
beq $endLabel
sta ${asmgen.asmVariableName(stmt.variable)}""")
asmgen.romableWarning("self-modifying code (forloop over iterable)", stmt.position) // TODO
asmgen.translate(stmt.statements)
asmgen.out("""
inc $loopLabel+1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
.word $subAsmName ; ${sub.address!!.address.toHex()}
+ .byte 0 ; modified"""
)
asmgen.romableWarning("self-modifying code for cx16 banked jsr", call.position) // TODO
}
"c64" -> {
asmgen.out("""
Expand All @@ -78,6 +79,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
.word $subAsmName ; ${sub.address!!.address.toHex()}
+ .byte 0 ; modified"""
)
asmgen.romableWarning("self-modifying code for c64 banked jsr", call.position) // TODO
}
"c128" -> {
asmgen.out("""
Expand All @@ -91,6 +93,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
.word $subAsmName ; ${sub.address!!.address.toHex()}
+ .byte 0 ; modified"""
)
asmgen.romableWarning("self-modifying code for c128 banked jsr", call.position) // TODO
}
else -> throw AssemblyError("callfar is not supported on the selected compilation target")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out("+\tinc ${'$'}ffff\t; modified")
asmgen.romableWarning("self-modifying code (access pointer)", pointervar.position) // TODO
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" clc | adc #$value")
Expand All @@ -976,6 +977,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(pointervar, RegisterOrPair.AY)
asmgen.out(" sta (+) + 1 | sty (+) + 2")
asmgen.out("+\tdec ${'$'}ffff\t; modified")
asmgen.romableWarning("self-modifying code (access pointer)", pointervar.position) // TODO
} else {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" sec | sbc #$value")
Expand Down
1 change: 1 addition & 0 deletions codeGenCpu6502/test/TestCodegen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class TestCodegen: FunSpec({
zpAllowed = CompilationOptions.AllZeropageAllowed,
floats = true,
noSysInit = false,
romable = false,
compTarget = target,
loadAddress = target.PROGRAM_LOAD_ADDRESS,
memtopAddress = 0xffffu
Expand Down
1 change: 1 addition & 0 deletions codeGenIntermediate/test/TestIRPeepholeOpt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class TestIRPeepholeOpt: FunSpec({
CompilationOptions.AllZeropageAllowed,
floats = false,
noSysInit = true,
romable = false,
compTarget = target,
loadAddress = target.PROGRAM_LOAD_ADDRESS,
memtopAddress = 0xffffu
Expand Down
1 change: 1 addition & 0 deletions codeGenIntermediate/test/TestVmCodeGen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TestVmCodeGen: FunSpec({
zpAllowed = CompilationOptions.AllZeropageAllowed,
floats = true,
noSysInit = false,
romable = false,
compTarget = target,
loadAddress = target.PROGRAM_LOAD_ADDRESS,
memtopAddress = 0xffffu
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/prog8/compiler/Compiler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ internal fun determineCompilationOptions(program: Program, compTarget: ICompilat
val allOptions = program.modules.flatMap { it.options() }.toSet()
val floatsEnabled = "enable_floats" in allOptions
var noSysInit = "no_sysinit" in allOptions
var rombale = "romable" in allOptions
var zpType: ZeropageType =
if (zpoption == null)
if (floatsEnabled) ZeropageType.FLOATSAFE else ZeropageType.KERNALSAFE
Expand Down Expand Up @@ -408,7 +409,7 @@ internal fun determineCompilationOptions(program: Program, compTarget: ICompilat

return CompilationOptions(
outputType, launcherType,
zpType, zpReserved, zpAllowed, floatsEnabled, noSysInit,
zpType, zpReserved, zpAllowed, floatsEnabled, noSysInit, rombale,
compTarget, 0u, 0xffffu
)
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/prog8/compiler/astprocessing/AstChecker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1033,14 +1033,14 @@ internal class AstChecker(private val program: Program,
err("this directive may only occur in a block or at module level")
if(directive.args.isEmpty())
err("missing option directive argument(s)")
else if(directive.args.map{it.string in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}.any { !it })
else if(directive.args.map{it.string in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused", "romable")}.any { !it })
err("invalid option directive argument(s)")
if(directive.parent is Block) {
if(directive.args.any {it.string !in arrayOf("force_output", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")})
err("using an option that is not valid for blocks")
}
if(directive.parent is Module) {
if(directive.args.any {it.string !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused")})
if(directive.args.any {it.string !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused", "romable")})
err("using an option that is not valid for modules")
}
if(directive.args.any { it.string=="verafxmuls" } && compilerOptions.compTarget.name != Cx16Target.NAME)
Expand Down
1 change: 1 addition & 0 deletions compiler/test/TestGoldenRam.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class TestGoldenRam: FunSpec({
CompilationOptions.AllZeropageAllowed,
floats = true,
noSysInit = false,
romable = false,
compTarget = VMTarget(),
loadAddress = 999u,
memtopAddress = 0xffffu
Expand Down
Loading

0 comments on commit e55ce55

Please sign in to comment.