This commit is contained in:
Irmen de Jong 2023-02-19 03:07:55 +01:00
parent f7dd388954
commit 9ca6860ffa
11 changed files with 145 additions and 45 deletions

View File

@ -65,7 +65,7 @@ internal class ProgramAndVarsGen(
asmgen.out("; assembler syntax is for the 64tasm cross-assembler")
asmgen.out("; output options: output=${options.output} launcher=${options.launcher} zp=${options.zeropage}")
asmgen.out("")
asmgen.out(".cpu '$cpu'\n.enc 'none'\n")
asmgen.out(".cpu '$cpu'\n.enc 'none'")
// the global prog8 variables needed
val zp = zeropage
@ -88,7 +88,7 @@ internal class ProgramAndVarsGen(
when(options.output) {
OutputType.RAW -> {
asmgen.out("; ---- raw assembler program ----")
asmgen.out("* = ${options.loadAddress.toHex()}\n")
asmgen.out("* = ${options.loadAddress.toHex()}")
}
OutputType.PRG -> {
when(options.launcher) {
@ -102,14 +102,14 @@ internal class ProgramAndVarsGen(
asmgen.out(" .word (+), $year")
asmgen.out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'")
asmgen.out("+\t.word 0")
asmgen.out("prog8_entrypoint\t; assembly code starts here\n")
asmgen.out("prog8_entrypoint\t; assembly code starts here")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
CbmPrgLauncherType.NONE -> {
asmgen.out("; ---- program without basic sys call ----")
asmgen.out("* = ${options.loadAddress.toHex()}\n")
asmgen.out("* = ${options.loadAddress.toHex()}")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
@ -118,7 +118,7 @@ internal class ProgramAndVarsGen(
}
OutputType.XEX -> {
asmgen.out("; ---- atari xex program ----")
asmgen.out("* = ${options.loadAddress.toHex()}\n")
asmgen.out("* = ${options.loadAddress.toHex()}")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
@ -189,7 +189,7 @@ internal class ProgramAndVarsGen(
asmgen.out("\t.align $100")
}
asmgen.out("${block.name}\t" + (if(block.forceOutput) ".block\n" else ".proc\n"))
asmgen.out("${block.name}\t" + (if(block.forceOutput) ".block" else ".proc"))
asmgen.outputSourceLine(block)
createBlockVariables(block)
@ -204,13 +204,13 @@ internal class ProgramAndVarsGen(
if(!options.dontReinitGlobals) {
// generate subroutine to initialize block-level (global) variables
if (initializers.isNotEmpty()) {
asmgen.out("prog8_init_vars\t.block\n")
asmgen.out("prog8_init_vars\t.block")
initializers.forEach { assign -> asmgen.translate(assign) }
asmgen.out(" rts\n .bend")
}
}
asmgen.out(if(block.forceOutput) "\n\t.bend\n" else "\n\t.pend\n")
asmgen.out(if(block.forceOutput) "\n\t.bend" else "\n\t.pend")
}
private fun getVars(scope: StNode): Map<String, StNode> =
@ -266,7 +266,7 @@ internal class ProgramAndVarsGen(
// asmsub with most likely just an inline asm in it
asmgen.out("${sub.name}\t$asmStartScope")
sub.children.forEach { asmgen.translate(it) }
asmgen.out(" $asmEndScope\n")
asmgen.out(" $asmEndScope")
}
@ -358,7 +358,7 @@ internal class ProgramAndVarsGen(
.map { it.value as StStaticVariable }
nonZpVariables2asm(variables)
asmgen.out(" $asmEndScope\n")
asmgen.out(" $asmEndScope")
}
private fun entrypointInitialization() {

View File

@ -19,10 +19,10 @@ class TestLaunchEmu: FunSpec({
<ASMSYMBOLS>
</ASMSYMBOLS>
<BSS>
</BSS>
<VARIABLES>
</VARIABLES>
<VARIABLESNOINIT>
</VARIABLESNOINIT>
<VARIABLESWITHINIT>
</VARIABLESWITHINIT>
<MEMORYMAPPEDVARIABLES>
</MEMORYMAPPEDVARIABLES>

View File

@ -14,7 +14,7 @@ import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8tests.helpers.compileText
class TestVarious: FunSpec({
class TestVariousCompilerAst: FunSpec({
test("symbol names in inline assembly blocks") {
val names1 = InlineAssembly("""

View File

@ -13,7 +13,7 @@ import prog8.code.core.DataType
import prog8.code.target.C64Target
import prog8tests.helpers.compileText
class TestVarious: FunSpec({
class TestVariousCodeGen: FunSpec({
test("bool to byte cast in expression is correct") {
val text="""
main {

View File

@ -3,10 +3,17 @@ TODO
For next minor release
^^^^^^^^^^^^^^^^^^^^^^
- fix hasInitValue() and isBssVar()
- BSS.
64tass can put variables into a section with .section BSS <variable> .send BSS
and then putting .dsection BSS where it should output the BSS
Define vars in BSS with .fill rather than .byte otherwise they STILL take up space!
- BSS in 6502 codegen: create BSS section in output assembly code and put StStaticVariables in there with bss=true.
Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE if possible.
Note that bss can still contain variables that have @zp tag and those are already dealt with differently
- BSS: subroutine parameters don't have to be set to 0.
Note that 'bss' can still be true for variables that were moved into zeropage, so have to check that!
- BSS subroutine parameters don't have to be set to 0.
- when putting BSS in specific memory block ($a000-$bfff, $c000-$cfff) add a .cerror check for overflow!
...

View File

@ -1,13 +1,107 @@
%import floats
%import textio
%option no_sysinit
%zeropage basicsafe
main {
&ubyte[40] topline = $0400
uword b_wordvar
ubyte b_bb =123
float b_fl
ubyte[10] b_emptyarray
ubyte[10] b_filledarray = [1,2,3,4,5,6,7,8,9,10]
float[3] b_floatarray
uword[3] b_wordarray
sub start() {
topline[0] = 'a'
topline[1] = 'b'
topline[2] = 'd'
topline[39] = '@'
uword wordvar
float fl
ubyte bb =123
ubyte[10] emptyarray
ubyte[10] filledarray = [1,2,3,4,5,6,7,8,9,10]
float[3] floatarray
uword[3] wordarray
txt.print("**subroutine scope**\n")
txt.print("uninit wordvar=")
txt.print_uw(wordvar)
txt.print("\nuninit float=")
floats.print_f(fl)
txt.print("\ninit bb=")
txt.print_ub(bb)
txt.print("\nuninit emptyarray[2]=")
txt.print_ub(emptyarray[2])
txt.print("\nuninit wordarray[2]=")
txt.print_uw(wordarray[2])
txt.print("\nuninit floatarray[2]=")
floats.print_f(floatarray[2])
txt.print("\ninit filledarray[2]=")
txt.print_ub(filledarray[2])
txt.print("\n**block scope**\n")
txt.print("uninit b_wordvar=")
txt.print_uw(b_wordvar)
txt.print("\nuninit b_float=")
floats.print_f(b_fl)
txt.print("\ninit b_bb=")
txt.print_ub(b_bb)
txt.print("\nuninit b_emptyarray[2]=")
txt.print_ub(b_emptyarray[2])
txt.print("\nuninit b_wordarray[2]=")
txt.print_uw(b_wordarray[2])
txt.print("\nuninit b_floatarray[2]=")
floats.print_f(b_floatarray[2])
txt.print("\ninit b_filledarray[2]=")
txt.print_ub(b_filledarray[2])
txt.print("\n\nadding 42 to all values.\n")
wordvar += 42
bb += 42
fl += 42.42
floatarray[2] += 42.42
wordarray[2] += 42
emptyarray[2] += 42
filledarray[2] += 42
b_wordvar += 42
b_bb += 42
b_fl += 42.42
b_floatarray[2] += 42.42
b_wordarray[2] += 42
b_emptyarray[2] += 42
b_filledarray[2] += 42
txt.print("\n**subroutine scope**\n")
txt.print("uninit wordvar=")
txt.print_uw(wordvar)
txt.print("\nuninit float=")
floats.print_f(fl)
txt.print("\ninit bb=")
txt.print_ub(bb)
txt.print("\nuninit emptyarray[2]=")
txt.print_ub(emptyarray[2])
txt.print("\nuninit wordarray[2]=")
txt.print_uw(wordarray[2])
txt.print("\nuninit floatarray[2]=")
floats.print_f(floatarray[2])
txt.print("\ninit filledarray[2]=")
txt.print_ub(filledarray[2])
txt.print("\n**block scope**\n")
txt.print("uninit b_wordvar=")
txt.print_uw(b_wordvar)
txt.print("\nuninit b_float=")
floats.print_f(b_fl)
txt.print("\ninit b_bb=")
txt.print_ub(b_bb)
txt.print("\nuninit b_emptyarray[2]=")
txt.print_ub(b_emptyarray[2])
txt.print("\nuninit b_wordarray[2]=")
txt.print_uw(b_wordarray[2])
txt.print("\nuninit b_floatarray[2]=")
floats.print_f(b_floatarray[2])
txt.print("\ninit b_filledarray[2]=")
txt.print_ub(b_filledarray[2])
txt.print("\n\nrun again to see effect of re-init.\n")
}
}

View File

@ -45,7 +45,7 @@ class IRFileReader {
val programName = start.attributes.asSequence().single { it.name.localPart == "NAME" }.value
val options = parseOptions(reader)
val asmsymbols = parseAsmSymbols(reader)
val bss = parseBss(reader)
val varsWithoutInit = parseVarsWithoutInit(reader)
val variables = parseVariables(reader, options.dontReinitGlobals)
val memorymapped = parseMemMapped(reader)
val slabs = parseSlabs(reader)
@ -54,7 +54,7 @@ class IRFileReader {
val st = IRSymbolTable(null)
asmsymbols.forEach { (name, value) -> st.addAsmSymbol(name, value)}
bss.forEach { st.add(it) }
varsWithoutInit.forEach { st.add(it) }
variables.forEach { st.add(it) }
memorymapped.forEach { st.add(it) }
slabs.forEach { st.add(it) }
@ -150,10 +150,10 @@ class IRFileReader {
}
}
private fun parseBss(reader: XMLEventReader): List<StStaticVariable> {
private fun parseVarsWithoutInit(reader: XMLEventReader): List<StStaticVariable> {
skipText(reader)
val start = reader.nextEvent().asStartElement()
require(start.name.localPart=="BSS") { "missing BSS" }
require(start.name.localPart=="VARIABLESNOINIT") { "missing VARIABLESNOINIT" }
val text = readText(reader).trim()
require(reader.nextEvent().isEndElement)
@ -161,10 +161,10 @@ class IRFileReader {
emptyList()
else {
val varPattern = Regex("(.+?)(\\[.+?\\])? (.+) (zp=(.+))?")
val bssVariables = mutableListOf<StStaticVariable>()
val variables = mutableListOf<StStaticVariable>()
text.lineSequence().forEach { line ->
// example: uword main.start.qq2 zp=DONTCARE
val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid BSS $line")
val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLESNOINIT $line")
val (type, arrayspec, name, _, zpwish) = match.destructured
if('.' !in name)
throw IRParseException("unscoped varname: $name")
@ -173,16 +173,16 @@ class IRFileReader {
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
val dummyNode = PtVariable(name, dt, zp, null, null, Position.DUMMY)
val newVar = StStaticVariable(name, dt, true, null, null, null, arraysize, zp, dummyNode)
bssVariables.add(newVar)
variables.add(newVar)
}
return bssVariables
return variables
}
}
private fun parseVariables(reader: XMLEventReader, dontReinitGlobals: Boolean): List<StStaticVariable> {
skipText(reader)
val start = reader.nextEvent().asStartElement()
require(start.name.localPart=="VARIABLES") { "missing VARIABLES" }
require(start.name.localPart=="VARIABLESWITHINIT") { "missing VARIABLESWITHINIT" }
val text = readText(reader).trim()
require(reader.nextEvent().isEndElement)

View File

@ -139,14 +139,13 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
private fun writeVariables() {
out.write("\n<BSS>\n")
out.write("\n<VARIABLESNOINIT>\n")
for (variable in irProgram.st.allVariables().filter { it.bss }) {
val typeStr = getTypeString(variable)
// bss variables have no initialization value
out.write("$typeStr ${variable.name} zp=${variable.zpwish}\n")
}
out.write("</BSS>\n<VARIABLES>\n")
out.write("</VARIABLESNOINIT>\n<VARIABLESWITHINIT>\n")
for (variable in irProgram.st.allVariables().filter { !it.bss }) {
val typeStr = getTypeString(variable)
val value: String = when(variable.dt) {
@ -179,7 +178,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
}
out.write("$typeStr ${variable.name}=$value zp=${variable.zpwish}\n")
}
out.write("</VARIABLES>\n")
out.write("</VARIABLESWITHINIT>\n")
out.write("\n<MEMORYMAPPEDVARIABLES>\n")
for (variable in irProgram.st.allMemMappedVariables()) {

View File

@ -55,12 +55,12 @@ evalStackBaseAddress=null
<ASMSYMBOLS>
</ASMSYMBOLS>
<BSS>
<VARIABLESNOINIT>
uword sys.bssvar zp=DONTCARE
</BSS>
<VARIABLES>
</VARIABLESNOINIT>
<VARIABLESWITHINIT>
uword sys.wait.jiffies=10 zp=DONTCARE
</VARIABLES>
</VARIABLESWITHINIT>
<MEMORYMAPPEDVARIABLES>
@uword cx16.r0=65282

View File

@ -176,7 +176,7 @@ class VmProgramLoader {
program.st.allVariables().forEach { variable ->
var addr = allocations.allocations.getValue(variable.name)
// zero out BSS variables.
// zero out uninitialized variables.
if(variable.bss) {
if(variable.dt in ArrayDatatypes) {
repeat(variable.length!!) {

View File

@ -115,10 +115,10 @@ class TestVm: FunSpec( {
<ASMSYMBOLS>
</ASMSYMBOLS>
<BSS>
</BSS>
<VARIABLES>
</VARIABLES>
<VARIABLESNOINIT>
</VARIABLESNOINIT>
<VARIABLESWITHINIT>
</VARIABLESWITHINIT>
<MEMORYMAPPEDVARIABLES>
</MEMORYMAPPEDVARIABLES>