Merge pull request #81 from kernigh/kernigh-libfp
software floats, line editor for CP/M
This commit is contained in:
commit
f8dfdef974
|
@ -4,6 +4,7 @@ vars.cflags = {
|
|||
vars.ackcflags = {
|
||||
"-O6"
|
||||
}
|
||||
vars.ackldflags = {}
|
||||
vars.plats = {
|
||||
"cpm",
|
||||
"linux386",
|
||||
|
|
|
@ -4,6 +4,10 @@ local conly = {
|
|||
rpi = true
|
||||
}
|
||||
|
||||
local softfp = {
|
||||
cpm = true,
|
||||
}
|
||||
|
||||
local sourcefiles = filenamesof(
|
||||
"./hilo.b",
|
||||
"./hilo.bas",
|
||||
|
@ -15,6 +19,11 @@ local sourcefiles = filenamesof(
|
|||
"./startrek.c"
|
||||
)
|
||||
|
||||
local usesfp = {
|
||||
["mandelbrot.c"] = true,
|
||||
["startrek.c"] = true,
|
||||
}
|
||||
|
||||
local installmap = {}
|
||||
for _, file in ipairs(sourcefiles) do
|
||||
local b = basename(file)
|
||||
|
@ -22,6 +31,12 @@ for _, file in ipairs(sourcefiles) do
|
|||
local _, _, e = b:find("%.(%w*)$")
|
||||
|
||||
for _, plat in ipairs(vars.plats) do
|
||||
local flags = {}
|
||||
|
||||
if softfp[plat] and usesfp[b] then
|
||||
flags[#flags+1] = "-fp"
|
||||
end
|
||||
|
||||
if (e == "c") or not conly[plat] then
|
||||
local exe = ackprogram {
|
||||
name = be.."_"..plat,
|
||||
|
@ -29,6 +44,7 @@ for _, file in ipairs(sourcefiles) do
|
|||
vars = {
|
||||
plat = plat,
|
||||
lang = e,
|
||||
["+ackldflags"] = flags,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ program hilo(input, output);
|
|||
|
||||
type
|
||||
string = packed array [0..255] of char;
|
||||
charstar = packed array [0..0] of char;
|
||||
|
||||
var
|
||||
playing : Boolean;
|
||||
|
@ -30,47 +29,25 @@ function random(range : integer) : integer;
|
|||
random := seed mod range;
|
||||
end;
|
||||
|
||||
{ Pascal doesn't provide string input, so we interface to the read() syscall
|
||||
and do it manually. But... we can't interface to read() directly because
|
||||
that conflicts with a Pascal keyword. Luckily there's a private function
|
||||
uread() in the ACK Pascal library that we can use instead. }
|
||||
|
||||
function uread(fd : integer; var buffer : charstar; count : integer) : integer;
|
||||
extern;
|
||||
{ Pascal doesn't provide string input, so we read characters until the
|
||||
end of line and put them in a string. }
|
||||
|
||||
function readchar : char;
|
||||
var
|
||||
c : charstar;
|
||||
dummy : integer;
|
||||
|
||||
begin
|
||||
c[0] := chr(0);
|
||||
dummy := uread(0, c, 1);
|
||||
readchar := c[0];
|
||||
end;
|
||||
|
||||
procedure readstring(var buffer : string; var length : integer);
|
||||
var
|
||||
finished : Boolean;
|
||||
c : char;
|
||||
|
||||
begin
|
||||
write('> ');
|
||||
|
||||
length := 0;
|
||||
finished := FALSE;
|
||||
seed := 0;
|
||||
while not finished do
|
||||
repeat
|
||||
begin
|
||||
c := readchar;
|
||||
if (ord(c) = 10) then
|
||||
finished := true
|
||||
else
|
||||
begin
|
||||
buffer[length] := c;
|
||||
length := length + 1;
|
||||
end
|
||||
end;
|
||||
read(c);
|
||||
buffer[length] := c;
|
||||
length := length + 1;
|
||||
end
|
||||
until eoln;
|
||||
readln; { discard end of line }
|
||||
end;
|
||||
|
||||
procedure getname;
|
||||
|
|
|
@ -58,7 +58,18 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* For `ack -mcpm -fp`, the i80 code was too big. Make it smaller by
|
||||
* removing the game's intro and replacing part of libc. */
|
||||
#ifdef __i80
|
||||
#define SMALL
|
||||
#endif
|
||||
|
||||
#ifdef SMALL
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
@ -134,13 +145,26 @@ int cint(double d);
|
|||
void compute_vector(void);
|
||||
void sub1(void);
|
||||
void sub2(void);
|
||||
#ifndef SMALL
|
||||
void showfile(char *filename);
|
||||
int openfile(char * sFilename, char * sMode);
|
||||
void closefile(void);
|
||||
int get_line(char *s);
|
||||
#endif
|
||||
void randomize(void);
|
||||
int get_rand(int iSpread);
|
||||
double rnd(void);
|
||||
#ifdef SMALL
|
||||
#undef atof
|
||||
#define atof trek_atof
|
||||
#define getchar trek_getchar
|
||||
#define putchar trek_putchar
|
||||
#define printf trek_printf
|
||||
double atof(const char *);
|
||||
static int getchar(void);
|
||||
static void putchar(int c);
|
||||
void printf(const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
/* Global Variables */
|
||||
|
||||
|
@ -196,14 +220,20 @@ char sQ[194]; /* Visual Display of Quadrant */
|
|||
|
||||
string sG2; /* Used to pass string results */
|
||||
|
||||
#ifndef SMALL
|
||||
FILE *stream;
|
||||
bool bFlag = FALSE; /* Prevent multiple file opens */
|
||||
#endif
|
||||
|
||||
void
|
||||
reads(char* buffer)
|
||||
{
|
||||
#ifdef SMALL
|
||||
read(0, buffer, sizeof(string));
|
||||
#else
|
||||
fflush(stdout);
|
||||
fgets(buffer, sizeof(string), stdin);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Main Program */
|
||||
|
@ -224,6 +254,7 @@ intro(void)
|
|||
{
|
||||
string sTemp;
|
||||
|
||||
#ifndef SMALL
|
||||
printf ("\n\n");
|
||||
printf (" *************************************\n");
|
||||
printf (" * *\n");
|
||||
|
@ -239,6 +270,7 @@ intro(void)
|
|||
|
||||
if (sTemp[0] == 'y' || sTemp[0] == 'Y')
|
||||
showfile("startrek.doc");
|
||||
#endif /* !SMALL */
|
||||
|
||||
printf ("\n\n\n\n\n\n\n");
|
||||
printf(" ------*------\n");
|
||||
|
@ -1879,6 +1911,7 @@ cint (double d)
|
|||
return(i);
|
||||
}
|
||||
|
||||
#ifndef SMALL
|
||||
void
|
||||
showfile(char *filename)
|
||||
{
|
||||
|
@ -1934,6 +1967,7 @@ get_line(char *s)
|
|||
else
|
||||
return(strlen(s));
|
||||
}
|
||||
#endif /* !SMALL */
|
||||
|
||||
/* Seed the randomizer with the timer */
|
||||
void
|
||||
|
@ -1960,3 +1994,164 @@ rnd(void)
|
|||
|
||||
return(d);
|
||||
}
|
||||
|
||||
#ifdef SMALL
|
||||
/* These are small but incomplete replacements for functions in libc.
|
||||
* Local variables are static for smaller i80 code. */
|
||||
|
||||
double
|
||||
atof(const char *str)
|
||||
{
|
||||
static double d;
|
||||
static char n, prec;
|
||||
|
||||
d = 0.0;
|
||||
n = prec = 0; /* Forget to skip whitespace before number */
|
||||
if (*str == '-') { n = 1; str++; }
|
||||
for (;;)
|
||||
{
|
||||
if (*str >= '0' && *str <= '9')
|
||||
{
|
||||
d = 10.0 * d + (double)(*str - '0');
|
||||
if (prec != 0) prec++;
|
||||
}
|
||||
else if (*str == '.')
|
||||
prec++;
|
||||
else
|
||||
break; /* Forget to parse exponent like "e10" */
|
||||
str++;
|
||||
}
|
||||
while (prec > 1) { d /= 10.0; prec--; }
|
||||
return n ? -d : d;
|
||||
}
|
||||
|
||||
static int
|
||||
getchar(void)
|
||||
{
|
||||
static unsigned char c[2]; /* CP/M read() needs 2 bytes */
|
||||
|
||||
if (read(0, c, 2) > 0)
|
||||
return c[0];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
putchar(int c)
|
||||
{
|
||||
write(1, &c, 1);
|
||||
}
|
||||
|
||||
struct printf_buf {
|
||||
char p_buf[13];
|
||||
char p_len;
|
||||
char *p_str;
|
||||
};
|
||||
|
||||
static struct printf_buf pfb;
|
||||
|
||||
static void
|
||||
pfb_put(int c)
|
||||
{
|
||||
if (pfb.p_str != pfb.p_buf)
|
||||
{
|
||||
pfb.p_str--;
|
||||
*pfb.p_str = c; /* Prepend character to buffer */
|
||||
pfb.p_len++;
|
||||
}
|
||||
else
|
||||
pfb.p_len = 0; /* No room in buffer; force empty string */
|
||||
}
|
||||
|
||||
void
|
||||
printf(const char *fmt, ...)
|
||||
{
|
||||
static va_list ap;
|
||||
static const char *s;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while (*fmt != '\0')
|
||||
{
|
||||
if (*fmt != '%')
|
||||
{
|
||||
s = fmt;
|
||||
do { s++; } while ( *s != '\0' && *s != '%');
|
||||
write(1, fmt, s - fmt);
|
||||
fmt = s;
|
||||
}
|
||||
if (*fmt == '%')
|
||||
{
|
||||
static char prec, width;
|
||||
|
||||
fmt++; /* Pass '%' */
|
||||
/* Read optional width.prec, as 4.2 in "%4.2f" */
|
||||
prec = width = 0;
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
width = *fmt - '0';
|
||||
fmt++;
|
||||
}
|
||||
if (*fmt == '.')
|
||||
{
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
prec = *fmt - '0';
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
if (*fmt == 's') /* Format "%s" */
|
||||
{
|
||||
static const char *s;
|
||||
|
||||
s = va_arg(ap, const char *);
|
||||
write(1, s, strlen(s));
|
||||
}
|
||||
else /* Format "%d" or "%f" */
|
||||
{
|
||||
static double d;
|
||||
static char n, pad;
|
||||
|
||||
if (*fmt == 'd')
|
||||
{
|
||||
d = (double)va_arg(ap, int);
|
||||
prec = 0; /* No digits after point */
|
||||
pad = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
d = va_arg(ap, double);
|
||||
/* Move digits before point */
|
||||
for (n = prec; n != 0; n--) d *= 10.0;
|
||||
pad = ' ';
|
||||
}
|
||||
/* Set up buffer */
|
||||
pfb.p_len = 0;
|
||||
pfb.p_str = pfb.p_buf + sizeof(pfb.p_buf);
|
||||
/* Change negative number to positive */
|
||||
n = 0;
|
||||
if (d < 0) { n = 1; d = -d; }
|
||||
modf(d + 0.5, &d); /* Round last digit */
|
||||
for (;;)
|
||||
{
|
||||
d /= 10.0; /* Extract next digit */
|
||||
/* Use 10.5 instead of 10.0 to decrease error */
|
||||
pfb_put('0' + (int)(10.5 * modf(d, &d)));
|
||||
if (prec != 0)
|
||||
{
|
||||
prec--;
|
||||
if (prec == 0) pfb_put('.');
|
||||
}
|
||||
else if (d < 1.0)
|
||||
break; /* No more digits */
|
||||
}
|
||||
if (n) pfb_put('-');
|
||||
while(pfb.p_len < width) pfb_put(pad);
|
||||
write(1, pfb.p_str, pfb.p_len);
|
||||
}
|
||||
fmt++; /* Pass 's' in "%s" */
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
#endif /* SMALL */
|
||||
|
|
|
@ -40,6 +40,7 @@ definerule("cfile",
|
|||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
suffix = { type="string", default=".o" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
|
@ -56,7 +57,7 @@ definerule("cfile",
|
|||
end
|
||||
hdrpaths = uniquify(hdrpaths)
|
||||
|
||||
local outleaf = basename(e.name)..".o"
|
||||
local outleaf = basename(e.name)..e.suffix
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
.define .adf4,.adf8,.sbf4,.sbf8,.mlf4,.mlf8,.dvf4,.dvf8
|
||||
.define .ngf4,.ngf8,.fif4,.fif8,.fef4,.fef8
|
||||
.define .zrf4,.zrf8
|
||||
.define .cfi,.cif,.cuf,.cff,.cfu
|
||||
.define .cfi,.cif4,.cif8,.cuf4,.cuf8,.cff4,.cff8,.cfu
|
||||
.define .cmf4,.cmf8
|
||||
.sect .text
|
||||
.sect .rom
|
||||
|
@ -25,12 +24,13 @@
|
|||
.fif8:
|
||||
.fef4:
|
||||
.fef8:
|
||||
.zrf4:
|
||||
.zrf8:
|
||||
.cfi:
|
||||
.cif:
|
||||
.cuf:
|
||||
.cff:
|
||||
.cif4:
|
||||
.cif8:
|
||||
.cuf4:
|
||||
.cuf8:
|
||||
.cff4:
|
||||
.cff8:
|
||||
.cfu:
|
||||
.cmf4:
|
||||
.cmf8:
|
||||
|
|
|
@ -41,21 +41,12 @@ con_mult(sz) word sz; {
|
|||
fprintf(codefile,".data4\t%ld\n",atol(str));
|
||||
}
|
||||
|
||||
void
|
||||
con_float() {
|
||||
static int warning_given;
|
||||
int i = argval;
|
||||
|
||||
if (!warning_given) {
|
||||
fprintf(stderr, "warning: dummy floating point constant\n");
|
||||
warning_given = 1;
|
||||
}
|
||||
while (i > 0) {
|
||||
fputs(".data4 0 !dummy float\n", codefile);
|
||||
i -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
#define CODE_GENERATOR
|
||||
#define IEEEFLOAT
|
||||
#define FL_MSL_AT_LOW_ADDRESS 0
|
||||
#define FL_MSW_AT_LOW_ADDRESS 0
|
||||
#define FL_MSB_AT_LOW_ADDRESS 0
|
||||
#include <con_float>
|
||||
|
||||
void
|
||||
prolog(nlocals) full nlocals; {
|
||||
|
|
|
@ -817,61 +817,28 @@ gen mvi a,{const1,0}
|
|||
/* Group 5: Floating point arithmetic */
|
||||
/********************************************/
|
||||
|
||||
pat adf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".adf4"}
|
||||
|
||||
pat adf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".adf8"}
|
||||
|
||||
pat sbf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".sbf4"}
|
||||
|
||||
pat sbf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".sbf8"}
|
||||
|
||||
pat mlf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".mlf4"}
|
||||
|
||||
pat mlf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".mlf8"}
|
||||
|
||||
pat dvf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".dvf4"}
|
||||
|
||||
pat dvf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".dvf8"}
|
||||
|
||||
pat ngf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".ngf4"}
|
||||
|
||||
pat ngf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".ngf8"}
|
||||
pat adf $1==4 leaving cal ".adf4" asp 4
|
||||
pat adf $1==8 leaving cal ".adf8" asp 8
|
||||
pat sbf $1==4 leaving cal ".sbf4" asp 4
|
||||
pat sbf $1==8 leaving cal ".sbf8" asp 8
|
||||
pat mlf $1==4 leaving cal ".mlf4" asp 4
|
||||
pat mlf $1==8 leaving cal ".mlf8" asp 8
|
||||
pat dvf $1==4 leaving cal ".dvf4" asp 4
|
||||
pat dvf $1==8 leaving cal ".dvf8" asp 8
|
||||
pat ngf $1==4 leaving cal ".ngf4"
|
||||
pat ngf $1==8 leaving cal ".ngf8"
|
||||
|
||||
pat fif $1==4
|
||||
kills ALL
|
||||
gen Call {label,".fif4"}
|
||||
leaving lor 1 cal ".fif4" asp 2
|
||||
|
||||
pat fif $1==8
|
||||
kills ALL
|
||||
gen Call {label,".fif8"}
|
||||
leaving lor 1 cal ".fif8" asp 2
|
||||
|
||||
pat fef $1==4
|
||||
kills ALL
|
||||
gen Call {label,".fef4"}
|
||||
leaving lor 1 adp 0-2 cal ".fef4"
|
||||
|
||||
pat fef $1==8
|
||||
kills ALL
|
||||
gen Call {label,".fef8"}
|
||||
leaving lor 1 adp 0-2 cal ".fef8"
|
||||
|
||||
/********************************************/
|
||||
/* Group 6: Pointer arithmetic */
|
||||
|
@ -964,13 +931,9 @@ pat zre
|
|||
uses hlreg={const2,0}
|
||||
gen shld {label,$1}
|
||||
|
||||
pat zrf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".zrf4"}
|
||||
pat zrf $1==4 leaving zer 4
|
||||
|
||||
pat zrf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".zrf8"}
|
||||
pat zrf $1==8 leaving zer 8
|
||||
|
||||
pat zer $1==2 yields {const2,0}
|
||||
|
||||
|
@ -1086,25 +1049,51 @@ kills ALL
|
|||
gen mvi a,{const1,0}
|
||||
Call {label,".cii"}
|
||||
|
||||
pat cfi
|
||||
kills ALL
|
||||
gen Call {label,".cfi"}
|
||||
pat loc loc cfi $2==2
|
||||
leaving loc $1 loc $2 cal ".cfi" asp 4+$1 loe ".fra"
|
||||
|
||||
pat cif
|
||||
kills ALL
|
||||
gen Call {label,".cif"}
|
||||
pat loc loc cfi $2==4
|
||||
leaving loc $1 loc $2 cal ".cfi" asp 4+$1 lfr 4
|
||||
|
||||
pat cuf
|
||||
kills ALL
|
||||
gen Call {label,".cuf"}
|
||||
pat loc loc cif $2==4
|
||||
leaving loc $1 cal ".cif4" asp $1-2
|
||||
|
||||
pat cff
|
||||
kills ALL
|
||||
gen Call {label,".cff"}
|
||||
pat loc loc cif $1==2 && $2==8
|
||||
with hl_or_de
|
||||
gen push %1
|
||||
push %1
|
||||
push %1 leaving loc $1 cal ".cif8"
|
||||
|
||||
pat cfu
|
||||
kills ALL
|
||||
gen Call {label,".cfu"}
|
||||
pat loc loc cif $1==4 && $2==8
|
||||
with hl_or_de hl_or_de
|
||||
gen push %2
|
||||
push %2
|
||||
push %1 leaving loc $1 cal ".cif8"
|
||||
|
||||
pat loc loc cuf $2==4
|
||||
leaving loc $1 cal ".cuf4" asp $1-2
|
||||
|
||||
pat loc loc cuf $1==2 && $2==8
|
||||
with hl_or_de
|
||||
gen push %1
|
||||
push %1
|
||||
push %1 leaving loc $1 cal ".cuf8"
|
||||
|
||||
pat loc loc cuf $1==4 && $2==8
|
||||
with hl_or_de hl_or_de
|
||||
gen push %1
|
||||
push %2
|
||||
push %1 leaving loc $1 cal ".cuf8"
|
||||
|
||||
pat loc loc cff $1==8 && $2==4 leaving cal ".cff4" asp 4
|
||||
|
||||
pat loc loc cff $1==4 && $2==8 leaving dup 4 cal ".cff8"
|
||||
|
||||
pat loc loc cfu $2==2
|
||||
leaving loc $1 loc $2 cal ".cfu" asp 4+$1 loe ".fra"
|
||||
|
||||
pat loc loc cfu $2==4
|
||||
leaving loc $1 loc $2 cal ".cfu" asp 4+$1 lfr 4
|
||||
|
||||
/*****************************************/
|
||||
/* Group 9: Logical instructions */
|
||||
|
@ -1408,12 +1397,10 @@ gen mvi a,{const1,1}
|
|||
Call {label,".cmi4"} yields de
|
||||
|
||||
pat cmf $1==4
|
||||
kills ALL
|
||||
gen Call {label,".cmf4"}
|
||||
leaving cal ".cmf4" asp 8 lfr 2
|
||||
|
||||
pat cmf $1==8
|
||||
kills ALL
|
||||
gen Call {label,".cmf8"}
|
||||
leaving cal ".cmf8" asp 16 lfr 2
|
||||
|
||||
pat cmu $1==2
|
||||
with hl_or_de hl_or_de
|
||||
|
|
|
@ -37,5 +37,5 @@ g/_b64_add/s//.b64_add/g
|
|||
g/_b64_sft/s//.b64_sft/g
|
||||
g/_b64_rsft/s//.b64_rsft/g
|
||||
g/_b64_lsft/s//.b64_lsft/g
|
||||
w
|
||||
1,$p
|
||||
q
|
||||
|
|
53
mach/proto/fp/build.lua
Normal file
53
mach/proto/fp/build.lua
Normal file
|
@ -0,0 +1,53 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
-- For now, all floats are little-endian.
|
||||
local byte_order = "mach/i86/libfp/byte_order.h"
|
||||
|
||||
-- For now, only cpm uses software floating-point.
|
||||
for _, plat in ipairs({"cpm"}) do
|
||||
local edits = {}
|
||||
for _, src in fpairs("./*.c", "./*.e") do
|
||||
|
||||
-- Compile each src file into assembly code.
|
||||
local n = basename(src):gsub("%.%w*$", "")
|
||||
local assembly = ackfile {
|
||||
name = "s_"..plat.."/"..n,
|
||||
srcs = { src },
|
||||
deps = {
|
||||
"./*.h",
|
||||
byte_order,
|
||||
},
|
||||
suffix = ".s",
|
||||
vars = {
|
||||
["+ackcflags"] = { "-I"..dirname(byte_order) },
|
||||
plat = plat
|
||||
}
|
||||
}
|
||||
|
||||
-- Run FP.script to edit the assembly code.
|
||||
edits[#edits+1] = normalrule {
|
||||
name = "ed_"..plat.."/"..n,
|
||||
ins = {
|
||||
"./FP.script",
|
||||
assembly,
|
||||
},
|
||||
outleaves = { n..".s" },
|
||||
commands = {
|
||||
"ed -s %{ins[2]} <%{ins[1]} >%{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
acklibrary {
|
||||
name = "lib_"..plat,
|
||||
srcs = { edits },
|
||||
vars = { plat = plat }
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg_"..plat,
|
||||
map = {
|
||||
["$(PLATIND)/"..plat.."/libfp.a"] = "+lib_"..plat,
|
||||
}
|
||||
}
|
||||
end
|
|
@ -8,8 +8,10 @@ definerule("ackfile",
|
|||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
suffix = { type="string", default=".o" },
|
||||
},
|
||||
function (e)
|
||||
local c = (e.suffix == ".o" and "-c" or "-c"..e.suffix)
|
||||
local plat = e.vars.plat
|
||||
|
||||
return cfile {
|
||||
|
@ -28,8 +30,9 @@ definerule("ackfile",
|
|||
"util/misc+pkg",
|
||||
e.deps
|
||||
},
|
||||
suffix = e.suffix,
|
||||
commands = {
|
||||
"ACKDIR=$(INSDIR) $(INSDIR)/bin/ack -m%{plat} -c -o %{outs} %{ins} %{hdrpaths} %{ackcflags}"
|
||||
"ACKDIR=$(INSDIR) $(INSDIR)/bin/ack -m%{plat} "..c.." -o %{outs} %{ins} %{hdrpaths} %{ackcflags}"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -88,7 +91,7 @@ definerule("ackprogram",
|
|||
},
|
||||
_clibrary = acklibrary,
|
||||
commands = {
|
||||
"ACKDIR=$(INSDIR) $(INSDIR)/bin/ack -m%{plat} -.%{lang} -o %{outs} %{ins}"
|
||||
"ACKDIR=$(INSDIR) $(INSDIR)/bin/ack -m%{plat} -.%{lang} -o %{outs} %{ins} %{ackldflags}"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -100,18 +103,25 @@ definerule("build_plat_libs",
|
|||
plat = { type="string" },
|
||||
},
|
||||
function(e)
|
||||
local installmap = {
|
||||
"lang/b/lib+pkg_"..e.plat,
|
||||
"lang/basic/lib+pkg_"..e.plat,
|
||||
"lang/cem/libcc.ansi+pkg_"..e.plat,
|
||||
"lang/m2/libm2+pkg_"..e.plat,
|
||||
"lang/pc/libpc+pkg_"..e.plat,
|
||||
"lang/b/lib+pkg_"..e.plat,
|
||||
["$(PLATIND)/"..e.plat.."/libem.a"] = "mach/"..e.arch.."/libem+lib_"..e.plat,
|
||||
["$(PLATIND)/"..e.plat.."/libend.a"] = "mach/"..e.arch.."/libend+lib_"..e.plat,
|
||||
}
|
||||
|
||||
-- For now, only cpm uses software floating-point.
|
||||
if e.plat == "cpm" then
|
||||
installmap[#installmap+1] = "mach/proto/fp+pkg_"..e.plat
|
||||
end
|
||||
|
||||
return installable {
|
||||
name = e.name,
|
||||
map = {
|
||||
"lang/b/lib+pkg_"..e.plat,
|
||||
"lang/basic/lib+pkg_"..e.plat,
|
||||
"lang/cem/libcc.ansi+pkg_"..e.plat,
|
||||
"lang/m2/libm2+pkg_"..e.plat,
|
||||
"lang/pc/libpc+pkg_"..e.plat,
|
||||
"lang/b/lib+pkg_"..e.plat,
|
||||
["$(PLATIND)/"..e.plat.."/libem.a"] = "mach/"..e.arch.."/libem+lib_"..e.plat,
|
||||
["$(PLATIND)/"..e.plat.."/libend.a"] = "mach/"..e.arch.."/libend+lib_"..e.plat,
|
||||
}
|
||||
map = installmap,
|
||||
}
|
||||
end
|
||||
)
|
||||
|
|
|
@ -11,14 +11,15 @@ 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).
|
||||
represent the console. Each read() blocks and reads an entire line (it can't
|
||||
read part of a line) from the CP/M line editor, then appends \n. Each write()
|
||||
converts \n to \r\n. The line editor and \n conversion 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.
|
||||
|
||||
IEEE floating point is not available. Attempts to use floating-point numbers
|
||||
will cause the program to terminate.
|
||||
Link with `ack -fp` to enable software floating point. Otherwise, attempts to
|
||||
use floating-point numbers will cause the program to terminate.
|
||||
|
||||
|
||||
Example command line
|
||||
|
|
|
@ -58,7 +58,7 @@ name led
|
|||
program {EM}/lib/ack/em_led
|
||||
mapflag -l* LNAME={PLATFORMDIR}/lib*
|
||||
mapflag -i SEPID=-b1:0
|
||||
mapflag -fp FLOATS={EM}/{ILIB}fp
|
||||
mapflag -fp FLOATS={PLATFORMDIR}/libfp.a
|
||||
args {ALIGN} {SEPID?} \
|
||||
({RTS}:.b=-u _i_main) \
|
||||
(.e:{HEAD}={PLATFORMDIR}/boot.o) \
|
||||
|
|
|
@ -10,29 +10,44 @@
|
|||
|
||||
int read(int fd, void* buffer, size_t count)
|
||||
{
|
||||
char i;
|
||||
|
||||
short save;
|
||||
unsigned char before_n;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* We need room for at least 1 char plus '\n'. */
|
||||
if (count < 2)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make room to append '\n' later. */
|
||||
before_n = count > 255 ? 255 : count - 1;
|
||||
|
||||
/* Borrow 2 bytes of RAM before the buffer. */
|
||||
/* This might overwrite count!!! */
|
||||
save = ((short*)buffer)[-1];
|
||||
|
||||
/* Read one line from the console. */
|
||||
((unsigned char*)buffer)[-2] = before_n;
|
||||
cpm_bc_register = CPM_BDOS_READ_CONSOLE_BUFFER;
|
||||
cpm_de_register = (char*)buffer - 2;
|
||||
cpm_bdos();
|
||||
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 = "\r\n$";
|
||||
cpm_bdos();
|
||||
|
||||
if (cpm_a_register == '\r')
|
||||
cpm_a_register = '\n';
|
||||
*(char*)buffer = cpm_a_register;
|
||||
|
||||
return 1;
|
||||
return (int)before_n + 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue