mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
added -varshigh
compiler option to move BSS section.
Documented BSS a bit in the manual.
This commit is contained in:
parent
fb9902c536
commit
ba9268a09e
@ -19,6 +19,7 @@ class CompilationOptions(val output: OutputType,
|
||||
var asmQuiet: Boolean = false,
|
||||
var asmListfile: Boolean = false,
|
||||
var experimentalCodegen: Boolean = false,
|
||||
var varsHigh: Boolean = false,
|
||||
var evalStackBaseAddress: UInt? = null,
|
||||
var outputDir: Path = Path(""),
|
||||
var symbolDefs: Map<String, String> = emptyMap()
|
||||
|
@ -16,6 +16,8 @@ interface IMachineDefinition {
|
||||
var ESTACK_LO: UInt
|
||||
var ESTACK_HI: UInt
|
||||
val PROGRAM_LOAD_ADDRESS : UInt
|
||||
val BSSHIGHRAM_START: UInt
|
||||
val BSSHIGHRAM_END: UInt
|
||||
|
||||
val cpu: CpuType
|
||||
var zeropage: Zeropage
|
||||
|
@ -17,6 +17,9 @@ class AtariMachineDefinition: IMachineDefinition {
|
||||
override var ESTACK_LO = 0x1b00u // $1b00-$1b7f inclusive // TODO
|
||||
override var ESTACK_HI = 0x1b80u // $1b80-$1bff inclusive // TODO
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
|
@ -17,6 +17,10 @@ class C128MachineDefinition: IMachineDefinition {
|
||||
// the 2*128 byte evaluation stack (1 page, on which bytes, words, and even floats are stored during calculations)
|
||||
override var ESTACK_LO = 0x1b00u // $1b00-$1b7f inclusive
|
||||
override var ESTACK_HI = 0x1b80u // $1b80-$1bff inclusive
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
|
@ -18,6 +18,10 @@ class C64MachineDefinition: IMachineDefinition {
|
||||
// the 2*128 byte evaluation stack (1 page, on which bytes, words, and even floats are stored during calculations)
|
||||
override var ESTACK_LO = 0xcf00u // $cf00-$cf7f inclusive
|
||||
override var ESTACK_HI = 0xcf80u // $cf80-$cfff inclusive
|
||||
|
||||
override val BSSHIGHRAM_START = 0xc000u
|
||||
override val BSSHIGHRAM_END = ESTACK_LO
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
|
@ -17,6 +17,10 @@ class CX16MachineDefinition: IMachineDefinition {
|
||||
// the 2*128 byte evaluation stack (1 page, on which bytes, words, and even floats are stored during calculations)
|
||||
override var ESTACK_LO = 0x0700u // $0700-$077f inclusive
|
||||
override var ESTACK_HI = 0x0780u // $0780-$07ff inclusive
|
||||
|
||||
override val BSSHIGHRAM_START = 0xa000u // hiram bank 1, 8Kb, assumed to be active
|
||||
override val BSSHIGHRAM_END = 0xc000u // rom starts here.
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
|
@ -17,6 +17,8 @@ class VirtualMachineDefinition: IMachineDefinition {
|
||||
|
||||
override var ESTACK_LO = 0u // not actually used
|
||||
override var ESTACK_HI = 0u // not actually used
|
||||
override val BSSHIGHRAM_START = 0u // not actually used
|
||||
override val BSSHIGHRAM_END = 0u // not actually used
|
||||
override lateinit var zeropage: Zeropage // not actually used
|
||||
override lateinit var golden: GoldenRam // not actually used
|
||||
|
||||
|
@ -162,23 +162,44 @@ internal class ProgramAndVarsGen(
|
||||
}
|
||||
|
||||
private fun memorySlabs() {
|
||||
asmgen.out("; memory slabs\n .section slabs_BSS")
|
||||
asmgen.out("prog8_slabs\t.block")
|
||||
for(slab in symboltable.allMemorySlabs) {
|
||||
if(slab.align>1u)
|
||||
asmgen.out("\t.align ${slab.align.toHex()}")
|
||||
asmgen.out("${slab.name}\t.fill ${slab.size}")
|
||||
if(symboltable.allMemorySlabs.isNotEmpty()) {
|
||||
asmgen.out("; memory slabs\n .section slabs_BSS")
|
||||
asmgen.out("prog8_slabs\t.block")
|
||||
for (slab in symboltable.allMemorySlabs) {
|
||||
if (slab.align > 1u)
|
||||
asmgen.out("\t.align ${slab.align.toHex()}")
|
||||
asmgen.out("${slab.name}\t.fill ${slab.size}")
|
||||
}
|
||||
asmgen.out("\t.bend\n .send slabs_BSS")
|
||||
}
|
||||
asmgen.out("\t.bend\n .send slabs_BSS")
|
||||
}
|
||||
|
||||
private fun footer() {
|
||||
asmgen.out("; bss sections")
|
||||
asmgen.out("prog8_bss_section_start")
|
||||
asmgen.out(" .dsection BSS")
|
||||
asmgen.out("prog8_bss_section_size = * - prog8_bss_section_start")
|
||||
asmgen.out(" .dsection slabs_BSS")
|
||||
asmgen.out("prog8_program_end\t; end of program label for progend()")
|
||||
if(options.varsHigh) {
|
||||
if(options.compTarget.machine.BSSHIGHRAM_START == 0u || options.compTarget.machine.BSSHIGHRAM_END==0u) {
|
||||
throw AssemblyError("current compilation target hasn't got the high ram area properly defined")
|
||||
}
|
||||
// BSS vars in high ram area, memory() slabs just concatenated at the end of the program.
|
||||
if(symboltable.allMemorySlabs.isNotEmpty()) {
|
||||
asmgen.out(" .dsection slabs_BSS")
|
||||
}
|
||||
asmgen.out("prog8_program_end\t; end of program label for progend()")
|
||||
asmgen.out(" * = ${options.compTarget.machine.BSSHIGHRAM_START.toHex()}")
|
||||
asmgen.out("prog8_bss_section_start")
|
||||
asmgen.out(" .dsection BSS")
|
||||
asmgen.out(" .cerror * >= ${options.compTarget.machine.BSSHIGHRAM_END.toHex()}, \"too many variables for BSS section\"")
|
||||
asmgen.out("prog8_bss_section_size = * - prog8_bss_section_start")
|
||||
} else {
|
||||
// BSS vars followed by memory() slabs, concatenated at the end of the program.
|
||||
asmgen.out("prog8_bss_section_start")
|
||||
asmgen.out(" .dsection BSS")
|
||||
asmgen.out("prog8_bss_section_size = * - prog8_bss_section_start")
|
||||
if(symboltable.allMemorySlabs.isNotEmpty()) {
|
||||
asmgen.out(" .dsection slabs_BSS")
|
||||
}
|
||||
asmgen.out("prog8_program_end\t; end of program label for progend()")
|
||||
}
|
||||
}
|
||||
|
||||
private fun block2asm(block: PtBlock) {
|
||||
|
@ -51,6 +51,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${VMTarget.NAME}')").default(C64Target.NAME)
|
||||
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
|
||||
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
|
||||
val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program")
|
||||
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
|
||||
|
||||
try {
|
||||
@ -124,6 +125,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
quietAssembler == true,
|
||||
asmListfile == true,
|
||||
experimentalCodegen == true,
|
||||
varsHigh == true,
|
||||
compilationTarget,
|
||||
evalStackAddr,
|
||||
processedSymbols,
|
||||
@ -187,6 +189,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
quietAssembler == true,
|
||||
asmListfile == true,
|
||||
experimentalCodegen == true,
|
||||
varsHigh == true,
|
||||
compilationTarget,
|
||||
evalStackAddr,
|
||||
processedSymbols,
|
||||
|
@ -35,6 +35,7 @@ class CompilerArguments(val filepath: Path,
|
||||
val quietAssembler: Boolean,
|
||||
val asmListfile: Boolean,
|
||||
val experimentalCodegen: Boolean,
|
||||
val varsHigh: Boolean,
|
||||
val compilationTarget: String,
|
||||
val evalStackBaseAddress: UInt?,
|
||||
val symbolDefs: Map<String, String>,
|
||||
@ -77,6 +78,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
asmQuiet = args.quietAssembler
|
||||
asmListfile = args.asmListfile
|
||||
experimentalCodegen = args.experimentalCodegen
|
||||
varsHigh = args.varsHigh
|
||||
evalStackBaseAddress = args.evalStackBaseAddress
|
||||
outputDir = args.outputDir.normalize()
|
||||
symbolDefs = args.symbolDefs
|
||||
|
@ -32,6 +32,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
experimentalCodegen = false,
|
||||
varsHigh = false,
|
||||
compilationTarget = target.name,
|
||||
evalStackBaseAddress = null,
|
||||
symbolDefs = emptyMap(),
|
||||
|
@ -49,6 +49,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
experimentalCodegen = false,
|
||||
varsHigh = false,
|
||||
compilationTarget = Cx16Target.NAME,
|
||||
evalStackBaseAddress = null,
|
||||
symbolDefs = emptyMap(),
|
||||
|
@ -30,6 +30,7 @@ internal fun compileFile(
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
experimentalCodegen = false,
|
||||
varsHigh = false,
|
||||
platform.name,
|
||||
evalStackBaseAddress = null,
|
||||
symbolDefs = emptyMap(),
|
||||
|
@ -175,6 +175,23 @@ One or more .p8 module files
|
||||
When not compiling for the Commander X16 target, the location of the 16 virtual registers cx16.r0..r15
|
||||
is changed accordingly (to keep them in the same memory space as the evaluation stack).
|
||||
|
||||
``-varshigh``
|
||||
Places the uninitialized (and zero-initialized) variables in a separate high memory area, instead of
|
||||
inside the program itself. This results in an increase of the amount of system ram available for the program
|
||||
itself. The amount of ram saved depends on the amount and types of variables in the program, but can be
|
||||
several hundreds of bytes or more.
|
||||
The new memory location of the variables depends on the compilation target machine
|
||||
|
||||
c64: $C000 - $CEFF
|
||||
|
||||
cx16: $A000 - $BFFF (note: assumes that the correct HiRam bank #1 is mapped in at all times!)
|
||||
|
||||
If you use this option, you can no longer use the part of the above memory area that is
|
||||
now alotted to the variables for your own purposes. The output of the 64tass assembler step at the
|
||||
end of compilation shows precise details of where and how much memory is used by the variables
|
||||
(it's called 'BSS' section or Gap). Compilation (or rather, assembling) will fail if there are too
|
||||
many variables to fit in the high ram block.
|
||||
|
||||
|
||||
Module source code files
|
||||
------------------------
|
||||
|
@ -12,6 +12,13 @@ but care should be taken of course to avoid unexpected side effects.
|
||||
Especially when you're dealing with interrupts or re-entrant routines: don't modify variables
|
||||
that you not own or else you will break stuff.
|
||||
|
||||
Uninitialized and zero-initialized variables that are not put into zeropage, will be put into
|
||||
a special 'BSS' section for the assembler. This section is usually placed at the end of the resulting program
|
||||
but because it only contains empty space it won't actually increase the size of the resulting program binary.
|
||||
Prog8 takes care of properly filling this memory area with zeros at program startup.
|
||||
It is possible to relocate the BSS section using a compiler option
|
||||
so that more system ram is available for the program code itself.
|
||||
|
||||
|
||||
.. _three-letter-prefixing:
|
||||
|
||||
|
@ -3,21 +3,18 @@ TODO
|
||||
|
||||
For next minor release
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
- option to put BSS in specific upper memory block ($a000-$bfff on x16, $c000-$cdff on C64) add a .cerror check for overflow!
|
||||
- document bss stuff in the manual
|
||||
|
||||
...
|
||||
|
||||
|
||||
For 9.0 major changes
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
- duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) + documentation
|
||||
- get f_seek_w working like in the BASIC program - this needs the changes to diskio.f_open to use suffixes ,p,m
|
||||
- SEGMENTS.
|
||||
- Some support for (64tass) SEGMENTS ?
|
||||
- Add a mechanism to allocate variables into golden ram (or segments really) (see GoldenRam class)
|
||||
- block "golden" treated specially: every var in here will be allocated in the Golden ram area
|
||||
- that block can only contain variables.
|
||||
- maybe treat block "golden" in a special way: can only contain vars, every var will be allocated in the Golden ram area?
|
||||
- the variables can NOT have initialization 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
|
||||
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?
|
||||
- (need separate step in codegen and IR to write the "golden" variables)
|
||||
|
@ -41,7 +41,8 @@ class RequestParser : Take {
|
||||
symbolDefs = emptyMap(),
|
||||
quietAssembler = false,
|
||||
asmListfile = false,
|
||||
experimentalCodegen = false
|
||||
experimentalCodegen = false,
|
||||
varsHigh = false
|
||||
)
|
||||
val compilationResult = compileProgram(args)
|
||||
return RsJson(Jsonding())
|
||||
|
Loading…
Reference in New Issue
Block a user