mirror of
https://github.com/irmen/prog8.git
synced 2024-11-28 10:51:14 +00:00
added memtop to machine definition and asm source code check
added %memtop directive
This commit is contained in:
parent
6fb05bdefc
commit
3b798097b9
@ -14,6 +14,7 @@ class CompilationOptions(val output: OutputType,
|
||||
val compTarget: ICompilationTarget,
|
||||
// these are set later, based on command line arguments or options in the source code:
|
||||
var loadAddress: UInt,
|
||||
var memtopAddress: UInt,
|
||||
var warnSymbolShadowing: Boolean = false,
|
||||
var optimize: Boolean = false,
|
||||
var asmQuiet: Boolean = false,
|
||||
|
@ -14,6 +14,7 @@ interface IMachineDefinition {
|
||||
val FLOAT_MAX_POSITIVE: Double
|
||||
val FLOAT_MEM_SIZE: Int
|
||||
val PROGRAM_LOAD_ADDRESS : UInt
|
||||
val PROGRAM_TOP_ADDRESS: UInt
|
||||
val BSSHIGHRAM_START: UInt
|
||||
val BSSHIGHRAM_END: UInt
|
||||
val BSSGOLDENRAM_START: UInt
|
||||
|
@ -12,6 +12,7 @@ class AtariMachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = -9.999999999e97
|
||||
override val FLOAT_MEM_SIZE = 6
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x2000u
|
||||
override val PROGRAM_TOP_ADDRESS = 0xffffu // TODO what's memtop
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
|
@ -14,6 +14,7 @@ class C128MachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x1c01u
|
||||
override val PROGRAM_TOP_ADDRESS = 0xfeffu
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
|
@ -15,6 +15,7 @@ class C64MachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x0801u
|
||||
override val PROGRAM_TOP_ADDRESS = 0xbfffu
|
||||
|
||||
override val BSSHIGHRAM_START = 0xc000u
|
||||
override val BSSHIGHRAM_END = 0xcfffu
|
||||
|
@ -14,6 +14,7 @@ class CX16MachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x0801u
|
||||
override val PROGRAM_TOP_ADDRESS = 0x9effu
|
||||
|
||||
override val BSSHIGHRAM_START = 0xa000u // hiram bank 1, 8Kb, assumed to be active
|
||||
override val BSSHIGHRAM_END = 0xbfffu // Rom starts at $c000
|
||||
|
@ -14,6 +14,7 @@ class PETMachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x0401u
|
||||
override val PROGRAM_TOP_ADDRESS = 0x7fffu
|
||||
|
||||
override val BSSHIGHRAM_START = 0u
|
||||
override val BSSHIGHRAM_END = 0u
|
||||
|
@ -14,6 +14,7 @@ class VirtualMachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_NEGATIVE = -Float.MAX_VALUE.toDouble()
|
||||
override val FLOAT_MEM_SIZE = 8 // 64-bits double
|
||||
override val PROGRAM_LOAD_ADDRESS = 0u // not actually used
|
||||
override val PROGRAM_TOP_ADDRESS = 0xffffu // not actually used
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // not actually used
|
||||
override val BSSHIGHRAM_END = 0u // not actually used
|
||||
|
@ -284,6 +284,8 @@ internal class ProgramAndVarsGen(
|
||||
asmgen.out(" .cerror * > ${relocatedBssEnd.toHex()}, \"too many data for slabs_BSS section\"")
|
||||
}
|
||||
}
|
||||
asmgen.out(" ; memtop check")
|
||||
asmgen.out(" .cerror * > ${options.memtopAddress.toHex()}, \"Program too long by \", * - ${options.memtopAddress.toHex()}, \" bytes, memtop=${options.memtopAddress.toHex()}\"")
|
||||
}
|
||||
|
||||
private fun block2asm(block: PtBlock) {
|
||||
|
@ -26,7 +26,8 @@ class TestCodegen: FunSpec({
|
||||
floats = true,
|
||||
noSysInit = false,
|
||||
compTarget = target,
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,8 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
floats = false,
|
||||
noSysInit = true,
|
||||
compTarget = target,
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
val prog = IRProgram("test", IRSymbolTable(), options, target)
|
||||
prog.addBlock(block)
|
||||
|
@ -23,7 +23,8 @@ class TestVmCodeGen: FunSpec({
|
||||
floats = true,
|
||||
noSysInit = false,
|
||||
compTarget = target,
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -263,6 +263,7 @@ internal fun determineProgramLoadAddress(program: Program, options: CompilationO
|
||||
}
|
||||
|
||||
options.loadAddress = loadAddress
|
||||
options.memtopAddress = program.toplevelModule.memtopAddress?.first ?: options.compTarget.machine.PROGRAM_TOP_ADDRESS
|
||||
}
|
||||
|
||||
|
||||
@ -398,7 +399,7 @@ fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget
|
||||
return CompilationOptions(
|
||||
outputType, launcherType,
|
||||
zpType, zpReserved, zpAllowed, floatsEnabled, noSysInit,
|
||||
compTarget, 0u
|
||||
compTarget, 0u, 0xffffu
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ class ModuleImporter(private val program: Program,
|
||||
|
||||
private fun removeDirectivesFromImportedModule(importedModule: Module) {
|
||||
// Most global directives don't apply for imported modules, so remove them
|
||||
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%zpallowed", "%address")
|
||||
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%zpallowed", "%address", "%memtop")
|
||||
var directives = importedModule.statements.filterIsInstance<Directive>()
|
||||
importedModule.statements.removeAll(directives.toSet())
|
||||
directives = directives.filter{ it.directive !in moduleLevelDirectives }
|
||||
|
@ -57,7 +57,7 @@ internal class AstChecker(private val program: Program,
|
||||
val directives = module.statements.filterIsInstance<Directive>().groupBy { it.directive }
|
||||
directives.filter { it.value.size > 1 }.forEach{ entry ->
|
||||
when(entry.key) {
|
||||
"%output", "%launcher", "%zeropage", "%address", "%encoding" ->
|
||||
"%output", "%launcher", "%zeropage", "%address", "%memtop", "%encoding" ->
|
||||
entry.value.forEach { errors.err("directive can just occur once", it.position) }
|
||||
}
|
||||
}
|
||||
@ -962,6 +962,12 @@ internal class AstChecker(private val program: Program,
|
||||
if(directive.args.size!=1 || directive.args[0].int == null)
|
||||
err("invalid address directive, expected numeric address argument")
|
||||
}
|
||||
"%memtop" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
if(directive.args.size!=1 || directive.args[0].int == null)
|
||||
err("invalid memtop directive, expected numeric address argument")
|
||||
}
|
||||
"%import" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
|
@ -22,7 +22,7 @@ internal class StatementReorderer(
|
||||
// - sorts the choices in when statement.
|
||||
// - insert AddressOf (&) expression where required (string params to a UWORD function param etc.).
|
||||
|
||||
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%zpallowed", "%address", "%option", "%encoding")
|
||||
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%zpallowed", "%address", "%memtop", "%option", "%encoding")
|
||||
|
||||
override fun after(module: Module, parent: Node): Iterable<IAstModification> {
|
||||
val (blocks, other) = module.statements.partition { it is Block }
|
||||
|
@ -20,7 +20,8 @@ class TestGoldenRam: FunSpec({
|
||||
floats = true,
|
||||
noSysInit = false,
|
||||
compTarget = VMTarget(),
|
||||
loadAddress = 999u
|
||||
loadAddress = 999u,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
|
||||
test("empty golden ram allocations") {
|
||||
|
@ -52,7 +52,8 @@ class TestAbstractZeropage: FunSpec({
|
||||
floats = false,
|
||||
noSysInit = false,
|
||||
compTarget = DummyCompilationTarget,
|
||||
loadAddress = 999u
|
||||
loadAddress = 999u,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
)
|
||||
zp.free.size shouldBe 256-6-16
|
||||
@ -70,7 +71,7 @@ class TestC64Zeropage: FunSpec({
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed,
|
||||
floats = false,
|
||||
noSysInit = false,
|
||||
compTarget = c64target, loadAddress = 999u
|
||||
compTarget = c64target, loadAddress = 999u, memtopAddress = 0xffffu
|
||||
))
|
||||
|
||||
var result = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
@ -85,33 +86,33 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testZpFloatEnable") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
var result = zp.allocate("", DataType.FLOAT, null, null, errors)
|
||||
result.expectError { "should be allocation error due to disabled floats" }
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
result = zp2.allocate("", DataType.FLOAT, null, null, errors)
|
||||
result.expectError { "should be allocation error due to disabled ZP use" }
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
zp3.allocate("", DataType.FLOAT, null, null, errors)
|
||||
}
|
||||
|
||||
test("testZpModesWithFloats") {
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
shouldThrow<InternalCompilerException> {
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
}
|
||||
shouldThrow<InternalCompilerException> {
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
}
|
||||
}
|
||||
|
||||
test("testZpDontuse") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
println(zp.free)
|
||||
zp.availableBytes() shouldBe 0
|
||||
val result = zp.allocate("", DataType.BYTE, null, null, errors)
|
||||
@ -119,13 +120,13 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testFreeSpacesBytes") {
|
||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
zp1.availableBytes() shouldBe 17
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp2.availableBytes() shouldBe 87
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp3.availableBytes() shouldBe 96
|
||||
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp4.availableBytes() shouldBe 207
|
||||
zp4.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
zp4.availableBytes() shouldBe 206
|
||||
@ -134,7 +135,7 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testReservedSpace") {
|
||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp1.availableBytes() shouldBe 207
|
||||
4u shouldNotBeIn zp1.free
|
||||
35u shouldNotBeIn zp1.free
|
||||
@ -145,7 +146,7 @@ class TestC64Zeropage: FunSpec({
|
||||
200u shouldBeIn zp1.free
|
||||
255u shouldBeIn zp1.free
|
||||
199u shouldBeIn zp1.free
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, listOf(50u .. 100u, 200u..255u), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, listOf(50u .. 100u, 200u..255u), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp2.availableBytes() shouldBe 107
|
||||
4u shouldNotBeIn zp2.free
|
||||
35u shouldNotBeIn zp2.free
|
||||
@ -156,14 +157,14 @@ class TestC64Zeropage: FunSpec({
|
||||
200u shouldNotBeIn zp2.free
|
||||
255u shouldNotBeIn zp2.free
|
||||
199u shouldBeIn zp2.free
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, listOf(50u .. 100u, 200u..255u), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, listOf(50u .. 100u, 200u..255u), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp2.availableBytes() shouldBe 107
|
||||
4u shouldBeIn zp3.free
|
||||
35u shouldNotBeIn zp3.free
|
||||
}
|
||||
|
||||
test("testBasicsafeAllocation") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
zp.availableBytes() shouldBe 17
|
||||
zp.hasByteAvailable() shouldBe true
|
||||
zp.hasWordAvailable() shouldBe true
|
||||
@ -185,7 +186,7 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testFullAllocation") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
zp.availableBytes() shouldBe 207
|
||||
zp.hasByteAvailable() shouldBe true
|
||||
zp.hasWordAvailable() shouldBe true
|
||||
@ -216,7 +217,7 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testEfficientAllocation") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u, 0xffffu))
|
||||
zp.availableBytes() shouldBe 17
|
||||
zp.allocate("", DataType.WORD, null, null, errors).getOrElse{throw it}.address shouldBe 0x04u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x06u
|
||||
@ -234,7 +235,7 @@ class TestC64Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testReservedLocations") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u, 0xffffu))
|
||||
withClue("zp _B1 and _REG must be next to each other to create a word") {
|
||||
zp.SCRATCH_B1 + 1u shouldBe zp.SCRATCH_REG
|
||||
}
|
||||
@ -247,18 +248,18 @@ class TestCx16Zeropage: FunSpec({
|
||||
val cx16target = Cx16Target()
|
||||
|
||||
test("testReservedLocations") {
|
||||
val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u, 0xffffu))
|
||||
withClue("zp _B1 and _REG must be next to each other to create a word") {
|
||||
zp.SCRATCH_B1 + 1u shouldBe zp.SCRATCH_REG
|
||||
}
|
||||
}
|
||||
|
||||
test("testFreeSpacesBytes") {
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, cx16target, 999u))
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, cx16target, 999u, 0xffffu))
|
||||
zp1.availableBytes() shouldBe 88
|
||||
val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u, 0xffffu))
|
||||
zp2.availableBytes() shouldBe 175
|
||||
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u, 0xffffu))
|
||||
zp3.availableBytes() shouldBe 216
|
||||
zp3.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
zp3.availableBytes() shouldBe 215
|
||||
@ -267,7 +268,7 @@ class TestCx16Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("testReservedSpace") {
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u, 0xffffu))
|
||||
zp1.availableBytes() shouldBe 216
|
||||
0x22u shouldBeIn zp1.free
|
||||
0x80u shouldBeIn zp1.free
|
||||
@ -277,7 +278,7 @@ class TestCx16Zeropage: FunSpec({
|
||||
}
|
||||
|
||||
test("preallocated zp vars") {
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u, 0xffffu))
|
||||
zp1.allocatedVariables["test"] shouldBe null
|
||||
zp1.allocatedVariables["cx16.r0"] shouldNotBe null
|
||||
zp1.allocatedVariables["cx16.r15"] shouldNotBe null
|
||||
|
@ -74,7 +74,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
|
||||
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
||||
val errors = ErrorReporterForTests()
|
||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, true, C64Target(), 999u)
|
||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, true, C64Target(), 999u, 0xffffu)
|
||||
val ptProgram = IntermediateAstMaker(program, errors).transform()
|
||||
val st = SymbolTableMaker(ptProgram, options).make()
|
||||
return AsmGen6502Internal(ptProgram, st, options, errors)
|
||||
|
@ -303,6 +303,14 @@ open class Module(final override val statements: MutableList<Statement>,
|
||||
Pair(address.args.single().int!!, address.position)
|
||||
}
|
||||
|
||||
val memtopAddress: Pair<UInt, Position>? by lazy {
|
||||
val address = (statements.singleOrNull { it is Directive && it.directive == "%memtop" } as? Directive)
|
||||
if(address==null || address.args.single().int==null)
|
||||
null
|
||||
else
|
||||
Pair(address.args.single().int!!, address.position)
|
||||
}
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
require(parent is GlobalNamespace)
|
||||
this.parent = parent
|
||||
|
@ -106,6 +106,7 @@ data class Directive(val directive: String, val args: List<DirectiveArg>, overri
|
||||
// init {
|
||||
// require(directive in arrayOf(
|
||||
// "%address",
|
||||
// "%memtop",
|
||||
// "%asmbinary",
|
||||
// "%asminclude",
|
||||
// "%breakpoint",
|
||||
|
@ -184,6 +184,17 @@ Directives
|
||||
- type ``none`` : no launcher logic is added at all
|
||||
|
||||
|
||||
.. data:: %memtop <address>
|
||||
|
||||
Level: module.
|
||||
Global setting, changes the program's top memory address. This is usually specified internally by the compiler target,
|
||||
but with this you can change it to another value. This can be useful for example to 'reserve' a piece
|
||||
of memory at the end of program space where other data such as external library files can be loaded into.
|
||||
This memtop value is used for a check instruction for the assembler to see if the resulting program size
|
||||
exceeds the given memtop address. This value is inclusive, so $9eff means that the program can use up to
|
||||
and including the address $9eff and that $9f00 is the first address out of bounds.
|
||||
|
||||
|
||||
.. data:: %option <option> [, <option> ...]
|
||||
|
||||
Level: module, block.
|
||||
|
@ -30,7 +30,7 @@ Future Things and Ideas
|
||||
- (What, how, isn't current BSS support enough?)
|
||||
- Add a mechanism to allocate variables into golden ram (or segments really) (see GoldenRam class)
|
||||
- maybe treat block "golden" in a special way: can only contain vars, every var will be allocated in the Golden ram area?
|
||||
- maybe or may not needed: the variables can NOT have initialization values, they will all be set to zero on startup (simple memset)
|
||||
- maybe or may not needed: the variables can NOT have initializfation values, they will all be set to zero on startup (simple memset)
|
||||
just initialize them yourself in start() if you need a non-zero value .
|
||||
- OR.... do all this automatically if 'golden' is enabled as a compiler option? So compiler allocates in ZP first, then Golden Ram, then regular ram
|
||||
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
|
||||
|
@ -1,6 +1,7 @@
|
||||
%import diskio
|
||||
%import textio
|
||||
%import zsmkit_high
|
||||
%memtop $8bff ; zsmkit is loaded from 8c00 onwards
|
||||
|
||||
;; Proof Of Concept ZSM player using a binary blob version of zsmkit by MooingLemur
|
||||
;; This version is a bit simpler as "demo1".
|
||||
|
@ -1,6 +1,7 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
%memtop $0840
|
||||
|
||||
main {
|
||||
|
||||
|
@ -126,6 +126,7 @@ class IRFileReader {
|
||||
false,
|
||||
target,
|
||||
loadAddress,
|
||||
0xffffu,
|
||||
outputDir = outputDir,
|
||||
optimize = optimize
|
||||
)
|
||||
|
@ -23,6 +23,7 @@ class TestIRFileInOut: FunSpec({
|
||||
noSysInit = true,
|
||||
compTarget = target,
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
||||
memtopAddress = 0xffffu,
|
||||
outputDir = tempdir
|
||||
)
|
||||
val program = IRProgram("unittest-irwriter", IRSymbolTable(), options, target)
|
||||
|
@ -148,7 +148,7 @@ labeldef : identifier ':' ;
|
||||
unconditionaljump : 'goto' (integerliteral | scoped_identifier) ;
|
||||
|
||||
directive :
|
||||
directivename=('%output' | '%launcher' | '%zeropage' | '%zpreserved' | '%zpallowed' | '%address' | '%import' |
|
||||
directivename=('%output' | '%launcher' | '%zeropage' | '%zpreserved' | '%zpallowed' | '%address' | '%memtop' | '%import' |
|
||||
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option' | '%encoding' | '%align' )
|
||||
(directivearg? | directivearg (',' directivearg)*)
|
||||
;
|
||||
|
@ -12,7 +12,7 @@
|
||||
<option name="HAS_STRING_ESCAPES" value="true" />
|
||||
</options>
|
||||
<keywords keywords="&;->;@;and;as;asmsub;break;clobbers;continue;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords3 keywords="bool;byte;const;float;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;call;callfar;callfar2;clamp;cmp;defer;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
</highlighting>
|
||||
|
@ -25,7 +25,7 @@
|
||||
<Keywords name="Folders in comment, middle"></Keywords>
|
||||
<Keywords name="Folders in comment, close"></Keywords>
|
||||
<Keywords name="Keywords1">void const
str
byte ubyte bool
word uword
float
zp shared split requirezp nozp</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%ir
%asmbinary
%asminclude
%align
%breakpoint
%encoding
%import
%launcher
%option
%output
%zeropage
%zpreserved
%zpallowed</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%ir
%asmbinary
%asminclude
%align
%breakpoint
%encoding
%import
%memtop
%launcher
%option
%output
%zeropage
%zpreserved
%zpallowed</Keywords>
|
||||
<Keywords name="Keywords3">inline sub asmsub romsub
clobbers
asm
if
when else
if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z
for in step do while repeat unroll
break continue return goto</Keywords>
|
||||
<Keywords name="Keywords4">abs call callfar callfar2 clamp cmp defer divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
||||
|
@ -24,7 +24,8 @@ class TestVm: FunSpec( {
|
||||
floats = true,
|
||||
noSysInit = false,
|
||||
compTarget = target,
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
||||
memtopAddress = 0xffffu
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user