1
0
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:
Karol Stasiak 2020-04-27 12:40:49 +02:00
parent c8492173ee
commit 78fe0e37bb
60 changed files with 115 additions and 23 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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

View 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
}

View 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
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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"))

View File

@ -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 = {

View File

@ -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) |

View File

@ -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)))
} }
} }

View File

@ -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()

View File

@ -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

View File

@ -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")
} }

View File

@ -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 =