2023-02-09 00:46:23 +00:00
|
|
|
package prog8tests.codegencpu6502
|
|
|
|
|
2023-05-23 18:42:36 +00:00
|
|
|
import io.kotest.assertions.throwables.shouldNotThrowAny
|
2023-07-16 18:05:59 +00:00
|
|
|
import io.kotest.assertions.withClue
|
2023-02-09 00:46:23 +00:00
|
|
|
import io.kotest.core.spec.style.FunSpec
|
2023-07-16 18:05:59 +00:00
|
|
|
import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual
|
2023-02-22 20:27:08 +00:00
|
|
|
import io.kotest.matchers.shouldBe
|
2023-02-15 21:50:35 +00:00
|
|
|
import prog8.code.SymbolTableMaker
|
|
|
|
import prog8.code.ast.*
|
|
|
|
import prog8.code.core.*
|
|
|
|
import prog8.code.target.C64Target
|
|
|
|
import prog8.codegen.cpu6502.AsmGen6502
|
2023-02-22 20:27:08 +00:00
|
|
|
import java.nio.file.Files
|
|
|
|
import kotlin.io.path.Path
|
2023-02-09 00:46:23 +00:00
|
|
|
|
|
|
|
class TestCodegen: FunSpec({
|
|
|
|
|
2023-02-15 21:50:35 +00:00
|
|
|
fun getTestOptions(): CompilationOptions {
|
|
|
|
val target = C64Target()
|
|
|
|
return CompilationOptions(
|
|
|
|
OutputType.RAW,
|
|
|
|
CbmPrgLauncherType.NONE,
|
|
|
|
ZeropageType.DONTUSE,
|
|
|
|
zpReserved = emptyList(),
|
2023-11-02 22:45:10 +00:00
|
|
|
zpAllowed = CompilationOptions.AllZeropageAllowed,
|
2023-02-15 21:50:35 +00:00
|
|
|
floats = true,
|
|
|
|
noSysInit = false,
|
|
|
|
compTarget = target,
|
2024-11-01 23:13:23 +00:00
|
|
|
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
|
|
|
|
memtopAddress = 0xffffu
|
2023-02-15 21:50:35 +00:00
|
|
|
)
|
|
|
|
}
|
2023-02-09 00:46:23 +00:00
|
|
|
|
2023-02-15 21:50:35 +00:00
|
|
|
test("augmented assign on arrays") {
|
|
|
|
//main {
|
|
|
|
// sub start() {
|
|
|
|
// ubyte[] particleX = [1,2,3]
|
|
|
|
// ubyte[] particleDX = [1,2,3]
|
|
|
|
// particleX[2] += particleDX[2]
|
|
|
|
//
|
|
|
|
// word @shared xx = 1
|
|
|
|
// xx = -xx
|
|
|
|
// xx += 42
|
|
|
|
// xx += cx16.r0
|
|
|
|
// }
|
|
|
|
//}
|
2024-11-10 14:11:14 +00:00
|
|
|
val codegen = AsmGen6502(prefixSymbols = false, 0)
|
2023-02-15 21:50:35 +00:00
|
|
|
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
2023-12-26 21:01:49 +00:00
|
|
|
val block = PtBlock("main",false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
2023-02-15 21:50:35 +00:00
|
|
|
val sub = PtSub("start", emptyList(), null, Position.DUMMY)
|
2024-10-25 22:30:14 +00:00
|
|
|
sub.add(PtVariable(
|
|
|
|
"pi",
|
|
|
|
DataType.UBYTE,
|
|
|
|
ZeropageWish.DONTCARE,
|
2024-10-26 18:13:45 +00:00
|
|
|
0u,
|
2024-10-25 22:30:14 +00:00
|
|
|
PtNumber(DataType.UBYTE, 0.0, Position.DUMMY),
|
|
|
|
null,
|
|
|
|
Position.DUMMY
|
|
|
|
))
|
|
|
|
sub.add(PtVariable(
|
|
|
|
"particleX",
|
|
|
|
DataType.ARRAY_UB,
|
|
|
|
ZeropageWish.DONTCARE,
|
2024-10-26 18:13:45 +00:00
|
|
|
0u,
|
2024-10-25 22:30:14 +00:00
|
|
|
null,
|
|
|
|
3u,
|
|
|
|
Position.DUMMY
|
|
|
|
))
|
|
|
|
sub.add(PtVariable(
|
|
|
|
"particleDX",
|
|
|
|
DataType.ARRAY_UB,
|
|
|
|
ZeropageWish.DONTCARE,
|
2024-10-26 18:13:45 +00:00
|
|
|
0u,
|
2024-10-25 22:30:14 +00:00
|
|
|
null,
|
|
|
|
3u,
|
|
|
|
Position.DUMMY
|
|
|
|
))
|
|
|
|
sub.add(PtVariable(
|
|
|
|
"xx",
|
|
|
|
DataType.WORD,
|
|
|
|
ZeropageWish.DONTCARE,
|
2024-10-26 18:13:45 +00:00
|
|
|
0u,
|
2024-10-25 22:30:14 +00:00
|
|
|
PtNumber(DataType.WORD, 1.0, Position.DUMMY),
|
|
|
|
null,
|
|
|
|
Position.DUMMY
|
|
|
|
))
|
2023-02-15 21:50:35 +00:00
|
|
|
|
|
|
|
val assign = PtAugmentedAssign("+=", Position.DUMMY)
|
2024-03-31 21:43:26 +00:00
|
|
|
val target = PtAssignTarget(false, Position.DUMMY).also {
|
2023-02-15 21:50:35 +00:00
|
|
|
val targetIdx = PtArrayIndexer(DataType.UBYTE, Position.DUMMY).also { idx ->
|
|
|
|
idx.add(PtIdentifier("main.start.particleX", DataType.ARRAY_UB, Position.DUMMY))
|
|
|
|
idx.add(PtNumber(DataType.UBYTE, 2.0, Position.DUMMY))
|
|
|
|
}
|
|
|
|
it.add(targetIdx)
|
|
|
|
}
|
|
|
|
val value = PtArrayIndexer(DataType.UBYTE, Position.DUMMY)
|
|
|
|
value.add(PtIdentifier("main.start.particleDX", DataType.ARRAY_UB, Position.DUMMY))
|
|
|
|
value.add(PtNumber(DataType.UBYTE, 2.0, Position.DUMMY))
|
|
|
|
assign.add(target)
|
|
|
|
assign.add(value)
|
|
|
|
sub.add(assign)
|
|
|
|
|
|
|
|
val prefixAssign = PtAugmentedAssign("-", Position.DUMMY)
|
2024-03-31 21:43:26 +00:00
|
|
|
val prefixTarget = PtAssignTarget(false, Position.DUMMY).also {
|
2023-02-15 21:50:35 +00:00
|
|
|
it.add(PtIdentifier("main.start.xx", DataType.WORD, Position.DUMMY))
|
|
|
|
}
|
|
|
|
prefixAssign.add(prefixTarget)
|
|
|
|
prefixAssign.add(PtIdentifier("main.start.xx", DataType.WORD, Position.DUMMY))
|
|
|
|
sub.add(prefixAssign)
|
|
|
|
|
|
|
|
val numberAssign = PtAugmentedAssign("-=", Position.DUMMY)
|
2024-03-31 21:43:26 +00:00
|
|
|
val numberAssignTarget = PtAssignTarget(false, Position.DUMMY).also {
|
2023-02-15 21:50:35 +00:00
|
|
|
it.add(PtIdentifier("main.start.xx", DataType.WORD, Position.DUMMY))
|
|
|
|
}
|
|
|
|
numberAssign.add(numberAssignTarget)
|
|
|
|
numberAssign.add(PtNumber(DataType.WORD, 42.0, Position.DUMMY))
|
|
|
|
sub.add(numberAssign)
|
|
|
|
|
|
|
|
val cxregAssign = PtAugmentedAssign("+=", Position.DUMMY)
|
2024-03-31 21:43:26 +00:00
|
|
|
val cxregAssignTarget = PtAssignTarget(false, Position.DUMMY).also {
|
2023-02-15 21:50:35 +00:00
|
|
|
it.add(PtIdentifier("main.start.xx", DataType.WORD, Position.DUMMY))
|
|
|
|
}
|
|
|
|
cxregAssign.add(cxregAssignTarget)
|
|
|
|
cxregAssign.add(PtIdentifier("cx16.r0", DataType.UWORD, Position.DUMMY))
|
|
|
|
sub.add(cxregAssign)
|
|
|
|
|
|
|
|
block.add(sub)
|
|
|
|
program.add(block)
|
|
|
|
|
|
|
|
// define the "cx16.r0" virtual register
|
2023-12-26 21:01:49 +00:00
|
|
|
val cx16block = PtBlock("cx16", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
2023-02-15 21:50:35 +00:00
|
|
|
cx16block.add(PtMemMapped("r0", DataType.UWORD, 100u, null, Position.DUMMY))
|
|
|
|
program.add(cx16block)
|
|
|
|
|
|
|
|
val options = getTestOptions()
|
|
|
|
val st = SymbolTableMaker(program, options).make()
|
|
|
|
val errors = ErrorReporterForTests()
|
2023-02-22 20:27:08 +00:00
|
|
|
val result = codegen.generate(program, st, options, errors)!!
|
|
|
|
result.name shouldBe "test"
|
|
|
|
Files.deleteIfExists(Path("${result.name}.asm"))
|
2023-02-15 21:50:35 +00:00
|
|
|
}
|
2023-05-23 18:42:36 +00:00
|
|
|
|
2023-08-01 20:49:55 +00:00
|
|
|
test("64tass assembler available? - if this fails you need to install 64tass version 1.58 or newer in the path") {
|
2023-05-23 18:42:36 +00:00
|
|
|
val command = mutableListOf("64tass", "--version")
|
|
|
|
shouldNotThrowAny {
|
2023-07-16 18:05:59 +00:00
|
|
|
val proc = ProcessBuilder(command).start()
|
|
|
|
val output = String(proc.inputStream.readBytes())
|
2023-05-23 18:42:36 +00:00
|
|
|
val result = proc.waitFor()
|
|
|
|
result.shouldBe(0)
|
2023-07-16 18:05:59 +00:00
|
|
|
val (_, version) = output.split('V')
|
|
|
|
val (major, minor, _) = version.split('.')
|
|
|
|
val majorNum = major.toInt()
|
|
|
|
val minorNum = minor.toInt()
|
|
|
|
withClue("64tass version should be 1.58 or newer") {
|
|
|
|
majorNum shouldBeGreaterThanOrEqual 1
|
|
|
|
if (majorNum == 1)
|
|
|
|
minorNum shouldBeGreaterThanOrEqual 58
|
|
|
|
}
|
2023-05-23 18:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
2023-02-09 00:46:23 +00:00
|
|
|
})
|
|
|
|
|