diff --git a/plat/e6800/README b/plat/e6800/README new file mode 100644 index 000000000..f1800fc8c --- /dev/null +++ b/plat/e6800/README @@ -0,0 +1,31 @@ +The emu6800 platform +==================== + +This port targets the emu6800 emulator and generates code for the Motorola 6800 architecture. It is intended to run within the emu6800 environment. + +This implementation is currently **under development and does not work yet**. Many features are incomplete or missing. + +**File I/O is not implemented and will not be supported in the future,** because the emu6800 environment does not provide any file input/output functionality. + +**Floating point support is not available yet.** Any attempt to use floating-point numbers will result in a build error or undefined behavior. Floating-point functionality may be added in the future. + +The code generator is designed specifically for the MC6800, which has a simple architecture and a limited register set. The compiler translates source code to EM (stack-based intermediate code), and then to MC6800 assembly. Arguments and local variables are accessed relative to the frame pointer (Local Base, LB), **which resides in zero page**. + +**Temporary results are kept either on the stack or in AccAB (the stack top).** See the source for details on stack frame layout and accumulator usage. + +This port is intended to be tested using the emu6800 emulator. + +Example command line +==================== + +ack -mm6800 -O -o hello.bin examples/hello.c + +The file hello.bin can then be run using emu6800. + +(Please note that this port is experimental and most programs will not yet function as expected.) + +---- + +Work in progress. Contributions and bug reports are welcome. + +@zu2 diff --git a/plat/e6800/boot.s b/plat/e6800/boot.s new file mode 100644 index 000000000..800b2bb7e --- /dev/null +++ b/plat/e6800/boot.s @@ -0,0 +1,176 @@ +.define BASE, EM_BSIZE +.define NBYTES +.define hol0, IGNMASK, ADDR, PROGNAME +.define LB, LBl, ERRPROC +.define ARTH, RETURN, SIGN +.define RETSIZE, TRAPVAL, BRANCH +.define START +.define TMP, TMP2 +.define __exit, EXIT +.define _putchar, _getchar, _print, _cpu_counter, _errno +.define _putstr, _puthexl,_puthexi, _puthexc +.define _emu6800_conout, _emu6800_conin + +BASE = 240 +EM_BSIZE = 4 + +.sect .zero +.sect .text +.sect .rom +.sect .data +.sect .bss +.sect .end + + +.sect .zero +hol0: .space 16 ! the hol0 block +IGNMASK: .space 2 ! can hold the ingnore mask +ADDR: .space 4 ! used for indirect addressing +LB: .space 2 ! the localbase +LBl: .space 2 ! the second localbase (localbase-BASE) +ERRPROC: .space 2 ! can hold the address of the error handler +ARTH: .space 16 ! used for arithmetic +RETURN: .space 4 ! the return area +SIGN: .space 1 +RETSIZE: .space 1 +TRAPVAL: .space 1 +BRANCH: .space 2 +NBYTES: .space 2 +TMP: .space 2 +TMP2: .space 2 +exitsp: .space 2 + +_errno: .space 2 + +.define Earray, Erange, Eset +.define Eiovfl, Eidivz, Eiund, Econv +.define Estack, Eheap, Eillins, Eoddz +.define Ecase , Ebadmon +.define Ebadlin, Ebadgto +Earray = 0 +Erange = 1 +Eset = 2 +Eiovfl = 3 +Eidivz = 6 +Eiund = 8 +Econv = 10 +Estack = 16 +Eheap = 17 +Eillins = 18 +Eoddz = 19 +Ecase = 20 +Ebadmon = 25 +Ebadlin = 26 +Ebadgto = 27 + +.define F_DUM +F_DUM = 0 ! Dummy floating point constant + +!.base 0x0100 ! where to start in the emu6800 +.sect .text +! GENERAL PURPOSE ROUTINES +START: + sts exitsp + lds #0xefff +! + clrb + clra + pshb ! envp + psha + pshb ! argv + psha + pshb ! argc + psha + jsr __m_a_i_n ! see. lang/cem/libcc/gen/head_cc.e + ins + ins + ins + ins +___exit: +EXIT: + lds exitsp + staa 0xfefb + ldab RETURN+1 + stab 0xfeff + rts +__exit: + tsx + ldab 3,x + stab RETURN+1 + bra ___exit +! +! minimal I/O routine +! +_puthexc: + tsx + bra _puthexi3 +_puthexl: + tsx + bsr _puthexi2 + inx + inx + bra _puthexi2 +_puthexi: + tsx +_puthexi2: + ldaa 2,x + bsr _puthex2 +_puthexi3: + ldaa 3,x +_puthex2: ! put AccA in 2 hexdigit + bsr _puthexhi + tab + bra _puthexlo +_puthexhi: + tab + lsrb + lsrb + lsrb + lsrb +_puthexlo: + andb #0x0f + cmpb #0x0a + bcs 1f + addb #'A'-'9'-1 +1: addb #'0' + stab 0xfefe + rts +_putstr: + stab < +# optimizer +# stdin +# stdout +#end +name as + from .s.so + to .o + program {EM}/lib/ack/{PLATFORM}/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* +# mapflag -i SEPID=-b1:0 + mapflag -fp FLOATS={PLATFORMDIR}/libfp.a + args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libc.a \ + {PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .img + program {EM}/bin/aslod68 + args -v -v -me6800 < > + outfile e6800.img +end diff --git a/plat/e6800/include/ack/plat.h b/plat/e6800/include/ack/plat.h new file mode 100644 index 000000000..edd7b9b50 --- /dev/null +++ b/plat/e6800/include/ack/plat.h @@ -0,0 +1,18 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#ifndef _ACK_PLAT_H +#define _ACK_PLAT_H + +#define ACKCONF_WANT_STDIO_FLOAT 0 +#define ACKCONF_WANT_EMULATED_TIME 1 +#define ACKCONF_WANT_EMULATED_POPEN 0 +#define ACKCONF_WANT_EMULATED_FILE 1 + +/* We have a very small address space, so override the default buffer size. */ + +#define BUFSIZ 256 + +#endif diff --git a/plat/e6800/include/build.py b/plat/e6800/include/build.py new file mode 100644 index 000000000..c754cef4b --- /dev/null +++ b/plat/e6800/include/build.py @@ -0,0 +1,16 @@ +from build.ab import export +from build.c import clibrary +from glob import glob +from build.ack import exportheaders + +headers = glob("**/*.h", root_dir="plat/e6800/include", recursive=True) + +clibrary( + name="include", + hdrs={k: f"./{k}" for k in headers}, +) + +export( + name="all", + items=exportheaders(".+include", prefix="$(PLATIND)/e6800/include"), +) diff --git a/plat/e6800/include/emu6800.h b/plat/e6800/include/emu6800.h new file mode 100644 index 000000000..aa82c147d --- /dev/null +++ b/plat/e6800/include/emu6800.h @@ -0,0 +1,24 @@ +/* + * emu6800.h + */ + +#include + +#define emu6800_ramtop ((uint8_t *)0xefff) + +/* + * boot.s minitourine + */ +/* extern void putchar(int ch); */ +/* extern int getchar(void); */ +extern void print(int x); +extern void cpu_counter(void); +extern void puthexc(int ch); +extern void puthexi(int x); +extern void putstr(char *s); + +uint8_t *emu6800_ram; + +extern int emu6800_conin(void); +extern void emu6800_conout(int chx); + diff --git a/plat/e6800/include/sys/types.h b/plat/e6800/include/sys/types.h new file mode 100644 index 000000000..6a0c3d3db --- /dev/null +++ b/plat/e6800/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +typedef int pid_t; +typedef int mode_t; +typedef long time_t; +typedef long suseconds_t; + +#endif diff --git a/plat/e6800/libsys/_hol0.s b/plat/e6800/libsys/_hol0.s new file mode 100644 index 000000000..287cc19fa --- /dev/null +++ b/plat/e6800/libsys/_hol0.s @@ -0,0 +1,20 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .zero +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .bss + +! This data block is used to store information about the current line number +! and file. + +.define hol0 +.comm hol0, 8 diff --git a/plat/e6800/libsys/asm.h b/plat/e6800/libsys/asm.h new file mode 100644 index 000000000..9c54fb2cc --- /dev/null +++ b/plat/e6800/libsys/asm.h @@ -0,0 +1,14 @@ +#ifndef ASM_H +#define ASM_H + +! Declare segments (the order is important). + +.sect .zero +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +#endif diff --git a/plat/e6800/libsys/brk.c b/plat/e6800/libsys/brk.c new file mode 100644 index 000000000..f54545188 --- /dev/null +++ b/plat/e6800/libsys/brk.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +#define OUT_OF_MEMORY (void*)(-1) /* sbrk returns this on failure */ + +extern uint8_t _end[1]; + +int brk(void* newend) +{ + uint8_t* p = newend; + + if ((p >= emu6800_ramtop) || + (p < _end)) { + return -1; + } + + emu6800_ram = (uint8_t*)p; + return 0; +} + +void* sbrk(int increment) +{ + uint8_t* old; + uint8_t* new; + + if (increment == 0) + return emu6800_ram; + + old = emu6800_ram; + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; + + return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; +} diff --git a/plat/e6800/libsys/build.py b/plat/e6800/libsys/build.py new file mode 100644 index 000000000..28b07d408 --- /dev/null +++ b/plat/e6800/libsys/build.py @@ -0,0 +1,14 @@ +from build.ack import ackclibrary +from glob import glob + +ackclibrary( + name="libsys", + plat="e6800", + srcs=( + glob("plat/e6800/libsys/*.s") + + glob("plat/e6800/libsys/*.c") + + glob("plat/e6800/libsys/*.h") + ), + deps=["lang/cem/libcc.ansi/headers", "plat/e6800/include"], +) + diff --git a/plat/e6800/libsys/close.c b/plat/e6800/libsys/close.c new file mode 100644 index 000000000..ba74ba47b --- /dev/null +++ b/plat/e6800/libsys/close.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include +#include + +int close(int fd) +{ + return 0; +} + diff --git a/plat/e6800/libsys/creat.c b/plat/e6800/libsys/creat.c new file mode 100644 index 000000000..65af5c2dc --- /dev/null +++ b/plat/e6800/libsys/creat.c @@ -0,0 +1,13 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include + +int creat(const char* path, int mode) +{ + return open(path, O_CREAT|O_WRONLY|O_TRUNC, mode); +} diff --git a/plat/e6800/libsys/errno.s b/plat/e6800/libsys/errno.s new file mode 100644 index 000000000..39506e982 --- /dev/null +++ b/plat/e6800/libsys/errno.s @@ -0,0 +1,29 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .zero +.sect .text +.sect .rom +.sect .data +.sect .bss + +#define D(e) .define e; e + +.sect .data + +! Define various ACK error numbers. Note that these are *not* ANSI C +! errnos, and are used for different purposes. + +D(ERANGE) = 1 +D(ESET) = 2 +D(EIDIVZ) = 6 +D(EHEAP) = 17 +D(EILLINS) = 18 +D(EODDZ) = 19 +D(ECASE) = 20 +D(EBADMON) = 25 + diff --git a/plat/e6800/libsys/getpid.c b/plat/e6800/libsys/getpid.c new file mode 100644 index 000000000..5e6eb003e --- /dev/null +++ b/plat/e6800/libsys/getpid.c @@ -0,0 +1,13 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include + +pid_t getpid(void) +{ + return 0; +} diff --git a/plat/e6800/libsys/isatty.c b/plat/e6800/libsys/isatty.c new file mode 100644 index 000000000..928287d39 --- /dev/null +++ b/plat/e6800/libsys/isatty.c @@ -0,0 +1,13 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include + +int isatty(int fd) +{ + return (fd>=0 && fd<=2); +} diff --git a/plat/e6800/libsys/kill.c b/plat/e6800/libsys/kill.c new file mode 100644 index 000000000..4a179c47c --- /dev/null +++ b/plat/e6800/libsys/kill.c @@ -0,0 +1,14 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include + +int kill(pid_t pid, int sig) +{ + errno = EINVAL; + return -1; +} diff --git a/plat/e6800/libsys/lseek.c b/plat/e6800/libsys/lseek.c new file mode 100644 index 000000000..cbc6f042d --- /dev/null +++ b/plat/e6800/libsys/lseek.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include +#include + +off_t lseek(int fd, off_t offset, int whence) +{ + return 0; +} diff --git a/plat/e6800/libsys/open.c b/plat/e6800/libsys/open.c new file mode 100644 index 000000000..275aeb968 --- /dev/null +++ b/plat/e6800/libsys/open.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include + +int open(const char* path, int access, ...) +{ + static int fd = 0; + + if (access & _IOWRITE) + return 1; + + return 0; +} + + diff --git a/plat/e6800/libsys/read.c b/plat/e6800/libsys/read.c new file mode 100644 index 000000000..853524c0e --- /dev/null +++ b/plat/e6800/libsys/read.c @@ -0,0 +1,28 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include +#include +#include +#include + +ssize_t read(int fd, void* buffer, size_t count) +{ + if (fd == 0) + { + /* Read from the console. */ + + if (count == 0) + return 0; + *(uint8_t*)buffer = emu6800_conin(); + return 1; + } + +eio: + errno = EIO; + return -1; +} diff --git a/plat/e6800/libsys/signal.c b/plat/e6800/libsys/signal.c new file mode 100644 index 000000000..8f145f6f1 --- /dev/null +++ b/plat/e6800/libsys/signal.c @@ -0,0 +1,14 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include +#include + +sighandler_t signal(int signum, sighandler_t handler) +{ + return SIG_DFL; +} diff --git a/plat/e6800/libsys/time.c b/plat/e6800/libsys/time.c new file mode 100644 index 000000000..4215a3b6f --- /dev/null +++ b/plat/e6800/libsys/time.c @@ -0,0 +1,16 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include +#include + +time_t time(time_t* t) +{ + if (t) + *t = 0; + return 0; +} diff --git a/plat/e6800/libsys/write.c b/plat/e6800/libsys/write.c new file mode 100644 index 000000000..2ab46216c --- /dev/null +++ b/plat/e6800/libsys/write.c @@ -0,0 +1,35 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include +#include +#include + +void _sys_write_tty(unsigned char c) +{ + if (c == '\n') + emu6800_conout('\r'); + emu6800_conout(c); +} + +ssize_t write(int fd, const void* buffer, size_t count) +{ + if (fd == 1) + { + /* Write to the console. */ + + unsigned char *p = buffer; + size_t i = count; + while (i--) + _sys_write_tty(*p++); + return count; + } + +eio: + errno = EIO; + return -1; +} diff --git a/plat/e6800/tests/build.py b/plat/e6800/tests/build.py new file mode 100644 index 000000000..4f95f1c16 --- /dev/null +++ b/plat/e6800/tests/build.py @@ -0,0 +1,9 @@ +from tests.plat.build import plat_testsuite + +plat_testsuite( + name="tests", + plat="e6800", + method="plat/e6800/tests/test-wrapper.sh", + extratests=[ ], + sets=["core", "bugs", "m2"], +) diff --git a/plat/e6800/tests/test-wrapper.sh b/plat/e6800/tests/test-wrapper.sh new file mode 100755 index 000000000..0d3167ddc --- /dev/null +++ b/plat/e6800/tests/test-wrapper.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +EMULATOR="/usr/local/bin/emu6800" +CPUTYPE="6800" + +exec "$EMULATOR" "$CPUTYPE" "$@" /dev/null