fix issues with memory() function, rewrite examples to use it

This commit is contained in:
Irmen de Jong 2020-12-27 03:35:56 +01:00
parent 7607d3d64a
commit e17c18b653
9 changed files with 72 additions and 100 deletions

View File

@ -73,21 +73,18 @@ io_error:
sub list_files(ubyte drivenumber, uword pattern, ubyte suffixmatch, uword name_ptrs, ubyte max_names) -> ubyte {
; -- fill the array 'name_ptrs' with (pointers to) the names of the files requested.
ubyte[256] names_buffer
ubyte[256] names_buffer1 ; to store a bit more names
; TODO names_buffer = memory("filenames", 512)
uword buf_ptr = &names_buffer
names_buffer1[0] = 0 ; TODO force array to exist
uword names_buffer = memory("filenames", 512)
uword buffer_start = names_buffer
ubyte files_found = 0
if lf_start_list(drivenumber, pattern, suffixmatch) {
while lf_next_entry() {
@(name_ptrs) = lsb(buf_ptr)
@(name_ptrs) = lsb(names_buffer)
name_ptrs++
@(name_ptrs) = msb(buf_ptr)
@(name_ptrs) = msb(names_buffer)
name_ptrs++
buf_ptr += strcopy(diskio.list_filename, buf_ptr) + 1
names_buffer += strcopy(diskio.list_filename, names_buffer) + 1
files_found++
if buf_ptr - &names_buffer > (len(names_buffer) + len(names_buffer1) - 18)
if names_buffer - buffer_start > 512-18
break
if files_found == max_names
break

View File

@ -697,7 +697,6 @@ class AsmGenInfo {
var usedRegsaveY = false
var usedFloatEvalResultVar1 = false
var usedFloatEvalResultVar2 = false
val removals = mutableListOf<Statement>()
class ArrayIndexerInfo(val name: String, val replaces: ArrayIndex)
}

View File

@ -51,6 +51,7 @@ internal class AsmGen(private val program: Program,
internal val loopEndLabels = ArrayDeque<String>()
private val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
internal val slabs = mutableMapOf<String, Int>()
internal val removals = mutableListOf<Pair<Statement, INameScope>>()
override fun compileToAssembly(): IAssemblyProgram {
assemblyLines.clear()
@ -64,6 +65,12 @@ internal class AsmGen(private val program: Program,
throw AssemblyError("first block should be 'main'")
for(b in program.allBlocks())
block2asm(b)
for(removal in removals.toList()) {
removal.second.remove(removal.first)
removals.remove(removal)
}
slaballocations()
footer()
@ -845,10 +852,12 @@ internal class AsmGen(private val program: Program,
out("; statements")
sub.statements.forEach{ translate(it) }
for(stmt in sub.asmGenInfo.removals) {
sub.remove(stmt)
for(removal in removals.toList()) {
if(removal.second==sub) {
removal.second.remove(removal.first)
removals.remove(removal)
}
}
sub.asmGenInfo.removals.clear()
out("; variables")
out("; register saves")

View File

@ -35,25 +35,25 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
if(discardResult && resultToStack)
throw AssemblyError("cannot both discard the result AND put it onto stack")
val scope = (fcall as Node).definingSubroutine()!!
val sscope = (fcall as Node).definingSubroutine()
when (func.name) {
"msb" -> funcMsb(fcall, resultToStack)
"lsb" -> funcLsb(fcall, resultToStack)
"mkword" -> funcMkword(fcall, resultToStack)
"abs" -> funcAbs(fcall, func, resultToStack, scope)
"abs" -> funcAbs(fcall, func, resultToStack, sscope)
"swap" -> funcSwap(fcall)
"min", "max" -> funcMinMax(fcall, func, resultToStack)
"sum" -> funcSum(fcall, resultToStack)
"any", "all" -> funcAnyAll(fcall, func, resultToStack)
"sin8", "sin8u", "sin16", "sin16u",
"cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, resultToStack, scope)
"sgn" -> funcSgn(fcall, func, resultToStack, scope)
"cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, resultToStack, sscope)
"sgn" -> funcSgn(fcall, func, resultToStack, sscope)
"sin", "cos", "tan", "atan",
"ln", "log2", "sqrt", "rad",
"deg", "round", "floor", "ceil",
"rndf" -> funcVariousFloatFuncs(fcall, func, resultToStack, scope)
"rndf" -> funcVariousFloatFuncs(fcall, func, resultToStack, sscope)
"rnd", "rndw" -> funcRnd(func, resultToStack)
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, scope)
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, sscope)
"rol" -> funcRol(fcall)
"rol2" -> funcRol2(fcall)
"ror" -> funcRor(fcall)
@ -80,21 +80,21 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
"clear_irqd" -> asmgen.out(" cli")
"set_irqd" -> asmgen.out(" sei")
"strlen" -> funcStrlen(fcall, resultToStack)
"strcmp" -> funcStrcmp(fcall, func, resultToStack, scope)
"strcmp" -> funcStrcmp(fcall, func, resultToStack, sscope)
"strcopy" -> {
translateArguments(fcall.args, func, scope)
translateArguments(fcall.args, func, sscope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strcopy_to_stack")
else
asmgen.out(" jsr prog8_lib.func_strcopy")
}
"memcopy", "memset", "memsetw" -> funcMemSetCopy(fcall, func, scope)
"memcopy", "memset", "memsetw" -> funcMemSetCopy(fcall, func, sscope)
"substr", "leftstr", "rightstr" -> {
translateArguments(fcall.args, func, scope)
translateArguments(fcall.args, func, sscope)
asmgen.out(" jsr prog8_lib.func_${func.name}")
}
"exit" -> {
translateArguments(fcall.args, func, scope)
translateArguments(fcall.args, func, sscope)
asmgen.out(" jmp prog8_lib.func_exit")
}
"progend" -> {
@ -138,14 +138,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
// remove the variable for the name, it's not used as a variable only as a tag for the assembler.
val nameDecl = scope.statements.single { it is VarDecl && it.name==nameRef.nameInSource.single() }
(scope as Subroutine).asmGenInfo.removals.add(nameDecl)
asmgen.removals.add(Pair(nameDecl, scope))
asmgen.slabs[name] = size
}
private fun funcMemSetCopy(fcall: IFunctionCall, func: FSignature, scope: Subroutine) {
private fun funcMemSetCopy(fcall: IFunctionCall, func: FSignature, scope: Subroutine?) {
if(CompilationTarget.instance is Cx16Target) {
when(func.name) {
"memset" -> {
if(scope==null)
throw AssemblyError("cannot call memset() outside of a subroutine scope")
// use the ROM function of the Cx16
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.R0)
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R1)
@ -164,6 +166,9 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
return
}
if(scope==null)
throw AssemblyError("cannot call memcopy() outside of a subroutine scope")
// use the ROM function of the Cx16
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.R0)
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R1)
@ -192,7 +197,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strcmp_stack")
@ -200,7 +205,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
asmgen.out(" jsr prog8_lib.func_strcmp")
}
private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
@ -208,7 +213,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
}
private fun funcSinCosInt(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcSinCosInt(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_${func.name}_stack")
@ -474,7 +479,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
asmgen.assignExpressionToVariable(indexerExpr, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE, null)
}
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr floats.func_${func.name}_stack")
@ -482,7 +487,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
asmgen.out(" jsr floats.func_${func.name}_fac1")
}
private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
val dt = fcall.args.single().inferType(program)
if(resultToStack) {
@ -972,7 +977,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) {
private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
val dt = fcall.args.single().inferType(program).typeOrElse(DataType.STRUCT)
if(resultToStack) {
@ -1070,7 +1075,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
""")
}
private fun translateArguments(args: MutableList<Expression>, signature: FSignature, scope: Subroutine) {
private fun translateArguments(args: MutableList<Expression>, signature: FSignature, scope: Subroutine?) {
val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.STRUCT) })
fun getSourceForFloat(value: Expression): AsmAssignSource {
@ -1083,6 +1088,9 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
throw AssemblyError("float literals should have been converted into autovar")
}
else -> {
if(scope==null)
throw AssemblyError("cannot use float arguments outside of a subroutine scope")
scope.asmGenInfo.usedFloatEvalResultVar2 = true
val variable = IdentifierReference(listOf(subroutineFloatEvalResultVar2), value.position)
val addr = AddressOf(variable, value.position)

View File

@ -13,17 +13,9 @@ bmp_module {
ubyte bpp
uword offsetx
uword offsety
ubyte[256] palette0
ubyte[256] palette1
ubyte[256] palette2
ubyte[256] palette3
uword palette = memory("palette", 256*4)
uword total_read = 0
palette0[0] = 0
palette1[0] = 0
palette2[0] = 0
palette3[0] = 0
if diskio.f_open(8, filenameptr) {
size = diskio.f_read(header, $36)
if size==$36 {
@ -41,13 +33,13 @@ bmp_module {
repeat skip_hdr
void c64.CHRIN()
total_read += skip_hdr
size = diskio.f_read(&palette0, num_colors*4)
size = diskio.f_read(palette, num_colors*4)
if size==num_colors*4 {
total_read += size
repeat bm_data_offset - total_read
void c64.CHRIN()
gfx2.clear_screen()
custompalette.set_bgra(&palette0, num_colors)
custompalette.set_bgra(palette, num_colors)
decode_bitmap()
load_ok = true
}

View File

@ -47,14 +47,9 @@
; (doing it in chunks of 8 kb allows for sticking each chunk in one of the banked 8kb ram blocks, or even copy it directly to the screen)
ci_module {
%option force_output
ubyte[256] buffer
ubyte[256] buffer2 ; add two more buffers to make enough space
ubyte[256] buffer3 ; to store a 256 color palette
ubyte[256] buffer4 ; .. and some more to be able to store 1280=
ubyte[256] buffer5 ; two 640 bytes worth of bitmap scanline data
sub show_image(uword filename) -> ubyte {
uword buffer = memory("buffer", 620*2) ; enough to store two scanlines of 640 bytes
ubyte read_success = false
uword bitmap_load_address = progend()
; uword max_bitmap_size = $9eff - bitmap_load_address
@ -62,18 +57,18 @@ ci_module {
if(diskio.f_open(8, filename)) {
uword size = diskio.f_read(buffer, 12) ; read the header
if size==12 {
if buffer[0]=='c' and buffer[1]=='i' and buffer[2] == 9 {
uword width = mkword(buffer[4], buffer[3])
uword height = mkword(buffer[6], buffer[5])
ubyte bpp = buffer[7]
if @(buffer+0)=='c' and @(buffer+1)=='i' and @(buffer+2) == 9 {
uword width = mkword(@(buffer+4), @(buffer+3))
uword height = mkword(@(buffer+6), @(buffer+5))
ubyte bpp = @(buffer+7)
uword num_colors = 2 ** bpp
ubyte flags = buffer[8]
ubyte flags = @(buffer+8)
ubyte compression = flags & %00000011
ubyte palette_format = (flags & %00000100) >> 2
ubyte bitmap_format = (flags & %00001000) >> 3
; ubyte hscale = (flags & %00010000) >> 4
; ubyte vscale = (flags & %00100000) >> 5
uword bitmap_size = mkword(buffer[10], buffer[9])
uword bitmap_size = mkword(@(buffer+10), @(buffer+9))
uword palette_size = num_colors*2
if palette_format
palette_size += num_colors ; 3

View File

@ -4,10 +4,7 @@
%import diskio
iff_module {
; TODO uword cmap = memory("palette", 768)
ubyte[256] cmap
ubyte[256] cmap1
ubyte[256] cmap2
uword cmap
uword num_colors
uword[16] cycle_rates
uword[16] cycle_rate_ticks
@ -33,10 +30,8 @@ iff_module {
ubyte have_cmap = false
ubyte cycle_crng = false
ubyte cycle_ccrt = false
cmap[0] = 0
cmap1[0] = 0
cmap2[0] = 0
num_cycles = 0
cmap = memory("palette", 256*4) ; only use 768 of these, but this allows re-use of the same block that the bmp module allocates
if diskio.f_open(8, filenameptr) {
size = diskio.f_read(buffer, 12)
@ -63,7 +58,7 @@ iff_module {
}
else if chunk_id == "cmap" {
have_cmap = true
diskio.f_read_exact(&cmap, chunk_size_lo)
diskio.f_read_exact(cmap, chunk_size_lo)
}
else if chunk_id == "crng" {
; DeluxePaint color cycle range
@ -110,7 +105,7 @@ iff_module {
height /= 2 ; interlaced: just skip every odd scanline later
if camg & $0080 and have_cmap
make_ehb_palette()
palette.set_rgb8(&cmap, num_colors)
palette.set_rgb8(cmap, num_colors)
if compression
decode_rle()
else
@ -154,7 +149,7 @@ iff_module {
sub make_ehb_palette() {
; generate 32 additional Extra-Halfbrite colors in the cmap
uword palletteptr = &cmap
uword palletteptr = cmap
uword ehbptr = palletteptr + 32*3
repeat 32 {
@(ehbptr) = @(palletteptr)>>1
@ -320,7 +315,7 @@ _masks .byte 128, 64, 32, 16, 8, 4, 2, 1
}
if changed
palette.set_rgb8(&cmap, num_colors) ; set the new palette
palette.set_rgb8(cmap, num_colors) ; set the new palette
sub do_cycle(uword low, uword high, ubyte reversed) {
low *= 3
@ -332,7 +327,7 @@ _masks .byte 128, 64, 32, 16, 8, 4, 2, 1
ubyte blue
if reversed {
cptr = &cmap + low
cptr = cmap + low
red = @(cptr)
green = @(cptr+1)
blue = @(cptr+2)
@ -346,7 +341,7 @@ _masks .byte 128, 64, 32, 16, 8, 4, 2, 1
cptr++
@(cptr) = blue
} else {
cptr = &cmap + high
cptr = cmap + high
red = @(cptr)
cptr++
green = @(cptr)

View File

@ -98,9 +98,9 @@ main {
}
}
; else if strcmp(extension, ".ci")==0 {
; txt.print("loading ")
; txt.print("ci\n")
; if bmp_module.ci_module(filenameptr) {
;; txt.print("loading ")
;; txt.print("ci\n")
; if ci_module.show_image(filenameptr) {
; cx16.wait(180)
; } else {
; load_error(filenameptr)

View File

@ -5,38 +5,15 @@
main {
;uword cmap = memory("palette", 256*4) ; only use 768 of these, but this allows re-use of the same block that the bmp module allocates
uword num_colors = rnd()
sub start () {
thing()
thing()
thing()
thing()
thing()
txt.chrout('\n')
txt.chrout('\n')
test_stack.test()
sub thing() -> ubyte {
uword buffer = memory("buffer", 512)
uword buffer2 = memory("buffer", 512)
uword buffer3 = memory("cache", 20)
txt.print_uwhex(buffer, true)
txt.chrout('\n')
txt.print_uwhex(buffer2, true)
txt.chrout('\n')
txt.print_uwhex(buffer3, true)
txt.chrout('\n')
buffer+=$1111
buffer2+=$1111
buffer3+=$1111
txt.print_uwhex(buffer, true)
txt.chrout('\n')
txt.print_uwhex(buffer2, true)
txt.chrout('\n')
txt.print_uwhex(buffer3, true)
txt.chrout('\n')
txt.chrout('\n')
return 0
}
}
}