mirror of
https://github.com/KarolS/millfork.git
synced 2024-06-25 19:29:49 +00:00
Allow importing modules from subdirectories. Move platform definitions
This commit is contained in:
parent
c8492173ee
commit
78fe0e37bb
|
@ -3,6 +3,7 @@
|
||||||
## Adding a custom platform
|
## Adding a custom platform
|
||||||
|
|
||||||
Every platform is defined in an `.ini` file with an appropriate name.
|
Every platform is defined in an `.ini` file with an appropriate name.
|
||||||
|
The file is looked up in the directories on the include path, first directly, then in the `platform` subdirectory.
|
||||||
|
|
||||||
As an extension, multiline entries are supported:
|
As an extension, multiline entries are supported:
|
||||||
if a line ends with a backslash character, the value continues to the next line.
|
if a line ends with a backslash character, the value continues to the next line.
|
||||||
|
|
|
@ -218,7 +218,11 @@ is equivalent to:
|
||||||
|
|
||||||
import <module>
|
import <module>
|
||||||
|
|
||||||
Adds a module to the program.
|
Adds a module to the program. The module name can be a valid identifier
|
||||||
|
or a sequence of identifiers separated by forward slashes:
|
||||||
|
|
||||||
|
import module1
|
||||||
|
import library1/module2
|
||||||
|
|
||||||
The module is looked up first in the current working directory, and then in the include directories.
|
The module is looked up first in the current working directory, and then in the include directories.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma zilog_syntax
|
#pragma zilog_syntax
|
||||||
|
|
||||||
import i80_math
|
import i80/i80_math
|
||||||
|
|
||||||
macro asm void poke(word const addr, byte register(a) value) {
|
macro asm void poke(word const addr, byte register(a) value) {
|
||||||
! LD (addr), A
|
! LD (addr), A
|
27
include/m6809/random_6809.mfk
Normal file
27
include/m6809/random_6809.mfk
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
#if not(ARCH_6809)
|
||||||
|
#warn random_6809 module should be only used on 6809-compatible targets
|
||||||
|
#endif
|
||||||
|
|
||||||
|
asm byte rand() {
|
||||||
|
? lda #8
|
||||||
|
? ldb rand_seed+0
|
||||||
|
__rand_loop:
|
||||||
|
aslb
|
||||||
|
? rolb rand_seed+1
|
||||||
|
bcc __no_eor
|
||||||
|
eorb #$2D
|
||||||
|
__no_eor:
|
||||||
|
deca
|
||||||
|
bne __rand_loop
|
||||||
|
? sta rand_seed+0
|
||||||
|
? rts
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init_rand_seed() {
|
||||||
|
// TODO: find a better source of randomness
|
||||||
|
rand_seed = 1
|
||||||
|
}
|
||||||
|
|
51
include/m6809/stdlib_6809.mfk
Normal file
51
include/m6809/stdlib_6809.mfk
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// target-independent things
|
||||||
|
|
||||||
|
#if not(ARCH_6809)
|
||||||
|
#warn stdlib_6809 module should be only used on 6809-compatible targets
|
||||||
|
#endif
|
||||||
|
|
||||||
|
word nmi_routine_addr @$FFFC
|
||||||
|
word reset_routine_addr @$FFFE
|
||||||
|
word irq_routine_addr @$FFF8
|
||||||
|
word swi_routine_addr @$FFFA
|
||||||
|
word firq_routine_addr @$FFF6
|
||||||
|
word swi2_routine_addr @$FFF4
|
||||||
|
word swi3_routine_addr @$FFF2
|
||||||
|
|
||||||
|
macro asm void poke(word const addr, byte register(b) value) {
|
||||||
|
! STB addr
|
||||||
|
}
|
||||||
|
|
||||||
|
macro asm byte peek(word const addr) {
|
||||||
|
! LDB addr
|
||||||
|
}
|
||||||
|
|
||||||
|
macro asm void disable_irq() {
|
||||||
|
ORCC #$30
|
||||||
|
}
|
||||||
|
|
||||||
|
macro asm void enable_irq() {
|
||||||
|
ANDCC #$CF
|
||||||
|
}
|
||||||
|
|
||||||
|
asm byte hi_nibble_to_hex(byte register(a) value) {
|
||||||
|
LSRB
|
||||||
|
LSRB
|
||||||
|
LSRB
|
||||||
|
LSRB
|
||||||
|
? JMP lo_nibble_to_hex
|
||||||
|
}
|
||||||
|
|
||||||
|
asm byte lo_nibble_to_hex(byte register(a) value) {
|
||||||
|
! ANDB #$F
|
||||||
|
ADDB #$30
|
||||||
|
CMPB #$3A
|
||||||
|
BCC _lo_nibble_to_hex_lbl
|
||||||
|
ADDB #$7 // carry is set
|
||||||
|
_lo_nibble_to_hex_lbl:
|
||||||
|
? RTS
|
||||||
|
}
|
||||||
|
|
||||||
|
macro asm void panic() {
|
||||||
|
? JSR _panic
|
||||||
|
}
|
|
@ -2,12 +2,14 @@
|
||||||
word rand_seed
|
word rand_seed
|
||||||
|
|
||||||
#if ARCH_6502
|
#if ARCH_6502
|
||||||
import random_6502
|
import m6502/random_6502
|
||||||
#elseif ARCH_I80
|
#elseif ARCH_I80
|
||||||
import random_i80
|
import i80/random_i80
|
||||||
#elseif ARCH_X86
|
#elseif ARCH_X86
|
||||||
#warn 8086 is a partially supported architecture
|
#warn 8086 is a partially supported architecture
|
||||||
import random_i80
|
import m6502/random_i80
|
||||||
|
#elseif ARCH_6809
|
||||||
|
import m6809/random_6809
|
||||||
#else
|
#else
|
||||||
#warn Unsupported architecture
|
#warn Unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,9 +12,9 @@ alias scrstrzappend = strzappend
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if ARCH_I80
|
#if ARCH_I80
|
||||||
import scrstring_fastpointers
|
import internal/scrstring_fastpointers
|
||||||
#else
|
#else
|
||||||
import scrstring_fastindices
|
import internal/scrstring_fastindices
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void scrstrzappend(pointer buffer, pointer str) {
|
void scrstrzappend(pointer buffer, pointer str) {
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// target-independent things
|
// target-independent things
|
||||||
|
|
||||||
#if ARCH_6502
|
#if ARCH_6502
|
||||||
import stdlib_6502
|
import m6502/stdlib_6502
|
||||||
#elseif ARCH_I80
|
#elseif ARCH_I80
|
||||||
import stdlib_i80
|
import i80/stdlib_i80
|
||||||
#elseif ARCH_X86
|
#elseif ARCH_X86
|
||||||
#warn 8086 is a partially supported architecture
|
#warn 8086 is a partially supported architecture
|
||||||
import stdlib_i80
|
import i80/stdlib_i80
|
||||||
|
#elseif ARCH_6809
|
||||||
|
import m6809/stdlib_6809
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PAL && NTSC
|
#if PAL && NTSC
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import err
|
import err
|
||||||
|
|
||||||
#if ARCH_I80
|
#if ARCH_I80
|
||||||
import string_fastpointers
|
import internal/string_fastpointers
|
||||||
#else
|
#else
|
||||||
import string_fastindices
|
import internal/string_fastindices
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void strzappend(pointer buffer, pointer str) {
|
void strzappend(pointer buffer, pointer str) {
|
||||||
|
|
|
@ -211,7 +211,7 @@ object Main {
|
||||||
"zxspectrum", "zxspectrum_8080", "pc88", "cpc464", "msx_crt",
|
"zxspectrum", "zxspectrum_8080", "pc88", "cpc464", "msx_crt",
|
||||||
"cpm", "cpm_z80", "dos_com")
|
"cpm", "cpm_z80", "dos_com")
|
||||||
case Right(path) =>
|
case Right(path) =>
|
||||||
Seq(new File(".").list(), new File(path).list())
|
Seq(new File(".").list(), new File(".", "platform").list(), new File(path).list(), new File(path, "platform").list())
|
||||||
.filter(_ ne null)
|
.filter(_ ne null)
|
||||||
.flatMap(_.toSeq)
|
.flatMap(_.toSeq)
|
||||||
.filter(_.endsWith(".ini"))
|
.filter(_.endsWith(".ini"))
|
||||||
|
|
|
@ -71,8 +71,13 @@ object Platform {
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return load(file)
|
return load(file)
|
||||||
}
|
}
|
||||||
|
val file2 = Paths.get(dir, "platform", platformName + ".ini").toFile
|
||||||
|
log.debug("Checking " + file2)
|
||||||
|
if (file2.exists()) {
|
||||||
|
return load(file2)
|
||||||
}
|
}
|
||||||
log.fatal(s"Platfom definition `$platformName` not found", None)
|
}
|
||||||
|
log.fatal(s"Platform definition `$platformName` not found", None)
|
||||||
}
|
}
|
||||||
|
|
||||||
def load(file: File)(implicit log: Logger): Platform = {
|
def load(file: File)(implicit log: Logger): Platform = {
|
||||||
|
|
|
@ -83,7 +83,7 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
|
||||||
|
|
||||||
val continueStatement: P[Seq[ExecutableStatement]] = ("continue" ~ !letterOrDigit ~/ HWS ~ identifier.?).map(l => Seq(ContinueStatement(l.getOrElse(""))))
|
val continueStatement: P[Seq[ExecutableStatement]] = ("continue" ~ !letterOrDigit ~/ HWS ~ identifier.?).map(l => Seq(ContinueStatement(l.getOrElse(""))))
|
||||||
|
|
||||||
val importStatement: P[Seq[ImportStatement]] = ("import" ~ !letterOrDigit ~/ SWS ~/ identifier).map(x => Seq(ImportStatement(x)))
|
val importStatement: P[Seq[ImportStatement]] = ("import" ~ !letterOrDigit ~/ SWS ~/ identifier.rep(min = 1, sep = "/")).map(x => Seq(ImportStatement(x.mkString("/"))))
|
||||||
|
|
||||||
val forDirection: P[ForDirection.Value] =
|
val forDirection: P[ForDirection.Value] =
|
||||||
("parallel" ~ HWS ~ "to").!.map(_ => ForDirection.ParallelTo) |
|
("parallel" ~ HWS ~ "to").!.map(_ => ForDirection.ParallelTo) |
|
||||||
|
|
|
@ -13,14 +13,14 @@ class MosSourceLoadingQueue(initialFilenames: List[String],
|
||||||
override def createParser(filename: String, src: String, parentDir: String, featureConstants: Map[String, Long], pragmas: Set[String]): MfParser[AssemblyLine] =
|
override def createParser(filename: String, src: String, parentDir: String, featureConstants: Map[String, Long], pragmas: Set[String]): MfParser[AssemblyLine] =
|
||||||
MosParser(filename, src, parentDir, options, featureConstants)
|
MosParser(filename, src, parentDir, options, featureConstants)
|
||||||
|
|
||||||
override def standardModules: IndexedSeq[String] = IndexedSeq("zp_reg", "bcd_6502")
|
override def standardModules: IndexedSeq[String] = IndexedSeq("m6502/zp_reg", "m6502/bcd_6502")
|
||||||
|
|
||||||
def enqueueStandardModules(): Unit = {
|
def enqueueStandardModules(): Unit = {
|
||||||
if (options.zpRegisterSize > 0) {
|
if (options.zpRegisterSize > 0) {
|
||||||
moduleQueue.enqueue(() => parseModule("zp_reg", includePath, Left(None)))
|
moduleQueue.enqueue(() => parseModule("m6502/zp_reg", includePath, Left(None)))
|
||||||
}
|
}
|
||||||
if (options.zpRegisterSize >= 4 && !options.flag(CompilationFlag.DecimalMode)) {
|
if (options.zpRegisterSize >= 4 && !options.flag(CompilationFlag.DecimalMode)) {
|
||||||
moduleQueue.enqueue(() => parseModule("bcd_6502", includePath, Left(None)))
|
moduleQueue.enqueue(() => parseModule("m6502/bcd_6502", includePath, Left(None)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ object EmuI86Run {
|
||||||
private def get(path: String): Program =
|
private def get(path: String): Program =
|
||||||
synchronized { cache.getOrElseUpdate(path, preload(path)).getOrElse(throw new IllegalStateException()) }
|
synchronized { cache.getOrElseUpdate(path, preload(path)).getOrElse(throw new IllegalStateException()) }
|
||||||
|
|
||||||
def cachedMath(): Program = get("include/i80_math.mfk") // TODO
|
def cachedMath(): Program = get("include/i80/i80_math.mfk") // TODO
|
||||||
def cachedStdio(): Program = get("src/test/resources/include/dummy_stdio.mfk")
|
def cachedStdio(): Program = get("src/test/resources/include/dummy_stdio.mfk")
|
||||||
|
|
||||||
val leakSaverCpu = new Intel8086()
|
val leakSaverCpu = new Intel8086()
|
||||||
|
|
|
@ -187,7 +187,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
|
||||||
// prepare
|
// prepare
|
||||||
val withLibraries = {
|
val withLibraries = {
|
||||||
var tmp = unoptimized
|
var tmp = unoptimized
|
||||||
if(source.contains("import zp_reg"))
|
if(source.contains("import zp_reg") || source.contains("import m6502/zp_reg"))
|
||||||
tmp += EmuRun.cachedZpreg
|
tmp += EmuRun.cachedZpreg
|
||||||
if(source.contains("import stdio"))
|
if(source.contains("import stdio"))
|
||||||
tmp += EmuRun.cachedStdio
|
tmp += EmuRun.cachedStdio
|
||||||
|
|
|
@ -56,7 +56,7 @@ object EmuZ80Run {
|
||||||
private def get(cpu: millfork.Cpu.Value, path: String): Program =
|
private def get(cpu: millfork.Cpu.Value, path: String): Program =
|
||||||
synchronized { cache.getOrElseUpdate(cpu->path, preload(cpu, path)).getOrElse(throw new IllegalStateException()) }
|
synchronized { cache.getOrElseUpdate(cpu->path, preload(cpu, path)).getOrElse(throw new IllegalStateException()) }
|
||||||
|
|
||||||
def cachedMath(cpu: millfork.Cpu.Value): Program = get(cpu, "include/i80_math.mfk")
|
def cachedMath(cpu: millfork.Cpu.Value): Program = get(cpu, "include/i80/i80_math.mfk")
|
||||||
def cachedStdio(cpu: millfork.Cpu.Value): Program = get(cpu, "src/test/resources/include/dummy_stdio.mfk")
|
def cachedStdio(cpu: millfork.Cpu.Value): Program = get(cpu, "src/test/resources/include/dummy_stdio.mfk")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@ object ShouldNotCompile extends Matchers {
|
||||||
else effectiveSource += "\nnoinline asm word call(word de) {\npush de\nret\n}\n"
|
else effectiveSource += "\nnoinline asm word call(word de) {\npush de\nret\n}\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (source.contains("import zp_reg"))
|
if (source.contains("import zp_reg") || source.contains("import m6502/zp_reg"))
|
||||||
effectiveSource += Files.readAllLines(Paths.get("include/zp_reg.mfk"), StandardCharsets.US_ASCII).asScala.mkString("\n", "\n", "")
|
effectiveSource += Files.readAllLines(Paths.get("include/m6502/zp_reg.mfk"), StandardCharsets.US_ASCII).asScala.mkString("\n", "\n", "")
|
||||||
log.setSource(Some(effectiveSource.linesIterator.toIndexedSeq))
|
log.setSource(Some(effectiveSource.linesIterator.toIndexedSeq))
|
||||||
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, effectiveSource)
|
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, effectiveSource)
|
||||||
val parserF =
|
val parserF =
|
||||||
|
|
Loading…
Reference in New Issue
Block a user