Added cpm platform.
authordtrg <none@none>
Fri, 27 Apr 2007 22:42:41 +0000 (22:42 +0000)
committerdtrg <none@none>
Fri, 27 Apr 2007 22:42:41 +0000 (22:42 +0000)
31 files changed:
mach/i80/libem/pmfile [new file with mode: 0644]
mach/i80/libend/em_end.s
mach/i80/libend/pmfile [new file with mode: 0644]
mach/i80/pmfile
plat/cpm/.distr [new file with mode: 0644]
plat/cpm/README [new file with mode: 0644]
plat/cpm/boot.s [new file with mode: 0644]
plat/cpm/descr [new file with mode: 0644]
plat/cpm/include/ack/config.h [new file with mode: 0644]
plat/cpm/include/cpm.h [new file with mode: 0644]
plat/cpm/include/unistd.h [new file with mode: 0644]
plat/cpm/libsys/_bdos.s [new file with mode: 0644]
plat/cpm/libsys/_hol0.s [new file with mode: 0644]
plat/cpm/libsys/_inn2.s [new file with mode: 0644]
plat/cpm/libsys/_trap.s [new file with mode: 0644]
plat/cpm/libsys/brk.c [new file with mode: 0644]
plat/cpm/libsys/close.c [new file with mode: 0644]
plat/cpm/libsys/creat.c [new file with mode: 0644]
plat/cpm/libsys/errno.s [new file with mode: 0644]
plat/cpm/libsys/getpid.c [new file with mode: 0644]
plat/cpm/libsys/isatty.c [new file with mode: 0644]
plat/cpm/libsys/kill.c [new file with mode: 0644]
plat/cpm/libsys/lseek.c [new file with mode: 0644]
plat/cpm/libsys/open.c [new file with mode: 0644]
plat/cpm/libsys/pmfile [new file with mode: 0644]
plat/cpm/libsys/read.c [new file with mode: 0644]
plat/cpm/libsys/signal.c [new file with mode: 0644]
plat/cpm/libsys/time.c [new file with mode: 0644]
plat/cpm/libsys/write.c [new file with mode: 0644]
plat/cpm/pmfile [new file with mode: 0644]
pmfile

diff --git a/mach/i80/libem/pmfile b/mach/i80/libem/pmfile
new file mode 100644 (file)
index 0000000..ecc69cf
--- /dev/null
@@ -0,0 +1,49 @@
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."mach/i80/libem/"
+
+libem_i80 = acklibrary {
+       outputs = {"%U%/libem-%PLATFORM%.a"},
+
+       ackfile (d.."aar2.s"),
+       ackfile (d.."adi4.s"),
+       ackfile (d.."and.s"),
+       ackfile (d.."blm.s"),
+       ackfile (d.."cii.s"),
+       ackfile (d.."cmi4.s"),
+       ackfile (d.."cms.s"),
+       ackfile (d.."com.s"),
+       ackfile (d.."csa.s"),
+       ackfile (d.."csb.s"),
+       ackfile (d.."dup.s"),
+       ackfile (d.."dvi2.s"),
+       ackfile (d.."exg.s"),
+       ackfile (d.."flp.s"),
+       ackfile (d.."inn.s"),
+       ackfile (d.."ior.s"),
+       ackfile (d.."lar2.s"),
+       ackfile (d.."mli2.s"),
+       ackfile (d.."mli4.s"),
+       ackfile (d.."mlu2.s"),
+       ackfile (d.."ngi4.s"),
+       ackfile (d.."nop.s"),
+       ackfile (d.."rol4.s"),
+       ackfile (d.."ror4.s"),
+       ackfile (d.."sar2.s"),
+       ackfile (d.."sbi4.s"),
+       ackfile (d.."set.s"),
+       ackfile (d.."set2.s"),
+       ackfile (d.."sli2.s"),
+       ackfile (d.."sli4.s"),
+       ackfile (d.."sri2.s"),
+       ackfile (d.."sri4.s"),
+       ackfile (d.."xor.s"),
+       ackfile (d.."loi.s"),
+       ackfile (d.."sti.s"),
+       ackfile (d.."dvi4.s"),
+       ackfile (d.."rck.s"),
+
+       install = pm.install("%BINDIR%lib/%PLATFORM%/libem.a"),
+}
index 6848f66..e95664e 100644 (file)
@@ -1,12 +1,18 @@
+! $Source$
+! $State$
+! $Revision$
+
 .sect .text
 .sect .rom
 .sect .data
 .sect .bss
 .sect .end ! only for declaration of _end, __end and endbss.
-.define        endtext,enddata,endbss,__end
+.define        endtext, endrom, enddata, endbss, __end
 
        .sect .text
 endtext:
+       .sect .rom
+endrom:
        .sect .data
 enddata:
        .sect .end
diff --git a/mach/i80/libend/pmfile b/mach/i80/libend/pmfile
new file mode 100644 (file)
index 0000000..78e6bb5
--- /dev/null
@@ -0,0 +1,16 @@
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."mach/i80/libend/"
+
+libend_i80 = acklibrary {
+       outputs = {"%U%/libend-%PLATFORM%.a"},
+
+       ackfile (d.."edata.s"),
+       ackfile (d.."em_end.s"),
+       ackfile (d.."end.s"),
+       ackfile (d.."etext.s"),
+
+       install = pm.install("%BINDIR%lib/%PLATFORM%/libend.a"),
+}
index 1fdc345..b5994f3 100644 (file)
@@ -3,6 +3,9 @@
 
 local d = ROOTDIR.."mach/i80/"
 
+include (d.."libem/pmfile")
+include (d.."libend/pmfile")
+
 mach_i80 = group {
        ARCH = "i80",
        
@@ -12,8 +15,10 @@ mach_i80 = group {
        install = pm.install("%ROOTDIR%/lib/%ARCH%/descr", "%BINDIR%%PLATIND%/%ARCH%/descr")
 }
 
--- Revision history
--- $Log$
--- Revision 1.1  2006-07-20 23:18:18  dtrg
--- First version in CVS.
---
+support_i80 = group {
+       OPTIMISATION = "-O",
+
+       libem_i80,
+       libend_i80,
+}
+
diff --git a/plat/cpm/.distr b/plat/cpm/.distr
new file mode 100644 (file)
index 0000000..9bcdd61
--- /dev/null
@@ -0,0 +1,24 @@
+descr
+boot.s
+pmfile
+README
+include/ack/config.h
+include/unistd.h
+libsys/pmfile
+libsys/_hol0.s
+libsys/brk.c
+libsys/close.c
+libsys/creat.c
+libsys/errno.s
+libsys/getpid.c
+libsys/isatty.c
+libsys/kill.c
+libsys/libsys.h
+libsys/lseek.c
+libsys/open.c
+libsys/read.c
+libsys/signal.c
+libsys/time.c
+libsys/write.c
+libsys/_sys_rawread.s
+libsys/_sys_rawwrite.s
diff --git a/plat/cpm/README b/plat/cpm/README
new file mode 100644 (file)
index 0000000..5b2bb9f
--- /dev/null
@@ -0,0 +1,33 @@
+# $Source$
+# $State$
+# $Revision$
+
+
+The cpm platform
+=================
+
+cpm is an i80-based BSP that generates CP/M executables that can be run on any
+CP/M-compliant machine.
+
+This port only implements a very limited set of syscalls --- and most of those
+are stubs required to make the demo apps link. File descriptors 0, 1 and 2
+represent the console. All reads block. There's enough TTY emulation to allow
+\n conversion and local echo (but it can't be turned off).
+
+There's a special, if rather minimilist, interface to give applications access
+to CP/M. See include/cpm.h for details.
+
+
+Example command line
+====================
+
+ack -mcpm -O -o cpm.com examples/paranoia.c
+
+The file cpm.com can then be run.
+
+(Although note that Paranoia is very big, and you'll need a CP/M machine with
+lots of memory for it to fit. Which it does, just.)
+
+
+David Given
+dg@cowlark.com
diff --git a/plat/cpm/boot.s b/plat/cpm/boot.s
new file mode 100644 (file)
index 0000000..bb55898
--- /dev/null
@@ -0,0 +1,66 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .bss
+STACKSIZE = 2*1024
+.comm stack, STACKSIZE
+.comm oldstack, 2
+
+.sect .text
+begtext:
+       lxi sp, oldstack + STACKSIZE
+       
+       lxi h, 0
+       push h
+       push h
+       push h
+       call __m_a_i_n
+       jmp EXIT
+       
+! Emergency exit routine.
+
+.define EXIT, __exit
+EXIT:
+__exit:
+       rst 0
+       
+! Define symbols at the beginning of our various segments, so that we can find
+! them. (Except .text, which has already been done.)
+
+.define begtext, begdata, begbss
+.sect .data;       begdata:
+.sect .rom;        begrom:
+.sect .bss;        begbss:
+
+! Some magic data. All EM systems need these.
+
+.define .trppc, .ignmask, _errno
+.comm .trppc, 2
+.comm .ignmask, 2
+.comm _errno, 2
+
+! These are used specifically by the CP/M port.
+
+.define .trapproc, .retadr, .retadr1
+.define .bcreg, .areg
+.define .tmp1, .fra, block1, block2, block3
+
+.comm .trapproc, 2
+.comm .retadr, 2        ! used to save return address
+.comm .retadr1, 2       ! reserve
+.comm .bcreg, 2
+.comm .areg, 1
+.comm .tmp1, 2
+.comm .fra, 8           ! 8 bytes function return area
+block1: .space 4        ! used by 32 bits divide and
+block2: .space 4        ! multiply routines
+block3: .space 4        ! must be contiguous (.comm doesn't guarantee this)
diff --git a/plat/cpm/descr b/plat/cpm/descr
new file mode 100644 (file)
index 0000000..a89c832
--- /dev/null
@@ -0,0 +1,69 @@
+# $Source$
+# $State$
+# $Revision$
+
+var w=2
+var p=2
+var s=2
+var l=4
+var f=4
+var d=8
+var ARCH=i80
+var PLATFORM=cpm
+var PLATFORMDIR={EM}/lib/{PLATFORM}
+var CPP_F=-D__unix
+var ALIGN=-a0:1 -a1:1 -a2:1 -a3:1 -b0:0x0100
+var MACHOPT_F=-m8
+
+# Override the setting in fe so that files compiled for linux386 can see
+# the platform-specific headers.
+
+var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/include/ansi
+
+name be
+       from .m.g
+       to .s
+       program {EM}/lib.bin/{PLATFORM}/ncg
+       args <
+       stdout
+       need .e
+end
+name as
+       from .s.so
+       to .o
+       program {EM}/lib.bin/{PLATFORM}/as
+       args - -o > <
+       prep cond
+end
+name led
+       from .o.a
+       to .out
+       program {EM}/lib.bin/em_led
+       mapflag -l* LNAME={PLATFORMDIR}/lib*
+       mapflag -i SEPID=-b1:0
+       mapflag -fp FLOATS={EM}/{ILIB}fp
+       args {ALIGN} {SEPID?} \
+           (.e:{HEAD}={PLATFORMDIR}/boot.o) \
+               ({RTS}:.ocm.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}/libbasic.a) \
+               (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
+               (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
+               (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
+               {FLOATS?} \
+               (.e:{TAIL}={PLATFORMDIR}/libem.a \
+                          {PLATFORMDIR}/libsys.a \
+                          {PLATFORMDIR}/libend.a)
+       linker
+end
+name cv
+       from .out
+       to .img
+       program {EM}/bin/aslod
+       args < >
+       outfile cpm.com
+end
diff --git a/plat/cpm/include/ack/config.h b/plat/cpm/include/ack/config.h
new file mode 100644 (file)
index 0000000..ebd5c11
--- /dev/null
@@ -0,0 +1,19 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#ifndef _ACK_CONFIG_H
+#define _ACK_CONFIG_H
+
+/* We're providing a time() system call rather than wanting a wrapper around
+ * gettimeofday() in the libc. */
+#define ACKCONF_TIME_IS_A_SYSCALL
+
+/* Since the i80 code generator doesn't support floating point, don't include
+ * it in the stdio libraries. */
+#define ACKCONF_NO_STDIO_FLOAT
+
+#endif
diff --git a/plat/cpm/include/cpm.h b/plat/cpm/include/cpm.h
new file mode 100644 (file)
index 0000000..bdda5ed
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * unistd.h - standard system calls
+ */
+/* $Id$ */
+
+#ifndef _CPM_H
+#define _CPM_H
+
+#include <stdint.h>
+
+/* These interface provides a very bare-bones interface to the CP/M BDOS. Set
+ * the following four variables as you wish, call cpm_bdos(), and the contents
+ * of the variables will have been updated accordingly. */
+extern uint8_t cpm_a_register;
+extern uint16_t cpm_bc_register;
+extern uint16_t cpm_de_register;
+extern uint16_t cpm_hl_register;
+
+extern void cpm_bdos(void);
+
+/* Describes the available CP/M BDOS calls. They're a fairly conservative set
+ * taken from the CP/M 2.0 manual. */
+
+enum
+{
+       CPM_BDOS_SYSTEM_RESET,
+       CPM_BDOS_CONSOLE_INPUT,
+       CPM_BDOS_CONSOLE_OUTPUT,
+       CPM_BDOS_READER_INPUT,
+       CPM_BDOS_PUNCH_OUTPUT,
+       CPM_BDOS_LIST_OUTPUT,
+       CPM_BDOS_CONSOLE_IO,
+       CPM_BDOS_GET_IO_BYTE,
+       CPM_BDOS_SET_IO_BYTE,
+       CPM_BDOS_PRINT_STRING,
+       CPM_BDOS_READ_CONSOLE_BUFFER,
+       CPM_BDOS_GET_CONSOLE_STATUS,
+       CPM_BDOS_GET_VERSION_NUMBER,
+       CPM_BDOS_RESET_DISK_SYSTEM,
+       CPM_BDOS_SELECT_DISK,
+       CPM_BDOS_OPEN_FILE,
+       CPM_BDOS_CLOSE_FILE,
+       CPM_BDOS_SEARCHFIRST,
+       CPM_BDOS_SEARCHNEXT,
+       CPM_BDOS_DELETE_FILE,
+       CPM_BDOS_READ_SEQ,
+       CPM_BDOS_WRITE_SEQ,
+       CPM_BDOS_MAKE_FILE,
+       CPM_BDOS_RENAME_FILE,
+       CPM_BDOS_GET_LOGIN_VECTOR,
+       CPM_BDOS_GET_CURRENT_DISK,
+       CPM_BDOS_SET_DMA_ADDRESS,
+       CPM_BDOS_GET_ALLOC_VECTOR,
+       CPM_BDOS_WRITE_PROTECT,
+       CPM_BDOS_GET_RO_VECTOR,
+       CPM_BDOS_SET_FILE_ATTR,
+       CPM_BDOS_GET_DISK_PARMS,
+       CPM_BDOS_SETGET_USER,
+       CPM_BDOS_READ_RANDOM,
+       CPM_BDOS_WRITE_RANDOM,
+       CPM_BDOS_GET_FILE_SIZE,
+       CPM_BDOS_SET_RANDOM
+};
+
+#endif
diff --git a/plat/cpm/include/unistd.h b/plat/cpm/include/unistd.h
new file mode 100644 (file)
index 0000000..2af9db9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * unistd.h - standard system calls
+ */
+/* $Id$ */
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#include <stddef.h>
+
+/* Types */
+
+typedef int pid_t;
+typedef int mode_t;
+
+/* Constants for file access (open and friends) */
+
+enum
+{
+       O_ACCMODE = 0x3,
+       
+       O_RDONLY = 0,
+       O_WRONLY = 1,
+       O_RDWR = 2,
+       
+       O_CREAT = 0100,
+       O_TRUNC = 01000,
+       O_APPEND = 02000,
+       O_NONBLOCK = 04000
+};
+
+/* Special variables */
+
+extern char** environ;
+
+/* Implemented system calls */
+
+extern void _exit(int);
+extern pid_t getpid(void);
+extern void* sbrk(intptr_t increment);
+extern int isatty(int d);
+extern off_t lseek(int fildes, off_t offset, int whence);
+extern int close(int d);
+extern int open(const char* path, int access, ...);
+extern int creat(const char* path, mode_t mode);
+extern int read(int fd, void* buffer, size_t count);
+extern int write(int fd, void* buffer, size_t count);
+
+/* Unimplemented system calls (these are just prototypes to let the library
+ * compile). */
+
+extern int fcntl(int fd, int op, ...);
+
+/* Signal handling */
+
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((sighandler_t) -1)           /* Error return.  */
+#define SIG_DFL ((sighandler_t) 0)            /* Default action.  */
+#define SIG_IGN ((sighandler_t) 1)            /* Ignore signal.  */
+
+#define SIGABRT         6       /* Abort (ANSI) */
+#define SIGILL          11      /* Illegal instruction */
+
+#define _NSIG           32      /* Biggest signal number + 1
+                                   (not including real-time signals).  */
+typedef void (*sighandler_t)(int);
+extern sighandler_t signal(int signum, sighandler_t handler);
+extern int raise(int signum);
+
+#endif
diff --git a/plat/cpm/libsys/_bdos.s b/plat/cpm/libsys/_bdos.s
new file mode 100644 (file)
index 0000000..4a05dfc
--- /dev/null
@@ -0,0 +1,55 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+! Calls a BDOS routine.
+
+.define _cpm_bdos
+_cpm_bdos:
+       push b
+       
+       lda _cpm_a_register
+       
+       lhld _cpm_bc_register
+       mov b, h
+       mov c, l
+       
+       lhld _cpm_de_register
+       mov d, h
+       mov e, l
+       
+       lhld _cpm_hl_register
+       
+       call 5
+       
+       shld _cpm_hl_register
+       
+       mov h, d
+       mov l, e
+       shld _cpm_de_register
+       
+       mov h, b
+       mov l, c
+       shld _cpm_bc_register
+       
+       sta _cpm_a_register
+       
+       pop b
+       ret
+
+.sect .bss
+.define _cpm_a_register, _cpm_bc_register, _cpm_de_register, _cpm_hl_register
+.comm _cpm_a_register, 1
+.comm _cpm_bc_register, 2
+.comm _cpm_de_register, 2
+.comm _cpm_hl_register, 2
diff --git a/plat/cpm/libsys/_hol0.s b/plat/cpm/libsys/_hol0.s
new file mode 100644 (file)
index 0000000..f01566f
--- /dev/null
@@ -0,0 +1,19 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.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/cpm/libsys/_inn2.s b/plat/cpm/libsys/_inn2.s
new file mode 100644 (file)
index 0000000..64cc8f2
--- /dev/null
@@ -0,0 +1,50 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+! Bit test on 16 bits set
+! Expects on stack:    bit number
+!                      set to be tested
+! Yields in de-registers:      0 if bit is reset or bit number out of range
+!                              1 if bit is set
+
+.sect .text
+.define .inn2
+.inn2: pop h
+       shld .retadr
+
+       pop d           !bit number
+       pop h           !set to be tested
+       mov a,e
+       cpi 16
+       jnc 3f
+       cpi 8
+       jnc 1f
+       mov e,a
+       mov a,l         !l-reg contains the wanted bit
+       jmp 2f
+
+1:     sbi 8
+       mov e,a
+       mov a,h         !h-reg contains the wanted bit
+
+2:     dcr e
+       jm 4f
+       rar
+       jmp 2b
+
+3:     xra a           !return 0 if bit number out of range
+4:     ani 1
+       mov e,a
+       mvi d,0
+
+       lhld .retadr
+       pchl
diff --git a/plat/cpm/libsys/_trap.s b/plat/cpm/libsys/_trap.s
new file mode 100644 (file)
index 0000000..543e0c6
--- /dev/null
@@ -0,0 +1,220 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.define .trp
+.define earray, erange, eset, eiovfl, efovfl, efunfl, eidivz, eidivz
+.define efdivz, eiund, efund, econv, estack, eheap, eillins, eoddz
+.define ecase, ememflt, ebadptr, ebadpc, ebadlae, ebadmon, ebadlin, ebadgto
+.define eunimpl
+
+.sect .text
+
+! Trap routine
+! Expects trap number on stack.
+! Just returns if trap has to be ignored.
+! Otherwise it calls a user-defined trap handler if provided.
+! When no user-defined trap handler is provided or when the user-defined
+! trap handler causes a new trap, a message is printed
+! and control is returned to the monitor.
+
+       EARRAY  =  0
+       ERANGE  =  1
+       ESET    =  2
+       EIOVFL  =  3
+       EFOVFL  =  4
+       EFUNFL  =  5
+       EIDIVZ  =  6
+       EFDIVZ  =  7
+       EIUND   =  8
+       EFUND   =  9
+       ECONV   = 10
+       ESTACK  = 16
+       EHEAP   = 17
+       EILLINS = 18
+       EODDZ   = 19
+       ECASE   = 20
+       EMEMFLT = 21
+       EBADPTR = 22
+       EBADPC  = 23
+       EBADLAE = 24
+       EBADMON = 25
+       EBADLIN = 26
+       EBADGTO = 27
+       EUNIMPL = 63            ! unimplemented em-instruction called
+
+earray:        lxi h,EARRAY
+       push h
+       call .trp
+       ret
+
+erange:        lxi h,ERANGE
+       push h
+       call .trp
+       ret
+
+eset:  lxi h,ESET
+       push h
+       call .trp
+       ret
+
+eiovfl:        lxi h,EIOVFL
+       push h
+       call .trp
+       ret
+
+efovfl:        lxi h,EFOVFL
+       push h
+       call .trp
+       ret
+
+efunfl:        lxi h,EFUNFL
+       push h
+       call .trp
+       ret
+
+eidivz:        lxi h,EIDIVZ
+       push h
+       call .trp
+       ret
+
+efdivz:        lxi h,EFDIVZ
+       push h
+       call .trp
+       ret
+
+eiund: lxi h,EIUND
+       push h
+       call .trp
+       ret
+
+efund: lxi h,EFUND
+       push h
+       call .trp
+       ret
+
+econv: lxi h,ECONV
+       push h
+       call .trp
+       ret
+
+estack:        lxi h,ESTACK
+       push h
+       call .trp
+       ret
+
+eheap: lxi h,EHEAP
+       push h
+       call .trp
+       ret
+
+eillins:lxi h,EILLINS
+       push h
+       call .trp
+       ret
+
+eoddz: lxi h,EODDZ
+       push h
+       call .trp
+       ret
+
+ecase: lxi h,ECASE
+       push h
+       call .trp
+       ret
+
+ememflt:lxi h,EMEMFLT
+       push h
+       call .trp
+       ret
+
+ebadptr:lxi h,EBADPTR
+       push h
+       call .trp
+       ret
+
+ebadpc:        lxi h,EBADPC
+       push h
+       call .trp
+       ret
+
+ebadlae:lxi h,EBADLAE
+       push h
+       call .trp
+       ret
+
+ebadmon:lxi h,EBADMON
+       push h
+       call .trp
+       ret
+
+ebadlin:lxi h,EBADLIN
+       push h
+       call .trp
+       ret
+
+ebadgto:lxi h,EBADGTO
+       push h
+       call .trp
+       ret
+
+eunimpl:lxi h,EUNIMPL
+       push h
+       call .trp
+       ret
+
+.trp:
+       pop h
+       xthl
+       push h                  ! trap number and return address exchanged
+       mov a,l
+       cpi 16
+       jnc 3f                  ! jump if trap cannot be ignored
+
+! check if trap has to be ignored
+       xchg                    ! de = trap number
+       lhld .ignmask
+       push h                  ! hl = set to be tested
+       push d
+       call .inn2              ! de = 1 if bit is set, 0 otherwise
+       mov a,e
+       rar
+       jnc 3f                  ! jump if trap should not be ignored
+       pop h                   ! remove trap number
+       ret                     ! OGEN DICHT EN ... SPRING!!!
+
+3:
+       lhld .trapproc          ! user defined trap handler?
+       mov a,l
+       ora h
+       jz 1f                   ! jump if there was not
+       xra a
+       sta .trapproc           ! .trapproc := 0
+       sta .trapproc+1
+       lxi d,2f                
+       push d
+       pchl                    ! call user defined trap handler
+2:
+       pop d
+       ret
+1:
+       lxi h, 1
+       push h
+       lxi h, text
+       push h
+       lxi h, 6
+       push h
+       call _write
+       jmp EXIT
+
+.sect .rom
+text: .ascii "TRAP!\n"
+
diff --git a/plat/cpm/libsys/brk.c b/plat/cpm/libsys/brk.c
new file mode 100644 (file)
index 0000000..e29dc56
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define        OUT_OF_MEMORY (void*)(-1)       /* sbrk returns this on failure */
+#define STACK_BUFFER 128 /* number of bytes to leave for stack */
+
+extern char _end[1];
+static char* current = _end;
+
+int brk(void* newend)
+{
+       /* We determine the amount of free memory by looking at the address of the
+        * BDOS vector at 0x0006. */
+       char* memtop = (char*) ((*(unsigned char*)0x0007)<<8);
+       char* p = newend;
+       
+       if ((p >= memtop) ||
+           (p < _end)) 
+               return -1;
+               
+       current = p;
+       return 0;
+}
+
+void* sbrk(intptr_t increment)
+{
+       char* old;
+       
+       if (increment == 0)
+               return current;
+               
+       old = current;
+       if (brk(old + increment) < 0)
+               return OUT_OF_MEMORY;
+               
+       return old;
+}
diff --git a/plat/cpm/libsys/close.c b/plat/cpm/libsys/close.c
new file mode 100644 (file)
index 0000000..1c57002
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int close(int fd)
+{
+       errno = EBADF;
+       return -1;
+}
diff --git a/plat/cpm/libsys/creat.c b/plat/cpm/libsys/creat.c
new file mode 100644 (file)
index 0000000..65af5c2
--- /dev/null
@@ -0,0 +1,13 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int creat(const char* path, int mode)
+{
+       return open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
+}
diff --git a/plat/cpm/libsys/errno.s b/plat/cpm/libsys/errno.s
new file mode 100644 (file)
index 0000000..9858d26
--- /dev/null
@@ -0,0 +1,28 @@
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.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/cpm/libsys/getpid.c b/plat/cpm/libsys/getpid.c
new file mode 100644 (file)
index 0000000..5e6eb00
--- /dev/null
@@ -0,0 +1,13 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+pid_t getpid(void)
+{
+       return 0;
+}
diff --git a/plat/cpm/libsys/isatty.c b/plat/cpm/libsys/isatty.c
new file mode 100644 (file)
index 0000000..ad01e34
--- /dev/null
@@ -0,0 +1,13 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int isatty(int fd)
+{
+       return 1;
+}
diff --git a/plat/cpm/libsys/kill.c b/plat/cpm/libsys/kill.c
new file mode 100644 (file)
index 0000000..4a179c4
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int kill(pid_t pid, int sig)
+{
+       errno = EINVAL;
+       return -1;
+}
diff --git a/plat/cpm/libsys/lseek.c b/plat/cpm/libsys/lseek.c
new file mode 100644 (file)
index 0000000..ecbc4b5
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+       errno = EINVAL;
+       return -1;
+}
diff --git a/plat/cpm/libsys/open.c b/plat/cpm/libsys/open.c
new file mode 100644 (file)
index 0000000..f3522ea
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int open(const char* path, int access, ...)
+{
+       errno = EACCES;
+       return -1;
+}
diff --git a/plat/cpm/libsys/pmfile b/plat/cpm/libsys/pmfile
new file mode 100644 (file)
index 0000000..cb564e9
--- /dev/null
@@ -0,0 +1,29 @@
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."plat/cpm/libsys/"
+
+libsys_cpm = acklibrary {
+       ACKINCLUDES = {"%BINDIR%include"},
+       
+       ackfile (d.."errno.s"),
+       ackfile (d.."_hol0.s"),
+       ackfile (d.."_bdos.s"),
+       ackfile (d.."_trap.s"),
+       ackfile (d.."_inn2.s"),
+       ackfile (d.."open.c"),
+       ackfile (d.."creat.c"),
+       ackfile (d.."close.c"),
+       ackfile (d.."read.c"),
+       ackfile (d.."write.c"),
+       ackfile (d.."brk.c"),
+       ackfile (d.."getpid.c"),
+       ackfile (d.."kill.c"),
+       ackfile (d.."isatty.c"),
+       ackfile (d.."lseek.c"),
+       ackfile (d.."time.c"),
+       ackfile (d.."signal.c"),
+       
+       install = pm.install("%BINDIR%lib/%PLATFORM%/libsys.a"),
+}
diff --git a/plat/cpm/libsys/read.c b/plat/cpm/libsys/read.c
new file mode 100644 (file)
index 0000000..8a0ba0c
--- /dev/null
@@ -0,0 +1,38 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cpm.h>
+
+int read(int fd, void* buffer, size_t count)
+{
+       char i;
+       
+       /* We're only allowed to read from fd 0, 1 or 2. */
+       
+       if ((fd < 0) || (fd > 2))
+       {
+               errno = EBADF;
+               return -1;
+       }
+       
+       /* Empty buffer? */
+       
+       if (count == 0)
+               return 0;
+       
+       /* Read one byte. */
+       
+       cpm_bc_register = CPM_BDOS_CONSOLE_INPUT;
+       cpm_bdos();
+
+       if (cpm_a_register == '\r') 
+               cpm_a_register = '\n';
+       *(char*)buffer = cpm_a_register;
+       
+       return 1;
+}
diff --git a/plat/cpm/libsys/signal.c b/plat/cpm/libsys/signal.c
new file mode 100644 (file)
index 0000000..8f145f6
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+
+sighandler_t signal(int signum, sighandler_t handler)
+{
+       return SIG_DFL;
+}
diff --git a/plat/cpm/libsys/time.c b/plat/cpm/libsys/time.c
new file mode 100644 (file)
index 0000000..4215a3b
--- /dev/null
@@ -0,0 +1,16 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+
+time_t time(time_t* t)
+{
+       if (t)
+               *t = 0;
+       return 0;
+}
diff --git a/plat/cpm/libsys/write.c b/plat/cpm/libsys/write.c
new file mode 100644 (file)
index 0000000..0b5f261
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cpm.h>
+
+void _sys_write_tty(char c)
+{
+       cpm_bc_register = CPM_BDOS_CONSOLE_OUTPUT;
+       cpm_de_register = c;
+       cpm_bdos();
+
+       if (c == '\n')
+       {
+               cpm_bc_register = CPM_BDOS_CONSOLE_OUTPUT;
+               cpm_de_register = '\r';
+               cpm_bdos();
+       }
+}
+
+int write(int fd, void* buffer, size_t count)
+{
+       int i;
+       char* p = buffer;
+       
+       /* We're only allowed to write to fd 0, 1 or 2. */
+       
+       if ((fd < 0) || (fd > 2))
+       {
+               errno = EBADF;
+               return -1;
+       }
+       
+       /* Write all data. */
+       
+       i = 0;
+       while (i < count)
+       {
+               _sys_write_tty(*p++);
+                       
+               i++;
+       }
+       
+       /* No failures. */
+       
+       return count;
+}
diff --git a/plat/cpm/pmfile b/plat/cpm/pmfile
new file mode 100644 (file)
index 0000000..43320f1
--- /dev/null
@@ -0,0 +1,47 @@
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."plat/cpm/"
+
+include (d.."libsys/pmfile")
+
+local bootsector = ackfile {
+       file (d.."boot.s"),
+       install = pm.install("%BINDIR%lib/cpm/boot.o"),
+}
+
+local descr = group {
+       install = pm.install(d.."descr", "%BINDIR%%PLATIND%/%PLATFORM%/descr")
+}
+
+local headers = group {
+       install = {
+               pm.install(d.."include/ack/config.h", "%BINDIR%%PLATIND%/%PLATFORM%/include/ack/config.h"),
+               pm.install(d.."include/unistd.h",     "%BINDIR%%PLATIND%/%PLATFORM%/include/unistd.h"),
+               pm.install(d.."include/cpm.h",        "%BINDIR%%PLATIND%/%PLATFORM%/include/cpm.h"),
+       }
+}
+
+platform_cpm = group {
+       ARCH = "i80",
+       PLATFORM = "cpm",
+       OPTIMISATION = "-O",
+       
+       -- Ensure the descr and headers are installed first because we'll need
+       -- them to build the libraries.
+       
+       descr,
+       headers,
+       
+       -- Build the back-end support.
+       
+       mach_i80,
+       support_i80,
+       lang_runtimes,
+
+       -- Build the CP/M syscall library.
+       
+       libsys_cpm,
+       bootsector,
+}
diff --git a/pmfile b/pmfile
index 2a47667..c7a806f 100644 (file)
--- a/pmfile
+++ b/pmfile
@@ -95,6 +95,9 @@ include "plat/pc86/pmfile"             -- PC standalone
 include "mach/i386/pmfile"             -- generic i386
 include "plat/linux386/pmfile"         -- Linux executables
 
+include "mach/i80/pmfile"              -- generic 8080
+include "plat/cpm/pmfile"              -- CP/M
+
 default = group {
        -- Lots of things use LLgen, so we need to build it first.
        
@@ -161,8 +164,6 @@ default = group {
        mach_6805,
        mach_6809,
        mach_arm,      lang_runtimes { ARCH="arm", OPTIMISATION="-O" },
-       mach_i386,     lang_runtimes { ARCH="i386", OPTIMISATION="-O" },
-       mach_i80,      lang_runtimes { ARCH="i80", OPTIMISATION="-O" },
 
        mach_m68020,   lang_runtimes { ARCH="m68020", OPTIMISATION="-O" },
 --     mach_m68k2,    lang_runtimes { ARCH="m68k2", OPTIMISATION="-O" },
@@ -178,7 +179,8 @@ default = group {
        -- Build the platforms.
        
        platform_pc86,
-       platform_linux386
+       platform_linux386,
+       platform_cpm
 }
 
 -- Ensure that the work directories exist.