mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-27 04:29:34 +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
|
||||
|
||||
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:
|
||||
if a line ends with a backslash character, the value continues to the next line.
|
||||
|
@ -218,7 +218,11 @@ is equivalent to:
|
||||
|
||||
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.
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#pragma zilog_syntax
|
||||
|
||||
import i80_math
|
||||
import i80/i80_math
|
||||
|
||||
macro asm void poke(word const addr, byte register(a) value) {
|
||||
! 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
|
||||
|
||||
#if ARCH_6502
|
||||
import random_6502
|
||||
import m6502/random_6502
|
||||
#elseif ARCH_I80
|
||||
import random_i80
|
||||
import i80/random_i80
|
||||
#elseif ARCH_X86
|
||||
#warn 8086 is a partially supported architecture
|
||||
import random_i80
|
||||
import m6502/random_i80
|
||||
#elseif ARCH_6809
|
||||
import m6809/random_6809
|
||||
#else
|
||||
#warn Unsupported architecture
|
||||
#endif
|
||||
|
@ -12,9 +12,9 @@ alias scrstrzappend = strzappend
|
||||
#else
|
||||
|
||||
#if ARCH_I80
|
||||
import scrstring_fastpointers
|
||||
import internal/scrstring_fastpointers
|
||||
#else
|
||||
import scrstring_fastindices
|
||||
import internal/scrstring_fastindices
|
||||
#endif
|
||||
|
||||
void scrstrzappend(pointer buffer, pointer str) {
|
||||
|
@ -1,12 +1,14 @@
|
||||
// target-independent things
|
||||
|
||||
#if ARCH_6502
|
||||
import stdlib_6502
|
||||
import m6502/stdlib_6502
|
||||
#elseif ARCH_I80
|
||||
import stdlib_i80
|
||||
import i80/stdlib_i80
|
||||
#elseif ARCH_X86
|
||||
#warn 8086 is a partially supported architecture
|
||||
import stdlib_i80
|
||||
import i80/stdlib_i80
|
||||
#elseif ARCH_6809
|
||||
import m6809/stdlib_6809
|
||||
#endif
|
||||
|
||||
#if PAL && NTSC
|
||||
|
@ -1,9 +1,9 @@
|
||||
import err
|
||||
|
||||
#if ARCH_I80
|
||||
import string_fastpointers
|
||||
import internal/string_fastpointers
|
||||
#else
|
||||
import string_fastindices
|
||||
import internal/string_fastindices
|
||||
#endif
|
||||
|
||||
void strzappend(pointer buffer, pointer str) {
|
||||
|
@ -211,7 +211,7 @@ object Main {
|
||||
"zxspectrum", "zxspectrum_8080", "pc88", "cpc464", "msx_crt",
|
||||
"cpm", "cpm_z80", "dos_com")
|
||||
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)
|
||||
.flatMap(_.toSeq)
|
||||
.filter(_.endsWith(".ini"))
|
||||
|
@ -71,8 +71,13 @@ object Platform {
|
||||
if (file.exists()) {
|
||||
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 = {
|
||||
|
@ -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 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] =
|
||||
("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] =
|
||||
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 = {
|
||||
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)) {
|
||||
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 =
|
||||
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")
|
||||
|
||||
val leakSaverCpu = new Intel8086()
|
||||
|
@ -187,7 +187,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
|
||||
// prepare
|
||||
val withLibraries = {
|
||||
var tmp = unoptimized
|
||||
if(source.contains("import zp_reg"))
|
||||
if(source.contains("import zp_reg") || source.contains("import m6502/zp_reg"))
|
||||
tmp += EmuRun.cachedZpreg
|
||||
if(source.contains("import stdio"))
|
||||
tmp += EmuRun.cachedStdio
|
||||
|
@ -56,7 +56,7 @@ object EmuZ80Run {
|
||||
private def get(cpu: millfork.Cpu.Value, path: String): Program =
|
||||
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")
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ object ShouldNotCompile extends Matchers {
|
||||
else effectiveSource += "\nnoinline asm word call(word de) {\npush de\nret\n}\n"
|
||||
}
|
||||
}
|
||||
if (source.contains("import zp_reg"))
|
||||
effectiveSource += Files.readAllLines(Paths.get("include/zp_reg.mfk"), StandardCharsets.US_ASCII).asScala.mkString("\n", "\n", "")
|
||||
if (source.contains("import zp_reg") || source.contains("import m6502/zp_reg"))
|
||||
effectiveSource += Files.readAllLines(Paths.get("include/m6502/zp_reg.mfk"), StandardCharsets.US_ASCII).asScala.mkString("\n", "\n", "")
|
||||
log.setSource(Some(effectiveSource.linesIterator.toIndexedSeq))
|
||||
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, effectiveSource)
|
||||
val parserF =
|
||||
|
Loading…
Reference in New Issue
Block a user