Added cpm platform.

This commit is contained in:
dtrg 2007-04-27 22:42:41 +00:00
parent 013f58f94e
commit be8baf3da6
31 changed files with 1140 additions and 9 deletions

49
mach/i80/libem/pmfile Normal file
View file

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

View 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

16
mach/i80/libend/pmfile Normal file
View file

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

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

24
plat/cpm/.distr Normal file
View file

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

33
plat/cpm/README Normal file
View file

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

66
plat/cpm/boot.s Normal file
View file

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

69
plat/cpm/descr Normal file
View file

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

View file

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

66
plat/cpm/include/cpm.h Normal file
View file

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

71
plat/cpm/include/unistd.h Normal file
View file

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

55
plat/cpm/libsys/_bdos.s Normal file
View file

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

19
plat/cpm/libsys/_hol0.s Normal file
View file

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

50
plat/cpm/libsys/_inn2.s Normal file
View file

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

220
plat/cpm/libsys/_trap.s Normal file
View file

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

43
plat/cpm/libsys/brk.c Normal file
View file

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

14
plat/cpm/libsys/close.c Normal file
View file

@ -0,0 +1,14 @@
/* $Source$
* $State$
* $Revision$
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int close(int fd)
{
errno = EBADF;
return -1;
}

13
plat/cpm/libsys/creat.c Normal file
View file

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

28
plat/cpm/libsys/errno.s Normal file
View file

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

13
plat/cpm/libsys/getpid.c Normal file
View file

@ -0,0 +1,13 @@
/* $Source$
* $State$
* $Revision$
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
pid_t getpid(void)
{
return 0;
}

13
plat/cpm/libsys/isatty.c Normal file
View file

@ -0,0 +1,13 @@
/* $Source$
* $State$
* $Revision$
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int isatty(int fd)
{
return 1;
}

14
plat/cpm/libsys/kill.c Normal file
View file

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

14
plat/cpm/libsys/lseek.c Normal file
View file

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

14
plat/cpm/libsys/open.c Normal file
View file

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

29
plat/cpm/libsys/pmfile Normal file
View file

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

38
plat/cpm/libsys/read.c Normal file
View file

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

14
plat/cpm/libsys/signal.c Normal file
View file

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

16
plat/cpm/libsys/time.c Normal file
View file

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

51
plat/cpm/libsys/write.c Normal file
View file

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

47
plat/cpm/pmfile Normal file
View file

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

8
pmfile
View file

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