Compare commits
No commits in common. "db5a32c68c4a60ca26a3927a799ea662b5b2b0e5" and "03420ef4ad9919d3eff410d4ce731e2a441818df" have entirely different histories.
db5a32c68c
...
03420ef4ad
86 changed files with 603 additions and 2388 deletions
8
README
8
README
|
@ -2,7 +2,7 @@
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
© 1987-2005 Vrije Universiteit, Amsterdam
|
© 1987-2005 Vrije Universiteit, Amsterdam
|
||||||
2022-08-19
|
2022-06-18
|
||||||
|
|
||||||
|
|
||||||
INTRODUCTION
|
INTRODUCTION
|
||||||
|
@ -38,7 +38,6 @@ cpm produces i80 CP/M .COM files
|
||||||
rpi produces Raspberry Pi GPU binaries
|
rpi produces Raspberry Pi GPU binaries
|
||||||
pdpv7 produces PDP/11 V7 Unix binaries
|
pdpv7 produces PDP/11 V7 Unix binaries
|
||||||
msdos86 produces i86 MS-DOS .COM files
|
msdos86 produces i86 MS-DOS .COM files
|
||||||
msdos386 produces i386 MS-DOS 32-bit DPMI .EXE files
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +62,11 @@ Requirements:
|
||||||
- (optionally) ninja; if you've got this, this will be autodetected and give
|
- (optionally) ninja; if you've got this, this will be autodetected and give
|
||||||
you faster builds.
|
you faster builds.
|
||||||
|
|
||||||
|
- (optionally) the qemu suite: if you have this installed, the build system
|
||||||
|
will detect it automatically and run the test suites for the supported
|
||||||
|
architectures. Get both the qemu-system-* platform emulators and the qemu-*
|
||||||
|
userland emulators (only works on Linux).
|
||||||
|
|
||||||
- about 115MB free in /tmp (or some other temporary directory).
|
- about 115MB free in /tmp (or some other temporary directory).
|
||||||
|
|
||||||
- about 15MB in the target directory.
|
- about 15MB in the target directory.
|
||||||
|
|
|
@ -12,7 +12,6 @@ vars.plats = {
|
||||||
"linuxppc",
|
"linuxppc",
|
||||||
"linuxmips",
|
"linuxmips",
|
||||||
"msdos86",
|
"msdos86",
|
||||||
"msdos386",
|
|
||||||
"osx386",
|
"osx386",
|
||||||
"osxppc",
|
"osxppc",
|
||||||
"pc86",
|
"pc86",
|
||||||
|
@ -23,9 +22,9 @@ vars.plats = {
|
||||||
vars.plats_with_tests = {
|
vars.plats_with_tests = {
|
||||||
"cpm",
|
"cpm",
|
||||||
"linux68k",
|
"linux68k",
|
||||||
--"linux386",
|
"linux386",
|
||||||
"linuxppc",
|
"linuxppc",
|
||||||
--"linuxmips",
|
"linuxmips",
|
||||||
"pc86",
|
"pc86",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ definerule("cprogram",
|
||||||
commands = {
|
commands = {
|
||||||
type="strings",
|
type="strings",
|
||||||
default={
|
default={
|
||||||
"$(CC) $(LDFLAGS) -o %{outs[1]} %{ins} %{ins}"
|
"$(CC) $LDFLAGS -o %{outs[1]} %{ins} %{ins}"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -184,13 +184,10 @@
|
||||||
{0, NOOP_1, 0155, "ins"},
|
{0, NOOP_1, 0155, "ins"},
|
||||||
{0, NOOP_1, 0252, "stosb"},
|
{0, NOOP_1, 0252, "stosb"},
|
||||||
{0, NOOP_1, 0253, "stos"},
|
{0, NOOP_1, 0253, "stos"},
|
||||||
{0, NOOP_1, 0253, "stosw"},
|
|
||||||
{0, NOOP_1, 0254, "lodsb"},
|
{0, NOOP_1, 0254, "lodsb"},
|
||||||
{0, NOOP_1, 0255, "lods"},
|
{0, NOOP_1, 0255, "lods"},
|
||||||
{0, NOOP_1, 0255, "lodsw"},
|
|
||||||
{0, NOOP_1, 0256, "scasb"},
|
{0, NOOP_1, 0256, "scasb"},
|
||||||
{0, NOOP_1, 0257, "scas"},
|
{0, NOOP_1, 0257, "scas"},
|
||||||
{0, NOOP_1, 0257, "scasw"},
|
|
||||||
{0, NOOP_1, 0311, "leave"},
|
{0, NOOP_1, 0311, "leave"},
|
||||||
{0, NOOP_1, 0316, "into"},
|
{0, NOOP_1, 0316, "into"},
|
||||||
{0, NOOP_1, 0317, "iret"},
|
{0, NOOP_1, 0317, "iret"},
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
|
|
||||||
void ea_1_16(int param)
|
void ea_1_16(int param)
|
||||||
{
|
{
|
||||||
reg_1 &= 0377;
|
reg_1 &= 0377;
|
||||||
if (param & ~070) {
|
if ((reg_1 & 070) || (param & ~070)) {
|
||||||
serror("bad operand");
|
serror("bad operand");
|
||||||
}
|
}
|
||||||
emit1(reg_1 | param);
|
emit1(reg_1 | param);
|
||||||
|
@ -39,545 +39,542 @@ void ea_1_16(int param)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ea_1(int param) {
|
void ea_1(int param) {
|
||||||
if (! address_long) {
|
if (! address_long) {
|
||||||
ea_1_16(param);
|
ea_1_16(param);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (is_expr(reg_1)) {
|
if (is_expr(reg_1)) {
|
||||||
serror("bad operand");
|
serror("bad operand");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (is_reg(reg_1)) {
|
if (is_reg(reg_1)) {
|
||||||
emit1(0300 | param | (reg_1&07));
|
emit1(0300 | param | (reg_1&07));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rm_1 == 04) {
|
if (rm_1 == 04) {
|
||||||
/* sib field use here */
|
/* sib field use here */
|
||||||
emit1(mod_1 << 6 | param | 04);
|
emit1(mod_1 << 6 | param | 04);
|
||||||
emit1(sib_1 | reg_1);
|
emit1(sib_1 | reg_1);
|
||||||
}
|
}
|
||||||
else emit1(mod_1<<6 | param | (reg_1&07));
|
else emit1(mod_1<<6 | param | (reg_1&07));
|
||||||
if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
|
if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
|
||||||
/* ??? should this be protected by a call to "small" ??? */
|
/* ??? should this be protected by a call to "small" ??? */
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
RELOMOVE(relonami, rel_1);
|
RELOMOVE(relonami, rel_1);
|
||||||
newrelo(exp_1.typ, RELO4);
|
newrelo(exp_1.typ, RELO4);
|
||||||
#endif
|
#endif
|
||||||
emit4((long)(exp_1.val));
|
emit4((long)(exp_1.val));
|
||||||
}
|
}
|
||||||
else if (mod_1 == 1) {
|
else if (mod_1 == 1) {
|
||||||
emit1((int)(exp_1.val));
|
emit1((int)(exp_1.val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ea_2(int param) {
|
void ea_2(int param) {
|
||||||
|
|
||||||
op_1 = op_2;
|
op_1 = op_2;
|
||||||
RELOMOVE(rel_1, rel_2);
|
RELOMOVE(rel_1, rel_2);
|
||||||
ea_1(param);
|
ea_1(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
int checkscale(valu_t val)
|
int checkscale(valu_t val)
|
||||||
{
|
{
|
||||||
int v = val;
|
int v = val;
|
||||||
|
|
||||||
if (! address_long) {
|
if (! address_long) {
|
||||||
serror("scaling not allowed in 16-bit mode");
|
serror("scaling not allowed in 16-bit mode");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (v != val) v = 0;
|
if (v != val) v = 0;
|
||||||
switch(v) {
|
switch(v) {
|
||||||
case 1:
|
case 1:
|
||||||
return 0;
|
return 0;
|
||||||
case 2:
|
case 2:
|
||||||
return 1 << 6;
|
return 1 << 6;
|
||||||
case 4:
|
case 4:
|
||||||
return 2 << 6;
|
return 2 << 6;
|
||||||
case 8:
|
case 8:
|
||||||
return 3 << 6;
|
return 3 << 6;
|
||||||
default:
|
default:
|
||||||
serror("bad scale");
|
serror("bad scale");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void reverse(void) {
|
void reverse(void) {
|
||||||
struct operand op;
|
struct operand op;
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
int r = rel_1;
|
int r = rel_1;
|
||||||
|
|
||||||
rel_1 = rel_2; rel_2 = r;
|
rel_1 = rel_2; rel_2 = r;
|
||||||
#endif
|
#endif
|
||||||
op = op_1; op_1 = op_2; op_2 = op;
|
op = op_1; op_1 = op_2; op_2 = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
void badsyntax(void)
|
void badsyntax(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
serror("bad operands");
|
serror("bad operands");
|
||||||
}
|
}
|
||||||
|
|
||||||
void regsize(int sz)
|
void regsize(int sz)
|
||||||
{
|
{
|
||||||
register int bit;
|
register int bit;
|
||||||
|
|
||||||
bit = (sz&1) ? 0 : IS_R8;
|
bit = (sz&1) ? 0 : IS_R8;
|
||||||
if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
|
if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
|
||||||
(is_reg(reg_2) && (reg_2 & IS_R8) != bit))
|
(is_reg(reg_2) && (reg_2 & IS_R8) != bit))
|
||||||
serror("register error");
|
serror("register error");
|
||||||
if (! address_long) {
|
if (! address_long) {
|
||||||
reg_1 &= ~010;
|
reg_1 &= ~010;
|
||||||
reg_2 &= ~010;
|
reg_2 &= ~010;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void indexed(void) {
|
void indexed(void) {
|
||||||
if (address_long) {
|
if (address_long) {
|
||||||
mod_2 = 0;
|
mod_2 = 0;
|
||||||
if (sib_2 == -1)
|
if (sib_2 == -1)
|
||||||
serror("register error");
|
serror("register error");
|
||||||
if (rm_2 == 0 && reg_2 == 4) {
|
if (rm_2 == 0 && reg_2 == 4) {
|
||||||
/* base register sp, no index register; use
|
/* base register sp, no index register; use
|
||||||
indexed mode without index register
|
indexed mode without index register
|
||||||
*/
|
*/
|
||||||
rm_2 = 04;
|
rm_2 = 04;
|
||||||
sib_2 = 044;
|
sib_2 = 044;
|
||||||
}
|
}
|
||||||
if (reg_2 == 015) {
|
if (reg_2 == 015) {
|
||||||
reg_2 = 05;
|
reg_2 = 05;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
|
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
|
||||||
if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
|
if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
|
||||||
}
|
}
|
||||||
else mod_2 = 01;
|
else mod_2 = 01;
|
||||||
}
|
}
|
||||||
else if (small(0, 1)) {
|
else if (small(0, 1)) {
|
||||||
}
|
}
|
||||||
else mod_2 = 02;
|
else mod_2 = 02;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (reg_2 & ~7)
|
if (reg_2 & ~7)
|
||||||
serror("register error");
|
serror("register error");
|
||||||
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
|
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
|
||||||
if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
|
if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
|
||||||
}
|
}
|
||||||
else reg_2 |= 0100;
|
else reg_2 |= 0100;
|
||||||
}
|
}
|
||||||
else if (small(0, 1)) {
|
else if (small(0, 1)) {
|
||||||
}
|
}
|
||||||
else reg_2 |= 0200;
|
else reg_2 |= 0200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ebranch(register int opc,expr_t exp)
|
void ebranch(register int opc,expr_t exp)
|
||||||
{
|
{
|
||||||
/* Conditional branching; Full displacements are available
|
/* Conditional branching; Full displacements are available
|
||||||
on the 80386, so the welknown trick with the reverse branch
|
on the 80386, so the welknown trick with the reverse branch
|
||||||
over a jump is not needed here.
|
over a jump is not needed here.
|
||||||
The only complication here is with the address size, which
|
The only complication here is with the address size, which
|
||||||
can be set with a prefix. In this case, the user gets what
|
can be set with a prefix. In this case, the user gets what
|
||||||
he asked for.
|
he asked for.
|
||||||
*/
|
*/
|
||||||
register int sm;
|
register int sm;
|
||||||
register long dist;
|
register long dist;
|
||||||
int saving = address_long ? 4 : 2;
|
int saving = address_long ? 4 : 2;
|
||||||
|
|
||||||
if (opc == 0353) saving--;
|
if (opc == 0353) saving--;
|
||||||
dist = exp.val - (DOTVAL + 2);
|
dist = exp.val - (DOTVAL + 2);
|
||||||
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
|
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
|
||||||
dist -= DOTGAIN;
|
dist -= DOTGAIN;
|
||||||
sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
|
sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
|
||||||
if ((exp.typ & ~S_DOT) != DOTTYP)
|
if ((exp.typ & ~S_DOT) != DOTTYP)
|
||||||
sm = 0;
|
sm = 0;
|
||||||
if ((sm = small(sm,saving)) == 0) {
|
if ((sm = small(sm,saving)) == 0) {
|
||||||
if (opc == 0353) {
|
if (opc == 0353) {
|
||||||
emit1(0xe9);
|
emit1(0xe9);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit1(0xF);
|
emit1(0xF);
|
||||||
emit1(opc | 0x80);
|
emit1(opc | 0x80);
|
||||||
}
|
}
|
||||||
dist -= saving;
|
dist -= saving;
|
||||||
exp.val = dist;
|
exp.val = dist;
|
||||||
adsize_exp(exp, RELPC);
|
adsize_exp(exp, RELPC);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (opc == 0353) {
|
if (opc == 0353) {
|
||||||
emit1(opc);
|
emit1(opc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit1(opc | 0x70);
|
emit1(opc | 0x70);
|
||||||
}
|
}
|
||||||
emit1((int)dist);
|
emit1((int)dist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void branch(register int opc,expr_t exp)
|
void branch(register int opc,expr_t exp)
|
||||||
{
|
{
|
||||||
/* LOOP, JCXZ, etc. branch instructions.
|
/* LOOP, JCXZ, etc. branch instructions.
|
||||||
Here, the offset just must fit in a byte.
|
Here, the offset just must fit in a byte.
|
||||||
*/
|
*/
|
||||||
register long dist;
|
register long dist;
|
||||||
|
|
||||||
dist = exp.val - (DOTVAL + 2);
|
dist = exp.val - (DOTVAL + 2);
|
||||||
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
|
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
|
||||||
dist -= DOTGAIN;
|
dist -= DOTGAIN;
|
||||||
fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
|
fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
|
||||||
emit1(opc);
|
emit1(opc);
|
||||||
emit1((int)dist);
|
emit1((int)dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushop(register int opc)
|
void pushop(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(1);
|
regsize(1);
|
||||||
if (is_segreg(reg_1)) {
|
if (is_segreg(reg_1)) {
|
||||||
/* segment register */
|
/* segment register */
|
||||||
if ((reg_1 & 07) <= 3)
|
if ((reg_1 & 07) <= 3)
|
||||||
emit1(6 | opc | (reg_1&7)<<3);
|
emit1(6 | opc | (reg_1&7)<<3);
|
||||||
else {
|
else {
|
||||||
emit1(0xF);
|
emit1(0xF);
|
||||||
emit1(0200 | opc | ((reg_1&7)<<3));
|
emit1(0200 | opc | ((reg_1&7)<<3));
|
||||||
}
|
}
|
||||||
} else if (is_reg(reg_1)) {
|
} else if (is_reg(reg_1)) {
|
||||||
/* normal register */
|
/* normal register */
|
||||||
emit1(0120 | opc<<3 | (reg_1&7));
|
emit1(0120 | opc<<3 | (reg_1&7));
|
||||||
} else if (opc == 0) {
|
} else if (opc == 0) {
|
||||||
if (is_expr(reg_1)) {
|
if (is_expr(reg_1)) {
|
||||||
if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
|
if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
|
||||||
operand_long ? 3 : 1)) {
|
operand_long ? 3 : 1)) {
|
||||||
emit1(0152);
|
emit1(0152);
|
||||||
emit1((int)(exp_1.val));
|
emit1((int)(exp_1.val));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit1(0150);
|
emit1(0150);
|
||||||
RELOMOVE(relonami, rel_1);
|
RELOMOVE(relonami, rel_1);
|
||||||
opsize_exp(exp_1, 1);
|
opsize_exp(exp_1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit1(0377); ea_1(6<<3);
|
emit1(0377); ea_1(6<<3);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit1(0217); ea_1(0<<3);
|
emit1(0217); ea_1(0<<3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void opsize_exp(expr_t exp, int nobyte)
|
void opsize_exp(expr_t exp, int nobyte)
|
||||||
{
|
{
|
||||||
if (! nobyte) {
|
if (! nobyte) {
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
newrelo(exp.typ, RELO1);
|
newrelo(exp.typ, RELO1);
|
||||||
#endif
|
#endif
|
||||||
emit1((int)(exp.val));
|
emit1((int)(exp.val));
|
||||||
}
|
}
|
||||||
else if (operand_long) {
|
else if (operand_long) {
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
newrelo(exp.typ, RELO4);
|
newrelo(exp.typ, RELO4);
|
||||||
#endif
|
#endif
|
||||||
emit4((long)(exp.val));
|
emit4((long)(exp.val));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
newrelo(exp.typ, RELO2);
|
newrelo(exp.typ, RELO2);
|
||||||
#endif
|
#endif
|
||||||
emit2((int)(exp.val));
|
emit2((int)(exp.val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void adsize_exp(expr_t exp, int relpc)
|
void adsize_exp(expr_t exp, int relpc)
|
||||||
{
|
{
|
||||||
if (address_long) {
|
if (address_long) {
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
newrelo(exp.typ, RELO4 | relpc);
|
newrelo(exp.typ, RELO4 | relpc);
|
||||||
#endif
|
#endif
|
||||||
emit4((long)(exp.val));
|
emit4((long)(exp.val));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
newrelo(exp.typ, RELO2 | relpc);
|
newrelo(exp.typ, RELO2 | relpc);
|
||||||
#endif
|
#endif
|
||||||
emit2((int)(exp.val));
|
emit2((int)(exp.val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addop(register int opc)
|
void addop(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if (is_reg(reg_2)) {
|
if (is_reg(reg_2)) {
|
||||||
/* Add register to register or memory */
|
/* Add register to register or memory */
|
||||||
emit1(opc); ea_1((reg_2&7)<<3);
|
emit1(opc); ea_1((reg_2&7)<<3);
|
||||||
} else if (is_acc(reg_1) && is_expr(reg_2)) {
|
} else if (is_acc(reg_1) && is_expr(reg_2)) {
|
||||||
/* Add immediate to accumulator */
|
/* Add immediate to accumulator */
|
||||||
emit1(opc | 4);
|
emit1(opc | 4);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, (opc&1));
|
opsize_exp(exp_2, (opc&1));
|
||||||
} else if (is_expr(reg_2)) {
|
} else if (is_expr(reg_2)) {
|
||||||
/* Add immediate to register or memory */
|
/* Add immediate to register or memory */
|
||||||
if ((opc&1) == 0) {
|
if ((opc&1) == 0) {
|
||||||
emit1(0200);
|
emit1(0200);
|
||||||
} else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
|
} else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
|
||||||
operand_long ? 3 : 1)) {
|
operand_long ? 3 : 1)) {
|
||||||
emit1(0201);
|
emit1(0201);
|
||||||
} else {
|
} else {
|
||||||
emit1(0203); opc &= ~1;
|
emit1(0203); opc &= ~1;
|
||||||
}
|
}
|
||||||
ea_1(opc & 070);
|
ea_1(opc & 070);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, (opc&1));
|
opsize_exp(exp_2, (opc&1));
|
||||||
} else if (is_reg(reg_1)) {
|
} else if (is_reg(reg_1)) {
|
||||||
/* Add register or memory to register */
|
/* Add register or memory to register */
|
||||||
emit1(opc | 2);
|
emit1(opc | 2);
|
||||||
ea_2((reg_1&7)<<3);
|
ea_2((reg_1&7)<<3);
|
||||||
} else
|
} else
|
||||||
badsyntax();
|
badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rolop(register int opc)
|
void rolop(register int opc)
|
||||||
{
|
{
|
||||||
register int oreg;
|
register int oreg;
|
||||||
|
|
||||||
oreg = reg_2;
|
oreg = reg_2;
|
||||||
reg_2 = reg_1;
|
reg_2 = reg_1;
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
|
if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
|
||||||
/* cl register */
|
/* cl register */
|
||||||
emit1(0322 | (opc&1)); ea_1(opc&070);
|
emit1(0322 | (opc&1)); ea_1(opc&070);
|
||||||
} else if (is_expr(oreg)) {
|
} else if (is_expr(oreg)) {
|
||||||
if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
|
if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
|
||||||
/* shift by 1 */
|
/* shift by 1 */
|
||||||
emit1(0320 | (opc&1)); ea_1(opc&070);
|
emit1(0320 | (opc&1)); ea_1(opc&070);
|
||||||
} else {
|
} else {
|
||||||
/* shift by byte count */
|
/* shift by byte count */
|
||||||
emit1(0300 | (opc & 1));
|
emit1(0300 | (opc & 1));
|
||||||
ea_1(opc & 070);
|
ea_1(opc & 070);
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
newrelo(exp_2.typ, RELO1);
|
newrelo(exp_2.typ, RELO1);
|
||||||
#endif
|
#endif
|
||||||
emit1((int)(exp_2.val));
|
emit1((int)(exp_2.val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
badsyntax();
|
badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void incop(register int opc)
|
void incop(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if ((opc&1) && is_reg(reg_1)) {
|
if ((opc&1) && is_reg(reg_1)) {
|
||||||
/* word register */
|
/* word register */
|
||||||
emit1(0100 | (opc&010) | (reg_1&7));
|
emit1(0100 | (opc&010) | (reg_1&7));
|
||||||
} else {
|
} else {
|
||||||
emit1(0376 | (opc&1));
|
emit1(0376 | (opc&1));
|
||||||
ea_1(opc & 010);
|
ea_1(opc & 010);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void callop(register int opc)
|
void callop(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(1);
|
regsize(1);
|
||||||
if (is_expr(reg_1)) {
|
if (is_expr(reg_1)) {
|
||||||
if (opc == (040+(0351<<8))) {
|
if (opc == (040+(0351<<8))) {
|
||||||
RELOMOVE(relonami, rel_1);
|
RELOMOVE(relonami, rel_1);
|
||||||
ebranch(0353,exp_1);
|
ebranch(0353,exp_1);
|
||||||
} else {
|
} else {
|
||||||
exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
|
exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
|
||||||
emit1(opc>>8);
|
emit1(opc>>8);
|
||||||
RELOMOVE(relonami, rel_1);
|
RELOMOVE(relonami, rel_1);
|
||||||
adsize_exp(exp_1, RELPC);
|
adsize_exp(exp_1, RELPC);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit1(0377); ea_1(opc&070);
|
emit1(0377); ea_1(opc&070);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xchg(register int opc)
|
void xchg(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if (! is_reg(reg_1) || is_acc(reg_2)) {
|
if (! is_reg(reg_1) || is_acc(reg_2)) {
|
||||||
reverse();
|
reverse();
|
||||||
}
|
}
|
||||||
if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
|
if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
|
||||||
emit1(0220 | (reg_2&7));
|
emit1(0220 | (reg_2&7));
|
||||||
} else if (is_reg(reg_1)) {
|
} else if (is_reg(reg_1)) {
|
||||||
emit1(0206 | opc); ea_2((reg_1&7)<<3);
|
emit1(0206 | opc); ea_2((reg_1&7)<<3);
|
||||||
} else
|
} else
|
||||||
badsyntax();
|
badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void test(register int opc)
|
void test(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if (is_reg(reg_2) || is_expr(reg_1))
|
if (is_reg(reg_2) || is_expr(reg_1))
|
||||||
reverse();
|
reverse();
|
||||||
if (is_expr(reg_2)) {
|
if (is_expr(reg_2)) {
|
||||||
if (is_acc(reg_1)) {
|
if (is_acc(reg_1)) {
|
||||||
emit1(0250 | opc);
|
emit1(0250 | opc);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, (opc&1));
|
opsize_exp(exp_2, (opc&1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit1(0366 | opc);
|
emit1(0366 | opc);
|
||||||
ea_1(0<<3);
|
ea_1(0<<3);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, (opc&1));
|
opsize_exp(exp_2, (opc&1));
|
||||||
}
|
}
|
||||||
} else if (is_reg(reg_1)) {
|
} else if (is_reg(reg_1)) {
|
||||||
emit1(0204 | opc); ea_2((reg_1&7)<<3);
|
emit1(0204 | opc); ea_2((reg_1&7)<<3);
|
||||||
} else
|
} else
|
||||||
badsyntax();
|
badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mov(register int opc)
|
void mov(register int opc)
|
||||||
{
|
{
|
||||||
|
|
||||||
regsize(opc);
|
regsize(opc);
|
||||||
if (is_segreg(reg_1)) {
|
if (is_segreg(reg_1)) {
|
||||||
/* to segment register */
|
/* to segment register */
|
||||||
emit1(0216); ea_2((reg_1&07)<<3);
|
emit1(0216); ea_2((reg_1&07)<<3);
|
||||||
} else if (is_segreg(reg_2)) {
|
} else if (is_segreg(reg_2)) {
|
||||||
/* from segment register */
|
/* from segment register */
|
||||||
emit1(0214); ea_1((reg_2&07)<<3);
|
emit1(0214); ea_1((reg_2&07)<<3);
|
||||||
} else if (is_expr(reg_2)) {
|
} else if (is_expr(reg_2)) {
|
||||||
/* from immediate */
|
/* from immediate */
|
||||||
if (is_reg(reg_1)) {
|
if (is_reg(reg_1)) {
|
||||||
/* to register */
|
/* to register */
|
||||||
emit1(0260 | opc<<3 | (reg_1&7));
|
emit1(0260 | opc<<3 | (reg_1&7));
|
||||||
} else {
|
} else {
|
||||||
/* to memory */
|
/* to memory */
|
||||||
emit1(0306 | opc); ea_1(0<<3);
|
emit1(0306 | opc); ea_1(0<<3);
|
||||||
}
|
}
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, (opc&1));
|
opsize_exp(exp_2, (opc&1));
|
||||||
} else if (rm_1 == 05 && is_acc(reg_2)) {
|
} else if (rm_1 == 05 && is_acc(reg_2)) {
|
||||||
/* from accumulator to memory (displacement) */
|
/* from accumulator to memory (displacement) */
|
||||||
emit1(0242 | opc);
|
emit1(0242 | opc);
|
||||||
RELOMOVE(relonami, rel_1);
|
RELOMOVE(relonami, rel_1);
|
||||||
adsize_exp(exp_1, 0);
|
adsize_exp(exp_1, 0);
|
||||||
} else if (rm_2 == 05 && is_acc(reg_1)) {
|
} else if (rm_2 == 05 && is_acc(reg_1)) {
|
||||||
/* from memory (displacement) to accumulator */
|
/* from memory (displacement) to accumulator */
|
||||||
emit1(0240 | opc);
|
emit1(0240 | opc);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
adsize_exp(exp_2, 0);
|
adsize_exp(exp_2, 0);
|
||||||
} else if (is_reg(reg_2)) {
|
} else if (is_reg(reg_2)) {
|
||||||
/* from register to memory or register */
|
/* from register to memory or register */
|
||||||
emit1(0210 | opc); ea_1((reg_2&07)<<3);
|
emit1(0210 | opc); ea_1((reg_2&07)<<3);
|
||||||
} else if (is_reg(reg_1)) {
|
} else if (is_reg(reg_1)) {
|
||||||
/* from memory or register to register */
|
/* from memory or register to register */
|
||||||
emit1(0212 | opc); ea_2((reg_1&07)<<3);
|
emit1(0212 | opc); ea_2((reg_1&07)<<3);
|
||||||
} else
|
} else
|
||||||
badsyntax();
|
badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void extshft(int opc, int reg)
|
void extshft(int opc, int reg)
|
||||||
{
|
{
|
||||||
int oreg2 = reg_2;
|
int oreg2 = reg_2;
|
||||||
|
|
||||||
reg_2 = reg_1;
|
reg_2 = reg_1;
|
||||||
regsize(1);
|
regsize(1);
|
||||||
|
|
||||||
emit1(0xF);
|
emit1(0xF);
|
||||||
if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
|
if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
|
||||||
/* cl register */
|
/* cl register */
|
||||||
emit1(opc|1);
|
emit1(opc|1);
|
||||||
ea_1(reg << 3);
|
ea_1(reg << 3);
|
||||||
}
|
}
|
||||||
else if (is_expr(oreg2)) {
|
else if (is_expr(oreg2)) {
|
||||||
emit1(opc);
|
emit1(opc);
|
||||||
ea_1(reg << 3);
|
ea_1(reg << 3);
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
newrelo(exp_2.typ, RELO1);
|
newrelo(exp_2.typ, RELO1);
|
||||||
#endif
|
#endif
|
||||||
emit1((int)(exp_2.val));
|
emit1((int)(exp_2.val));
|
||||||
}
|
}
|
||||||
else badsyntax();
|
else badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bittestop(int opc)
|
void bittestop(int opc)
|
||||||
{
|
{
|
||||||
regsize(1);
|
regsize(1);
|
||||||
emit1(0xF);
|
emit1(0xF);
|
||||||
if (is_expr(reg_2)) {
|
if (is_expr(reg_2)) {
|
||||||
emit1(0272);
|
emit1(0272);
|
||||||
ea_1(opc << 3);
|
ea_1(opc << 3);
|
||||||
#ifdef RELOCATION
|
#ifdef RELOCATION
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
newrelo(exp_2.typ, RELO1);
|
newrelo(exp_2.typ, RELO1);
|
||||||
#endif
|
#endif
|
||||||
emit1((int)(exp_2.val));
|
emit1((int)(exp_2.val));
|
||||||
}
|
}
|
||||||
else if (is_reg(reg_2)) {
|
else if (is_reg(reg_2)) {
|
||||||
emit1(0203 | (opc<<3));
|
emit1(0203 | (opc<<3));
|
||||||
ea_1((reg_2&7)<<3);
|
ea_1((reg_2&7)<<3);
|
||||||
}
|
}
|
||||||
else badsyntax();
|
else badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void imul(int reg)
|
void imul(int reg)
|
||||||
{
|
{
|
||||||
/* This instruction is more elaborate on the 80386. Its most
|
/* This instruction is more elaborate on the 80386. Its most
|
||||||
general form is:
|
general form is:
|
||||||
imul reg, reg_or_mem, immediate.
|
imul reg, reg_or_mem, immediate.
|
||||||
This is the form processed here.
|
This is the form processed here.
|
||||||
*/
|
*/
|
||||||
regsize(1);
|
regsize(1);
|
||||||
if (is_expr(reg_1)) {
|
if (is_expr(reg_1)) {
|
||||||
/* To also handle
|
/* To also handle
|
||||||
imul reg, immediate, reg_or_mem
|
imul reg, immediate, reg_or_mem
|
||||||
*/
|
*/
|
||||||
reverse();
|
reverse();
|
||||||
}
|
}
|
||||||
if (is_expr(reg_2)) {
|
if (is_expr(reg_2)) {
|
||||||
/* The immediate form; two cases: */
|
/* The immediate form; two cases: */
|
||||||
if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
|
if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
|
||||||
operand_long ? 3 : 1)) {
|
operand_long ? 3 : 1)) {
|
||||||
/* case 1: 1 byte encoding of immediate */
|
/* case 1: 1 byte encoding of immediate */
|
||||||
emit1(0153);
|
emit1(0153);
|
||||||
ea_1((reg & 07) << 3);
|
ea_1((reg & 07) << 3);
|
||||||
emit1((int)(exp_2.val));
|
emit1((int)(exp_2.val));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* case 2: WORD or DWORD encoding of immediate */
|
/* case 2: WORD or DWORD encoding of immediate */
|
||||||
emit1(0151);
|
emit1(0151);
|
||||||
ea_1((reg & 07) << 3);
|
ea_1((reg & 07) << 3);
|
||||||
RELOMOVE(relonami, rel_2);
|
RELOMOVE(relonami, rel_2);
|
||||||
opsize_exp(exp_2, 1);
|
opsize_exp(exp_2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
|
else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
|
||||||
/* the "reg" field and the "reg_or_mem" field are the same,
|
/* the "reg" field and the "reg_or_mem" field are the same,
|
||||||
and the 3rd operand is not an immediate ...
|
and the 3rd operand is not an immediate ...
|
||||||
*/
|
*/
|
||||||
if (reg == 0) {
|
if (reg == 0) {
|
||||||
/* how lucky we are, the target is the ax register */
|
/* how lucky we are, the target is the ax register */
|
||||||
/* However, we cannot make an optimization for f.i.
|
/* However, we cannot make an optimization for f.i.
|
||||||
imul eax, blablabla
|
imul eax, blablabla
|
||||||
because the latter does not affect edx, whereas
|
because the latter does not affect edx, whereas
|
||||||
imul blablabla
|
imul blablabla
|
||||||
does! Therefore, "reg" is or-ed with 0x10 in the
|
does! Therefore, "reg" is or-ed with 0x10 in the
|
||||||
former case, so that the test above fails.
|
former case, so that the test above fails.
|
||||||
*/
|
*/
|
||||||
emit1(0367);
|
emit1(0367);
|
||||||
ea_2(050);
|
ea_2(050);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* another register ... */
|
/* another register ... */
|
||||||
emit1(0xF);
|
emit1(0xF);
|
||||||
emit1(0257);
|
emit1(0257);
|
||||||
ea_2((reg & 07) << 3);
|
ea_2((reg & 07) << 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else badsyntax();
|
else badsyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: ts=8 sw=8 et
|
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,6 @@ char* remember(char* s)
|
||||||
|
|
||||||
int combine(int typ1, int typ2, int op)
|
int combine(int typ1, int typ2, int op)
|
||||||
{
|
{
|
||||||
typ1 &= ~S_VAR;
|
|
||||||
typ2 &= ~S_VAR;
|
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
|
|
|
@ -78,7 +78,7 @@ for _, plat in ipairs({"cpm"}) do
|
||||||
},
|
},
|
||||||
outleaves = { n..".s" },
|
outleaves = { n..".s" },
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} <%{ins[2]} >%{outs}"
|
"$LUA %{ins[1]} <%{ins[2]} >%{outs}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#ifndef PMAP_H
|
#ifndef PMAP_H
|
||||||
#define PMAP_H
|
#define PMAP_H
|
||||||
|
|
||||||
/* A bidirectional multimap, storing (left, right) tuples.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct pmap_node
|
struct pmap_node
|
||||||
{
|
{
|
||||||
void* left;
|
void* left;
|
||||||
|
@ -26,33 +23,10 @@ struct pmap
|
||||||
int max; \
|
int max; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds a new relation `(left -> right)` to the map
|
|
||||||
* if `left` is not present. Otherwise replaces the
|
|
||||||
* `right` associated with the first `left`.
|
|
||||||
*
|
|
||||||
* Use this in normal map mode.
|
|
||||||
*/
|
|
||||||
extern void pmap_put(void* map, void* left, void* right);
|
extern void pmap_put(void* map, void* left, void* right);
|
||||||
|
|
||||||
/** Adds a new relation to the map if that relation does
|
|
||||||
* not already exist.
|
|
||||||
*
|
|
||||||
* Use this in multimap mode.
|
|
||||||
*/
|
|
||||||
extern void pmap_add(void* map, void* left, void* right);
|
extern void pmap_add(void* map, void* left, void* right);
|
||||||
|
|
||||||
/** Removes a relation from the map.
|
|
||||||
*
|
|
||||||
* Use this in multimap mode.
|
|
||||||
*/
|
|
||||||
extern void pmap_remove(void* map, void* left, void* right);
|
extern void pmap_remove(void* map, void* left, void* right);
|
||||||
|
|
||||||
/** Given a `left`, find the first matching `right`.
|
|
||||||
*/
|
|
||||||
extern void* pmap_findleft(void* map, void* left);
|
extern void* pmap_findleft(void* map, void* left);
|
||||||
|
|
||||||
/** Given a `right`, find the first matching `left`.
|
|
||||||
*/
|
|
||||||
extern void* pmap_findright(void* map, void* right);
|
extern void* pmap_findright(void* map, void* right);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
#ifndef SMAP_H
|
#ifndef SMAP_H
|
||||||
#define SMAP_H
|
#define SMAP_H
|
||||||
|
|
||||||
/* A string multimap (each key can have multiple values). */
|
|
||||||
|
|
||||||
struct smap_node
|
struct smap_node
|
||||||
{
|
{
|
||||||
const char* left;
|
const char* left;
|
||||||
|
@ -30,33 +28,24 @@ struct smap
|
||||||
int max; \
|
int max; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes a string map. Optional; a zero-initialised map
|
/** Initializes a string map and returns the initialized
|
||||||
* structure is a valid empty map.
|
* handle in `mapp`.
|
||||||
*/
|
*/
|
||||||
extern void smap_init(void *mapp);
|
extern void smap_init(void *mapp);
|
||||||
|
/** Adds a new item with name `key` in the string map if
|
||||||
/** Adds a new item with name `key` in the string map if it does not already
|
* it does not already exist, otherwise replaces the
|
||||||
* exist. Otherwise replaces the value `value` associated with the existing
|
* value `value` associated with the existing `key`.
|
||||||
* `key`.
|
|
||||||
*
|
|
||||||
* Use this for normal map mode.
|
|
||||||
*/
|
*/
|
||||||
extern void smap_put(void *mapp, const char* key, void* value);
|
extern void smap_put(void *mapp, const char* key, void* value);
|
||||||
|
/** Adds a new item in a string map only if `key` does
|
||||||
/** Adds a new item with name `key` and value `value`. If that relation already
|
* not already exist in the string map.
|
||||||
* exists, nothing happens.
|
|
||||||
*
|
|
||||||
* Use this for multimap mode.
|
|
||||||
*/
|
*/
|
||||||
extern void smap_add(void *mapp, const char* key, void* value);
|
extern void smap_add(void *mapp, const char* key, void* value);
|
||||||
|
/** Returns the value associated with the specified `key`, returns
|
||||||
/** Returns the first value associated with the specified `key`. Returns NULL
|
* NULL if `key` is not present in the string map.
|
||||||
* if `key` is not present in the string map.
|
|
||||||
*
|
*
|
||||||
* Use this in normal map mode.
|
|
||||||
*/
|
*/
|
||||||
extern void* smap_get(void* mapp, const char* key);
|
extern void* smap_get(void* mapp, const char* key);
|
||||||
|
|
||||||
/** Frees the data structure associated with the string map.
|
/** Frees the data structure associated with the string map.
|
||||||
* Also frees the memory associated with the key if
|
* Also frees the memory associated with the key if
|
||||||
* `free_key` is non-zero, and free the memory associated
|
* `free_key` is non-zero, and free the memory associated
|
||||||
|
|
|
@ -39,7 +39,7 @@ void stringlist_free(struct stringlist* list, int freedata)
|
||||||
struct stringfragment* next = f->next;
|
struct stringfragment* next = f->next;
|
||||||
if (freedata)
|
if (freedata)
|
||||||
{
|
{
|
||||||
free((void*) f->data);
|
free(f->data);
|
||||||
f->data = NULL;
|
f->data = NULL;
|
||||||
}
|
}
|
||||||
free(f);
|
free(f);
|
||||||
|
@ -54,7 +54,7 @@ void stringlist_init(struct stringlist* list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* stringlist_get(struct stringlist *list, int index)
|
char* stringlist_get(struct stringlist *list, int index)
|
||||||
{
|
{
|
||||||
struct stringfragment* f = list->first;
|
struct stringfragment* f = list->first;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
struct stringfragment
|
struct stringfragment
|
||||||
{
|
{
|
||||||
const char* data;
|
char* data;
|
||||||
struct stringfragment* next;
|
struct stringfragment* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ extern void stringlist_addall(struct stringlist* list, struct stringlist* src);
|
||||||
extern void stringlist_free(struct stringlist* list, int freedata);
|
extern void stringlist_free(struct stringlist* list, int freedata);
|
||||||
extern void stringlist_init(struct stringlist* list);
|
extern void stringlist_init(struct stringlist* list);
|
||||||
extern int stringlist_count(struct stringlist *list);
|
extern int stringlist_count(struct stringlist *list);
|
||||||
extern const char* stringlist_get(struct stringlist *list, int index);
|
extern char* stringlist_get(struct stringlist *list, int index);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@ normalrule {
|
||||||
},
|
},
|
||||||
outleaves = { "em_codeEK.h" },
|
outleaves = { "em_codeEK.h" },
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} < %{ins[3]} > %{outs}",
|
"$LUA %{ins[1]} < %{ins[3]} > %{outs}",
|
||||||
"cat %{ins[4]} >> %{outs}"
|
"cat %{ins[4]} >> %{outs}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ for _, f in ipairs(GENFILES) do
|
||||||
"h+emheaders"
|
"h+emheaders"
|
||||||
},
|
},
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} < %{ins[3]} > %{outs}"
|
"$LUA %{ins[1]} < %{ins[3]} > %{outs}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ normalrule {
|
||||||
},
|
},
|
||||||
outleaves = "C_mnem_narg.h",
|
outleaves = "C_mnem_narg.h",
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} < %{ins[3]} > %{outs}"
|
"$LUA %{ins[1]} < %{ins[3]} > %{outs}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ normalrule {
|
||||||
},
|
},
|
||||||
outleaves = "C_mnem.h",
|
outleaves = "C_mnem.h",
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} < %{ins[3]} > %{outs}"
|
"$LUA %{ins[1]} < %{ins[3]} > %{outs}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
plat/linux386/tests/build.lua
Normal file
7
plat/linux386/tests/build.lua
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
include("tests/plat/build.lua")
|
||||||
|
|
||||||
|
plat_testsuite {
|
||||||
|
name = "tests",
|
||||||
|
plat = "linux386",
|
||||||
|
method = "qemu-i386"
|
||||||
|
}
|
10
plat/linuxmips/tests/build.lua
Normal file
10
plat/linuxmips/tests/build.lua
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
include("tests/plat/build.lua")
|
||||||
|
|
||||||
|
plat_testsuite {
|
||||||
|
name = "tests",
|
||||||
|
plat = "linuxmips",
|
||||||
|
method = "qemu-mipsel",
|
||||||
|
skipsets = {
|
||||||
|
"long-long",
|
||||||
|
},
|
||||||
|
}
|
|
@ -325,12 +325,6 @@ void dump_state(FILE* stream)
|
||||||
fprintf(stream, "\n");
|
fprintf(stream, "\n");
|
||||||
fprintf(stream, "gpr%02d=0x%08x ", i, cpu.gpr[i]);
|
fprintf(stream, "gpr%02d=0x%08x ", i, cpu.gpr[i]);
|
||||||
}
|
}
|
||||||
for (i=0; i<32; i++)
|
|
||||||
{
|
|
||||||
if ((i % 3) == 0)
|
|
||||||
fprintf(stream, "\n");
|
|
||||||
fprintf(stream, "fpr%02d=0x%016lx ", i, cpu.fpr[i]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
/* This might fail and cause a reentrant trap if cia is invalid, so
|
/* This might fail and cause a reentrant trap if cia is invalid, so
|
||||||
|
|
|
@ -207,5 +207,5 @@
|
||||||
|
|
||||||
# Floating point conversions
|
# Floating point conversions
|
||||||
|
|
||||||
<63--><FRT>.....<FRB><14------>R setcr1(R, fpr(FRB)); cpu.fpr[FRT] = (uint32_t)(int32_t)fpr(FRB);
|
<63--><FRT>.....<FRB><14------>R setcr1(R, fpr(FRB)); cpu.fpr[FRT] = (uint32_t)fpr(FRB);
|
||||||
<63--><FRT>.....<FRB><15------>R setcr1(R, fpr(FRB)); cpu.fpr[FRT] = (uint32_t)(int32_t)fpr(FRB);
|
<63--><FRT>.....<FRB><15------>R setcr1(R, fpr(FRB)); cpu.fpr[FRT] = (uint32_t)fpr(FRB);
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
/* $Source$
|
|
||||||
* $State$
|
|
||||||
* $Revision$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ACK_PLAT_H
|
|
||||||
#define _ACK_PLAT_H
|
|
||||||
|
|
||||||
#define ACKCONF_WANT_O_TEXT_O_BINARY 1
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,24 +0,0 @@
|
||||||
include("plat/build.lua")
|
|
||||||
|
|
||||||
headermap = {}
|
|
||||||
packagemap = {}
|
|
||||||
|
|
||||||
local function addheader(h)
|
|
||||||
headermap[h] = "./"..h
|
|
||||||
packagemap["$(PLATIND)/msdos86/include/"..h] = "./"..h
|
|
||||||
end
|
|
||||||
|
|
||||||
addheader("ack/plat.h")
|
|
||||||
addheader("sys/types.h")
|
|
||||||
|
|
||||||
acklibrary {
|
|
||||||
name = "headers",
|
|
||||||
hdrs = headermap
|
|
||||||
}
|
|
||||||
|
|
||||||
installable {
|
|
||||||
name = "pkg",
|
|
||||||
map = packagemap
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#ifndef _SYS_TYPES_H
|
|
||||||
#define _SYS_TYPES_H
|
|
||||||
|
|
||||||
typedef long pid_t;
|
|
||||||
typedef int mode_t;
|
|
||||||
typedef long time_t;
|
|
||||||
typedef long suseconds_t;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,28 +0,0 @@
|
||||||
bundle {
|
|
||||||
name = "srcs",
|
|
||||||
srcs = {
|
|
||||||
"./creat.c",
|
|
||||||
"./gettimeofday.c",
|
|
||||||
"./kill.c",
|
|
||||||
"./lseek.c",
|
|
||||||
"./open.c",
|
|
||||||
"./read.c",
|
|
||||||
"./setmode.c",
|
|
||||||
"./signal.c",
|
|
||||||
"./sys_fdmodes.c",
|
|
||||||
"./sys_getmode.c",
|
|
||||||
"./sys_initmain.c",
|
|
||||||
"./sys_iseof.c",
|
|
||||||
"./sys_seteof.c",
|
|
||||||
"./sys_seterrno.c",
|
|
||||||
"./sys_setmode.c",
|
|
||||||
"./write.c",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle {
|
|
||||||
name = "headers",
|
|
||||||
srcs = {
|
|
||||||
"./libsys.h"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/* $Source$
|
|
||||||
* $State$
|
|
||||||
* $Revision$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "libsys.h"
|
|
||||||
|
|
||||||
ssize_t write(int fd, void* buffer, size_t count)
|
|
||||||
{
|
|
||||||
static const char crlf[2] = "\r\n";
|
|
||||||
int i;
|
|
||||||
char *p, *q;
|
|
||||||
size_t left, n;
|
|
||||||
ssize_t r, tot;
|
|
||||||
|
|
||||||
if (!count)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
p = buffer;
|
|
||||||
left = count;
|
|
||||||
tot = 0;
|
|
||||||
|
|
||||||
if (_sys_getmode(fd) == O_BINARY)
|
|
||||||
{
|
|
||||||
while (left)
|
|
||||||
{
|
|
||||||
r = _sys_rawwrite(fd, p, left);
|
|
||||||
if (r <= 0)
|
|
||||||
return tot ? tot : r;
|
|
||||||
tot += r;
|
|
||||||
p += r;
|
|
||||||
left -= r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If the file descriptor is an O_TEXT fd, translate LFs to CRLFs. */
|
|
||||||
while (left)
|
|
||||||
{
|
|
||||||
q = memchr(p, '\n', left);
|
|
||||||
if (!q)
|
|
||||||
return _sys_rawwrite(fd, p, left);
|
|
||||||
|
|
||||||
n = q - p;
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
r = _sys_rawwrite(fd, p, n);
|
|
||||||
if (r <= 0)
|
|
||||||
return tot ? tot : r;
|
|
||||||
tot += r;
|
|
||||||
p += r;
|
|
||||||
left -= r;
|
|
||||||
if (r != n)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = _sys_rawwrite(fd, crlf, sizeof crlf);
|
|
||||||
if (r != 2)
|
|
||||||
{
|
|
||||||
if (r > 0)
|
|
||||||
r = 0;
|
|
||||||
return tot ? tot : r;
|
|
||||||
}
|
|
||||||
++tot;
|
|
||||||
++p;
|
|
||||||
--left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tot;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
The msdos386 platform
|
|
||||||
=====================
|
|
||||||
|
|
||||||
msdos386 is an i386-based BSP that produces DPMI DOS executables. It should
|
|
||||||
have the same functionality as msdos86 (as the libc is all the same code), but
|
|
||||||
has been much less well tested.
|
|
||||||
|
|
||||||
The code runs in flat 32-bit mode, so normal 32-bit pointers work with no
|
|
||||||
worries about segmentation. It requires a DPMI host to run; it was tested with
|
|
||||||
CWSDPMI. It will _not_ automatically load the host --- you need to manually
|
|
||||||
install the DPMI hsot first.
|
|
||||||
|
|
||||||
IEEE floating point is available, but requires an FPU.
|
|
||||||
|
|
||||||
|
|
||||||
Example command line
|
|
||||||
====================
|
|
||||||
|
|
||||||
ack -mmsdos386 -O -o msdos386.exe examples/paranoia.c
|
|
||||||
|
|
||||||
|
|
||||||
David Given
|
|
||||||
dg@cowlark.com
|
|
||||||
|
|
|
@ -1,235 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
! Declare segments (the order is important).
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
.sect .rom
|
|
||||||
.sect .data
|
|
||||||
.sect .bss
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
|
|
||||||
|
|
||||||
! g 18b to break at the retf before coming here
|
|
||||||
begtext:
|
|
||||||
! On entry, the stub has cs and ds pointing at the 32-bit
|
|
||||||
! segment, but ss is still pointing at the 16-bit segment.
|
|
||||||
!
|
|
||||||
! ax: pmode code segment of stub
|
|
||||||
! bx: pmode data segment of stub
|
|
||||||
! cx: rmode segment of stub
|
|
||||||
! dx: pointer to realloc routine (in stub)
|
|
||||||
! si: pointer to interrupt routine (in stub)
|
|
||||||
! di: pointer to transfer buffer (in stub)
|
|
||||||
! bp: rmode PSP segment
|
|
||||||
|
|
||||||
! Resize the segment to include the BSS.
|
|
||||||
|
|
||||||
o16 mov (realloc_ptr+4), ax
|
|
||||||
mov (realloc_ptr+0), edx
|
|
||||||
o16 mov (pmode_cs), ax
|
|
||||||
o16 mov (pmode_ds), bx
|
|
||||||
o16 mov (rmode), cx
|
|
||||||
o16 mov (interrupt_ptr+4), ax
|
|
||||||
mov (interrupt_ptr+0), esi
|
|
||||||
o16 mov (transfer_buffer_ptr), di
|
|
||||||
|
|
||||||
mov eax, __end
|
|
||||||
callf (realloc_ptr)
|
|
||||||
|
|
||||||
! Clear BSS.
|
|
||||||
|
|
||||||
mov edi, begbss
|
|
||||||
mov ecx, endbss+3
|
|
||||||
sub ecx, edi
|
|
||||||
shr ecx, 2
|
|
||||||
xor eax, eax
|
|
||||||
cld
|
|
||||||
rep stos
|
|
||||||
|
|
||||||
! It's now safe to switch stacks.
|
|
||||||
|
|
||||||
cli
|
|
||||||
mov eax, ds
|
|
||||||
mov ss, eax
|
|
||||||
mov sp, .stack
|
|
||||||
sti
|
|
||||||
|
|
||||||
! Create a handle for low 1MB access.
|
|
||||||
|
|
||||||
o16 mov ax, 0x0000
|
|
||||||
o16 mov cx, 1
|
|
||||||
int 0x31 ! allocate LDT
|
|
||||||
o16 mov (.doshandle), ax
|
|
||||||
mov es, ax
|
|
||||||
xchg ebx, eax
|
|
||||||
|
|
||||||
xor ecx, ecx
|
|
||||||
xor edx, edx
|
|
||||||
o16 mov ax, 0x0007
|
|
||||||
int 0x31 ! set base address to 0
|
|
||||||
o16 dec dx
|
|
||||||
o16 mov cx, 0x000f
|
|
||||||
o16 mov ax, 0x0008
|
|
||||||
int 0x31 ! set limit to 1MB
|
|
||||||
|
|
||||||
mov cx, ds
|
|
||||||
and cx, 3
|
|
||||||
shl cx, 5
|
|
||||||
or cx, 0xc093 ! 32-bit, big, data, r/w, expand-up
|
|
||||||
mov ax, 0x0009
|
|
||||||
int 0x31 ! set descriptor access rights
|
|
||||||
|
|
||||||
! Locate the PSP.
|
|
||||||
|
|
||||||
movzx esi, bp
|
|
||||||
shl esi, 4 ! convert to linear address
|
|
||||||
|
|
||||||
! Copy the whole thing into 32-bit memory.
|
|
||||||
|
|
||||||
mov ecx, 0x100/4
|
|
||||||
mov edi, .psp
|
|
||||||
cld
|
|
||||||
1:
|
|
||||||
eseg lods
|
|
||||||
mov (edi), eax
|
|
||||||
add edi, 4
|
|
||||||
loop 1b
|
|
||||||
|
|
||||||
! Find the environment.
|
|
||||||
|
|
||||||
mov es, (.psp + 0x002C) ! converted to pmode segment
|
|
||||||
|
|
||||||
! Count the size of the environment variable block.
|
|
||||||
|
|
||||||
xorb al, al ! byte to test for
|
|
||||||
xor edi, edi
|
|
||||||
xor edx, edx
|
|
||||||
cld
|
|
||||||
mov ecx, -1
|
|
||||||
scasb
|
|
||||||
jz 2f ! empty environment
|
|
||||||
1:
|
|
||||||
repnz scasb
|
|
||||||
inc edx
|
|
||||||
scasb
|
|
||||||
jnz 1b
|
|
||||||
2:
|
|
||||||
add edi, 2 ! skip the mysterious word
|
|
||||||
repnz scasb ! program name
|
|
||||||
|
|
||||||
! Copy the whole environment block onto the stack.
|
|
||||||
|
|
||||||
mov esi, edi
|
|
||||||
add esi, 3
|
|
||||||
and esi, ~3 ! round up
|
|
||||||
jz empty_environment
|
|
||||||
mov ecx, esi
|
|
||||||
shr ecx, 2 ! number of dwords
|
|
||||||
std
|
|
||||||
sub esi, 4
|
|
||||||
1:
|
|
||||||
eseg lods
|
|
||||||
push eax
|
|
||||||
loop 1b
|
|
||||||
empty_environment:
|
|
||||||
mov ecx, esp ! environment data
|
|
||||||
|
|
||||||
! Reset DF and es properly.
|
|
||||||
|
|
||||||
cld
|
|
||||||
push ss
|
|
||||||
pop es
|
|
||||||
|
|
||||||
! Reserve space for argc and the argv and envp pointers on the
|
|
||||||
! stack. These will be passed to __m_a_i_n later.
|
|
||||||
|
|
||||||
sub esp, 3*4
|
|
||||||
mov eax, esp
|
|
||||||
|
|
||||||
! Build up argc, argv[], and envp[].
|
|
||||||
push eax ! output buffer for argc, argv, envp
|
|
||||||
push 3 ! MS-DOS version
|
|
||||||
push ecx ! env. string data
|
|
||||||
push edx ! count of env. vars.
|
|
||||||
push .psp+0x80 ! raw command line
|
|
||||||
call __sys_initmain
|
|
||||||
add esp, 5*4
|
|
||||||
|
|
||||||
! Bail out if something went wrong.
|
|
||||||
test eax, eax
|
|
||||||
jnz no_room
|
|
||||||
|
|
||||||
! argc, argv, and envp are now at the stack top. Now go.
|
|
||||||
call __m_a_i_n
|
|
||||||
add sp, 3*4
|
|
||||||
push ax
|
|
||||||
call _exit
|
|
||||||
|
|
||||||
no_room:
|
|
||||||
mov dx, no_room_msg
|
|
||||||
!call dos_msg
|
|
||||||
movb al, -1
|
|
||||||
jmp al_exit
|
|
||||||
|
|
||||||
! Exit.
|
|
||||||
.define __exit
|
|
||||||
.extern __exit
|
|
||||||
.define EXIT
|
|
||||||
.extern EXIT
|
|
||||||
__exit:
|
|
||||||
EXIT:
|
|
||||||
pop bx
|
|
||||||
pop ax
|
|
||||||
al_exit:
|
|
||||||
movb ah, 0x4c
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
! These must be in the code segment due to bootstrap issues.
|
|
||||||
realloc_ptr: .space 6 ! far
|
|
||||||
interrupt_ptr: .space 6 ! far
|
|
||||||
transfer_buffer_ptr: .space 2 ! near
|
|
||||||
rmode: .space 2
|
|
||||||
pmode_cs: .space 2
|
|
||||||
pmode_ds: .space 2
|
|
||||||
|
|
||||||
.define realloc_ptr
|
|
||||||
.define interrupt_ptr
|
|
||||||
.define rmode
|
|
||||||
.define pmode_cs
|
|
||||||
.define pmode_ds
|
|
||||||
.define transfer_buffer_ptr
|
|
||||||
|
|
||||||
! 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:
|
|
||||||
|
|
||||||
.sect .rom
|
|
||||||
|
|
||||||
! Some text messages.
|
|
||||||
bad_sys_msg: .ascii 'Bad DOS$'
|
|
||||||
no_room_msg: .ascii 'No room$'
|
|
||||||
|
|
||||||
! Some magic data. All EM systems need these.
|
|
||||||
|
|
||||||
.define .trppc, .ignmask, _errno
|
|
||||||
.comm .trppc, 4
|
|
||||||
.comm .ignmask, 4
|
|
||||||
.comm _errno, 4
|
|
||||||
|
|
||||||
.comm .doshandle, 2
|
|
||||||
.comm .psp, 256
|
|
||||||
|
|
||||||
.sect .bss
|
|
||||||
.space 32*1024
|
|
||||||
.stack:
|
|
||||||
|
|
||||||
! vim: ts=4 sw=4 et ft=asm
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
include("plat/build.lua")
|
|
||||||
|
|
||||||
ackfile {
|
|
||||||
name = "boot",
|
|
||||||
srcs = { "./boot.s" },
|
|
||||||
vars = { plat = "msdos386" }
|
|
||||||
}
|
|
||||||
|
|
||||||
ackfile {
|
|
||||||
name = "stub",
|
|
||||||
srcs = { "./stub.s" },
|
|
||||||
deps = { "plat/msdos386/libsys+headers" },
|
|
||||||
vars = { plat = "msdos386" }
|
|
||||||
}
|
|
||||||
|
|
||||||
normalrule {
|
|
||||||
name = "stub_aout",
|
|
||||||
ins = {
|
|
||||||
"util/led+led",
|
|
||||||
"+stub"
|
|
||||||
},
|
|
||||||
outleaves = { "stub.aout" },
|
|
||||||
commands = { "%{ins[1]} %{ins[2]} -o %{outs[1]}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
normalrule {
|
|
||||||
name = "stub_exe",
|
|
||||||
ins = {
|
|
||||||
"util/amisc+aslod",
|
|
||||||
"+stub_aout"
|
|
||||||
},
|
|
||||||
outleaves = { "stub.exe" },
|
|
||||||
commands = { "%{ins[1]} %{ins[2]} %{outs[1]}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
build_plat_libs {
|
|
||||||
name = "libs",
|
|
||||||
arch = "i386",
|
|
||||||
plat = "msdos386",
|
|
||||||
}
|
|
||||||
|
|
||||||
installable {
|
|
||||||
name = "pkg",
|
|
||||||
map = {
|
|
||||||
"+tools",
|
|
||||||
"+libs",
|
|
||||||
"./include+pkg",
|
|
||||||
["$(PLATIND)/msdos386/boot.o"] = "+boot",
|
|
||||||
["$(PLATIND)/msdos386/stub.exe"] = "+stub_exe",
|
|
||||||
["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
include("plat/build.lua")
|
|
||||||
|
|
||||||
build_as {
|
|
||||||
name = "as",
|
|
||||||
arch = "i386",
|
|
||||||
}
|
|
||||||
|
|
||||||
build_ncg {
|
|
||||||
name = "ncg",
|
|
||||||
arch = "i386",
|
|
||||||
}
|
|
||||||
|
|
||||||
return installable {
|
|
||||||
name = "tools",
|
|
||||||
map = {
|
|
||||||
["$(PLATDEP)/msdos386/as"] = "+as",
|
|
||||||
["$(PLATDEP)/msdos386/ncg"] = "+ncg",
|
|
||||||
["$(PLATIND)/descr/msdos386"] = "./descr",
|
|
||||||
"util/opt+pkg",
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
var w=4
|
|
||||||
var wa=2
|
|
||||||
var p=4
|
|
||||||
var pa=2
|
|
||||||
var s=2
|
|
||||||
var sa=2
|
|
||||||
var l=4
|
|
||||||
var la=2
|
|
||||||
var f=4
|
|
||||||
var fa=2
|
|
||||||
var d=8
|
|
||||||
var da=2
|
|
||||||
var x=8
|
|
||||||
var xa=2
|
|
||||||
var ARCH=i386
|
|
||||||
var PLATFORM=msdos386
|
|
||||||
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
|
|
||||||
var CPP_F=-D__MSDOS__ -D__DOS__ -D_DOS
|
|
||||||
var ALIGN=-a0:2 -a1:2 -a2:2 -a3:2
|
|
||||||
var MACHOPT_F=-m8
|
|
||||||
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
|
|
||||||
|
|
||||||
# Override the setting in fe so that files compiled for this platform can see
|
|
||||||
# the platform-specific headers.
|
|
||||||
|
|
||||||
var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi
|
|
||||||
|
|
||||||
name be
|
|
||||||
from .m.g
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/ack/{PLATFORM}/ncg
|
|
||||||
args <
|
|
||||||
stdout
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name as
|
|
||||||
from .s.so
|
|
||||||
to .o
|
|
||||||
program {EM}/lib/ack/{PLATFORM}/as
|
|
||||||
args - -o > <
|
|
||||||
prep cond
|
|
||||||
end
|
|
||||||
name led
|
|
||||||
from .o.a
|
|
||||||
to .out
|
|
||||||
program {EM}/lib/ack/em_led
|
|
||||||
mapflag -l* LNAME={PLATFORMDIR}/lib*
|
|
||||||
mapflag -fp FLOATS={EM}/{ILIB}fp
|
|
||||||
args {ALIGN} \
|
|
||||||
({RTS}:.b=-u _i_main) \
|
|
||||||
(.e:{HEAD}={PLATFORMDIR}/boot.o) \
|
|
||||||
({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \
|
|
||||||
({RTS}:.c={PLATFORMDIR}/c-ansi.o) \
|
|
||||||
({RTS}:.mod={PLATFORMDIR}/modula2.o) \
|
|
||||||
({RTS}:.p={PLATFORMDIR}/pascal.o) \
|
|
||||||
-o > < \
|
|
||||||
(.p:{TAIL}={PLATFORMDIR}/libpascal.a) \
|
|
||||||
(.b:{TAIL}={PLATFORMDIR}/libb.a) \
|
|
||||||
(.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \
|
|
||||||
(.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
|
|
||||||
(.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
|
|
||||||
(.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
|
|
||||||
{FLOATS?} \
|
|
||||||
(.e:{TAIL}={PLATFORMDIR}/libem.a \
|
|
||||||
{PLATFORMDIR}/libsys.a \
|
|
||||||
{PLATFORMDIR}/libc.a \
|
|
||||||
{PLATFORMDIR}/libem.a \
|
|
||||||
{PLATFORMDIR}/libend.a)
|
|
||||||
linker
|
|
||||||
end
|
|
||||||
name cv
|
|
||||||
from .out
|
|
||||||
to .exe
|
|
||||||
program {EM}/bin/aslod
|
|
||||||
args -p {PLATFORMDIR}/stub.exe < >
|
|
||||||
outfile msdos386.exe
|
|
||||||
end
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef _ACK_PLAT_H
|
|
||||||
#define _ACK_PLAT_H
|
|
||||||
|
|
||||||
#define ACKCONF_WANT_O_TEXT_O_BINARY 1
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,24 +0,0 @@
|
||||||
include("plat/build.lua")
|
|
||||||
|
|
||||||
headermap = {}
|
|
||||||
packagemap = {}
|
|
||||||
|
|
||||||
local function addheader(h)
|
|
||||||
headermap[h] = "./"..h
|
|
||||||
packagemap["$(PLATIND)/msdos386/include/"..h] = "./"..h
|
|
||||||
end
|
|
||||||
|
|
||||||
addheader("ack/plat.h")
|
|
||||||
addheader("sys/types.h")
|
|
||||||
|
|
||||||
acklibrary {
|
|
||||||
name = "headers",
|
|
||||||
hdrs = headermap
|
|
||||||
}
|
|
||||||
|
|
||||||
installable {
|
|
||||||
name = "pkg",
|
|
||||||
map = packagemap
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#ifndef _SYS_TYPES_H
|
|
||||||
#define _SYS_TYPES_H
|
|
||||||
|
|
||||||
typedef long pid_t;
|
|
||||||
typedef int mode_t;
|
|
||||||
typedef long time_t;
|
|
||||||
typedef long suseconds_t;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,14 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
.sect .bss
|
|
||||||
|
|
||||||
! This data block is used to store information about the current line number
|
|
||||||
! and file.
|
|
||||||
|
|
||||||
.define hol0
|
|
||||||
.comm hol0, 8
|
|
|
@ -1,16 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
.define _brk
|
|
||||||
_brk:
|
|
||||||
mov ebx, esp
|
|
||||||
mov eax, 1*4(ebx)
|
|
||||||
callf (realloc_ptr)
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
bundle {
|
|
||||||
name = "headers",
|
|
||||||
srcs = {
|
|
||||||
"./libsysasm.h"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acklibrary {
|
|
||||||
name = "lib",
|
|
||||||
srcs = {
|
|
||||||
"./_hol0.s",
|
|
||||||
"./brk.s",
|
|
||||||
"./close.s",
|
|
||||||
"./errno.s",
|
|
||||||
"./getpid.s",
|
|
||||||
"./isatty.s",
|
|
||||||
"./rename.s",
|
|
||||||
"./sbrk.c",
|
|
||||||
"./sys_cpyin.s",
|
|
||||||
"./sys_cpyout.s",
|
|
||||||
"./sys_dpmidos.s",
|
|
||||||
"./sys_exists.s",
|
|
||||||
"./sys_getdate.s",
|
|
||||||
"./sys_gettime.s",
|
|
||||||
"./sys_isopen.s",
|
|
||||||
"./sys_isreadyr.s",
|
|
||||||
"./sys_rawcreat.s",
|
|
||||||
"./sys_rawlseek.s",
|
|
||||||
"./sys_rawopen.s",
|
|
||||||
"./sys_rawread.s",
|
|
||||||
"./sys_rawwrite.s",
|
|
||||||
"./sys_scpyout.s",
|
|
||||||
"./sys_xret.s",
|
|
||||||
"./unlink.s",
|
|
||||||
"plat/msdos/libsys+srcs",
|
|
||||||
},
|
|
||||||
deps = {
|
|
||||||
"plat/msdos/libsys+headers",
|
|
||||||
"+headers"
|
|
||||||
},
|
|
||||||
vars = {
|
|
||||||
plat = "msdos386"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Close a file.
|
|
||||||
|
|
||||||
.define _close
|
|
||||||
_close:
|
|
||||||
mov ebx, esp
|
|
||||||
mov ebx, 1*4(esp)
|
|
||||||
movb ah, 0x3E
|
|
||||||
int 0x21
|
|
||||||
jmp .sys_zret
|
|
|
@ -1,23 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
! Copyright (c) 2021--2022 TK Chia
|
|
||||||
!
|
|
||||||
! The authors hereby grant permission to use, copy, modify, distribute,
|
|
||||||
! and license this software and its documentation for any purpose, provided
|
|
||||||
! that existing copyright notices are retained in all copies and that this
|
|
||||||
! notice is included verbatim in any distributions. No written agreement,
|
|
||||||
! license, or royalty fee is required for any of the authorized uses.
|
|
||||||
! Modifications to this software may be copyrighted by their authors
|
|
||||||
! and need not follow the licensing terms described here, provided that
|
|
||||||
! the new terms are clearly indicated on the first page of each file where
|
|
||||||
! they apply.
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Get the current process identifier. For MS-DOS, use the Program Segment
|
|
||||||
! Prefix (PSP) segment as the PID, unless the system supports an actual
|
|
||||||
! `getpid' syscall, e.g. European MS-DOS 4.0.
|
|
||||||
!
|
|
||||||
! (Note that pid_t is a 32-bit type. This is to allow for PSP segments and
|
|
||||||
! MS-DOS PIDs above 0x7FFF.)
|
|
||||||
|
|
||||||
.define _getpid
|
|
||||||
_getpid:
|
|
||||||
movb ah, 0x87
|
|
||||||
stc
|
|
||||||
int 0x21
|
|
||||||
jnc .eur_dos
|
|
||||||
movb ah, 0x51
|
|
||||||
mov ebx, 0x210000
|
|
||||||
callf (interrupt_ptr)
|
|
||||||
xchg ebx, eax
|
|
||||||
.eur_dos:
|
|
||||||
movzx eax, ax
|
|
||||||
ret
|
|
|
@ -1,30 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Say whether a given file descriptor number refers to a terminal.
|
|
||||||
|
|
||||||
.define _isatty
|
|
||||||
_isatty:
|
|
||||||
mov ebx, esp
|
|
||||||
mov ebx, 4(ebx)
|
|
||||||
o16 mov ax, 0x4400
|
|
||||||
int 0x21
|
|
||||||
jc error
|
|
||||||
testb dl, dl
|
|
||||||
jz not_tty
|
|
||||||
mov eax, 1
|
|
||||||
ret
|
|
||||||
not_tty:
|
|
||||||
mov (_errno), 25 ! ENOTTY
|
|
||||||
not_tty_2:
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
error:
|
|
||||||
push eax
|
|
||||||
call __sys_seterrno
|
|
||||||
pop ecx
|
|
||||||
jmp not_tty_2
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* © 2013 David Given
|
|
||||||
* © 2022 TK Chia
|
|
||||||
* This file is redistributable under the terms of the 3-clause BSD license.
|
|
||||||
* See the file 'Copying' in the root of the distribution for the full text.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBSYSASM_H
|
|
||||||
#define LIBSYSASM_H
|
|
||||||
|
|
||||||
! Declare segments (the order is important).
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
.sect .rom
|
|
||||||
.sect .data
|
|
||||||
.sect .bss
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
|
|
||||||
! Size of transfer buffer, for 32-bit DPMI mode.
|
|
||||||
|
|
||||||
TRANSFER_BUFFER_SIZE = 32 * 1024
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,42 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Rename a file.
|
|
||||||
|
|
||||||
.define _rename
|
|
||||||
_rename:
|
|
||||||
push edi
|
|
||||||
|
|
||||||
! Destination filename.
|
|
||||||
|
|
||||||
mov eax, 4+8(esp)
|
|
||||||
#define DEST_NAME_OFFSET (TRANSFER_BUFFER_SIZE / 2)
|
|
||||||
mov edx, DEST_NAME_OFFSET
|
|
||||||
mov ecx, edx
|
|
||||||
call .sys_sncpyout
|
|
||||||
jc 9f
|
|
||||||
xchg edi, eax
|
|
||||||
|
|
||||||
! Source filename.
|
|
||||||
|
|
||||||
mov eax, 4+4(esp)
|
|
||||||
xor edx, edx
|
|
||||||
call .sys_sncpyout
|
|
||||||
jc 9f
|
|
||||||
xchg edx, eax
|
|
||||||
|
|
||||||
! Make the DOS call.
|
|
||||||
|
|
||||||
movb ah, 0x56
|
|
||||||
call .sys_dpmidos
|
|
||||||
|
|
||||||
pop edi
|
|
||||||
jmp .sys_zret
|
|
||||||
|
|
||||||
9:
|
|
||||||
pop edi
|
|
||||||
jmp .sys_toolongret
|
|
|
@ -1,40 +0,0 @@
|
||||||
/* $Source$
|
|
||||||
* $State$
|
|
||||||
* $Revision$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "libsys.h"
|
|
||||||
|
|
||||||
extern char _end[1];
|
|
||||||
static char* current = _end;
|
|
||||||
|
|
||||||
void* sbrk(int increment)
|
|
||||||
{
|
|
||||||
char* old;
|
|
||||||
char* new;
|
|
||||||
|
|
||||||
if (increment == 0)
|
|
||||||
return current;
|
|
||||||
|
|
||||||
old = current;
|
|
||||||
|
|
||||||
new = old + increment;
|
|
||||||
|
|
||||||
if ((increment > 0) && (new <= old))
|
|
||||||
goto out_of_memory;
|
|
||||||
else if ((increment < 0) && (new >= old))
|
|
||||||
goto out_of_memory;
|
|
||||||
|
|
||||||
if (brk(new) < 0)
|
|
||||||
goto out_of_memory;
|
|
||||||
|
|
||||||
current = new;
|
|
||||||
return old;
|
|
||||||
|
|
||||||
out_of_memory:
|
|
||||||
errno = ENOMEM;
|
|
||||||
return OUT_OF_MEMORY;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! .sys_cpyin: copy ecx bytes from the transfer buffer to es:eax (= ds:eax).
|
|
||||||
! Preserve all registers, except the flags.
|
|
||||||
|
|
||||||
.extern .sys_cpyin
|
|
||||||
.sys_cpyin:
|
|
||||||
push eax
|
|
||||||
push ecx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
movzx esi, (transfer_buffer_ptr)
|
|
||||||
xchg edi, eax
|
|
||||||
mov ds, (pmode_ds)
|
|
||||||
mov eax, ecx
|
|
||||||
shr ecx, 2
|
|
||||||
rep movs
|
|
||||||
andb al, 3
|
|
||||||
movb cl, al
|
|
||||||
rep movsb
|
|
||||||
mov eax, ss
|
|
||||||
mov ds, eax
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ecx
|
|
||||||
pop eax
|
|
||||||
ret
|
|
|
@ -1,34 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! .sys_cpyout: copy ecx bytes starting from ds:eax to the transfer
|
|
||||||
! buffer. Return eax := offset of transfer buffer in the real mode data
|
|
||||||
! segment. Preserve all other registers, except the flags.
|
|
||||||
|
|
||||||
.extern .sys_cpyout
|
|
||||||
.sys_cpyout:
|
|
||||||
push ecx
|
|
||||||
push edx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
xchg esi, eax
|
|
||||||
movzx edi, (transfer_buffer_ptr)
|
|
||||||
mov eax, edi
|
|
||||||
mov es, (pmode_ds)
|
|
||||||
mov edx, ecx
|
|
||||||
shr ecx, 2
|
|
||||||
rep movs
|
|
||||||
movb cl, dl
|
|
||||||
andb cl, 3
|
|
||||||
rep movsb
|
|
||||||
mov ecx, ss
|
|
||||||
mov es, ecx
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop edx
|
|
||||||
pop ecx
|
|
||||||
ret
|
|
|
@ -1,16 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! .sys_dpmidos: simulate a call to real-mode int 0x21 with the current
|
|
||||||
! 16-bit register values.
|
|
||||||
|
|
||||||
.extern .sys_dpmidos
|
|
||||||
.sys_dpmidos:
|
|
||||||
movzx ebx, bx
|
|
||||||
or ebx, 0x210000
|
|
||||||
callf (interrupt_ptr)
|
|
||||||
ret
|
|
|
@ -1,21 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Say whether a file exists with the given name.
|
|
||||||
|
|
||||||
.define __sys_exists
|
|
||||||
__sys_exists:
|
|
||||||
mov eax, 4(esp)
|
|
||||||
call .sys_scpyout
|
|
||||||
jc 9f
|
|
||||||
xchg edx, eax
|
|
||||||
mov eax, 0x4300
|
|
||||||
call .sys_dpmidos
|
|
||||||
9:
|
|
||||||
sbb eax, eax
|
|
||||||
inc eax
|
|
||||||
ret
|
|
|
@ -1,18 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Get the current system date from MS-DOS.
|
|
||||||
|
|
||||||
.define __sys_getdate
|
|
||||||
__sys_getdate:
|
|
||||||
movb ah, 0x2a
|
|
||||||
int 0x21
|
|
||||||
mov ebx, esp
|
|
||||||
mov ebx, 4(ebx)
|
|
||||||
o16 mov 0(ebx), dx
|
|
||||||
o16 mov 2(ebx), cx
|
|
||||||
ret
|
|
|
@ -1,18 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Get the current system time from MS-DOS.
|
|
||||||
|
|
||||||
.define __sys_gettime
|
|
||||||
__sys_gettime:
|
|
||||||
movb ah, 0x2c
|
|
||||||
int 0x21
|
|
||||||
mov ebx, esp
|
|
||||||
mov ebx, 4(ebx)
|
|
||||||
o16 mov 0(ebx), cx
|
|
||||||
o16 mov 2(ebx), dx
|
|
||||||
ret
|
|
|
@ -1,18 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Say whether a given file descriptor number refers to a valid open file
|
|
||||||
! descriptor.
|
|
||||||
|
|
||||||
.define __sys_isopen
|
|
||||||
__sys_isopen:
|
|
||||||
mov ebx, 4(esp)
|
|
||||||
mov eax, 0x4400
|
|
||||||
int 0x21
|
|
||||||
sbb eax, eax
|
|
||||||
inc eax
|
|
||||||
ret
|
|
|
@ -1,22 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Say whether a file descriptor is ready for input, i.e. reading from the
|
|
||||||
! fd will immediately return something.
|
|
||||||
|
|
||||||
.define __sys_isreadyr
|
|
||||||
__sys_isreadyr:
|
|
||||||
mov ebx, esp
|
|
||||||
mov eax, 0x4406
|
|
||||||
mov ebx, 4(ebx)
|
|
||||||
int 0x21
|
|
||||||
jnc ok
|
|
||||||
movb al, 0
|
|
||||||
ok:
|
|
||||||
o16 cbw
|
|
||||||
cwde
|
|
||||||
ret
|
|
|
@ -1,28 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Create or truncate a file.
|
|
||||||
|
|
||||||
.define __sys_rawcreat
|
|
||||||
__sys_rawcreat:
|
|
||||||
! Copy filename to transfer buffer.
|
|
||||||
|
|
||||||
mov eax, 4(esp)
|
|
||||||
call .sys_scpyout
|
|
||||||
jc 9f
|
|
||||||
|
|
||||||
! Make the DOS call.
|
|
||||||
|
|
||||||
xchg edx, eax
|
|
||||||
movb ah, 0x3c
|
|
||||||
movb al, 8(esp)
|
|
||||||
call .sys_dpmidos
|
|
||||||
|
|
||||||
jmp .sys_axret
|
|
||||||
|
|
||||||
9:
|
|
||||||
jmp .sys_toolongret
|
|
|
@ -1,20 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Move the current file position for a file descriptor.
|
|
||||||
|
|
||||||
.define __sys_rawlseek
|
|
||||||
__sys_rawlseek:
|
|
||||||
movb ah, 0x42
|
|
||||||
mov ebx, esp
|
|
||||||
mov edx, 8(ebx)
|
|
||||||
mov ecx, edx
|
|
||||||
shr ecx, 16
|
|
||||||
movb al, 12(ebx)
|
|
||||||
mov ebx, 4(ebx)
|
|
||||||
int 0x21
|
|
||||||
jmp .sys_dxaxret
|
|
|
@ -1,24 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Open an existing file.
|
|
||||||
|
|
||||||
.define __sys_rawopen
|
|
||||||
__sys_rawopen:
|
|
||||||
! Copy filename to transfer buffer.
|
|
||||||
|
|
||||||
mov eax, 4(esp)
|
|
||||||
call .sys_scpyout
|
|
||||||
|
|
||||||
! Make the DOS call.
|
|
||||||
|
|
||||||
xchg edx, eax
|
|
||||||
movb ah, 0x3d
|
|
||||||
movb al, 8(esp)
|
|
||||||
call .sys_dpmidos
|
|
||||||
|
|
||||||
jmp .sys_axret
|
|
|
@ -1,50 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Read bytes from a file descriptor. These routines do not do any
|
|
||||||
! translation between CRLF and LF line endings.
|
|
||||||
!
|
|
||||||
! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate
|
|
||||||
! (or extend) the file to the current file position.
|
|
||||||
|
|
||||||
.define __sys_rawread
|
|
||||||
__sys_rawread:
|
|
||||||
file_handle = 1*4
|
|
||||||
write_buffer = 2*4
|
|
||||||
amount_to_read = 3*4
|
|
||||||
|
|
||||||
mov eax, amount_to_read(esp)
|
|
||||||
mov ecx, TRANSFER_BUFFER_SIZE
|
|
||||||
cmp eax, ecx
|
|
||||||
jge 2f
|
|
||||||
mov ecx, eax
|
|
||||||
2:
|
|
||||||
|
|
||||||
! Read from DOS into the transfer buffer.
|
|
||||||
|
|
||||||
movb ah, 0x3f
|
|
||||||
o16 mov dx, (transfer_buffer_ptr)
|
|
||||||
o16 mov bx, file_handle(esp)
|
|
||||||
call .sys_dpmidos
|
|
||||||
jc 3f
|
|
||||||
|
|
||||||
! Copy eax bytes out of the transfer buffer.
|
|
||||||
|
|
||||||
movzx ecx, ax
|
|
||||||
mov eax, write_buffer(esp)
|
|
||||||
call .sys_cpyin
|
|
||||||
|
|
||||||
xchg eax, ecx
|
|
||||||
ret
|
|
||||||
|
|
||||||
3:
|
|
||||||
! Process errors.
|
|
||||||
|
|
||||||
push eax
|
|
||||||
call __sys_seterrno
|
|
||||||
pop ecx
|
|
||||||
ret
|
|
|
@ -1,48 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Write bytes to/to a file descriptor. These routines do not do any
|
|
||||||
! translation between CRLF and LF line endings.
|
|
||||||
!
|
|
||||||
! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate
|
|
||||||
! (or extend) the file to the current file position.
|
|
||||||
|
|
||||||
.define __sys_rawwrite
|
|
||||||
__sys_rawwrite:
|
|
||||||
file_handle = 1*4
|
|
||||||
read_buffer = 2*4
|
|
||||||
amount_to_write = 3*4
|
|
||||||
|
|
||||||
mov eax, amount_to_write(esp)
|
|
||||||
mov ecx, TRANSFER_BUFFER_SIZE
|
|
||||||
cmp eax, ecx
|
|
||||||
jge 2f
|
|
||||||
mov ecx, eax
|
|
||||||
2:
|
|
||||||
|
|
||||||
! Copy ecx bytes into the transfer buffer.
|
|
||||||
|
|
||||||
mov eax, read_buffer(esp)
|
|
||||||
call .sys_cpyout
|
|
||||||
|
|
||||||
! Write from the transfer buffer to DOS.
|
|
||||||
|
|
||||||
xchg edx, eax
|
|
||||||
movb ah, 0x40
|
|
||||||
o16 mov bx, file_handle(esp)
|
|
||||||
call .sys_dpmidos
|
|
||||||
movzx eax, ax
|
|
||||||
jnc exit
|
|
||||||
|
|
||||||
push eax
|
|
||||||
call __sys_seterrno
|
|
||||||
pop ecx
|
|
||||||
exit:
|
|
||||||
ret
|
|
||||||
|
|
||||||
! vim: sw=4 ts=4 et
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! .sys_scpyout: copy the ASCIIZ string starting from ds:eax to the
|
|
||||||
! transfer buffer. The resulting ASCIIZ string, including the final null,
|
|
||||||
! should fit into the entire transfer buffer. Return eax := offset of
|
|
||||||
! transfer buffer in real mode data segment. Return CF = 1 if and only if
|
|
||||||
! the ASCIIZ string is too long to fit. Preserve all other registers,
|
|
||||||
! except the flags.
|
|
||||||
!
|
|
||||||
! .sys_sncpyout: copy the ASCIIZ string starting from ds:eax to offset
|
|
||||||
! edx into the transfer buffer. The resulting ASCIIZ string should occupy
|
|
||||||
! at most ecx bytes, including the final null. Return eax : offset of
|
|
||||||
! string in real mode data segment. Return CF = 1 if and only if the ASCIIZ
|
|
||||||
! string is too long to fit. Preserve all other registers, except the
|
|
||||||
! flags.
|
|
||||||
|
|
||||||
.extern .sys_scpyout
|
|
||||||
.extern .sys_sncpyout
|
|
||||||
.sys_scpyout:
|
|
||||||
push ecx
|
|
||||||
push edx
|
|
||||||
mov ecx, TRANSFER_BUFFER_SIZE
|
|
||||||
xor edx, edx
|
|
||||||
jmp .cont
|
|
||||||
.sys_sncpyout:
|
|
||||||
push ecx
|
|
||||||
push edx
|
|
||||||
.cont:
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
mov esi, eax
|
|
||||||
movzx edi, (transfer_buffer_ptr)
|
|
||||||
add edi, edx
|
|
||||||
mov edx, edi
|
|
||||||
mov es, (pmode_ds)
|
|
||||||
jcxz .error
|
|
||||||
.loop:
|
|
||||||
lodsb
|
|
||||||
stosb
|
|
||||||
testb al, al
|
|
||||||
loopnz .loop
|
|
||||||
jz .ok
|
|
||||||
.error:
|
|
||||||
stc
|
|
||||||
.ok:
|
|
||||||
xchg edx, eax
|
|
||||||
mov edx, ss
|
|
||||||
mov es, edx
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop edx
|
|
||||||
pop ecx
|
|
||||||
ret
|
|
|
@ -1,54 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! .sys_zret: if the carry flag is set, then set `errno' from the DOS error
|
|
||||||
! code in ax, and return an int -1. If the carry flag is clear, just
|
|
||||||
! return an int zero.
|
|
||||||
!
|
|
||||||
! .sys_axret: if the carry flag is set, then set `errno' from the DOS error
|
|
||||||
! code in ax, and return a shortword -1. If the carry flag is clear, just
|
|
||||||
! return eax := ax as a return value.
|
|
||||||
!
|
|
||||||
! .sys_dxaxret: same as .sys_axret, but return -1 or eax := dx:ax as a
|
|
||||||
! return value.
|
|
||||||
!
|
|
||||||
! .sys_toolongret: a file name is too long: set `errno' to E2BIG, and return
|
|
||||||
! -1.
|
|
||||||
|
|
||||||
.extern .sys_zret
|
|
||||||
.extern .sys_axret
|
|
||||||
.extern .sys_dxaxret
|
|
||||||
.extern .sys_toolongret
|
|
||||||
.sys_zret:
|
|
||||||
jc error
|
|
||||||
xor eax, eax
|
|
||||||
no_error:
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sys_axret:
|
|
||||||
jc error
|
|
||||||
movzx eax, ax
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sys_dxaxret:
|
|
||||||
jc error
|
|
||||||
shl edx, 16
|
|
||||||
o16 mov dx, ax
|
|
||||||
mov eax, edx
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sys_toolongret:
|
|
||||||
mov (_errno), 7 ! E2BIG
|
|
||||||
or eax, -1
|
|
||||||
ret
|
|
||||||
|
|
||||||
error:
|
|
||||||
movzx eax, ax
|
|
||||||
push eax
|
|
||||||
call __sys_seterrno
|
|
||||||
pop ecx
|
|
||||||
ret
|
|
|
@ -1,23 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
! Remove a file.
|
|
||||||
|
|
||||||
.define _unlink
|
|
||||||
_unlink:
|
|
||||||
! Copy filename to transfer buffer.
|
|
||||||
|
|
||||||
mov eax, 4(esp)
|
|
||||||
call .sys_scpyout
|
|
||||||
|
|
||||||
! Make the DOS call.
|
|
||||||
|
|
||||||
xchg edx, eax
|
|
||||||
movb ah, 0x41
|
|
||||||
call .sys_dpmidos
|
|
||||||
|
|
||||||
jmp .sys_zret
|
|
|
@ -1,414 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
#include "libsysasm.h"
|
|
||||||
|
|
||||||
.use16
|
|
||||||
exe_header:
|
|
||||||
.data2 0x5a4d ! magic number
|
|
||||||
.data2 exe_last_page ! number of bytes in last loadable page
|
|
||||||
.data2 exe_text_pages ! size of .exe, in pages
|
|
||||||
.data2 0 ! number of relocation entries
|
|
||||||
.data2 0 ! start of loadable area, in 16-byte paragraphs
|
|
||||||
.data2 exe_ram_paras ! required RAM size, in 16-byte paragraphs
|
|
||||||
.data2 exe_ram_paras ! maximum RAM siz, in 16-byte paragraphs
|
|
||||||
.data2 0 ! initial SS, relative to program
|
|
||||||
.data2 stack ! initial SP
|
|
||||||
.data2 0 ! checksum (ignored)
|
|
||||||
.data2 exe_start ! initial IP
|
|
||||||
.data2 0 ! initial CS, relative to program
|
|
||||||
.data2 0 ! offset of relocation table
|
|
||||||
.data2 0 ! overlay number
|
|
||||||
|
|
||||||
exe_start:
|
|
||||||
! On entry, DS=ES=PSP. Make DS=CS, so we're running in tiny mode.
|
|
||||||
|
|
||||||
push cs
|
|
||||||
pop ds
|
|
||||||
mov (rseg), ds
|
|
||||||
mov (pspseg), es
|
|
||||||
|
|
||||||
! Ensure that at least two handles are available by blindly closing some.
|
|
||||||
|
|
||||||
mov bx, 19 ! close handle
|
|
||||||
movb ah, 0x3e
|
|
||||||
int 0x21
|
|
||||||
mov bx, 18 ! close handle
|
|
||||||
movb ah, 0x3e
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
! Scan the environment to find the program name.
|
|
||||||
|
|
||||||
eseg mov es, (0x2c) ! environment pointer segment from PSP
|
|
||||||
xor di, di
|
|
||||||
xorb al, al
|
|
||||||
mov cx, 0xffff
|
|
||||||
cld
|
|
||||||
1:
|
|
||||||
repne scasb ! find end of next string
|
|
||||||
eseg cmpb (di), 0
|
|
||||||
jnz 1b
|
|
||||||
2:
|
|
||||||
add di, 3
|
|
||||||
mov si, di
|
|
||||||
repne scasb
|
|
||||||
|
|
||||||
! es:si now points at the program name, and es:di at one past the end.
|
|
||||||
|
|
||||||
mov cx, di
|
|
||||||
sub cx, si
|
|
||||||
sub sp, cx ! allocate space on stack
|
|
||||||
mov di, sp ! es:si source, ds:di dest
|
|
||||||
1:
|
|
||||||
eseg movb al, (si)
|
|
||||||
inc si
|
|
||||||
movb (di), al
|
|
||||||
inc di
|
|
||||||
cmpb al, 0
|
|
||||||
jnz 1b
|
|
||||||
|
|
||||||
! Open the file. (0x5f)
|
|
||||||
|
|
||||||
mov dx, sp
|
|
||||||
mov ax, 0x3d00
|
|
||||||
int 0x21
|
|
||||||
jc no_file
|
|
||||||
mov (fh), ax
|
|
||||||
add sp, cx ! don't need filename any more
|
|
||||||
|
|
||||||
! Get the file length (== text len).
|
|
||||||
|
|
||||||
mov bx, ax
|
|
||||||
mov ax, 0x4202
|
|
||||||
xor cx, cx ! high offset
|
|
||||||
xor dx, dx ! low offset
|
|
||||||
int 0x21 ! lseek
|
|
||||||
mov (pmemlen+0), ax
|
|
||||||
mov (pmemlen+2), dx
|
|
||||||
|
|
||||||
! Initialise DPMI.
|
|
||||||
|
|
||||||
mov ax, 0x1687
|
|
||||||
int 0x2f
|
|
||||||
or ax, ax
|
|
||||||
jnz no_dpmi
|
|
||||||
mov (pmode_switch+0), di ! write back PMODE switch routine
|
|
||||||
mov (pmode_switch+2), es
|
|
||||||
or si, si ! do we need a DPMI private area?
|
|
||||||
jz 1f
|
|
||||||
|
|
||||||
mov bx, si
|
|
||||||
movb ah, 0x48
|
|
||||||
int 0x21 ! allocate memory from DOS
|
|
||||||
mov es, ax ! data area segment -> es
|
|
||||||
1:
|
|
||||||
! Switch to protected mode.
|
|
||||||
|
|
||||||
mov ax, 1 ! 32-bit app
|
|
||||||
callf (pmode_switch)
|
|
||||||
jc bad_dpmi
|
|
||||||
|
|
||||||
! We're now in protected mode.
|
|
||||||
|
|
||||||
mov (psegcs), cs
|
|
||||||
mov (psegds), ds
|
|
||||||
|
|
||||||
! Allocate space for the code segment.
|
|
||||||
|
|
||||||
mov ax, 0x0000
|
|
||||||
mov cx, 1
|
|
||||||
int 0x31 ! allocate LDT
|
|
||||||
jc bad_dpmi
|
|
||||||
mov fs, ax
|
|
||||||
mov (psegcs32), ax
|
|
||||||
|
|
||||||
mov cx, (pmemlen+0)
|
|
||||||
mov bx, (pmemlen+2)
|
|
||||||
mov ax, 0x0501
|
|
||||||
int 0x31 ! allocate linear address
|
|
||||||
jc bad_dpmi
|
|
||||||
mov (pmemhandle+0), di
|
|
||||||
mov (pmemhandle+2), si
|
|
||||||
|
|
||||||
mov dx, cx
|
|
||||||
mov cx, bx
|
|
||||||
mov bx, fs
|
|
||||||
mov ax, 0x0007
|
|
||||||
int 0x31 ! set segment base address
|
|
||||||
jc bad_dpmi
|
|
||||||
|
|
||||||
mov bx, fs
|
|
||||||
mov dx, (pmemlen+0)
|
|
||||||
mov cx, (pmemlen+2)
|
|
||||||
sub dx, 1
|
|
||||||
sbb cx, 0
|
|
||||||
mov ax, 0x0008
|
|
||||||
int 0x31 ! set segment limit
|
|
||||||
|
|
||||||
mov cx, cs
|
|
||||||
and cx, 3
|
|
||||||
shl cx, 5
|
|
||||||
or cx, 0xc09b ! 32-bit, big, code, non-conforming, readable
|
|
||||||
mov bx, fs
|
|
||||||
mov ax, 0x0009
|
|
||||||
int 0x31 ! set descriptor access rights
|
|
||||||
|
|
||||||
! Allocate the data segment (as a simple clone of the code segment). (10e)
|
|
||||||
|
|
||||||
mov ax, 0x000a
|
|
||||||
mov bx, fs
|
|
||||||
int 0x31
|
|
||||||
mov es, ax
|
|
||||||
mov (psegds32), ax
|
|
||||||
|
|
||||||
mov cx, ax
|
|
||||||
and cx, 3
|
|
||||||
shl cx, 5
|
|
||||||
or cx, 0xc093 ! 32-bit, big, data, r/w, expand-up
|
|
||||||
mov bx, es
|
|
||||||
mov ax, 0x0009
|
|
||||||
int 0x31 ! set descriptor access rights
|
|
||||||
|
|
||||||
! Load the program.
|
|
||||||
|
|
||||||
mov bx, (fh)
|
|
||||||
mov ax, 0x4200
|
|
||||||
xor cx, cx ! high offset
|
|
||||||
mov dx, text_top ! low offset
|
|
||||||
int 0x21 ! lseek
|
|
||||||
|
|
||||||
o32 xor edi, edi ! destination 32-bit register
|
|
||||||
1:
|
|
||||||
movb ah, 0x3f
|
|
||||||
mov bx, (fh)
|
|
||||||
mov cx, TRANSFER_BUFFER_SIZE
|
|
||||||
mov dx, transfer_buffer
|
|
||||||
o32 push edi
|
|
||||||
call int21 ! read up to 32kB into transfer buffer
|
|
||||||
o32 pop edi
|
|
||||||
cmp ax, 0
|
|
||||||
je 2f
|
|
||||||
|
|
||||||
o32 movzx ecx, ax ! number of bytes read
|
|
||||||
o32 mov esi, transfer_buffer
|
|
||||||
cld
|
|
||||||
rep a32 movsb
|
|
||||||
jmp 1b
|
|
||||||
2:
|
|
||||||
|
|
||||||
! Close the file.
|
|
||||||
|
|
||||||
movb ah, 0x3e
|
|
||||||
mov bx, (fh)
|
|
||||||
int 0x21 ! close
|
|
||||||
|
|
||||||
! Jump to the new segment and enter 32-bit mode!
|
|
||||||
|
|
||||||
o32 movzx eax, (psegcs)
|
|
||||||
o32 movzx ebx, (psegds)
|
|
||||||
o32 movzx ecx, (rseg)
|
|
||||||
o32 mov edx, realloc
|
|
||||||
o32 mov esi, interruptf
|
|
||||||
o32 mov edi, transfer_buffer
|
|
||||||
o32 movzx ebp, (pspseg)
|
|
||||||
push es
|
|
||||||
pop ds
|
|
||||||
push fs
|
|
||||||
push 0
|
|
||||||
retf ! 19b
|
|
||||||
|
|
||||||
! Helper routine which reallocates the linear block that the 32-bit code
|
|
||||||
! is running from. This can't happen from inside the 32-bit code itself
|
|
||||||
! because it might move.
|
|
||||||
!
|
|
||||||
! On entry, ds and ss are ignored. On exit, ds and es are set to the
|
|
||||||
! 32-bit segment.
|
|
||||||
! eax: new block size
|
|
||||||
realloc:
|
|
||||||
cseg mov ds, (psegds)
|
|
||||||
cli ! atomically switch stacks
|
|
||||||
o32 mov (dpmi_ebp), esp ! yes, saving esp into the ebp field
|
|
||||||
mov (dpmi_ss), ss
|
|
||||||
mov ss, (psegds)
|
|
||||||
mov sp, dosstack
|
|
||||||
sti
|
|
||||||
pusha
|
|
||||||
|
|
||||||
o32 add eax, 1024*1024 - 1
|
|
||||||
o32 and eax, ~[1024*1024 - 1]
|
|
||||||
o32 mov (pmemlen), eax
|
|
||||||
mov cx, (pmemlen+0)
|
|
||||||
mov bx, (pmemlen+2)
|
|
||||||
mov di, (pmemhandle+0)
|
|
||||||
mov si, (pmemhandle+2)
|
|
||||||
mov ax, 0x0503
|
|
||||||
int 0x31 ! resize memory block
|
|
||||||
jc bad_dpmi
|
|
||||||
mov (pmemhandle+0), di
|
|
||||||
mov (pmemhandle+2), si
|
|
||||||
mov (pmemaddr+0), cx
|
|
||||||
mov (pmemaddr+2), bx
|
|
||||||
|
|
||||||
mov bx, (psegcs32)
|
|
||||||
mov dx, (pmemaddr+0)
|
|
||||||
mov cx, (pmemaddr+2)
|
|
||||||
mov ax, 0x0007
|
|
||||||
int 0x31 ! set cs linear address
|
|
||||||
jc bad_dpmi
|
|
||||||
mov bx, (psegds32)
|
|
||||||
int 0x31 ! set ds linear address
|
|
||||||
jc bad_dpmi
|
|
||||||
mov dx, (pmemlen+0)
|
|
||||||
mov cx, (pmemlen+2)
|
|
||||||
sub dx, 1
|
|
||||||
sbb cx, 0
|
|
||||||
mov ax, 0x0008
|
|
||||||
int 0x31 ! set ds segment limit
|
|
||||||
jc bad_dpmi
|
|
||||||
|
|
||||||
popa
|
|
||||||
o32 mov eax, (pmemlen)
|
|
||||||
cli ! atomically switch stacks back
|
|
||||||
mov ss, (dpmi_ss)
|
|
||||||
o32 mov esp, (dpmi_ebp)
|
|
||||||
mov es, (psegds32)
|
|
||||||
mov ds, (psegds32)
|
|
||||||
sti
|
|
||||||
|
|
||||||
o32 retf
|
|
||||||
|
|
||||||
bad_dpmi:
|
|
||||||
mov si, bad_dpmi_msg
|
|
||||||
jmp exit_with_error
|
|
||||||
|
|
||||||
no_file:
|
|
||||||
mov si, no_file_msg
|
|
||||||
jmp exit_with_error
|
|
||||||
|
|
||||||
no_dpmi:
|
|
||||||
mov si, no_dpmi_msg
|
|
||||||
! fall through
|
|
||||||
|
|
||||||
! Displays the message in si and exits.
|
|
||||||
! This uses a loop because from protected mode any interrupt which
|
|
||||||
! takes a pointer parameter requires special treatment.
|
|
||||||
exit_with_error:
|
|
||||||
movb dl, (si)
|
|
||||||
cmpb dl, 0
|
|
||||||
je 1f
|
|
||||||
inc si
|
|
||||||
|
|
||||||
movb ah, 2
|
|
||||||
int 0x21 ! print character
|
|
||||||
jmp exit_with_error
|
|
||||||
1:
|
|
||||||
mov ax, 0x4cff
|
|
||||||
int 0x21 ! terminate with error code al
|
|
||||||
|
|
||||||
! Simulate DOS interrupt.
|
|
||||||
int21:
|
|
||||||
o32 movzx ebx, bx
|
|
||||||
o32 or ebx, 0x210000
|
|
||||||
! Simulate interrupt in the high half of ebx.
|
|
||||||
interrupt:
|
|
||||||
o32 mov (dpmi_eax), eax
|
|
||||||
o32 mov (dpmi_ebx), ebx
|
|
||||||
o32 mov (dpmi_ecx), ecx
|
|
||||||
o32 mov (dpmi_edx), edx
|
|
||||||
o32 mov (dpmi_esi), esi
|
|
||||||
o32 mov (dpmi_edi), edi
|
|
||||||
pushf
|
|
||||||
pop (dpmi_flags)
|
|
||||||
mov ax, (rseg)
|
|
||||||
mov (dpmi_ds), ax
|
|
||||||
mov (dpmi_ss), ax
|
|
||||||
push es
|
|
||||||
mov (dpmi_sp), dosstack ! auto stack is too small
|
|
||||||
push ds
|
|
||||||
pop es
|
|
||||||
o32 mov edi, dpmi_edi
|
|
||||||
mov ax, 0x300
|
|
||||||
o32 shr ebx, 16
|
|
||||||
xor cx, cx
|
|
||||||
int 0x31 ! simulate DOS interrupt
|
|
||||||
pop es
|
|
||||||
o32 mov eax, (dpmi_eax)
|
|
||||||
o32 mov ebx, (dpmi_ebx)
|
|
||||||
o32 mov ecx, (dpmi_ecx)
|
|
||||||
o32 mov edx, (dpmi_edx)
|
|
||||||
o32 mov esi, (dpmi_esi)
|
|
||||||
o32 mov edi, (dpmi_edi)
|
|
||||||
push (dpmi_flags)
|
|
||||||
popf
|
|
||||||
ret
|
|
||||||
|
|
||||||
! Far call wrapper around interrupt.
|
|
||||||
interruptf:
|
|
||||||
push ds
|
|
||||||
cseg mov ds, (psegds)
|
|
||||||
call interrupt
|
|
||||||
pop ds
|
|
||||||
o32 retf
|
|
||||||
|
|
||||||
bad_dpmi_msg:
|
|
||||||
.asciz "DPMI error during setup"
|
|
||||||
no_file_msg:
|
|
||||||
.asciz "Couldn't open .exe"
|
|
||||||
no_dpmi_msg:
|
|
||||||
.asciz "No DPMI host installed"
|
|
||||||
.align 4
|
|
||||||
text_top:
|
|
||||||
|
|
||||||
exe_text_pages = [text_top - exe_header + 511] / 512
|
|
||||||
exe_last_page = [text_top - exe_header] % 512
|
|
||||||
|
|
||||||
.sect .rom
|
|
||||||
|
|
||||||
.sect .bss
|
|
||||||
bss_start:
|
|
||||||
|
|
||||||
dpmi_edi: .space 4
|
|
||||||
dpmi_esi: .space 4
|
|
||||||
dpmi_ebp: .space 4
|
|
||||||
.space 4 ! reserved
|
|
||||||
dpmi_ebx: .space 4
|
|
||||||
dpmi_edx: .space 4
|
|
||||||
dpmi_ecx: .space 4
|
|
||||||
dpmi_eax: .space 4
|
|
||||||
dpmi_flags: .space 2
|
|
||||||
dpmi_es: .space 2
|
|
||||||
dpmi_ds: .space 2
|
|
||||||
dpmi_fs: .space 2
|
|
||||||
dpmi_gs: .space 2
|
|
||||||
dpmi_ip: .space 2
|
|
||||||
dpmi_cs: .space 2
|
|
||||||
dpmi_sp: .space 2
|
|
||||||
dpmi_ss: .space 2
|
|
||||||
|
|
||||||
pmode_switch: .space 4
|
|
||||||
rseg: .space 2 ! real mode
|
|
||||||
pspseg: .space 2 ! real mode
|
|
||||||
psegcs: .space 2 ! protected mode 16-bit code segment
|
|
||||||
psegds: .space 2 ! protected mode 16-bit data segment
|
|
||||||
psegcs32: .space 2 ! protected mode 32-bit code segment
|
|
||||||
psegds32: .space 2 ! protected mode 32-bit data segment
|
|
||||||
pmemaddr: .space 4 ! protected mode linear memory address
|
|
||||||
pmemhandle: .space 4 ! protected mode linear memory handle
|
|
||||||
pmemlen: .space 4 ! protected mode linear memory length
|
|
||||||
fh: .space 2
|
|
||||||
|
|
||||||
.space 512
|
|
||||||
stack:
|
|
||||||
.space 512
|
|
||||||
dosstack:
|
|
||||||
|
|
||||||
transfer_buffer:
|
|
||||||
.space TRANSFER_BUFFER_SIZE
|
|
||||||
|
|
||||||
bss_top:
|
|
||||||
exe_ram_paras = [bss_top - bss_start + 15] / 16
|
|
||||||
|
|
||||||
! vim: ts=4 sw=4 et ft=asm
|
|
||||||
|
|
|
@ -84,5 +84,5 @@ name cv
|
||||||
mapflag -i LOD=amzlod
|
mapflag -i LOD=amzlod
|
||||||
program {EM}/bin/{LOD}
|
program {EM}/bin/{LOD}
|
||||||
args < >
|
args < >
|
||||||
outfile msdos86.com
|
outfile msdos86.exe
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,28 +3,41 @@ acklibrary {
|
||||||
srcs = {
|
srcs = {
|
||||||
"./brk.c",
|
"./brk.c",
|
||||||
"./close.s",
|
"./close.s",
|
||||||
|
"./creat.c",
|
||||||
"./errno.s",
|
"./errno.s",
|
||||||
"./getpid.s",
|
"./getpid.s",
|
||||||
|
"./gettimeofday.c",
|
||||||
"./_hol0.s",
|
"./_hol0.s",
|
||||||
"./isatty.s",
|
"./isatty.s",
|
||||||
"./rename.s",
|
"./kill.c",
|
||||||
|
"./lseek.c",
|
||||||
|
"./open.c",
|
||||||
|
"./read.c",
|
||||||
|
"./setmode.c",
|
||||||
|
"./signal.c",
|
||||||
"./sys_exists.s",
|
"./sys_exists.s",
|
||||||
|
"./sys_fdmodes.c",
|
||||||
"./sys_getdate.s",
|
"./sys_getdate.s",
|
||||||
|
"./sys_getmode.c",
|
||||||
"./sys_gettime.s",
|
"./sys_gettime.s",
|
||||||
|
"./sys_initmain.c",
|
||||||
|
"./sys_iseof.c",
|
||||||
"./sys_isopen.s",
|
"./sys_isopen.s",
|
||||||
"./sys_isreadyr.s",
|
"./sys_isreadyr.s",
|
||||||
"./sys_rawcreat.s",
|
"./sys_rawcreat.s",
|
||||||
"./sys_rawlseek.s",
|
"./sys_rawlseek.s",
|
||||||
"./sys_rawopen.s",
|
"./sys_rawopen.s",
|
||||||
"./sys_rawrw.s",
|
"./sys_rawrw.s",
|
||||||
|
"./sys_seteof.c",
|
||||||
|
"./sys_seterrno.c",
|
||||||
|
"./sys_setmode.c",
|
||||||
"./sys_xret.s",
|
"./sys_xret.s",
|
||||||
"./unlink.s",
|
"./unlink.s",
|
||||||
"plat/msdos/libsys+srcs",
|
"./write.c",
|
||||||
},
|
},
|
||||||
deps = {
|
deps = {
|
||||||
"lang/cem/libcc.ansi/headers+headers",
|
"lang/cem/libcc.ansi/headers+headers",
|
||||||
"plat/msdos86/include+headers",
|
"plat/msdos86/include+headers",
|
||||||
"plat/msdos/libsys+headers",
|
|
||||||
},
|
},
|
||||||
vars = {
|
vars = {
|
||||||
plat = "msdos86"
|
plat = "msdos86"
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -17,7 +16,9 @@ ssize_t read(int fd, void* buffer, size_t count)
|
||||||
ssize_t r, tot;
|
ssize_t r, tot;
|
||||||
size_t left;
|
size_t left;
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
bool text = _sys_getmode(fd) == O_TEXT;
|
|
||||||
|
if (!count || _sys_getmode(fd) == O_BINARY)
|
||||||
|
return _sys_rawread(fd, buffer, count);
|
||||||
|
|
||||||
if (_sys_iseof(fd))
|
if (_sys_iseof(fd))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -46,36 +47,33 @@ ssize_t read(int fd, void* buffer, size_t count)
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return tot ? tot : r;
|
return tot ? tot : r;
|
||||||
|
|
||||||
if (text)
|
q = memchr(p, 0x1a, (size_t)r);
|
||||||
|
if (q)
|
||||||
{
|
{
|
||||||
q = memchr(p, 0x1a, (size_t)r);
|
_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
|
||||||
if (q)
|
r = q - p;
|
||||||
|
eof = 1;
|
||||||
|
_sys_seteof(fd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
q = memchr(p, '\r', (size_t)r);
|
||||||
|
if (!q)
|
||||||
|
return tot + r;
|
||||||
|
|
||||||
|
tot += q - p;
|
||||||
|
left = r - (q + 1 - p);
|
||||||
|
p = q;
|
||||||
|
++q;
|
||||||
|
|
||||||
|
while (left)
|
||||||
|
{
|
||||||
|
char c = *q++;
|
||||||
|
if (c != '\r')
|
||||||
{
|
{
|
||||||
_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
|
*p++ = c;
|
||||||
r = q - p;
|
++tot;
|
||||||
eof = 1;
|
|
||||||
_sys_seteof(fd, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
q = memchr(p, '\r', (size_t)r);
|
|
||||||
if (!q)
|
|
||||||
return tot + r;
|
|
||||||
|
|
||||||
tot += q - p;
|
|
||||||
left = r - (q + 1 - p);
|
|
||||||
p = q;
|
|
||||||
++q;
|
|
||||||
|
|
||||||
while (left)
|
|
||||||
{
|
|
||||||
char c = *q++;
|
|
||||||
if (c != '\r')
|
|
||||||
{
|
|
||||||
*p++ = c;
|
|
||||||
++tot;
|
|
||||||
}
|
|
||||||
--left;
|
|
||||||
}
|
}
|
||||||
|
--left;
|
||||||
}
|
}
|
||||||
} while (tot < count && !eof && _sys_isreadyr(fd));
|
} while (tot < count && !eof && _sys_isreadyr(fd));
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
#
|
|
||||||
! $Source$
|
|
||||||
! $State$
|
|
||||||
! $Revision$
|
|
||||||
|
|
||||||
! Declare segments (the order is important).
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
.sect .rom
|
|
||||||
.sect .data
|
|
||||||
.sect .bss
|
|
||||||
|
|
||||||
.sect .text
|
|
||||||
|
|
||||||
! Rename a file.
|
|
||||||
|
|
||||||
.define _rename
|
|
||||||
_rename:
|
|
||||||
mov bx, sp
|
|
||||||
push di
|
|
||||||
mov dx, 2(bx)
|
|
||||||
mov di, 4(bx)
|
|
||||||
movb ah, 0x56
|
|
||||||
int 0x21
|
|
||||||
pop di
|
|
||||||
jmp .sys_zret
|
|
|
@ -35,7 +35,7 @@ static const signed char err_map[] =
|
||||||
* Map an MS-DOS 2+ system error code to an `errno' value and store that in
|
* Map an MS-DOS 2+ system error code to an `errno' value and store that in
|
||||||
* `errno'. Return a longword -1.
|
* `errno'. Return a longword -1.
|
||||||
*/
|
*/
|
||||||
long _sys_seterrno(unsigned short dos_err)
|
long _sys_seterrno(unsigned dos_err)
|
||||||
{
|
{
|
||||||
if (dos_err < sizeof(err_map) / sizeof(err_map[0]))
|
if (dos_err < sizeof(err_map) / sizeof(err_map[0]))
|
||||||
errno = err_map[dos_err];
|
errno = err_map[dos_err];
|
61
plat/msdos86/libsys/write.c
Normal file
61
plat/msdos86/libsys/write.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* $Source$
|
||||||
|
* $State$
|
||||||
|
* $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "libsys.h"
|
||||||
|
|
||||||
|
ssize_t write(int fd, void* buffer, size_t count)
|
||||||
|
{
|
||||||
|
static const char crlf[2] = "\r\n";
|
||||||
|
int i;
|
||||||
|
char *p, *q;
|
||||||
|
size_t left, n;
|
||||||
|
ssize_t r, tot;
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (_sys_getmode(fd) == O_BINARY)
|
||||||
|
return _sys_rawwrite(fd, buffer, count);
|
||||||
|
|
||||||
|
/* If the file descriptor is an O_TEXT fd, translate LFs to CRLFs. */
|
||||||
|
p = buffer;
|
||||||
|
left = count;
|
||||||
|
tot = 0;
|
||||||
|
while (left)
|
||||||
|
{
|
||||||
|
q = memchr(p, '\n', left);
|
||||||
|
if (!q)
|
||||||
|
return _sys_rawwrite(fd, p, left);
|
||||||
|
|
||||||
|
n = q - p;
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
r = _sys_rawwrite(fd, p, n);
|
||||||
|
if (r <= 0)
|
||||||
|
return tot ? tot : r;
|
||||||
|
tot += r;
|
||||||
|
p += r;
|
||||||
|
left -= r;
|
||||||
|
if (r != n)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = _sys_rawwrite(fd, crlf, sizeof crlf);
|
||||||
|
if (r != 2)
|
||||||
|
{
|
||||||
|
if (r > 0)
|
||||||
|
r = 0;
|
||||||
|
return tot ? tot : r;
|
||||||
|
}
|
||||||
|
++tot;
|
||||||
|
++p;
|
||||||
|
--left;
|
||||||
|
}
|
||||||
|
return tot;
|
||||||
|
}
|
|
@ -302,21 +302,6 @@ argv: .data2 exename, 0
|
||||||
envp: .data2 0
|
envp: .data2 0
|
||||||
exename: .asciz 'pc86.img'
|
exename: .asciz 'pc86.img'
|
||||||
|
|
||||||
! A degenerate "hard disk partition table" covering this boot
|
|
||||||
! sector (possibly needed if booting from a USB drive).
|
|
||||||
|
|
||||||
.seek 0x1BE
|
|
||||||
.data1 0x80 ! boot indicator (0x80 = active)
|
|
||||||
.data1 0x00 ! partition start head
|
|
||||||
.data1 0x01 ! partition start sector and start track high
|
|
||||||
.data1 0x00 ! partition start track low
|
|
||||||
.data1 0x7F ! OS or filesystem indicator
|
|
||||||
.data1 0xFF ! partition end head
|
|
||||||
.data1 0xFF ! partition end sector and end track high
|
|
||||||
.data1 0xFF ! partition end track low
|
|
||||||
.data4 0 ! partition start LBA
|
|
||||||
.data4 0xFFFFFFFF ! length of partition in sectors
|
|
||||||
|
|
||||||
! ...and we need this to fool the PC into booting our boot sector.
|
! ...and we need this to fool the PC into booting our boot sector.
|
||||||
|
|
||||||
.seek 0x1FE
|
.seek 0x1FE
|
||||||
|
|
|
@ -12,9 +12,29 @@ errcho() {
|
||||||
|
|
||||||
get_test_output() {
|
get_test_output() {
|
||||||
case $method in
|
case $method in
|
||||||
|
qemu-system-*)
|
||||||
|
if ! command -v $method >/dev/null 2>&1 ; then
|
||||||
|
errcho "Warning: $method not installed, skipping test"
|
||||||
|
echo "@@SKIPPED"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $method in
|
||||||
|
qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;;
|
||||||
|
qemu-system-ppc) img="-kernel $img" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$timeoutprog -t $timeout -- $method -nographic $img 2>&1
|
||||||
|
;;
|
||||||
|
|
||||||
qemu-*)
|
qemu-*)
|
||||||
errcho "qemu tests no longer supported (method $method)"
|
if ! command -v $method >/dev/null 2>&1 ; then
|
||||||
exit 1
|
errcho "Warning: $method not installed, skipping test"
|
||||||
|
echo "@@SKIPPED"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
$method $img 2>&1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|
|
@ -42,11 +42,11 @@ $(OBJDIR)/%.o: %.c
|
||||||
|
|
||||||
$(OBJDIR)/%.pdf: doc/%.n doc/LLgen.refs
|
$(OBJDIR)/%.pdf: doc/%.n doc/LLgen.refs
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
refer -p doc/LLgen.refs $< | groff -G -e -g -p -ms -Tpdf $< > $@
|
refer $< | groff -G -e -g -p -ms -Tpdf $< > $@
|
||||||
|
|
||||||
$(OBJDIR)/%/index.html: doc/%.n doc/LLgen.refs
|
$(OBJDIR)/%/index.html: doc/%.n doc/LLgen.refs
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
(cd $(dir $@) && refer -p $(PWD)/doc/LLgen.refs | groff -G -e -g -p -ms -Thtml) < $< > $@
|
refer $< | (cd $(dir $@) && groff -I$(PWD) -G -e -g -p -ms -Thtml) > $@
|
||||||
|
|
||||||
doc:: $(PDFS) $(HTMLS)
|
doc:: $(PDFS) $(HTMLS)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
\}\
|
\}\
|
||||||
\}
|
\}
|
||||||
.R1
|
.R1
|
||||||
|
database doc/LLgen.refs
|
||||||
accumulate
|
accumulate
|
||||||
.R2
|
.R2
|
||||||
.ND
|
.ND
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
.RP
|
||||||
.TL
|
.TL
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
aslod \- ACK simple loader
|
aslod \- ACK simple loader
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B aslod
|
.B aslod
|
||||||
[\-h] [\-v] [\-p prefixfile] inputfile outputfile
|
[\-h] [\-v] inputfile outputfile
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.I aslod
|
.I aslod
|
||||||
converts an absolute ack.out file into a simple binary memory dump.
|
converts an absolute ack.out file into a simple binary memory dump.
|
||||||
|
@ -16,8 +16,5 @@ The file must have all references resolved and be linked to a
|
||||||
fixed address. aslod will dump the segments, in order, such
|
fixed address. aslod will dump the segments, in order, such
|
||||||
that the first byte of TEXT is at offset 0 in the file
|
that the first byte of TEXT is at offset 0 in the file
|
||||||
(regardless of where it is in memory).
|
(regardless of where it is in memory).
|
||||||
.PP
|
|
||||||
If a prefix file is specified, this is prepended to the output before writing.
|
|
||||||
No changes to the output itself are made.
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
ack.out(5)
|
ack.out(5)
|
||||||
|
|
|
@ -37,7 +37,6 @@ struct outsect outsect[S_MAX];
|
||||||
char* stringarea;
|
char* stringarea;
|
||||||
|
|
||||||
char* outputfile = NULL; /* Name of output file, or NULL */
|
char* outputfile = NULL; /* Name of output file, or NULL */
|
||||||
char* prefixfile = NULL; /* Name of prefix file, or NULL */
|
|
||||||
char* program; /* Name of current program: argv[0] */
|
char* program; /* Name of current program: argv[0] */
|
||||||
|
|
||||||
FILE* input; /* Input stream */
|
FILE* input; /* Input stream */
|
||||||
|
@ -137,19 +136,6 @@ void emits(struct outsect* section, struct outsect* nextsect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitprefixfile(void)
|
|
||||||
{
|
|
||||||
FILE* fp = fopen(prefixfile, "rb");
|
|
||||||
|
|
||||||
while (!feof(fp))
|
|
||||||
{
|
|
||||||
char buffer[BUFSIZ];
|
|
||||||
size_t blocksize = fread(buffer, 1, BUFSIZ, fp);
|
|
||||||
writef(buffer, 1, blocksize);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Macros from modules/src/object/obj.h */
|
/* Macros from modules/src/object/obj.h */
|
||||||
#define Xchar(ch) ((ch) & 0377)
|
#define Xchar(ch) ((ch) & 0377)
|
||||||
|
@ -218,12 +204,6 @@ int main(int argc, char* argv[])
|
||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
|
||||||
argv++;
|
|
||||||
argc--;
|
|
||||||
prefixfile = argv[1];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntaxerror:
|
syntaxerror:
|
||||||
fatal("syntax error --- try -h for help");
|
fatal("syntax error --- try -h for help");
|
||||||
|
@ -308,8 +288,6 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
/* And go! */
|
/* And go! */
|
||||||
|
|
||||||
if (prefixfile)
|
|
||||||
emitprefixfile();
|
|
||||||
emits(&outsect[TEXT], &outsect[ROM]);
|
emits(&outsect[TEXT], &outsect[ROM]);
|
||||||
emits(&outsect[ROM], &outsect[DATA]);
|
emits(&outsect[ROM], &outsect[DATA]);
|
||||||
emits(&outsect[DATA], NULL);
|
emits(&outsect[DATA], NULL);
|
||||||
|
|
|
@ -18,7 +18,7 @@ normalrule {
|
||||||
},
|
},
|
||||||
outleaves = { "enterkeyw.c" },
|
outleaves = { "enterkeyw.c" },
|
||||||
commands = {
|
commands = {
|
||||||
"$(LUA) %{ins[1]} < %{ins[2]} > %{outs[1]}"
|
"$LUA %{ins[1]} < %{ins[2]} > %{outs[1]}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue