Merge pull request #269 from davidgiven/dtrg-msdos386
Add a plat for 32-bit DOS executables.
This commit is contained in:
		
						commit
						0165c07c7b
					
				
					 61 changed files with 2277 additions and 529 deletions
				
			
		
							
								
								
									
										3
									
								
								README
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								README
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
                     ===================================
 | 
			
		||||
 | 
			
		||||
                  © 1987-2005 Vrije Universiteit, Amsterdam
 | 
			
		||||
                                2022-06-18
 | 
			
		||||
                                2022-08-19
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
INTRODUCTION
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ cpm           produces i80 CP/M .COM files
 | 
			
		|||
rpi           produces Raspberry Pi GPU binaries
 | 
			
		||||
pdpv7         produces PDP/11 V7 Unix binaries
 | 
			
		||||
msdos86       produces i86 MS-DOS .COM files
 | 
			
		||||
msdos386      produces i386 MS-DOS 32-bit DPMI .EXE files
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ vars.plats = {
 | 
			
		|||
	"linuxppc",
 | 
			
		||||
	"linuxmips",
 | 
			
		||||
	"msdos86",
 | 
			
		||||
	"msdos386",
 | 
			
		||||
	"osx386",
 | 
			
		||||
	"osxppc",
 | 
			
		||||
	"pc86",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,10 +184,13 @@
 | 
			
		|||
{0,	NOOP_1,		0155,		"ins"},
 | 
			
		||||
{0,	NOOP_1,		0252,		"stosb"},
 | 
			
		||||
{0,	NOOP_1,		0253,		"stos"},
 | 
			
		||||
{0,	NOOP_1,		0253,		"stosw"},
 | 
			
		||||
{0,	NOOP_1,		0254,		"lodsb"},
 | 
			
		||||
{0,	NOOP_1,		0255,		"lods"},
 | 
			
		||||
{0,	NOOP_1,		0255,		"lodsw"},
 | 
			
		||||
{0,	NOOP_1,		0256,		"scasb"},
 | 
			
		||||
{0,	NOOP_1,		0257,		"scas"},
 | 
			
		||||
{0,	NOOP_1,		0257,		"scasw"},
 | 
			
		||||
{0,	NOOP_1,		0311,		"leave"},
 | 
			
		||||
{0,	NOOP_1,		0316,		"into"},
 | 
			
		||||
{0,	NOOP_1,		0317,		"iret"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,8 @@
 | 
			
		|||
 | 
			
		||||
void ea_1_16(int param)
 | 
			
		||||
{
 | 
			
		||||
	reg_1 &= 0377;
 | 
			
		||||
        if ((reg_1 & 070) || (param & ~070)) {
 | 
			
		||||
        reg_1 &= 0377;
 | 
			
		||||
        if (param & ~070) {
 | 
			
		||||
                serror("bad operand");
 | 
			
		||||
        }
 | 
			
		||||
        emit1(reg_1 | param);
 | 
			
		||||
| 
						 | 
				
			
			@ -39,542 +39,545 @@ void ea_1_16(int param)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void ea_1(int param) {
 | 
			
		||||
	if (! address_long) {
 | 
			
		||||
		ea_1_16(param);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (is_expr(reg_1)) {
 | 
			
		||||
		serror("bad operand");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (is_reg(reg_1)) {
 | 
			
		||||
		emit1(0300 | param | (reg_1&07));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (rm_1 == 04) {
 | 
			
		||||
		/* sib field use here */
 | 
			
		||||
		emit1(mod_1 << 6 | param | 04);
 | 
			
		||||
		emit1(sib_1 | reg_1);
 | 
			
		||||
	}
 | 
			
		||||
	else emit1(mod_1<<6 | param | (reg_1&07));
 | 
			
		||||
	if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
 | 
			
		||||
		/* ??? should this be protected by a call to "small" ??? */
 | 
			
		||||
        if (! address_long) {
 | 
			
		||||
                ea_1_16(param);
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_expr(reg_1)) {
 | 
			
		||||
                serror("bad operand");
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_reg(reg_1)) {
 | 
			
		||||
                emit1(0300 | param | (reg_1&07));
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
        if (rm_1 == 04) {
 | 
			
		||||
                /* sib field use here */
 | 
			
		||||
                emit1(mod_1 << 6 | param | 04);
 | 
			
		||||
                emit1(sib_1 | reg_1);
 | 
			
		||||
        }
 | 
			
		||||
        else emit1(mod_1<<6 | param | (reg_1&07));
 | 
			
		||||
        if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
 | 
			
		||||
                /* ??? should this be protected by a call to "small" ??? */
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		RELOMOVE(relonami, rel_1);
 | 
			
		||||
		newrelo(exp_1.typ, RELO4);
 | 
			
		||||
                RELOMOVE(relonami, rel_1);
 | 
			
		||||
                newrelo(exp_1.typ, RELO4);
 | 
			
		||||
#endif
 | 
			
		||||
		emit4((long)(exp_1.val));
 | 
			
		||||
	}
 | 
			
		||||
	else if (mod_1 == 1) {
 | 
			
		||||
		emit1((int)(exp_1.val));
 | 
			
		||||
	}
 | 
			
		||||
                emit4((long)(exp_1.val));
 | 
			
		||||
        }
 | 
			
		||||
        else if (mod_1 == 1) {
 | 
			
		||||
                emit1((int)(exp_1.val));
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ea_2(int param) {
 | 
			
		||||
 | 
			
		||||
	op_1 = op_2;
 | 
			
		||||
	RELOMOVE(rel_1, rel_2);
 | 
			
		||||
	ea_1(param);
 | 
			
		||||
        op_1 = op_2;
 | 
			
		||||
        RELOMOVE(rel_1, rel_2);
 | 
			
		||||
        ea_1(param);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int checkscale(valu_t val)
 | 
			
		||||
{
 | 
			
		||||
	int v = val;
 | 
			
		||||
        int v = val;
 | 
			
		||||
 | 
			
		||||
	if (! address_long) {
 | 
			
		||||
		serror("scaling not allowed in 16-bit mode");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (v != val) v = 0;
 | 
			
		||||
	switch(v) {
 | 
			
		||||
	case 1:
 | 
			
		||||
		return 0;
 | 
			
		||||
	case 2:
 | 
			
		||||
		return 1 << 6;
 | 
			
		||||
	case 4:
 | 
			
		||||
		return 2 << 6;
 | 
			
		||||
	case 8:
 | 
			
		||||
		return 3 << 6;
 | 
			
		||||
	default:
 | 
			
		||||
		serror("bad scale");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	/*NOTREACHED*/
 | 
			
		||||
        if (! address_long) {
 | 
			
		||||
                serror("scaling not allowed in 16-bit mode");
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (v != val) v = 0;
 | 
			
		||||
        switch(v) {
 | 
			
		||||
        case 1:
 | 
			
		||||
                return 0;
 | 
			
		||||
        case 2:
 | 
			
		||||
                return 1 << 6;
 | 
			
		||||
        case 4:
 | 
			
		||||
                return 2 << 6;
 | 
			
		||||
        case 8:
 | 
			
		||||
                return 3 << 6;
 | 
			
		||||
        default:
 | 
			
		||||
                serror("bad scale");
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
        /*NOTREACHED*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reverse(void) {
 | 
			
		||||
	struct operand op;
 | 
			
		||||
        struct operand op;
 | 
			
		||||
#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
 | 
			
		||||
	op = op_1; op_1 = op_2; op_2 = op;
 | 
			
		||||
        op = op_1; op_1 = op_2; op_2 = op;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void badsyntax(void)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	serror("bad operands");
 | 
			
		||||
        serror("bad operands");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void regsize(int sz)
 | 
			
		||||
{
 | 
			
		||||
	register int bit;
 | 
			
		||||
        register int bit;
 | 
			
		||||
 | 
			
		||||
	bit = (sz&1) ? 0 : IS_R8;
 | 
			
		||||
	if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
 | 
			
		||||
	    (is_reg(reg_2) && (reg_2 & IS_R8) != bit)) 
 | 
			
		||||
		serror("register error");
 | 
			
		||||
	if (! address_long) {
 | 
			
		||||
		reg_1 &= ~010;
 | 
			
		||||
		reg_2 &= ~010;
 | 
			
		||||
	}
 | 
			
		||||
        bit = (sz&1) ? 0 : IS_R8;
 | 
			
		||||
        if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
 | 
			
		||||
            (is_reg(reg_2) && (reg_2 & IS_R8) != bit)) 
 | 
			
		||||
                serror("register error");
 | 
			
		||||
        if (! address_long) {
 | 
			
		||||
                reg_1 &= ~010;
 | 
			
		||||
                reg_2 &= ~010;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void indexed(void) {
 | 
			
		||||
	if (address_long) {
 | 
			
		||||
		mod_2 = 0;
 | 
			
		||||
		if (sib_2 == -1)
 | 
			
		||||
			serror("register error");
 | 
			
		||||
		if (rm_2 == 0 && reg_2 == 4) {
 | 
			
		||||
			/* base register sp, no index register; use
 | 
			
		||||
		   	   indexed mode without index register
 | 
			
		||||
			*/
 | 
			
		||||
			rm_2 = 04;
 | 
			
		||||
			sib_2 = 044;
 | 
			
		||||
		}
 | 
			
		||||
		if (reg_2 == 015) {
 | 
			
		||||
			reg_2 = 05;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
 | 
			
		||||
			if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
 | 
			
		||||
			}
 | 
			
		||||
			else mod_2 = 01;
 | 
			
		||||
		}
 | 
			
		||||
		else	if (small(0, 1)) {
 | 
			
		||||
		}
 | 
			
		||||
		else mod_2 = 02;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
        	if (reg_2 & ~7)
 | 
			
		||||
                	serror("register error");
 | 
			
		||||
        	if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
 | 
			
		||||
			if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
 | 
			
		||||
			}
 | 
			
		||||
			else reg_2 |= 0100;
 | 
			
		||||
		}
 | 
			
		||||
		else if (small(0, 1)) {
 | 
			
		||||
		}
 | 
			
		||||
		else reg_2 |= 0200;
 | 
			
		||||
	}
 | 
			
		||||
        if (address_long) {
 | 
			
		||||
                mod_2 = 0;
 | 
			
		||||
                if (sib_2 == -1)
 | 
			
		||||
                        serror("register error");
 | 
			
		||||
                if (rm_2 == 0 && reg_2 == 4) {
 | 
			
		||||
                        /* base register sp, no index register; use
 | 
			
		||||
                           indexed mode without index register
 | 
			
		||||
                        */
 | 
			
		||||
                        rm_2 = 04;
 | 
			
		||||
                        sib_2 = 044;
 | 
			
		||||
                }
 | 
			
		||||
                if (reg_2 == 015) {
 | 
			
		||||
                        reg_2 = 05;
 | 
			
		||||
                        return;
 | 
			
		||||
                }
 | 
			
		||||
                if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
 | 
			
		||||
                        if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
 | 
			
		||||
                        }
 | 
			
		||||
                        else mod_2 = 01;
 | 
			
		||||
                }
 | 
			
		||||
                else    if (small(0, 1)) {
 | 
			
		||||
                }
 | 
			
		||||
                else mod_2 = 02;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
                if (reg_2 & ~7)
 | 
			
		||||
                        serror("register error");
 | 
			
		||||
                if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
 | 
			
		||||
                        if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
 | 
			
		||||
                        }
 | 
			
		||||
                        else reg_2 |= 0100;
 | 
			
		||||
                }
 | 
			
		||||
                else if (small(0, 1)) {
 | 
			
		||||
                }
 | 
			
		||||
                else reg_2 |= 0200;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ebranch(register int opc,expr_t exp)
 | 
			
		||||
{
 | 
			
		||||
	/*	Conditional branching; Full displacements are available
 | 
			
		||||
		on the 80386, so the welknown trick with the reverse branch
 | 
			
		||||
		over a jump is not needed here.
 | 
			
		||||
		The only complication here is with the address size, which
 | 
			
		||||
		can be set with a prefix. In this case, the user gets what
 | 
			
		||||
		he asked for.
 | 
			
		||||
	*/
 | 
			
		||||
	register int sm;
 | 
			
		||||
	register long dist;
 | 
			
		||||
	int saving = address_long ? 4 : 2;
 | 
			
		||||
        /*      Conditional branching; Full displacements are available
 | 
			
		||||
                on the 80386, so the welknown trick with the reverse branch
 | 
			
		||||
                over a jump is not needed here.
 | 
			
		||||
                The only complication here is with the address size, which
 | 
			
		||||
                can be set with a prefix. In this case, the user gets what
 | 
			
		||||
                he asked for.
 | 
			
		||||
        */
 | 
			
		||||
        register int sm;
 | 
			
		||||
        register long dist;
 | 
			
		||||
        int saving = address_long ? 4 : 2;
 | 
			
		||||
 | 
			
		||||
	if (opc == 0353) saving--;
 | 
			
		||||
	dist = exp.val - (DOTVAL + 2);
 | 
			
		||||
	if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
 | 
			
		||||
		dist -= DOTGAIN;
 | 
			
		||||
	sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
 | 
			
		||||
	if ((exp.typ & ~S_DOT) != DOTTYP)
 | 
			
		||||
		sm = 0;
 | 
			
		||||
	if ((sm = small(sm,saving)) == 0) {
 | 
			
		||||
		if (opc == 0353) {
 | 
			
		||||
			emit1(0xe9);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			emit1(0xF);
 | 
			
		||||
			emit1(opc | 0x80);
 | 
			
		||||
		}
 | 
			
		||||
		dist -= saving;
 | 
			
		||||
		exp.val = dist;
 | 
			
		||||
		adsize_exp(exp, RELPC);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		if (opc == 0353) {
 | 
			
		||||
			emit1(opc);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			emit1(opc | 0x70);
 | 
			
		||||
		}
 | 
			
		||||
		emit1((int)dist);
 | 
			
		||||
	}
 | 
			
		||||
        if (opc == 0353) saving--;
 | 
			
		||||
        dist = exp.val - (DOTVAL + 2);
 | 
			
		||||
        if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
 | 
			
		||||
                dist -= DOTGAIN;
 | 
			
		||||
        sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
 | 
			
		||||
        if ((exp.typ & ~S_DOT) != DOTTYP)
 | 
			
		||||
                sm = 0;
 | 
			
		||||
        if ((sm = small(sm,saving)) == 0) {
 | 
			
		||||
                if (opc == 0353) {
 | 
			
		||||
                        emit1(0xe9);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        emit1(0xF);
 | 
			
		||||
                        emit1(opc | 0x80);
 | 
			
		||||
                }
 | 
			
		||||
                dist -= saving;
 | 
			
		||||
                exp.val = dist;
 | 
			
		||||
                adsize_exp(exp, RELPC);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
                if (opc == 0353) {
 | 
			
		||||
                        emit1(opc);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        emit1(opc | 0x70);
 | 
			
		||||
                }
 | 
			
		||||
                emit1((int)dist);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void branch(register int opc,expr_t exp)
 | 
			
		||||
{
 | 
			
		||||
	/*	LOOP, JCXZ, etc. branch instructions.
 | 
			
		||||
		Here, the offset just must fit in a byte.
 | 
			
		||||
	*/
 | 
			
		||||
	register long dist;
 | 
			
		||||
        /*      LOOP, JCXZ, etc. branch instructions.
 | 
			
		||||
                Here, the offset just must fit in a byte.
 | 
			
		||||
        */
 | 
			
		||||
        register long dist;
 | 
			
		||||
 | 
			
		||||
	dist = exp.val - (DOTVAL + 2);
 | 
			
		||||
	if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
 | 
			
		||||
		dist -= DOTGAIN;
 | 
			
		||||
	fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
 | 
			
		||||
	emit1(opc);
 | 
			
		||||
	emit1((int)dist);
 | 
			
		||||
        dist = exp.val - (DOTVAL + 2);
 | 
			
		||||
        if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
 | 
			
		||||
                dist -= DOTGAIN;
 | 
			
		||||
        fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
 | 
			
		||||
        emit1(opc);
 | 
			
		||||
        emit1((int)dist);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pushop(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(1);
 | 
			
		||||
	if (is_segreg(reg_1)) {
 | 
			
		||||
		/* segment register */
 | 
			
		||||
		if ((reg_1 & 07) <= 3)
 | 
			
		||||
			emit1(6 | opc | (reg_1&7)<<3);
 | 
			
		||||
		else {
 | 
			
		||||
			emit1(0xF);
 | 
			
		||||
			emit1(0200 | opc | ((reg_1&7)<<3));
 | 
			
		||||
		}
 | 
			
		||||
	} else if (is_reg(reg_1)) {
 | 
			
		||||
		/* normal register */
 | 
			
		||||
		emit1(0120 | opc<<3 | (reg_1&7));
 | 
			
		||||
	} else if (opc == 0) {
 | 
			
		||||
		if (is_expr(reg_1)) {
 | 
			
		||||
			if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
 | 
			
		||||
				  operand_long ? 3 : 1)) {
 | 
			
		||||
				emit1(0152);
 | 
			
		||||
				emit1((int)(exp_1.val));
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				emit1(0150);
 | 
			
		||||
				RELOMOVE(relonami, rel_1);
 | 
			
		||||
				opsize_exp(exp_1, 1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			emit1(0377); ea_1(6<<3);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		emit1(0217); ea_1(0<<3);
 | 
			
		||||
	}
 | 
			
		||||
        regsize(1);
 | 
			
		||||
        if (is_segreg(reg_1)) {
 | 
			
		||||
                /* segment register */
 | 
			
		||||
                if ((reg_1 & 07) <= 3)
 | 
			
		||||
                        emit1(6 | opc | (reg_1&7)<<3);
 | 
			
		||||
                else {
 | 
			
		||||
                        emit1(0xF);
 | 
			
		||||
                        emit1(0200 | opc | ((reg_1&7)<<3));
 | 
			
		||||
                }
 | 
			
		||||
        } else if (is_reg(reg_1)) {
 | 
			
		||||
                /* normal register */
 | 
			
		||||
                emit1(0120 | opc<<3 | (reg_1&7));
 | 
			
		||||
        } else if (opc == 0) {
 | 
			
		||||
                if (is_expr(reg_1)) {
 | 
			
		||||
                        if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
 | 
			
		||||
                                  operand_long ? 3 : 1)) {
 | 
			
		||||
                                emit1(0152);
 | 
			
		||||
                                emit1((int)(exp_1.val));
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                                emit1(0150);
 | 
			
		||||
                                RELOMOVE(relonami, rel_1);
 | 
			
		||||
                                opsize_exp(exp_1, 1);
 | 
			
		||||
                        }
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        emit1(0377); ea_1(6<<3);
 | 
			
		||||
                }
 | 
			
		||||
        } else {
 | 
			
		||||
                emit1(0217); ea_1(0<<3);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void opsize_exp(expr_t exp, int nobyte)
 | 
			
		||||
{
 | 
			
		||||
	if (! nobyte) {
 | 
			
		||||
        if (! nobyte) {
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		newrelo(exp.typ, RELO1);
 | 
			
		||||
                newrelo(exp.typ, RELO1);
 | 
			
		||||
#endif
 | 
			
		||||
		emit1((int)(exp.val));
 | 
			
		||||
	}
 | 
			
		||||
	else if (operand_long) {
 | 
			
		||||
                emit1((int)(exp.val));
 | 
			
		||||
        }
 | 
			
		||||
        else if (operand_long) {
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		newrelo(exp.typ, RELO4);
 | 
			
		||||
                newrelo(exp.typ, RELO4);
 | 
			
		||||
#endif
 | 
			
		||||
		emit4((long)(exp.val));
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
                emit4((long)(exp.val));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		newrelo(exp.typ, RELO2);
 | 
			
		||||
                newrelo(exp.typ, RELO2);
 | 
			
		||||
#endif
 | 
			
		||||
		emit2((int)(exp.val));
 | 
			
		||||
	}
 | 
			
		||||
                emit2((int)(exp.val));
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void adsize_exp(expr_t exp, int relpc)
 | 
			
		||||
{
 | 
			
		||||
	if (address_long) {
 | 
			
		||||
        if (address_long) {
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		newrelo(exp.typ, RELO4 | relpc);
 | 
			
		||||
                newrelo(exp.typ, RELO4 | relpc);
 | 
			
		||||
#endif
 | 
			
		||||
		emit4((long)(exp.val));
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
                emit4((long)(exp.val));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		newrelo(exp.typ, RELO2 | relpc);
 | 
			
		||||
                newrelo(exp.typ, RELO2 | relpc);
 | 
			
		||||
#endif
 | 
			
		||||
		emit2((int)(exp.val));
 | 
			
		||||
	}
 | 
			
		||||
                emit2((int)(exp.val));
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void addop(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if (is_reg(reg_2)) {
 | 
			
		||||
		/*	Add register to register or memory */
 | 
			
		||||
		emit1(opc); ea_1((reg_2&7)<<3);
 | 
			
		||||
	} else if (is_acc(reg_1) && is_expr(reg_2)) {
 | 
			
		||||
		/*	Add immediate to accumulator */
 | 
			
		||||
		emit1(opc | 4);
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		opsize_exp(exp_2, (opc&1));
 | 
			
		||||
	} else if (is_expr(reg_2)) {
 | 
			
		||||
		/*	Add immediate to register or memory */
 | 
			
		||||
		if ((opc&1) == 0) {
 | 
			
		||||
			emit1(0200);
 | 
			
		||||
		} else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
 | 
			
		||||
			   	   operand_long ? 3 : 1)) {
 | 
			
		||||
			emit1(0201);
 | 
			
		||||
		} else {
 | 
			
		||||
			emit1(0203); opc &= ~1;
 | 
			
		||||
		}
 | 
			
		||||
		ea_1(opc & 070);
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		opsize_exp(exp_2, (opc&1));
 | 
			
		||||
	} else if (is_reg(reg_1)) {
 | 
			
		||||
		/*	Add register or memory to register */
 | 
			
		||||
		emit1(opc | 2);
 | 
			
		||||
		ea_2((reg_1&7)<<3);
 | 
			
		||||
	} else
 | 
			
		||||
		badsyntax();
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if (is_reg(reg_2)) {
 | 
			
		||||
                /*      Add register to register or memory */
 | 
			
		||||
                emit1(opc); ea_1((reg_2&7)<<3);
 | 
			
		||||
        } else if (is_acc(reg_1) && is_expr(reg_2)) {
 | 
			
		||||
                /*      Add immediate to accumulator */
 | 
			
		||||
                emit1(opc | 4);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                opsize_exp(exp_2, (opc&1));
 | 
			
		||||
        } else if (is_expr(reg_2)) {
 | 
			
		||||
                /*      Add immediate to register or memory */
 | 
			
		||||
                if ((opc&1) == 0) {
 | 
			
		||||
                        emit1(0200);
 | 
			
		||||
                } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
 | 
			
		||||
                                   operand_long ? 3 : 1)) {
 | 
			
		||||
                        emit1(0201);
 | 
			
		||||
                } else {
 | 
			
		||||
                        emit1(0203); opc &= ~1;
 | 
			
		||||
                }
 | 
			
		||||
                ea_1(opc & 070);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                opsize_exp(exp_2, (opc&1));
 | 
			
		||||
        } else if (is_reg(reg_1)) {
 | 
			
		||||
                /*      Add register or memory to register */
 | 
			
		||||
                emit1(opc | 2);
 | 
			
		||||
                ea_2((reg_1&7)<<3);
 | 
			
		||||
        } else
 | 
			
		||||
                badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rolop(register int opc)
 | 
			
		||||
{
 | 
			
		||||
	register int oreg;
 | 
			
		||||
        register int oreg;
 | 
			
		||||
 | 
			
		||||
	oreg = reg_2;
 | 
			
		||||
	reg_2 = reg_1;
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
 | 
			
		||||
		/* cl register */
 | 
			
		||||
		emit1(0322 | (opc&1)); ea_1(opc&070);
 | 
			
		||||
	} else if (is_expr(oreg)) {
 | 
			
		||||
	    if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
 | 
			
		||||
		/* shift by 1 */
 | 
			
		||||
		emit1(0320 | (opc&1)); ea_1(opc&070);
 | 
			
		||||
	    } else {
 | 
			
		||||
		/* shift by byte count */
 | 
			
		||||
		emit1(0300 | (opc & 1)); 
 | 
			
		||||
		ea_1(opc & 070);
 | 
			
		||||
        oreg = reg_2;
 | 
			
		||||
        reg_2 = reg_1;
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
 | 
			
		||||
                /* cl register */
 | 
			
		||||
                emit1(0322 | (opc&1)); ea_1(opc&070);
 | 
			
		||||
        } else if (is_expr(oreg)) {
 | 
			
		||||
            if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
 | 
			
		||||
                /* shift by 1 */
 | 
			
		||||
                emit1(0320 | (opc&1)); ea_1(opc&070);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* shift by byte count */
 | 
			
		||||
                emit1(0300 | (opc & 1)); 
 | 
			
		||||
                ea_1(opc & 070);
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		newrelo(exp_2.typ, RELO1);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                newrelo(exp_2.typ, RELO1);
 | 
			
		||||
#endif
 | 
			
		||||
		emit1((int)(exp_2.val));
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		badsyntax();
 | 
			
		||||
                emit1((int)(exp_2.val));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
                badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void incop(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if ((opc&1) && is_reg(reg_1)) {
 | 
			
		||||
		/* word register */
 | 
			
		||||
		emit1(0100 | (opc&010) | (reg_1&7));
 | 
			
		||||
	} else {
 | 
			
		||||
		emit1(0376 | (opc&1));
 | 
			
		||||
		ea_1(opc & 010);
 | 
			
		||||
	}
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if ((opc&1) && is_reg(reg_1)) {
 | 
			
		||||
                /* word register */
 | 
			
		||||
                emit1(0100 | (opc&010) | (reg_1&7));
 | 
			
		||||
        } else {
 | 
			
		||||
                emit1(0376 | (opc&1));
 | 
			
		||||
                ea_1(opc & 010);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void callop(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(1);
 | 
			
		||||
	if (is_expr(reg_1)) {
 | 
			
		||||
		if (opc == (040+(0351<<8))) {
 | 
			
		||||
			RELOMOVE(relonami, rel_1);
 | 
			
		||||
			ebranch(0353,exp_1);
 | 
			
		||||
		} else {
 | 
			
		||||
			exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
 | 
			
		||||
			emit1(opc>>8);
 | 
			
		||||
			RELOMOVE(relonami, rel_1);
 | 
			
		||||
			adsize_exp(exp_1, RELPC);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		emit1(0377); ea_1(opc&070);
 | 
			
		||||
	}
 | 
			
		||||
        regsize(1);
 | 
			
		||||
        if (is_expr(reg_1)) {
 | 
			
		||||
                if (opc == (040+(0351<<8))) {
 | 
			
		||||
                        RELOMOVE(relonami, rel_1);
 | 
			
		||||
                        ebranch(0353,exp_1);
 | 
			
		||||
                } else {
 | 
			
		||||
                        exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
 | 
			
		||||
                        emit1(opc>>8);
 | 
			
		||||
                        RELOMOVE(relonami, rel_1);
 | 
			
		||||
                        adsize_exp(exp_1, RELPC);
 | 
			
		||||
                }
 | 
			
		||||
        } else {
 | 
			
		||||
                emit1(0377); ea_1(opc&070);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void xchg(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if (! is_reg(reg_1) || is_acc(reg_2)) {
 | 
			
		||||
		reverse();
 | 
			
		||||
	}
 | 
			
		||||
	if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
 | 
			
		||||
		emit1(0220 | (reg_2&7));
 | 
			
		||||
	} else if (is_reg(reg_1)) {
 | 
			
		||||
		emit1(0206 | opc); ea_2((reg_1&7)<<3);
 | 
			
		||||
	} else
 | 
			
		||||
		badsyntax();
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if (! is_reg(reg_1) || is_acc(reg_2)) {
 | 
			
		||||
                reverse();
 | 
			
		||||
        }
 | 
			
		||||
        if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
 | 
			
		||||
                emit1(0220 | (reg_2&7));
 | 
			
		||||
        } else if (is_reg(reg_1)) {
 | 
			
		||||
                emit1(0206 | opc); ea_2((reg_1&7)<<3);
 | 
			
		||||
        } else
 | 
			
		||||
                badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if (is_reg(reg_2) || is_expr(reg_1))
 | 
			
		||||
		reverse();
 | 
			
		||||
	if (is_expr(reg_2)) {
 | 
			
		||||
		if (is_acc(reg_1)) {
 | 
			
		||||
			emit1(0250 | opc);
 | 
			
		||||
			RELOMOVE(relonami, rel_2);
 | 
			
		||||
			opsize_exp(exp_2, (opc&1));
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			emit1(0366 | opc);
 | 
			
		||||
			ea_1(0<<3);
 | 
			
		||||
			RELOMOVE(relonami, rel_2);
 | 
			
		||||
			opsize_exp(exp_2, (opc&1));
 | 
			
		||||
		}
 | 
			
		||||
	} else if (is_reg(reg_1)) {
 | 
			
		||||
		emit1(0204 | opc); ea_2((reg_1&7)<<3);
 | 
			
		||||
	} else
 | 
			
		||||
		badsyntax();
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if (is_reg(reg_2) || is_expr(reg_1))
 | 
			
		||||
                reverse();
 | 
			
		||||
        if (is_expr(reg_2)) {
 | 
			
		||||
                if (is_acc(reg_1)) {
 | 
			
		||||
                        emit1(0250 | opc);
 | 
			
		||||
                        RELOMOVE(relonami, rel_2);
 | 
			
		||||
                        opsize_exp(exp_2, (opc&1));
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        emit1(0366 | opc);
 | 
			
		||||
                        ea_1(0<<3);
 | 
			
		||||
                        RELOMOVE(relonami, rel_2);
 | 
			
		||||
                        opsize_exp(exp_2, (opc&1));
 | 
			
		||||
                }
 | 
			
		||||
        } else if (is_reg(reg_1)) {
 | 
			
		||||
                emit1(0204 | opc); ea_2((reg_1&7)<<3);
 | 
			
		||||
        } else
 | 
			
		||||
                badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mov(register int opc)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	regsize(opc);
 | 
			
		||||
	if (is_segreg(reg_1)) {
 | 
			
		||||
		/* to segment register */
 | 
			
		||||
		emit1(0216); ea_2((reg_1&07)<<3);
 | 
			
		||||
	} else if (is_segreg(reg_2)) {
 | 
			
		||||
		/* from segment register */
 | 
			
		||||
		emit1(0214); ea_1((reg_2&07)<<3);
 | 
			
		||||
	} else if (is_expr(reg_2)) {
 | 
			
		||||
		/* from immediate */
 | 
			
		||||
		if (is_reg(reg_1)) {
 | 
			
		||||
			/* to register */
 | 
			
		||||
			emit1(0260 | opc<<3 | (reg_1&7)); 
 | 
			
		||||
		} else {
 | 
			
		||||
			/* to memory */
 | 
			
		||||
			emit1(0306 | opc); ea_1(0<<3); 
 | 
			
		||||
		}
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		opsize_exp(exp_2, (opc&1));
 | 
			
		||||
	} else if (rm_1 == 05 && is_acc(reg_2)) {
 | 
			
		||||
		/* from accumulator to memory  (displacement) */
 | 
			
		||||
		emit1(0242 | opc);
 | 
			
		||||
		RELOMOVE(relonami, rel_1);
 | 
			
		||||
		adsize_exp(exp_1, 0);
 | 
			
		||||
	} else if (rm_2 == 05 && is_acc(reg_1)) {
 | 
			
		||||
		/* from memory (displacement) to accumulator */
 | 
			
		||||
		emit1(0240 | opc);
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		adsize_exp(exp_2, 0);
 | 
			
		||||
	} else if (is_reg(reg_2)) {
 | 
			
		||||
		/* from register to memory or register */
 | 
			
		||||
		emit1(0210 | opc); ea_1((reg_2&07)<<3);
 | 
			
		||||
	} else if (is_reg(reg_1)) {
 | 
			
		||||
		/* from memory or register to register */
 | 
			
		||||
		emit1(0212 | opc); ea_2((reg_1&07)<<3);
 | 
			
		||||
	} else
 | 
			
		||||
		badsyntax();
 | 
			
		||||
        regsize(opc);
 | 
			
		||||
        if (is_segreg(reg_1)) {
 | 
			
		||||
                /* to segment register */
 | 
			
		||||
                emit1(0216); ea_2((reg_1&07)<<3);
 | 
			
		||||
        } else if (is_segreg(reg_2)) {
 | 
			
		||||
                /* from segment register */
 | 
			
		||||
                emit1(0214); ea_1((reg_2&07)<<3);
 | 
			
		||||
        } else if (is_expr(reg_2)) {
 | 
			
		||||
                /* from immediate */
 | 
			
		||||
                if (is_reg(reg_1)) {
 | 
			
		||||
                        /* to register */
 | 
			
		||||
                        emit1(0260 | opc<<3 | (reg_1&7)); 
 | 
			
		||||
                } else {
 | 
			
		||||
                        /* to memory */
 | 
			
		||||
                        emit1(0306 | opc); ea_1(0<<3); 
 | 
			
		||||
                }
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                opsize_exp(exp_2, (opc&1));
 | 
			
		||||
        } else if (rm_1 == 05 && is_acc(reg_2)) {
 | 
			
		||||
                /* from accumulator to memory  (displacement) */
 | 
			
		||||
                emit1(0242 | opc);
 | 
			
		||||
                RELOMOVE(relonami, rel_1);
 | 
			
		||||
                adsize_exp(exp_1, 0);
 | 
			
		||||
        } else if (rm_2 == 05 && is_acc(reg_1)) {
 | 
			
		||||
                /* from memory (displacement) to accumulator */
 | 
			
		||||
                emit1(0240 | opc);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                adsize_exp(exp_2, 0);
 | 
			
		||||
        } else if (is_reg(reg_2)) {
 | 
			
		||||
                /* from register to memory or register */
 | 
			
		||||
                emit1(0210 | opc); ea_1((reg_2&07)<<3);
 | 
			
		||||
        } else if (is_reg(reg_1)) {
 | 
			
		||||
                /* from memory or register to register */
 | 
			
		||||
                emit1(0212 | opc); ea_2((reg_1&07)<<3);
 | 
			
		||||
        } else
 | 
			
		||||
                badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extshft(int opc, int reg)
 | 
			
		||||
{
 | 
			
		||||
	int oreg2 = reg_2;
 | 
			
		||||
        int oreg2 = reg_2;
 | 
			
		||||
 | 
			
		||||
	reg_2 = reg_1;
 | 
			
		||||
	regsize(1);
 | 
			
		||||
        reg_2 = reg_1;
 | 
			
		||||
        regsize(1);
 | 
			
		||||
 | 
			
		||||
	emit1(0xF);
 | 
			
		||||
	if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
 | 
			
		||||
		/* cl register */
 | 
			
		||||
		emit1(opc|1);
 | 
			
		||||
		ea_1(reg << 3);
 | 
			
		||||
	}
 | 
			
		||||
	else if (is_expr(oreg2)) {
 | 
			
		||||
		emit1(opc);
 | 
			
		||||
		ea_1(reg << 3);
 | 
			
		||||
        emit1(0xF);
 | 
			
		||||
        if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
 | 
			
		||||
                /* cl register */
 | 
			
		||||
                emit1(opc|1);
 | 
			
		||||
                ea_1(reg << 3);
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_expr(oreg2)) {
 | 
			
		||||
                emit1(opc);
 | 
			
		||||
                ea_1(reg << 3);
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		newrelo(exp_2.typ, RELO1);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                newrelo(exp_2.typ, RELO1);
 | 
			
		||||
#endif
 | 
			
		||||
		emit1((int)(exp_2.val));
 | 
			
		||||
	}
 | 
			
		||||
	else	badsyntax();
 | 
			
		||||
                emit1((int)(exp_2.val));
 | 
			
		||||
        }
 | 
			
		||||
        else    badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bittestop(int opc)
 | 
			
		||||
{
 | 
			
		||||
	regsize(1);
 | 
			
		||||
	emit1(0xF);
 | 
			
		||||
	if (is_expr(reg_2)) {
 | 
			
		||||
		emit1(0272);
 | 
			
		||||
		ea_1(opc << 3);
 | 
			
		||||
        regsize(1);
 | 
			
		||||
        emit1(0xF);
 | 
			
		||||
        if (is_expr(reg_2)) {
 | 
			
		||||
                emit1(0272);
 | 
			
		||||
                ea_1(opc << 3);
 | 
			
		||||
#ifdef RELOCATION
 | 
			
		||||
		RELOMOVE(relonami, rel_2);
 | 
			
		||||
		newrelo(exp_2.typ, RELO1);
 | 
			
		||||
                RELOMOVE(relonami, rel_2);
 | 
			
		||||
                newrelo(exp_2.typ, RELO1);
 | 
			
		||||
#endif
 | 
			
		||||
		emit1((int)(exp_2.val));
 | 
			
		||||
	}
 | 
			
		||||
	else if (is_reg(reg_2)) {
 | 
			
		||||
		emit1(0203 | (opc<<3));
 | 
			
		||||
		ea_1((reg_2&7)<<3);
 | 
			
		||||
	}
 | 
			
		||||
	else	badsyntax();
 | 
			
		||||
                emit1((int)(exp_2.val));
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_reg(reg_2)) {
 | 
			
		||||
                emit1(0203 | (opc<<3));
 | 
			
		||||
                ea_1((reg_2&7)<<3);
 | 
			
		||||
        }
 | 
			
		||||
        else    badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void imul(int reg)
 | 
			
		||||
{
 | 
			
		||||
	/*	This instruction is more elaborate on the 80386. Its most
 | 
			
		||||
		general form is:
 | 
			
		||||
			imul reg, reg_or_mem, immediate.
 | 
			
		||||
		This is the form processed here.
 | 
			
		||||
	*/
 | 
			
		||||
	regsize(1);
 | 
			
		||||
	if (is_expr(reg_1)) {
 | 
			
		||||
		/* To also handle
 | 
			
		||||
			imul reg, immediate, reg_or_mem
 | 
			
		||||
		*/
 | 
			
		||||
		reverse();
 | 
			
		||||
	}
 | 
			
		||||
	if (is_expr(reg_2)) {
 | 
			
		||||
		/* The immediate form; two cases: */
 | 
			
		||||
		if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
 | 
			
		||||
			  operand_long ? 3 : 1)) {
 | 
			
		||||
			/* case 1: 1 byte encoding of immediate */
 | 
			
		||||
			emit1(0153);
 | 
			
		||||
			ea_1((reg & 07) << 3);
 | 
			
		||||
			emit1((int)(exp_2.val));
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			/* case 2: WORD or DWORD encoding of immediate */
 | 
			
		||||
			emit1(0151);
 | 
			
		||||
			ea_1((reg & 07) << 3);
 | 
			
		||||
			RELOMOVE(relonami, rel_2);
 | 
			
		||||
			opsize_exp(exp_2, 1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
 | 
			
		||||
		/* the "reg" field and the "reg_or_mem" field are the same,
 | 
			
		||||
		   and the 3rd operand is not an immediate ...
 | 
			
		||||
		*/
 | 
			
		||||
		if (reg == 0) {
 | 
			
		||||
			/* how lucky we are, the target is the ax register */
 | 
			
		||||
			/* However, we cannot make an optimization for f.i.
 | 
			
		||||
				imul eax, blablabla
 | 
			
		||||
			   because the latter does not affect edx, whereas
 | 
			
		||||
				imul blablabla
 | 
			
		||||
			   does! Therefore, "reg" is or-ed with 0x10 in the
 | 
			
		||||
			   former case, so that the test above fails.
 | 
			
		||||
			*/
 | 
			
		||||
			emit1(0367);
 | 
			
		||||
			ea_2(050);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			/* another register ... */
 | 
			
		||||
			emit1(0xF);
 | 
			
		||||
			emit1(0257);
 | 
			
		||||
			ea_2((reg & 07) << 3);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else badsyntax();
 | 
			
		||||
        /*      This instruction is more elaborate on the 80386. Its most
 | 
			
		||||
                general form is:
 | 
			
		||||
                        imul reg, reg_or_mem, immediate.
 | 
			
		||||
                This is the form processed here.
 | 
			
		||||
        */
 | 
			
		||||
        regsize(1);
 | 
			
		||||
        if (is_expr(reg_1)) {
 | 
			
		||||
                /* To also handle
 | 
			
		||||
                        imul reg, immediate, reg_or_mem
 | 
			
		||||
                */
 | 
			
		||||
                reverse();
 | 
			
		||||
        }
 | 
			
		||||
        if (is_expr(reg_2)) {
 | 
			
		||||
                /* The immediate form; two cases: */
 | 
			
		||||
                if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
 | 
			
		||||
                          operand_long ? 3 : 1)) {
 | 
			
		||||
                        /* case 1: 1 byte encoding of immediate */
 | 
			
		||||
                        emit1(0153);
 | 
			
		||||
                        ea_1((reg & 07) << 3);
 | 
			
		||||
                        emit1((int)(exp_2.val));
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        /* case 2: WORD or DWORD encoding of immediate */
 | 
			
		||||
                        emit1(0151);
 | 
			
		||||
                        ea_1((reg & 07) << 3);
 | 
			
		||||
                        RELOMOVE(relonami, rel_2);
 | 
			
		||||
                        opsize_exp(exp_2, 1);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
 | 
			
		||||
                /* the "reg" field and the "reg_or_mem" field are the same,
 | 
			
		||||
                   and the 3rd operand is not an immediate ...
 | 
			
		||||
                */
 | 
			
		||||
                if (reg == 0) {
 | 
			
		||||
                        /* how lucky we are, the target is the ax register */
 | 
			
		||||
                        /* However, we cannot make an optimization for f.i.
 | 
			
		||||
                                imul eax, blablabla
 | 
			
		||||
                           because the latter does not affect edx, whereas
 | 
			
		||||
                                imul blablabla
 | 
			
		||||
                           does! Therefore, "reg" is or-ed with 0x10 in the
 | 
			
		||||
                           former case, so that the test above fails.
 | 
			
		||||
                        */
 | 
			
		||||
                        emit1(0367);
 | 
			
		||||
                        ea_2(050);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                        /* another register ... */
 | 
			
		||||
                        emit1(0xF);
 | 
			
		||||
                        emit1(0257);
 | 
			
		||||
                        ea_2((reg & 07) << 3);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
        else badsyntax();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// vim: ts=8 sw=8 et
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,6 +86,9 @@ char* remember(char* s)
 | 
			
		|||
 | 
			
		||||
int combine(int typ1, int typ2, int op)
 | 
			
		||||
{
 | 
			
		||||
	typ1 &= ~S_VAR;
 | 
			
		||||
	typ2 &= ~S_VAR;
 | 
			
		||||
 | 
			
		||||
	switch (op)
 | 
			
		||||
	{
 | 
			
		||||
		case '+':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								plat/msdos/include/ack/plat.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								plat/msdos/include/ack/plat.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
/* $Source$
 | 
			
		||||
 * $State$
 | 
			
		||||
 * $Revision$
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ACK_PLAT_H
 | 
			
		||||
#define _ACK_PLAT_H
 | 
			
		||||
 | 
			
		||||
#define ACKCONF_WANT_O_TEXT_O_BINARY 1
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								plat/msdos/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plat/msdos/include/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								plat/msdos/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								plat/msdos/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
#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
 | 
			
		||||
							
								
								
									
										28
									
								
								plat/msdos/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								plat/msdos/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
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"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -16,9 +17,7 @@ ssize_t read(int fd, void* buffer, size_t count)
 | 
			
		|||
	ssize_t r, tot;
 | 
			
		||||
	size_t left;
 | 
			
		||||
	int eof = 0;
 | 
			
		||||
 | 
			
		||||
	if (!count || _sys_getmode(fd) == O_BINARY)
 | 
			
		||||
		return _sys_rawread(fd, buffer, count);
 | 
			
		||||
	bool text = _sys_getmode(fd) == O_TEXT;
 | 
			
		||||
 | 
			
		||||
	if (_sys_iseof(fd))
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -47,33 +46,36 @@ ssize_t read(int fd, void* buffer, size_t count)
 | 
			
		|||
		if (r <= 0)
 | 
			
		||||
			return tot ? tot : r;
 | 
			
		||||
 | 
			
		||||
		q = memchr(p, 0x1a, (size_t)r);
 | 
			
		||||
		if (q)
 | 
			
		||||
		if (text)
 | 
			
		||||
		{
 | 
			
		||||
			_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
 | 
			
		||||
			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')
 | 
			
		||||
			q = memchr(p, 0x1a, (size_t)r);
 | 
			
		||||
			if (q)
 | 
			
		||||
			{
 | 
			
		||||
				*p++ = c;
 | 
			
		||||
				++tot;
 | 
			
		||||
				_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
 | 
			
		||||
				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')
 | 
			
		||||
				{
 | 
			
		||||
					*p++ = c;
 | 
			
		||||
					++tot;
 | 
			
		||||
				}
 | 
			
		||||
				--left;
 | 
			
		||||
			}
 | 
			
		||||
			--left;
 | 
			
		||||
		}
 | 
			
		||||
	} while (tot < count && !eof && _sys_isreadyr(fd));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										74
									
								
								plat/msdos/libsys/write.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								plat/msdos/libsys/write.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
/* $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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								plat/msdos386/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plat/msdos386/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										236
									
								
								plat/msdos386/boot.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								plat/msdos386/boot.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,236 @@
 | 
			
		|||
#
 | 
			
		||||
! $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)e
 | 
			
		||||
    !   si: pointer to interrupt routine (in stub)
 | 
			
		||||
    !   di: pointer to transfer buffer (in stub)
 | 
			
		||||
 | 
			
		||||
    ! Resize the segment to include the BSS.
 | 
			
		||||
 | 
			
		||||
    o16 cseg mov (realloc_ptr+4), ax
 | 
			
		||||
    cseg mov (realloc_ptr+0), edx
 | 
			
		||||
    cseg o16 mov (pmode_cs), ax
 | 
			
		||||
    cseg o16 mov (pmode_ds), bx
 | 
			
		||||
    cseg o16 mov (rmode), cx
 | 
			
		||||
    cseg o16 mov (interrupt_ptr+4), ax
 | 
			
		||||
    cseg mov (interrupt_ptr+0), esi
 | 
			
		||||
    cseg o16 mov (transfer_buffer_ptr), di
 | 
			
		||||
 | 
			
		||||
    mov eax, __end
 | 
			
		||||
    cseg callf (realloc_ptr)
 | 
			
		||||
 | 
			
		||||
    ! Clear BSS.
 | 
			
		||||
 | 
			
		||||
    mov edi, begbss
 | 
			
		||||
    mov ecx, endbss+1
 | 
			
		||||
    sub ecx, edi
 | 
			
		||||
    shr ecx, 1
 | 
			
		||||
    xor eax, eax
 | 
			
		||||
    cld
 | 
			
		||||
    rep stosw
 | 
			
		||||
 | 
			
		||||
    ! 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
 | 
			
		||||
    mov es, ax
 | 
			
		||||
    o16 mov bx, ax
 | 
			
		||||
    o16 mov (.doshandle), bx
 | 
			
		||||
    mov es, bx
 | 
			
		||||
 | 
			
		||||
    xor ecx, ecx
 | 
			
		||||
    xor edx, edx
 | 
			
		||||
    o16 mov ax, 0x0007
 | 
			
		||||
    int 0x31                    ! set base address to 0
 | 
			
		||||
    o16 mov cx, 0x0010
 | 
			
		||||
    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.
 | 
			
		||||
    
 | 
			
		||||
    movb ah, 0x62
 | 
			
		||||
    int 0x21
 | 
			
		||||
    movzx esi, bx
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								plat/msdos386/build-pkg.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								plat/msdos386/build-pkg.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
include("plat/build.lua")
 | 
			
		||||
 | 
			
		||||
ackfile {
 | 
			
		||||
	name = "boot",
 | 
			
		||||
	srcs = { "./boot.s" },
 | 
			
		||||
	vars = { plat = "msdos386" }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ackfile {
 | 
			
		||||
	name = "stub",
 | 
			
		||||
	srcs = { "./stub.s" },
 | 
			
		||||
	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",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								plat/msdos386/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								plat/msdos386/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
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",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								plat/msdos386/descr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								plat/msdos386/descr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
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
 | 
			
		||||
							
								
								
									
										6
									
								
								plat/msdos386/include/ack/plat.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								plat/msdos386/include/ack/plat.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
#ifndef _ACK_PLAT_H
 | 
			
		||||
#define _ACK_PLAT_H
 | 
			
		||||
 | 
			
		||||
#define ACKCONF_WANT_O_TEXT_O_BINARY 1
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								plat/msdos386/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plat/msdos386/include/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								plat/msdos386/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								plat/msdos386/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
#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
 | 
			
		||||
							
								
								
									
										19
									
								
								plat/msdos386/libsys/_hol0.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								plat/msdos386/libsys/_hol0.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
! This data block is used to store information about the current line number
 | 
			
		||||
! and file.
 | 
			
		||||
 | 
			
		||||
.define hol0
 | 
			
		||||
.comm hol0, 8
 | 
			
		||||
							
								
								
									
										18
									
								
								plat/msdos386/libsys/brk.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								plat/msdos386/libsys/brk.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
.define _brk
 | 
			
		||||
_brk:
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov eax, 1*4(ebx)
 | 
			
		||||
	callf (realloc_ptr)
 | 
			
		||||
	xor eax, eax
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								plat/msdos386/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								plat/msdos386/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
acklibrary {
 | 
			
		||||
    name = "lib",
 | 
			
		||||
    srcs = {
 | 
			
		||||
		"./_hol0.s",
 | 
			
		||||
		"./brk.s",
 | 
			
		||||
		"./close.s",
 | 
			
		||||
		"./errno.s",
 | 
			
		||||
		"./getpid.s",
 | 
			
		||||
		"./isatty.s",
 | 
			
		||||
		"./rename.s",
 | 
			
		||||
		"./sbrk.c",
 | 
			
		||||
		"./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_xret.s",
 | 
			
		||||
		"./unlink.s",
 | 
			
		||||
		"plat/msdos/libsys+srcs",
 | 
			
		||||
    },
 | 
			
		||||
	deps = {
 | 
			
		||||
		"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
		"plat/msdos386/include+headers",
 | 
			
		||||
		"plat/msdos/libsys+headers",
 | 
			
		||||
	},
 | 
			
		||||
    vars = {
 | 
			
		||||
        plat = "msdos386"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								plat/msdos386/libsys/close.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								plat/msdos386/libsys/close.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Close a file.
 | 
			
		||||
 | 
			
		||||
.define _close
 | 
			
		||||
_close:
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov ebx, 1*4(esp)
 | 
			
		||||
	movb ah, 0x3E
 | 
			
		||||
	int 0x21
 | 
			
		||||
	jmp .sys_zret
 | 
			
		||||
							
								
								
									
										28
									
								
								plat/msdos386/libsys/errno.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								plat/msdos386/libsys/errno.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
#define D(e) .define e; e
 | 
			
		||||
 | 
			
		||||
.sect .data
 | 
			
		||||
 | 
			
		||||
! Define various ACK error numbers. Note that these are *not* ANSI C
 | 
			
		||||
! errnos, and are used for different purposes.
 | 
			
		||||
 | 
			
		||||
D(ERANGE)         = 1
 | 
			
		||||
D(ESET)           = 2
 | 
			
		||||
D(EIDIVZ)         = 6
 | 
			
		||||
D(EHEAP)          = 17
 | 
			
		||||
D(EILLINS)        = 18
 | 
			
		||||
D(EODDZ)          = 19
 | 
			
		||||
D(ECASE)          = 20
 | 
			
		||||
D(EBADMON)        = 25
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								plat/msdos386/libsys/getpid.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								plat/msdos386/libsys/getpid.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
#
 | 
			
		||||
! $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.
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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
 | 
			
		||||
	int 0x21
 | 
			
		||||
	xchg ebx, eax
 | 
			
		||||
.eur_dos:
 | 
			
		||||
	xor edx, edx
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										37
									
								
								plat/msdos386/libsys/isatty.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								plat/msdos386/libsys/isatty.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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
 | 
			
		||||
							
								
								
									
										54
									
								
								plat/msdos386/libsys/rename.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								plat/msdos386/libsys/rename.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
#
 | 
			
		||||
! $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 ebx, esp
 | 
			
		||||
	push esi
 | 
			
		||||
	push edi
 | 
			
		||||
 | 
			
		||||
	! Source filename.
 | 
			
		||||
 | 
			
		||||
	mov esi, 4(ebx)
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
    mov es, (pmode_ds)
 | 
			
		||||
    cld
 | 
			
		||||
1:
 | 
			
		||||
	lodsb
 | 
			
		||||
	stosb
 | 
			
		||||
	testb al, al
 | 
			
		||||
	jnz 1b
 | 
			
		||||
	
 | 
			
		||||
	! Destination filename.
 | 
			
		||||
 | 
			
		||||
	mov eax, edi
 | 
			
		||||
	mov esi, 8(ebx)
 | 
			
		||||
1:
 | 
			
		||||
	lodsb
 | 
			
		||||
	stosb
 | 
			
		||||
	testb al, al
 | 
			
		||||
	jnz 1b
 | 
			
		||||
	
 | 
			
		||||
	! Make the DOS call.
 | 
			
		||||
 | 
			
		||||
	o16 mov dx, (transfer_buffer_ptr)
 | 
			
		||||
	o16 mov di, ax
 | 
			
		||||
	movb ah, 0x56
 | 
			
		||||
	or ebx, 0x210000
 | 
			
		||||
	callf (interrupt_ptr)
 | 
			
		||||
	pop edi
 | 
			
		||||
	pop esi
 | 
			
		||||
	jmp .sys_zret
 | 
			
		||||
							
								
								
									
										40
									
								
								plat/msdos386/libsys/sbrk.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								plat/msdos386/libsys/sbrk.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
/* $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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								plat/msdos386/libsys/sys_exists.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plat/msdos386/libsys/sys_exists.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Say whether a file exists with the given name.
 | 
			
		||||
 | 
			
		||||
.define __sys_exists
 | 
			
		||||
__sys_exists:
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov edx, 4(ebx)
 | 
			
		||||
	mov eax, 0x4300
 | 
			
		||||
	int 0x21
 | 
			
		||||
	sbb eax, eax
 | 
			
		||||
	inc eax
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										25
									
								
								plat/msdos386/libsys/sys_getdate.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plat/msdos386/libsys/sys_getdate.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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
 | 
			
		||||
							
								
								
									
										26
									
								
								plat/msdos386/libsys/sys_gettime.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								plat/msdos386/libsys/sys_gettime.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Get the current system time from MS-DOS.
 | 
			
		||||
 | 
			
		||||
.define __sys_gettime
 | 
			
		||||
__sys_gettime:
 | 
			
		||||
	int 3
 | 
			
		||||
	movb ah, 0x2c
 | 
			
		||||
	int 0x21
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov ebx, 4(ebx)
 | 
			
		||||
	o16 mov 0(ebx), cx
 | 
			
		||||
	o16 mov 2(ebx), dx
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										26
									
								
								plat/msdos386/libsys/sys_isopen.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								plat/msdos386/libsys/sys_isopen.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Say whether a given file descriptor number refers to a valid open file
 | 
			
		||||
! descriptor.
 | 
			
		||||
 | 
			
		||||
.define __sys_isopen
 | 
			
		||||
__sys_isopen:
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov ebx, 4(bx)
 | 
			
		||||
	mov eax, 0x4400
 | 
			
		||||
	int 0x21
 | 
			
		||||
	sbb eax, eax
 | 
			
		||||
	inc eax
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										29
									
								
								plat/msdos386/libsys/sys_isreadyr.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								plat/msdos386/libsys/sys_isreadyr.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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
 | 
			
		||||
							
								
								
									
										45
									
								
								plat/msdos386/libsys/sys_rawcreat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								plat/msdos386/libsys/sys_rawcreat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Create or truncate a file.
 | 
			
		||||
 | 
			
		||||
.define __sys_rawcreat
 | 
			
		||||
__sys_rawcreat:
 | 
			
		||||
	! Copy filename to transfer buffer.
 | 
			
		||||
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	push esi
 | 
			
		||||
	push edi
 | 
			
		||||
	mov esi, 4(ebx)
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
    mov es, (pmode_ds)
 | 
			
		||||
    cld
 | 
			
		||||
1:
 | 
			
		||||
	lodsb
 | 
			
		||||
	stosb
 | 
			
		||||
	testb al, al
 | 
			
		||||
	jnz 1b
 | 
			
		||||
 | 
			
		||||
	! Make the DOS call.
 | 
			
		||||
 | 
			
		||||
	movb ah, 0x3c
 | 
			
		||||
	movzx edx, (transfer_buffer_ptr)
 | 
			
		||||
	movb al, 8(ebx)
 | 
			
		||||
	or ebx, 0x210000
 | 
			
		||||
	callf (interrupt_ptr)
 | 
			
		||||
 | 
			
		||||
	pop edi
 | 
			
		||||
	pop esi
 | 
			
		||||
	jmp .sys_axret
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								plat/msdos386/libsys/sys_rawlseek.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								plat/msdos386/libsys/sys_rawlseek.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Move the current file position for a file descriptor.
 | 
			
		||||
 | 
			
		||||
.define __sys_rawlseek
 | 
			
		||||
__sys_rawlseek:
 | 
			
		||||
	movb ah, 0x42
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	mov edx, 8(bx)
 | 
			
		||||
	mov ecx, 12(bx)
 | 
			
		||||
	movb al, 16(bx)
 | 
			
		||||
	mov ebx, 4(bx)
 | 
			
		||||
	int 0x21
 | 
			
		||||
	jmp .sys_dxaxret
 | 
			
		||||
							
								
								
									
										45
									
								
								plat/msdos386/libsys/sys_rawopen.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								plat/msdos386/libsys/sys_rawopen.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Open an existing file.
 | 
			
		||||
 | 
			
		||||
.define __sys_rawopen
 | 
			
		||||
__sys_rawopen:
 | 
			
		||||
	! Copy filename to transfer buffer.
 | 
			
		||||
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	push esi
 | 
			
		||||
	push edi
 | 
			
		||||
 | 
			
		||||
	mov esi, 4(ebx)
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
    mov es, (pmode_ds)
 | 
			
		||||
    cld
 | 
			
		||||
1:
 | 
			
		||||
	lodsb
 | 
			
		||||
	stosb
 | 
			
		||||
	testb al, al
 | 
			
		||||
	jnz 1b
 | 
			
		||||
 | 
			
		||||
	! Make the DOS call.
 | 
			
		||||
 | 
			
		||||
	movb ah, 0x3d
 | 
			
		||||
	o16 mov dx, (transfer_buffer_ptr)
 | 
			
		||||
	movb al, 8(ebx)
 | 
			
		||||
	or ebx, 0x210000
 | 
			
		||||
	callf (interrupt_ptr)
 | 
			
		||||
 | 
			
		||||
	pop edi
 | 
			
		||||
	pop esi
 | 
			
		||||
	jmp .sys_axret
 | 
			
		||||
							
								
								
									
										74
									
								
								plat/msdos386/libsys/sys_rawread.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								plat/msdos386/libsys/sys_rawread.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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:
 | 
			
		||||
	enter 0, 0
 | 
			
		||||
	push esi
 | 
			
		||||
	push edi
 | 
			
		||||
file_handle = 2*4
 | 
			
		||||
write_buffer = 3*4
 | 
			
		||||
amount_to_read = 4*4
 | 
			
		||||
 | 
			
		||||
	mov eax, amount_to_read(ebp)
 | 
			
		||||
	mov ecx, 32*1024
 | 
			
		||||
	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(ebp)
 | 
			
		||||
	or ebx, 0x210000
 | 
			
		||||
	callf (interrupt_ptr)
 | 
			
		||||
	jnc success
 | 
			
		||||
 | 
			
		||||
	! Process errors.
 | 
			
		||||
 | 
			
		||||
	push eax
 | 
			
		||||
	call __sys_seterrno
 | 
			
		||||
	pop ecx
 | 
			
		||||
	jmp exit
 | 
			
		||||
success:
 | 
			
		||||
 | 
			
		||||
	! Copy eax bytes out of the transfer buffer.
 | 
			
		||||
 | 
			
		||||
	push eax
 | 
			
		||||
	mov ecx, eax
 | 
			
		||||
	movzx esi, (transfer_buffer_ptr)
 | 
			
		||||
	mov edi, write_buffer(ebp)
 | 
			
		||||
	mov es, (pmode_ds)
 | 
			
		||||
	cld
 | 
			
		||||
1:
 | 
			
		||||
	eseg lodsb
 | 
			
		||||
	movb (edi), al
 | 
			
		||||
	inc edi
 | 
			
		||||
	loop 1b
 | 
			
		||||
	pop eax
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
	pop edi
 | 
			
		||||
	pop esi
 | 
			
		||||
	leave
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								plat/msdos386/libsys/sys_rawwrite.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								plat/msdos386/libsys/sys_rawwrite.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! 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:
 | 
			
		||||
    enter 0, 0
 | 
			
		||||
    push esi
 | 
			
		||||
    push edi
 | 
			
		||||
file_handle = 2*4
 | 
			
		||||
read_buffer = 3*4
 | 
			
		||||
amount_to_write = 4*4
 | 
			
		||||
 | 
			
		||||
    mov eax, amount_to_write(ebp)
 | 
			
		||||
    mov ecx, 32*1024        ! size of transfer buffer
 | 
			
		||||
    cmp eax, ecx
 | 
			
		||||
    jge 2f
 | 
			
		||||
    mov ecx, eax
 | 
			
		||||
2:
 | 
			
		||||
 | 
			
		||||
    ! Copy ecx bytes into the transfer buffer.
 | 
			
		||||
 | 
			
		||||
    push ecx
 | 
			
		||||
    mov esi, read_buffer(ebp)
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
    mov es, (pmode_ds)
 | 
			
		||||
    cld
 | 
			
		||||
    rep movsb
 | 
			
		||||
    pop ecx
 | 
			
		||||
 | 
			
		||||
    ! Write from the transfer buffer to DOS.
 | 
			
		||||
 | 
			
		||||
    movb ah, 0x40
 | 
			
		||||
    o16 mov dx, (transfer_buffer_ptr)
 | 
			
		||||
    o16 mov bx, file_handle(ebp)
 | 
			
		||||
    or ebx, 0x210000
 | 
			
		||||
    callf (interrupt_ptr)
 | 
			
		||||
    jnc exit
 | 
			
		||||
 | 
			
		||||
    push eax
 | 
			
		||||
    call __sys_seterrno
 | 
			
		||||
    pop ecx
 | 
			
		||||
exit:
 | 
			
		||||
    pop edi
 | 
			
		||||
    pop esi
 | 
			
		||||
    leave
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
! vim: sw=4 ts=4 et
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								plat/msdos386/libsys/sys_xret.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								plat/msdos386/libsys/sys_xret.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! .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 ax as a return value.
 | 
			
		||||
!
 | 
			
		||||
! .sys_dxaxret: same as .sys_axret, but return -1 or dx:ax as a return value.
 | 
			
		||||
 | 
			
		||||
.extern .sys_zret
 | 
			
		||||
.extern .sys_axret
 | 
			
		||||
.extern .sys_dxaxret
 | 
			
		||||
.sys_zret:
 | 
			
		||||
	jc error
 | 
			
		||||
	xor eax, eax
 | 
			
		||||
no_error:
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.sys_axret:
 | 
			
		||||
	jc error
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.sys_dxaxret:
 | 
			
		||||
	jc error
 | 
			
		||||
	shl edx, 16
 | 
			
		||||
	o16 mov dx, ax
 | 
			
		||||
	mov eax, edx
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	movzx eax, ax
 | 
			
		||||
	push eax
 | 
			
		||||
	call __sys_seterrno
 | 
			
		||||
	pop ecx
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										44
									
								
								plat/msdos386/libsys/unlink.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								plat/msdos386/libsys/unlink.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
 | 
			
		||||
! Remove a file.
 | 
			
		||||
 | 
			
		||||
.define _unlink
 | 
			
		||||
_unlink:
 | 
			
		||||
	! Copy filename to transfer buffer.
 | 
			
		||||
 | 
			
		||||
	mov ebx, esp
 | 
			
		||||
	push esi
 | 
			
		||||
	push edi
 | 
			
		||||
 | 
			
		||||
	mov esi, 4(ebx)
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
    mov es, (pmode_ds)
 | 
			
		||||
    cld
 | 
			
		||||
1:
 | 
			
		||||
	lodsb
 | 
			
		||||
	stosb
 | 
			
		||||
	testb al, al
 | 
			
		||||
	jnz 1b
 | 
			
		||||
 | 
			
		||||
	! Make the DOS call.
 | 
			
		||||
 | 
			
		||||
    movzx edi, (transfer_buffer_ptr)
 | 
			
		||||
	movb ah, 0x41
 | 
			
		||||
	or ebx, 0x210000
 | 
			
		||||
	callf (interrupt_ptr)
 | 
			
		||||
 | 
			
		||||
	pop edi
 | 
			
		||||
	pop esi
 | 
			
		||||
	jmp .sys_zret
 | 
			
		||||
							
								
								
									
										410
									
								
								plat/msdos386/stub.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								plat/msdos386/stub.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,410 @@
 | 
			
		|||
#
 | 
			
		||||
! $Source$
 | 
			
		||||
! $State$
 | 
			
		||||
! $Revision$
 | 
			
		||||
 | 
			
		||||
! Declare segments (the order is important).
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.sect .rom
 | 
			
		||||
.sect .data
 | 
			
		||||
.sect .bss
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.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 es, 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, es
 | 
			
		||||
    mov ax, 0x0007
 | 
			
		||||
    int 0x31                    ! set segment base address
 | 
			
		||||
    jc bad_dpmi
 | 
			
		||||
 | 
			
		||||
    mov bx, es
 | 
			
		||||
    mov dx, (pmemlen+0)
 | 
			
		||||
    mov cx, (pmemlen+2)
 | 
			
		||||
    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, es
 | 
			
		||||
    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, es
 | 
			
		||||
    int 0x31
 | 
			
		||||
    mov fs, 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, fs
 | 
			
		||||
    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
 | 
			
		||||
    o32 rep 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
 | 
			
		||||
    push es
 | 
			
		||||
    pop ds
 | 
			
		||||
    push es
 | 
			
		||||
    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 is 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, (psegds32)
 | 
			
		||||
    mov dx, (pmemlen+0)
 | 
			
		||||
    mov cx, (pmemlen+2)
 | 
			
		||||
    mov ax, 0x0008
 | 
			
		||||
    int 0x31                    ! set ds segment limit
 | 
			
		||||
    jc bad_dpmi
 | 
			
		||||
    mov dx, (pmemaddr+0)
 | 
			
		||||
    mov cx, (pmemaddr+2)
 | 
			
		||||
    mov ax, 0x0007
 | 
			
		||||
    int 0x31                    ! set ds linear address
 | 
			
		||||
    jc bad_dpmi
 | 
			
		||||
    mov bx, (psegcs32)
 | 
			
		||||
    int 0x31                    ! set cs linear address
 | 
			
		||||
    jc bad_dpmi
 | 
			
		||||
    
 | 
			
		||||
    popa
 | 
			
		||||
    o32 mov eax, (pmemlen)
 | 
			
		||||
    cli                         ! atomically switch stacks back
 | 
			
		||||
    mov ss, (dpmi_ss)
 | 
			
		||||
    o32 mov esp, (dpmi_ebp)
 | 
			
		||||
    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 or ebx, 0x210000
 | 
			
		||||
    ! Simulate interrupt in the high half of ebx.
 | 
			
		||||
interrupt:
 | 
			
		||||
    mov (dpmi_eax), ax
 | 
			
		||||
    mov (dpmi_ebx), bx
 | 
			
		||||
    mov (dpmi_ecx), cx
 | 
			
		||||
    mov (dpmi_edx), dx
 | 
			
		||||
    mov (dpmi_esi), si
 | 
			
		||||
    mov (dpmi_edi), di
 | 
			
		||||
    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
 | 
			
		||||
    int 0x31                    ! simulate DOS interrupt
 | 
			
		||||
    pop es
 | 
			
		||||
    o32 movzx eax, (dpmi_eax)
 | 
			
		||||
    o32 movzx ebx, (dpmi_ebx)
 | 
			
		||||
    o32 movzx ecx, (dpmi_ecx)
 | 
			
		||||
    o32 movzx edx, (dpmi_edx)
 | 
			
		||||
    o32 movzx esi, (dpmi_esi)
 | 
			
		||||
    o32 movzx 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_SIZE = 32*1024
 | 
			
		||||
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
 | 
			
		||||
	program {EM}/bin/{LOD}
 | 
			
		||||
	args < >
 | 
			
		||||
	outfile msdos86.exe
 | 
			
		||||
	outfile msdos86.com
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,42 +3,28 @@ acklibrary {
 | 
			
		|||
    srcs = {
 | 
			
		||||
		"./brk.c",
 | 
			
		||||
		"./close.s",
 | 
			
		||||
		"./creat.c",
 | 
			
		||||
		"./errno.s",
 | 
			
		||||
		"./getpid.s",
 | 
			
		||||
		"./gettimeofday.c",
 | 
			
		||||
		"./_hol0.s",
 | 
			
		||||
		"./isatty.s",
 | 
			
		||||
		"./kill.c",
 | 
			
		||||
		"./lseek.c",
 | 
			
		||||
		"./open.c",
 | 
			
		||||
		"./read.c",
 | 
			
		||||
		"./rename.s",
 | 
			
		||||
		"./setmode.c",
 | 
			
		||||
		"./signal.c",
 | 
			
		||||
		"./sys_exists.s",
 | 
			
		||||
		"./sys_fdmodes.c",
 | 
			
		||||
		"./sys_getdate.s",
 | 
			
		||||
		"./sys_getmode.c",
 | 
			
		||||
		"./sys_gettime.s",
 | 
			
		||||
		"./sys_initmain.c",
 | 
			
		||||
		"./sys_iseof.c",
 | 
			
		||||
		"./sys_isopen.s",
 | 
			
		||||
		"./sys_isreadyr.s",
 | 
			
		||||
		"./sys_rawcreat.s",
 | 
			
		||||
		"./sys_rawlseek.s",
 | 
			
		||||
		"./sys_rawopen.s",
 | 
			
		||||
		"./sys_rawrw.s",
 | 
			
		||||
		"./sys_seteof.c",
 | 
			
		||||
		"./sys_seterrno.c",
 | 
			
		||||
		"./sys_setmode.c",
 | 
			
		||||
		"./sys_xret.s",
 | 
			
		||||
		"./unlink.s",
 | 
			
		||||
		"./write.c",
 | 
			
		||||
		"plat/msdos/libsys+srcs",
 | 
			
		||||
    },
 | 
			
		||||
	deps = {
 | 
			
		||||
		"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
		"plat/msdos86/include+headers",
 | 
			
		||||
		"plat/msdos/libsys+headers",
 | 
			
		||||
	},
 | 
			
		||||
    vars = {
 | 
			
		||||
        plat = "msdos86"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,61 +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;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
aslod \- ACK simple loader
 | 
			
		||||
.SH SYNOPSIS
 | 
			
		||||
.B aslod
 | 
			
		||||
[\-h] [\-v] inputfile outputfile
 | 
			
		||||
[\-h] [\-v] [\-p prefixfile] inputfile outputfile
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
.I aslod
 | 
			
		||||
converts an absolute ack.out file into a simple binary memory dump.
 | 
			
		||||
| 
						 | 
				
			
			@ -16,5 +16,8 @@ The file must have all references resolved and be linked to a
 | 
			
		|||
fixed address. aslod will dump the segments, in order, such
 | 
			
		||||
that the first byte of TEXT is at offset 0 in the file
 | 
			
		||||
(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"
 | 
			
		||||
ack.out(5)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ struct outsect outsect[S_MAX];
 | 
			
		|||
char* stringarea;
 | 
			
		||||
 | 
			
		||||
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] */
 | 
			
		||||
 | 
			
		||||
FILE* input;                            /* Input stream */
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +137,19 @@ 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 */
 | 
			
		||||
#define Xchar(ch)	((ch) & 0377)
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +218,12 @@ int main(int argc, char* argv[])
 | 
			
		|||
				verbose = true;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case 'p':
 | 
			
		||||
				argv++;
 | 
			
		||||
				argc--;
 | 
			
		||||
				prefixfile = argv[1];
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
			syntaxerror:
 | 
			
		||||
				fatal("syntax error --- try -h for help");
 | 
			
		||||
| 
						 | 
				
			
			@ -288,6 +308,8 @@ int main(int argc, char* argv[])
 | 
			
		|||
 | 
			
		||||
	/* And go! */
 | 
			
		||||
	
 | 
			
		||||
	if (prefixfile)
 | 
			
		||||
		emitprefixfile();
 | 
			
		||||
	emits(&outsect[TEXT], &outsect[ROM]);
 | 
			
		||||
	emits(&outsect[ROM], &outsect[DATA]);
 | 
			
		||||
	emits(&outsect[DATA], NULL);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue