API change: added alignment parameter to memory() function

This commit is contained in:
Irmen de Jong 2022-01-24 18:58:57 +01:00
parent 118196a0bf
commit b7d06f2c0a
10 changed files with 37 additions and 38 deletions

View File

@ -56,7 +56,7 @@ class AsmGen(private val program: Program,
private val assignmentAsmGen = AssignmentAsmGen(program, this)
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
internal val loopEndLabels = ArrayDeque<String>()
internal val slabs = mutableMapOf<String, UInt>()
internal val slabs = mutableMapOf<String, Pair<UInt, UInt>>()
internal val removals = mutableListOf<Pair<Statement, IStatementContainer>>()
private val blockVariableInitializers = program.allBlocks.associateWith { it.statements.filterIsInstance<Assignment>() }
@ -245,8 +245,11 @@ class AsmGen(private val program: Program,
private fun slaballocations() {
out("; memory slabs")
out("prog8_slabs\t.block")
for((name, size) in slabs)
out("$name\t.fill $size")
for((name, info) in slabs) {
if(info.second>1u)
out("\t.align ${info.second.toHex()}")
out("$name\t.fill ${info.first}")
}
out("\t.bend")
}

View File

@ -453,10 +453,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
val name = (nameRef.targetVarDecl(program)!!.value as StringLiteralValue).value
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name"}
val size = (fcall.args[1] as NumericLiteralValue).number.toUInt()
val align = (fcall.args[2] as NumericLiteralValue).number.toUInt()
val existingSize = asmgen.slabs[name]
if(existingSize!=null && existingSize!=size)
throw AssemblyError("memory slab '$name' already exists with a different size ($size) at ${fcall.position}")
val existing = asmgen.slabs[name]
if(existing!=null && (existing.first!=size || existing.second!=size))
throw AssemblyError("memory slab '$name' already exists with a different size or alignment at ${fcall.position}")
val slabname = IdentifierReference(listOf("prog8_slabs", name), fcall.position)
slabname.linkParents(fcall)
@ -468,7 +469,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, null, program, asmgen)
val assign = AsmAssignment(src, target, false, program.memsizer, fcall.position)
asmgen.translateNormalAssignment(assign)
asmgen.slabs[name] = size
asmgen.slabs[name] = Pair(size, align)
}
private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {

View File

@ -76,7 +76,7 @@ io_error:
sub list_files(ubyte drivenumber, uword pattern_ptr, uword name_ptrs, ubyte max_names) -> ubyte {
; -- fill the array 'name_ptrs' with (pointers to) the names of the files requested.
uword names_buffer = memory("filenames", 512)
uword names_buffer = memory("filenames", 512, 0)
uword buffer_start = names_buffer
ubyte files_found = 0
if lf_start_list(drivenumber, pattern_ptr) {

View File

@ -228,9 +228,19 @@ class TestMemory: FunSpec({
compileText(C64Target, false, """
main {
sub start() {
uword @shared mem = memory("a b c", 100)
uword @shared mem = memory("a b c", 100, $100)
}
}
""", writeAssembly = true).assertSuccess()
}
test("memory() with invalid argument") {
compileText(C64Target, false, """
main {
sub start() {
uword @shared mem1 = memory("abc", 100, -2)
}
}
""", writeAssembly = true).assertFailure()
}
})

View File

@ -154,7 +154,7 @@ private val functionSignatures: List<FSignature> = listOf(
FSignature("rnd" , false, emptyList(), DataType.UBYTE),
FSignature("rndw" , false, emptyList(), DataType.UWORD),
FSignature("rndf" , false, emptyList(), DataType.FLOAT),
FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD))), DataType.UWORD),
FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null),
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),

View File

@ -979,9 +979,12 @@ sizeof(name)
swap(x, y)
Swap the values of numerical variables (or memory locations) x and y in a fast way.
memory(name, size)
memory(name, size, alignment)
Returns the address of the first location of a statically "reserved" block of memory of the given size in bytes,
with the given name. Requesting the address of such a named memory block again later with
with the given name. If you specify an alignment value >1, it means the block of memory will
be aligned to such a dividable address in memory, for instance an alignment of $100 means the
memory block is aligned on a page boundary, and $2 means word aligned (even addresses).
Requesting the address of such a named memory block again later with
the same name, will result in the same address as before.
When reusing blocks in that way, it is required that the size argument is the same,
otherwise you'll get a compilation error.

View File

@ -3,6 +3,8 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- string.find should return index of found character + carry set if found, carry clear if not found. (fix cx16assem, it uses current behavior. Also fix docs!)
- if char in "string" should fall back to string.find if string is longer than... 16?
...
@ -22,9 +24,6 @@ Blocked by an official Commander-x16 r39 release
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- nameInAssemblyCode() should search smarter
- string.find should return index of found character + carry set if found, carry clear if not found. (fix cx16assem, it uses current behavior. Also fix docs!)
- if char in "string" should fall back to string.find if string is longer than... 16?
- add option to memory() to get aligned memory block (word, page aligned)
- Typecastexpression.isSimple: make it 'expression.isSimple' rather than always false. (this breaks some things atm)
- IdentifierReference: fix equality to also include position. CallGraph can then also only store IdentifierRef instead of pair(ident, position) as keys.
- Fix: don't report as recursion if code assigns address of its own subroutine to something, rather than calling it

View File

@ -8,8 +8,8 @@
main {
const ubyte database_size = 100
uword animal_names_buf = memory("animalnames", 500)
uword questions_buf = memory("questions", 2000)
uword animal_names_buf = memory("animalnames", 500, 0)
uword questions_buf = memory("questions", 2000, 0)
uword animal_names_ptr
uword questions_ptr

View File

@ -18,12 +18,9 @@ main {
}
sub demo1() {
uword pixels = memory("pixels", 320)
uword yy = 10
uword xx
uword pp
uword cnt
pp=pixels
gfx2.monochrome_stipple(true)
gfx2.disc(320,240,200,1)
@ -34,11 +31,6 @@ main {
gfx2.vertical_line(xx, 0, 480, 0)
}
for cnt in 0 to 319 {
@(pp) = 255
pp++
}
xx=gfx2.width/2
yy=10
gfx2.monochrome_stipple(false)

View File

@ -4,20 +4,11 @@
main {
sub start() {
word ww = calculate(6)
txt.print_w(ww)
uword m1 = memory("mem1", 123, $100)
uword m2 = memory("mem2", 999, 2)
txt.print_uwhex(m1, true)
txt.nl()
ubyte bb = calculate2(6)
txt.print_ub(bb)
txt.print_uwhex(m2, true)
txt.nl()
}
sub calculate2(ubyte row) -> ubyte {
return 8+row
}
sub calculate(ubyte row) -> word {
return 8+row
}
}