Merge pull request #195 from davidgiven/dtrg-cpm
Various CP/M improvement
This commit is contained in:
commit
3d877ae3f8
36
build.lua
36
build.lua
|
@ -27,17 +27,8 @@ vars.plats_with_tests = {
|
|||
"pc86",
|
||||
}
|
||||
|
||||
local plat_packages = {}
|
||||
local test_packages = {}
|
||||
for _, p in ipairs(vars.plats) do
|
||||
plat_packages[#plat_packages+1] = "plat/"..p.."+pkg"
|
||||
end
|
||||
for _, p in ipairs(vars.plats_with_tests) do
|
||||
test_packages[#test_packages+1] = "plat/"..p.."/tests+tests"
|
||||
end
|
||||
|
||||
installable {
|
||||
name = "ack",
|
||||
name = "ack-common",
|
||||
map = {
|
||||
"lang/basic/src+pkg",
|
||||
"lang/cem/cemcom.ansi+pkg",
|
||||
|
@ -53,6 +44,31 @@ installable {
|
|||
"util/led+pkg",
|
||||
"util/misc+pkg",
|
||||
"util/opt+pkg",
|
||||
},
|
||||
}
|
||||
|
||||
local plat_packages = {}
|
||||
local test_packages = {}
|
||||
for _, p in ipairs(vars.plats) do
|
||||
local pkg = "plat/"..p.."+pkg"
|
||||
plat_packages[#plat_packages+1] = pkg
|
||||
|
||||
installable {
|
||||
name = "ack-"..p,
|
||||
map = {
|
||||
"+ack-common",
|
||||
pkg,
|
||||
},
|
||||
}
|
||||
end
|
||||
for _, p in ipairs(vars.plats_with_tests) do
|
||||
test_packages[#test_packages+1] = "plat/"..p.."/tests+tests"
|
||||
end
|
||||
|
||||
installable {
|
||||
name = "ack",
|
||||
map = {
|
||||
"+ack-common",
|
||||
"examples+pkg",
|
||||
plat_packages
|
||||
},
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
-- is = { set of rule types which made the target }
|
||||
-- }
|
||||
|
||||
local posix = require("posix")
|
||||
local emitter = {}
|
||||
local rules = {}
|
||||
local targets = {}
|
||||
|
@ -544,7 +545,7 @@ local function definerule(rulename, types, cb)
|
|||
|
||||
local args = {}
|
||||
for propname, typespec in pairs(types) do
|
||||
if not e[propname] then
|
||||
if e[propname] == nil then
|
||||
if not typespec.optional and (typespec.default == nil) then
|
||||
error(string.format("missing mandatory property '%s'", propname))
|
||||
end
|
||||
|
|
|
@ -2475,5 +2475,6 @@ with hlreg
|
|||
gen shld {label,".reghp"}
|
||||
|
||||
pat trp
|
||||
kills ALL
|
||||
gen Call {label,".trp"}
|
||||
with areg
|
||||
kills ALL
|
||||
gen Call {label,".trp"}
|
||||
|
|
|
@ -22,12 +22,13 @@ begtext:
|
|||
! BDOS and crash CP/M. We cheat by comparing only high bytes
|
||||
! of each address.
|
||||
|
||||
lxi b, __end
|
||||
lda 0x0007
|
||||
mov c, a ! c = high byte of BDOS address
|
||||
mov a, b ! a = high byte of _end
|
||||
mov c, a ! c = high byte of BDOS address
|
||||
lda _cpm_ram+1 ! a = high byte of top of BSS, a.k.a. _end
|
||||
cmp c
|
||||
jnc __exit ! emergency exit if a >= c
|
||||
lxi d, noroom
|
||||
mvi c, 9
|
||||
jnc 0x0005 ! print error and exit if a >= c
|
||||
|
||||
! We have to clear the bss. (argify requires it.)
|
||||
|
||||
|
@ -46,6 +47,9 @@ begtext:
|
|||
|
||||
! Set up the stack (now it's been cleared, since it's in the BSS).
|
||||
|
||||
lxi h, 0
|
||||
dad sp
|
||||
shld saved_sp ! save old stack pointer
|
||||
lxi sp, stack + STACKSIZE
|
||||
|
||||
! Initialise the rsts (if desired).
|
||||
|
@ -54,8 +58,15 @@ begtext:
|
|||
call .rst_init
|
||||
#endif
|
||||
|
||||
! Now the 'heap'.
|
||||
|
||||
lhld 0x0006 ! BDOS entry point
|
||||
lxi d, -0x806 ! offset to start of CCP
|
||||
dad d
|
||||
shld _cpm_ramtop
|
||||
|
||||
! C-ify the command line at 0x0080.
|
||||
|
||||
|
||||
lxi h, 0x0080
|
||||
mov a, m ! a = length of command line
|
||||
cpi 0x7F ! 127-byte command lines...
|
||||
|
@ -120,15 +131,40 @@ end_of_argify:
|
|||
mvi h, 0
|
||||
push h
|
||||
call __m_a_i_n
|
||||
! FALLTHROUGH
|
||||
.define _cpm_exit, EXIT, __exit
|
||||
_cpm_exit:
|
||||
EXIT:
|
||||
__exit:
|
||||
stc ! set carry bit
|
||||
jnc _cpm_warmboot ! warm boot if not set
|
||||
saved_sp = . + 1
|
||||
lxi sp, 0 ! patched on startup
|
||||
ret
|
||||
|
||||
! Emergency exit routine.
|
||||
|
||||
.define EXIT, __exit
|
||||
EXIT:
|
||||
__exit:
|
||||
rst 0
|
||||
.define _cpm_warmboot
|
||||
_cpm_warmboot = 0
|
||||
|
||||
! Special CP/M stuff.
|
||||
|
||||
.define _cpm_fcb, _cpm_fcb2
|
||||
_cpm_fcb = 0x005c
|
||||
_cpm_fcb2 = 0x006c
|
||||
|
||||
.define _cpm_ramtop
|
||||
.comm _cpm_ramtop, 2
|
||||
|
||||
.define _cpm_default_dma
|
||||
_cpm_default_dma = 0x0080
|
||||
|
||||
.define _cpm_iobyte
|
||||
_cpm_iobyte = 3
|
||||
|
||||
.define _cpm_cmdlinelen, _cpm_cmdline
|
||||
_cpm_cmdlinelen = 0x0080
|
||||
_cpm_cmdline = 0x0081
|
||||
|
||||
! Define symbols at the beginning of our various segments, so that we can find
|
||||
! them. (Except .text, which has already been done.)
|
||||
|
||||
|
@ -139,8 +175,7 @@ __exit:
|
|||
|
||||
! Some magic data. All EM systems need these.
|
||||
|
||||
.define .trppc, .ignmask, _errno
|
||||
.comm .trppc, 2
|
||||
.define .ignmask, _errno
|
||||
.comm .ignmask, 2
|
||||
.comm _errno, 2
|
||||
|
||||
|
@ -153,11 +188,10 @@ envp: .space 2 ! envp array (always empty, must be after argv)
|
|||
|
||||
! These are used specifically by the i80 code generator.
|
||||
|
||||
.define .trapproc, .retadr, .retadr1
|
||||
.define .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
|
||||
|
@ -168,5 +202,10 @@ 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)
|
||||
|
||||
.sect .data
|
||||
.define _cpm_ram
|
||||
_cpm_ram: .data2 __end
|
||||
|
||||
.sect .rom
|
||||
progname: .asciz 'ACKCPM'
|
||||
noroom: .ascii 'No room$'
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
# $Revision$
|
||||
|
||||
var w=2
|
||||
var wa=1
|
||||
var wa=2
|
||||
var p=2
|
||||
var pa=1
|
||||
var pa=2
|
||||
var s=2
|
||||
var sa=1
|
||||
var sa=2
|
||||
var l=4
|
||||
var la=1
|
||||
var la=2
|
||||
var f=4
|
||||
var fa=1
|
||||
var fa=2
|
||||
var d=8
|
||||
var da=1
|
||||
var da=2
|
||||
var x=8
|
||||
var xa=1
|
||||
var xa=2
|
||||
var ARCH=i80
|
||||
var PLATFORM=cpm
|
||||
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
|
||||
|
|
|
@ -1,66 +1,117 @@
|
|||
/*
|
||||
* unistd.h - standard system calls
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef _CPM_H
|
||||
#define _CPM_H
|
||||
#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;
|
||||
/* EM requires 2-byte alignment, even on the i80, so we can't declare these
|
||||
* structures to contain uint16_ts. Use U16() to access them. */
|
||||
|
||||
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
|
||||
typedef struct
|
||||
{
|
||||
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
|
||||
};
|
||||
uint8_t dr;
|
||||
uint8_t f[11];
|
||||
uint8_t ex;
|
||||
uint8_t s1;
|
||||
uint8_t s2;
|
||||
uint8_t rc;
|
||||
uint8_t d[16];
|
||||
uint8_t cr;
|
||||
uint8_t r[3];
|
||||
}
|
||||
FCB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t dr;
|
||||
uint8_t src[11];
|
||||
uint8_t _padding[5];
|
||||
uint8_t dest[11];
|
||||
}
|
||||
RCB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t us;
|
||||
uint8_t f[11];
|
||||
uint8_t ex;
|
||||
uint8_t s[2];
|
||||
uint8_t rc;
|
||||
uint8_t al[16];
|
||||
}
|
||||
DIRE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t spt[2]; /* number of 128-byte sectors per track */
|
||||
uint8_t bsh; /* block shift; 3=1kB, 4=2kB, 5=4kB etc */
|
||||
uint8_t blm; /* block mask; 0x07=1kB, 0x0f=2kB, 0x1f=4k etc */
|
||||
uint8_t exm; /* extent mask */
|
||||
uint8_t dsm[2]; /* maximum block number */
|
||||
uint8_t drm[2]; /* maximum directory entry number */
|
||||
uint8_t al[2]; /* directory allocation bitmap */
|
||||
uint8_t cks[2]; /* checksum vector size */
|
||||
uint8_t off[2]; /* number of reserved tracks */
|
||||
}
|
||||
DPB;
|
||||
|
||||
/* Access an unaligned field (see above). */
|
||||
#define U16(ptr) (*(uint16_t*)(ptr))
|
||||
|
||||
extern FCB cpm_fcb; /* primary FCB */
|
||||
extern FCB cpm_fcb2; /* secondary FCB (special purpose) */
|
||||
extern uint8_t cpm_iobyte;
|
||||
|
||||
extern uint8_t cpm_default_dma[128]; /* also contains the parsed command line */
|
||||
extern uint8_t* cpm_ram;
|
||||
extern uint8_t* cpm_ramtop;
|
||||
extern uint8_t cpm_cmdlinelen;
|
||||
extern char cpm_cmdline[0x7f];
|
||||
|
||||
/* Special: if the CCP hasn't been overwritten, returns to it; otherwise does
|
||||
* a warmboot. */
|
||||
extern void cpm_exit(void);
|
||||
|
||||
/* Extends cpm_ramtop over the CCP, for a little extra space. */
|
||||
extern void cpm_overwrite_ccp(void);
|
||||
|
||||
/* 0 */ extern void cpm_warmboot(void);
|
||||
/* 1 */ extern uint8_t cpm_conin(void);
|
||||
/* 2 */ extern void cpm_conout(uint8_t b);
|
||||
/* 3 */ extern uint8_t cpm_auxin(void);
|
||||
/* 4 */ extern void cpm_auxout(uint8_t b);
|
||||
/* 5 */ extern void cpm_lstout(uint8_t b);
|
||||
/* 6 */ extern uint8_t cpm_conio(uint8_t b);
|
||||
/* 7 */ extern uint8_t cpm_get_iobyte(void);
|
||||
/* 8 */ extern void cpm_set_iobyte(uint8_t iob);
|
||||
/* 9 */ extern void cpm_printstring(const char* s); /* $-terminated */
|
||||
/* 10 */ extern uint8_t cpm_readline(uint8_t* buffer);
|
||||
/* 11 */ extern uint8_t cpm_const(void);
|
||||
/* 12 */ extern uint16_t cpm_get_version(void);
|
||||
/* 13 */ extern void cpm_reset_disk_system(void);
|
||||
/* 14 */ extern void cpm_select_drive(uint8_t disk);
|
||||
/* 15 */ extern uint8_t cpm_open_file(FCB* fcb);
|
||||
/* 16 */ extern uint8_t cpm_close_file(FCB* fcb);
|
||||
/* 17 */ extern uint8_t cpm_findfirst(FCB* fcb);
|
||||
/* 18 */ extern uint8_t cpm_findnext(FCB* fcb);
|
||||
/* 19 */ extern uint8_t cpm_delete_file(FCB* fcb);
|
||||
/* 20 */ extern uint8_t cpm_read_sequential(FCB* fcb);
|
||||
/* 21 */ extern uint8_t cpm_write_sequential(FCB* fcb);
|
||||
/* 22 */ extern uint8_t cpm_make_file(FCB* fcb);
|
||||
/* 23 */ extern uint8_t cpm_rename_file(RCB* rcb);
|
||||
/* 24 */ extern uint16_t cpm_get_login_vector(void);
|
||||
/* 25 */ extern uint8_t cpm_get_current_drive(void);
|
||||
/* 26 */ extern void cpm_set_dma(void* ptr);
|
||||
/* 27 */ extern uint8_t* cpm_get_allocation_vector(void);
|
||||
/* 28 */ extern void cpm_write_protect_drive(void);
|
||||
/* 29 */ extern uint16_t cpm_get_readonly_vector(void);
|
||||
/* 30 */ extern uint8_t cpm_set_file_attributes(FCB* fcb);
|
||||
/* 31 */ extern DPB* cpm_get_dpb(void);
|
||||
/* 32 */ extern uint8_t cpm_get_set_user(uint8_t user);
|
||||
/* 33 */ extern uint8_t cpm_read_random(FCB* fcb);
|
||||
/* 34 */ extern uint8_t cpm_write_random(FCB* fcb);
|
||||
/* 35 */ extern void cpm_seek_to_end(FCB* fcb);
|
||||
/* 36 */ extern void cpm_seek_to_seq_pos(FCB* fcb);
|
||||
/* 37 */ extern uint8_t cpm_reset_drives(uint16_t drive_bitmap);
|
||||
/* 40 */ extern uint8_t cpm_write_random_filled(FCB* fcb);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,55 +1,20 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
#include "asm.h"
|
||||
|
||||
! Declare segments (the order is important).
|
||||
! Calls a BDOS routine and returns the result.
|
||||
! a = BDOS opcode
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
.define call_bdos
|
||||
call_bdos:
|
||||
pop h ! pop return address
|
||||
pop d ! pop parameter (possibly junk)
|
||||
push d
|
||||
push h
|
||||
|
||||
.sect .text
|
||||
|
||||
! Calls a BDOS routine.
|
||||
|
||||
.define _cpm_bdos
|
||||
_cpm_bdos:
|
||||
push b
|
||||
push b ! save FP as the BDOS will corrupt it
|
||||
mov c, a ! move opcode to C
|
||||
call 0x0005
|
||||
pop b ! restore FP
|
||||
|
||||
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
|
||||
xchg ! DE = HL
|
||||
ret
|
|
@ -3,23 +3,18 @@
|
|||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
#
|
||||
#include "asm.h"
|
||||
|
||||
.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
|
||||
.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
|
||||
|
||||
! Trap routine
|
||||
! Expects trap number on stack.
|
||||
! Expects trap number in A, and must be called directly from the code
|
||||
! where execution should resume (for those traps which support it).
|
||||
! 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
|
||||
|
@ -51,130 +46,7 @@
|
|||
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
|
||||
|
@ -192,10 +64,12 @@ eunimpl:lxi h,EUNIMPL
|
|||
ret ! OGEN DICHT EN ... SPRING!!!
|
||||
|
||||
3:
|
||||
lhld .trapproc ! user defined trap handler?
|
||||
.define .trapproc
|
||||
.trapproc = . + 1
|
||||
lxi h, 0 ! user defined trap handler held inline here
|
||||
mov a,l
|
||||
ora h
|
||||
jz 1f ! jump if there was not
|
||||
jz 1f ! jump if there was not
|
||||
xra a
|
||||
sta .trapproc ! .trapproc := 0
|
||||
sta .trapproc+1
|
||||
|
@ -206,15 +80,11 @@ eunimpl:lxi h,EUNIMPL
|
|||
pop d
|
||||
ret
|
||||
1:
|
||||
lxi h, 6
|
||||
push h
|
||||
lxi h, text
|
||||
push h
|
||||
lxi h, 1
|
||||
push h
|
||||
call _write
|
||||
jmp EXIT
|
||||
lxi d, text
|
||||
mvi c, 9 ! write $-terminated string
|
||||
call 0x0005
|
||||
rst 0 ! abend
|
||||
|
||||
.sect .rom
|
||||
text: .ascii "TRAP!\n"
|
||||
text: .ascii "TRAP!\r\n$"
|
||||
|
||||
|
|
13
plat/cpm/libsys/asm.h
Normal file
13
plat/cpm/libsys/asm.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef ASM_H
|
||||
#define ASM_H
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
#endif
|
|
@ -1,42 +1,34 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <cpm.h>
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
extern uint8_t _end[1];
|
||||
|
||||
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;
|
||||
uint8_t* p = newend;
|
||||
|
||||
if ((p >= memtop) ||
|
||||
if ((p >= cpm_ramtop) ||
|
||||
(p < _end))
|
||||
return -1;
|
||||
|
||||
current = p;
|
||||
cpm_ram = (uint8_t*)p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* sbrk(int increment)
|
||||
{
|
||||
char* old;
|
||||
char* new;
|
||||
uint8_t* old;
|
||||
uint8_t* new;
|
||||
|
||||
if (increment == 0)
|
||||
return current;
|
||||
return cpm_ram;
|
||||
|
||||
old = current;
|
||||
old = cpm_ram;
|
||||
new = old + increment;
|
||||
|
||||
if ((increment > 0) && (new <= old))
|
||||
|
|
|
@ -1,12 +1,110 @@
|
|||
acklibrary {
|
||||
name = "internal",
|
||||
hdrs = { "./*.h" }
|
||||
}
|
||||
|
||||
local bdos_calls = {
|
||||
[ 0] = "cpm_exit",
|
||||
[ 1] = "cpm_conin",
|
||||
[ 2] = "cpm_conout",
|
||||
[ 3] = "cpm_auxin",
|
||||
[ 4] = "cpm_auxout",
|
||||
[ 5] = "cpm_lstout",
|
||||
[ 6] = "cpm_conio",
|
||||
[ 7] = "cpm_get_iobyte",
|
||||
[ 8] = "cpm_set_iobyte",
|
||||
[ 9] = "cpm_printstring",
|
||||
[10] = "cpm_readline",
|
||||
[11] = "cpm_const",
|
||||
[12] = "cpm_get_version",
|
||||
[13] = "cpm_reset_disk_system",
|
||||
[14] = "cpm_select_drive",
|
||||
[15] = "cpm_open_file",
|
||||
[16] = "cpm_close_file",
|
||||
[17] = "cpm_findfirst",
|
||||
[18] = "cpm_findnext",
|
||||
[19] = "cpm_delete_file",
|
||||
[20] = "cpm_read_sequential",
|
||||
[21] = "cpm_write_sequential",
|
||||
[22] = "cpm_make_file",
|
||||
[23] = "cpm_rename_file",
|
||||
[24] = "cpm_get_login_vector",
|
||||
[25] = "cpm_get_current_drive",
|
||||
[26] = "cpm_set_dma",
|
||||
[27] = "cpm_get_allocation_vector",
|
||||
[28] = "cpm_write_protect_drive",
|
||||
[29] = "cpm_get_readonly_vector",
|
||||
[30] = "cpm_set_file_attributes",
|
||||
[31] = "cpm_get_dpb",
|
||||
[32] = "cpm_get_set_user",
|
||||
[33] = "cpm_read_random",
|
||||
[34] = "cpm_write_random",
|
||||
[35] = "cpm_seek_to_end",
|
||||
[36] = "cpm_seek_to_seq_pos",
|
||||
[37] = "cpm_reset_drives",
|
||||
[40] = "cpm_write_random_filled",
|
||||
}
|
||||
|
||||
local trap_calls = {
|
||||
"EARRAY",
|
||||
"ERANGE",
|
||||
"ESET",
|
||||
"EIOVFL",
|
||||
"EFOVFL",
|
||||
"EFUNFL",
|
||||
"EIDIVZ",
|
||||
"EFDIVZ",
|
||||
"EIUND",
|
||||
"EFUND",
|
||||
"ECONV",
|
||||
"ESTACK",
|
||||
"EHEAP",
|
||||
"EILLINS",
|
||||
"EODDZ",
|
||||
"ECASE",
|
||||
"EMEMFLT",
|
||||
"EBADPTR",
|
||||
"EBADPC",
|
||||
"EBADLAE",
|
||||
"EBADMON",
|
||||
"EBADLIN",
|
||||
"EBADGTO",
|
||||
"EUNIMPL",
|
||||
}
|
||||
|
||||
local generated = {}
|
||||
for n, name in pairs(bdos_calls) do
|
||||
generated[#generated+1] = normalrule {
|
||||
name = name,
|
||||
ins = { "./make_bdos_call.sh" },
|
||||
outleaves = { name..".s" },
|
||||
commands = {
|
||||
"%{ins[1]} "..n.." "..name.." > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
for _, name in pairs(trap_calls) do
|
||||
generated[#generated+1] = normalrule {
|
||||
name = name,
|
||||
ins = { "./make_trap.sh" },
|
||||
outleaves = { name..".s" },
|
||||
commands = {
|
||||
"%{ins[1]} "..name:lower().." "..name.." > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
acklibrary {
|
||||
name = "lib",
|
||||
srcs = {
|
||||
"./*.c",
|
||||
"./*.s",
|
||||
generated
|
||||
},
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/cpm/include+headers",
|
||||
"plat/cpm/include+headers",
|
||||
"+internal",
|
||||
},
|
||||
vars = {
|
||||
plat = "cpm"
|
||||
|
|
12
plat/cpm/libsys/cpm_overwrite_ccp.s
Normal file
12
plat/cpm/libsys/cpm_overwrite_ccp.s
Normal file
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
#include "asm.h"
|
||||
|
||||
.define _cpm_overwrite_ccp
|
||||
_cpm_overwrite_ccp:
|
||||
mvi a, 0xaf ! 0xaf = xor a = clear carry bit
|
||||
sta _cpm_exit
|
||||
lhld _cpm_ramtop
|
||||
lxi d, 0x800
|
||||
dad d
|
||||
shld _cpm_ramtop
|
||||
ret
|
10
plat/cpm/libsys/make_bdos_call.sh
Executable file
10
plat/cpm/libsys/make_bdos_call.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/sh
|
||||
cat <<EOF
|
||||
#
|
||||
#include "asm.h"
|
||||
.define _$2
|
||||
_$2:
|
||||
mvi a, $1
|
||||
jmp call_bdos
|
||||
EOF
|
||||
|
10
plat/cpm/libsys/make_trap.sh
Executable file
10
plat/cpm/libsys/make_trap.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/sh
|
||||
cat <<EOF
|
||||
#
|
||||
#include "asm.h"
|
||||
.define $1
|
||||
$1:
|
||||
mvi a, $2
|
||||
jmp .trp
|
||||
EOF
|
||||
|
|
@ -36,18 +36,14 @@ ssize_t read(int fd, void* buffer, size_t count)
|
|||
|
||||
/* Read one line from the console. */
|
||||
((unsigned char*)buffer)[-2] = before_n;
|
||||
cpm_bc_register = CPM_BDOS_READ_CONSOLE_BUFFER;
|
||||
cpm_de_register = (uint16_t)(char*)buffer - 2;
|
||||
cpm_bdos();
|
||||
cpm_readline((uint8_t*)buffer - 2);
|
||||
before_n = ((unsigned char*)buffer)[-1];
|
||||
|
||||
((char*)buffer)[before_n] = '\n'; /* Append '\n'. */
|
||||
((short*)buffer)[-1] = save; /* Give back borrowed bytes. */
|
||||
|
||||
/* Echo '\n' to console. */
|
||||
cpm_bc_register = CPM_BDOS_PRINT_STRING;
|
||||
cpm_de_register = (uint16_t)"\r\n$";
|
||||
cpm_bdos();
|
||||
cpm_printstring("\r\n$");
|
||||
|
||||
return (int)before_n + 1;
|
||||
}
|
||||
|
|
|
@ -10,16 +10,9 @@
|
|||
|
||||
void _sys_write_tty(char c)
|
||||
{
|
||||
cpm_bc_register = CPM_BDOS_CONSOLE_OUTPUT;
|
||||
cpm_de_register = c;
|
||||
cpm_bdos();
|
||||
|
||||
cpm_conout(c);
|
||||
if (c == '\n')
|
||||
{
|
||||
cpm_bc_register = CPM_BDOS_CONSOLE_OUTPUT;
|
||||
cpm_de_register = '\r';
|
||||
cpm_bdos();
|
||||
}
|
||||
cpm_conout(c);
|
||||
}
|
||||
|
||||
ssize_t write(int fd, void* buffer, size_t count)
|
||||
|
@ -37,13 +30,9 @@ ssize_t write(int fd, void* buffer, size_t count)
|
|||
|
||||
/* Write all data. */
|
||||
|
||||
i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
i = count;
|
||||
while (i--)
|
||||
_sys_write_tty(*p++);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* No failures. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue