home *** CD-ROM | disk | FTP | other *** search
- {Inline16}
-
- (********* Source code Copyright 1986, by L. David Baldwin *********)
-
- {Compiling with mAx=2000 will give sufficient heap for most applications
- and prevent overwriting COMMAND.COM in most cases.}
-
- {$v-}
- PROGRAM Inline_Asm;
-
- const
- CommentColumn = 25; {column where comments start in object file}
- symbolleng = 32; {maximum of 32 char symbols}
- cr = 13; lf = 10; tab = 9;
- maxbyte = MaxInt;
- bigstringsize = 127;
-
- signon1 : string[32] =
-
- ^m^j'Inline Assembler, Vers 2.02';
-
- signon2 : string[43] =
-
- ^m^j'(C) Copyright 1986 by L. David Baldwin'^m^j;
-
- type
- filestring = string[64];
- symstring = string[symbolleng];
- indxreg = (bx, si, di, bp, none);
- indxset = set of indxreg;
- ptrtype = (bptr, wptr, dwptr, qwptr, tbptr, unkptr); {keep order}
- string4 = string[4];
- string5 = array[1..5] of Char;
- symtype = (address, disp8, disp16, othersym, EOLsym, identifier, jmpdist,
- lfbrack, rtbrack, plus, comma, STsym);
- table = array[0..20] of symstring; {fake}
- bigstring = string[bigstringsize]; {125 chars on a turbo line}
- label_info_ptr = ^label_info;
- label_info = record
- name : symstring;
- bytecnt : Integer;
- next : label_info_ptr;
- end;
- fixup_info_ptr = ^fixup_info;
- fixup_info = record
- name : symstring;
- indx, indx2, fix_pt : Integer;
- jmptype : (short, med);
- prev, next : fixup_info_ptr;
- end;
-
- var
- NoAddrs, aerr, symbol, str_start, TheEnd, st_first : Boolean;
- Addr : Integer;
- sym : symtype;
- modebyt, reg1, reg2, w1, w2, sti_val : Integer;
- displace, wordd, bits_7 : Boolean;
- SaveOfs, DataVal : record
- symb : Boolean;
- sname : symstring;
- value : Integer;
- end;
- irset : indxset;
- rmm, md : Integer;
- ByWord : ptrtype;
- byt, signext : Byte;
- tindex, tindex0, column, I, ByteCount : Integer;
- TextArray : array[0..maxbyte] of Char;
-
- Lsid : symstring;
- Str8 : array[1..9] of Char; {the following 4 are at the same location}
- Str : string5 absolute Str8;
- id2 : array[1..2] of Char absolute Str8;
- id3 : array[1..3] of Char absolute Str8;
- Uch, Lch : Char;
- Chi, OldChi : Integer;
- out, inn : Text;
-
- start_col : Integer;
- st : bigstring;
- id : string[2];
- firstlabel, pl : label_info_ptr;
- firstfix, pf : fixup_info_ptr;
-
- {-------------DefaultExtension}
- PROCEDURE DefaultExtension(extension:filestring;VAR infile,name :filestring);
- {Given a filename, infile, add a default extension if none exists. Return
- also the name without any extension.}
- var
- I,J : Integer;
- temp : filestring;
- begin
- I:=Pos('..',infile);
- if I=0 then
- temp:=infile
- else
- {a pathname starting with ..}
- temp:=Copy(infile,I+2,64);
- J:=Pos('.',temp);
- if J=0 then
- begin
- name := infile;
- infile:=infile+'.'+extension;
- end
- else name:=Copy(infile,1,I+J);
- end;
-
- {-------------Space}
- PROCEDURE Space(N : Integer);
- var I : Integer;
- begin for I := 1 to N do Write(' '); end;
-
- {-------------Error}
- PROCEDURE Error(ii : Integer; S : bigstring);
- var C : Char;
- begin
- if not aerr then
- begin
- WriteLn(st);
- Space(start_col+ii-4);
- Write('^Error');
- if Length(S) > 0 then
- begin Write(', '); Write(S); end;
- WriteLn;
- aerr := True;
- end;
- end;
-
- {the following are definitions and variables for the parser}
- const
- letter : set of Char = ['A'..'Z'];
- var segm, nvalue : Integer;
- symname : symstring;
- {end of parser defs}
-
- {-------------GetCh}
- PROCEDURE GetCh;
- {return next char in uch and lch with uch in upper case.}
- begin
- if Chi <= Ord(st[0]) then Lch := st[Chi] else Lch := Chr(cr);
- Uch := UpCase(Lch);
- Chi := Chi+1;
- end;
-
- {-------------skipspaces}
- PROCEDURE skipspaces;
- begin
- while (Uch = ' ') or (Uch = Chr(tab)) do GetCh;
- end;
-
- {-------------getdec}
- FUNCTION getdec(var v : Integer) : Boolean;
- const ssize = 8;
- var
- S : string[ssize];
- getd : Boolean;
- code : Integer;
- begin
- getd := False;
- S := '';
- while (Uch >= '0') and (Uch <= '9') do
- begin
- getd := True;
- if Ord(S[0]) < ssize then S := S+Uch;
- GetCh;
- end;
- if getd then
- begin
- Val(S, v, code);
- if code <> 0 then Error(Chi, 'Bad number format');
- end;
- getdec := getd;
- end;
-
- {-------------gethex}
- FUNCTION gethex(var h : Integer) : Boolean;
- var digit : Integer; {check for '$' before the call}
- begin
- h := 0; gethex := False;
- while (Uch in ['A'..'F', '0'..'9']) do
- begin
- gethex := True;
- if (Uch >= 'A') then digit := Ord(Uch)-Ord('A')+10
- else digit := Ord(Uch)-Ord('0');
- if h >= $1000 then Error(Chi, 'Overflow');
- h := (h shl 4)+digit;
- GetCh;
- end;
- end;
-
- {-------------getnumber}
- FUNCTION getnumber(var N : Integer) : Boolean;
- {get a number and return it in n}
- var term : Char;
- err : Boolean;
- begin {should also handle characters in quotes!!}
- N := 0;
- if Uch = '(' then GetCh; {ignore ( }
- if (Uch = '''') or (Uch = '"') then
- begin
- term := Uch; GetCh; err := False;
- while (Uch <> term) and not err do
- begin
- err := N and $ff00 <> 0;
- N := (N shl 8)+Ord(Lch);
- GetCh;
- if err then Error(Chi, 'Overflow');
- end;
- GetCh; {use up termination char}
- end
- else if Uch = '$' then
- begin {a hex number}
- GetCh;
- if not gethex(N) then Error(Chi, 'Hex number exp');
- getnumber := True;
- end
- else
- getnumber := getdec(N); {maybe a decimal number}
- if Uch = ')' then GetCh; {ignore an ending parenthesis}
- end;
-
- {-------------getexpr}
- FUNCTION getexpr(var rslt : Integer) : Boolean;
- var
- rs1, rs2, SaveChi : Integer;
- Pos, Neg : Boolean;
- begin
- SaveChi := Chi;
- getexpr := False;
- skipspaces;
- Neg := Uch = '-';
- Pos := Uch = '+';
- if Pos or Neg then GetCh;
- if getnumber(rs1) then
- begin
- getexpr := True;
- if Neg then rs1 := -rs1;
- if (Uch = '+') or (Uch = '-') then
- if getexpr(rs2) then
- rs1 := rs1+rs2; {getexpr will take care of sign}
- rslt := rs1;
- end
- else
- begin
- Chi := SaveChi-1; GetCh;
- end;
- end;
-
- {$v+}
- {-------------getsymbol}
- FUNCTION getsymbol(var S : symstring) : Boolean;
- const symchars : set of Char = ['A'..'Z', '0'..'9', '_', '+', '-'];
- begin
- if Uch in letter then
- begin
- getsymbol := True;
- S[0] := Chr(0);
- while Uch in symchars do
- begin
- if Ord(S[0]) < symbolleng then S := S+Uch;
- GetCh;
- end
- end
- else getsymbol := False;
- end;
- {$v-}
-
- {-------------getaddress}
- FUNCTION getaddress : Boolean;
- var result : Boolean;
- SaveChi : Integer;
- begin
- result := False; SaveChi := Chi;
- if getexpr(segm) then
- begin
- skipspaces;
- if Uch = ':' then
- begin
- GetCh; skipspaces;
- result := getexpr(nvalue);
- end;
- end;
- getaddress := result;
- if not result then
- begin Chi := SaveChi-1; GetCh; end;
- end;
-
- {-------------errnull}
- PROCEDURE errnull;
- begin Error(Chi, ''); end;
-
- {-------------errincorrect}
- PROCEDURE errincorrect;
- begin Error(Chi, 'Incorrect or No Operand'); end;
-
- {-------------segmerr}
- PROCEDURE segmerr;
- begin Error(Chi, 'Segm Reg not Permitted'); end;
-
- {-------------wordreg}
- PROCEDURE wordreg;
- begin Error(Chi, 'Word Reg Exp'); end;
-
- {-------------datalarge}
- PROCEDURE datalarge;
- begin Error(Chi, 'Data Too Large'); end;
-
- {-------------chk_bwptr}
- PROCEDURE chk_bwptr;
- begin
- if ByWord >= dwptr then Error(Chi, 'BYTE or WORD Req''d');
- end;
-
- {-------------bytesize}
- FUNCTION bytesize(Val : Integer) : Boolean;
- {return true if val is a byte}
- begin
- bytesize := (Hi(Val) = 0) or (Val and $ff80 = $ff80);
- end;
-
- {-------------readbyte}
- FUNCTION readbyte : Boolean;
- var rb : Boolean;
- begin
- rb := getexpr(nvalue);
- if rb then
- if bytesize(nvalue) then
- byt := Lo(nvalue)
- else datalarge;
- readbyte := rb;
- end;
-
- {-------------matchlst}
- FUNCTION matchlst(var table; size, maxindx : Integer; var indx : Integer) :
- Boolean; {see if str8 matches any string in a table}
- var ca : array[0..MaxInt] of Char absolute table;
- rslt : Boolean;
-
- FUNCTION eqarray(var a1; N : Integer) : Boolean;
- type bigarray = array[1..MaxInt] of Char;
- var
- b1 : bigarray absolute a1;
- I : Integer;
- begin
- for I := 1 to N do
- if b1[I] <> Str8[I] then
- begin eqarray := False; Exit; end;
- eqarray := Str8[N+1] = ' '; {must have blank on end for complete match}
- end;
-
- begin
- indx := 0; rslt := False;
- while (indx <= maxindx) and not rslt do
- if eqarray(ca[indx*size], size) then
- rslt := True
- else
- indx := indx+1;
- matchlst := rslt;
- end;
-
- {-------------getstring}
- PROCEDURE getstring;
- {Fill in lsid, str8, str, id2,id3. They are, in fact, all in the
- same locations}
- var I : Integer;
- begin
- skipspaces;
- Lsid := ' ';
- I := 1;
- if (Uch >= 'A') and (Uch <= 'Z') then
- begin
- while (Uch >= 'A') and (Uch <= 'Z') or (Uch >= '0') and (Uch <= '9') do
- begin
- if I <= symbolleng then
- begin Lsid[I] := Uch; I := I+1; end;
- GetCh;
- end;
- end;
- Lsid[0] := Chr(I-1);
- Move(Lsid[1], Str8, 9); {Fill in str8,str,id2,id3}
- end;
-
- {-------------InsertChr}
- PROCEDURE InsertChr(C : Char);
- begin
- if tindex <= maxbyte then
- begin
- TextArray[tindex] := C;
- tindex := tindex+1; column := column+1;
- end
- else
- begin
- WriteLn('Object Code Overflow!');
- Halt(1);
- end;
- end;
-
- {-------------InsertStr}
- PROCEDURE InsertStr(S : bigstring);
- var I : Integer;
- begin
- for I := 1 to Ord(S[0]) do InsertChr(S[I]);
- end;
-
- {-------------Hex2}
- FUNCTION Hex2(B : Byte) : string4;
- const hexdigs : array[0..15] of Char = '0123456789ABCDEF';
- var bz : Byte;
- begin
- bz := B and $f; B := B shr 4;
- Hex2 := hexdigs[B]+hexdigs[bz];
- end;
-
- {-------------Hex4}
- FUNCTION Hex4(W : Integer) : string4;
- begin Hex4 := Hex2(Lo(W))+Hex2(Hi(W)); end;
-
- {-------------InsertByte}
- PROCEDURE InsertByte(B : Byte);
- begin
- if not str_start then InsertChr('/');
- InsertStr('$'+Hex2(B));
- ByteCount := ByteCount+1;
- str_start := False;
- end;
-
- {-------------InsertWord}
- PROCEDURE InsertWord(W : Integer);
- begin
- InsertByte(Lo(W)); InsertByte(Hi(W));
- end;
-
- {-------------InsertHi_Low}
- PROCEDURE InsertHi_Low(W : Integer);
- {insert a word in reverse order}
- begin
- InsertByte(Hi(W)); InsertByte(Lo(W));
- end;
-
- {-------------modify_byte}
- PROCEDURE modify_byte(I : Integer; modify : Byte);
- {Modify an ascii byte string in textarray by adding modify to its value}
- var
- st : string4;
- J : Integer;
-
- FUNCTION hextobyte(I : Integer; var J : Integer) : Byte;
- {Starting at tindex, i, convert hex to a byte. return j, the tindex where
- byte started}
- var
- result, tmp : Byte;
- C : Char;
- const hex : set of Char = ['0'..'9', 'A'..'F'];
- begin
- result := 0;
- while not(TextArray[I] in hex) do I := I+1; {skip '/' and '$'}
- J := I; C := TextArray[I];
- while C in hex do
- begin
- if C <= '9' then tmp := Ord(C)-Ord('0') else tmp := Ord(C)-Ord('A')+10;
- result := (result shl 4)+tmp;
- I := I+1;
- C := TextArray[I];
- end;
- hextobyte := result;
- end;
-
- begin
- st := Hex2(hextobyte(I, J)+modify);
- TextArray[J] := st[1];
- TextArray[J+1] := st[2];
- end;
-
- {-------------DoNext}
- PROCEDURE DoNext;
- var I : Integer;
- err : Boolean;
- tmpch : Char;
-
- begin
- OldChi := Chi;
- symbol := False;
- if sym = EOLsym then Exit; {do nothing}
- skipspaces; {note commas are significant}
- if (Uch = Chr(cr)) or (Uch = ';') then sym := EOLsym
- else if Uch = ',' then begin sym := comma; GetCh; end
- else if (Uch = '>') or (Uch = '<') then
- begin
- tmpch := Uch; GetCh;
- if not getsymbol(symname) then Error(Chi, 'Symbol Name Exp');
- if tmpch = '<' then sym := disp8 else sym := disp16;
- symbol := True; {disp8/16 is a symbol}
- end
- else if getaddress then
- begin
- if NoAddrs then errnull
- else sym := address;
- end
- else if getexpr(nvalue) then
- begin
- if bytesize(nvalue) then
- sym := disp8 else sym := disp16;
- end
- else if (Uch >= 'A') and (Uch <= 'Z') then
- begin getstring; symname := Lsid;
- if (Lsid = 'FAR') or (Lsid = 'NEAR') or (Lsid = 'SHORT') then
- sym := jmpdist
- else if Lsid = 'ST' then sym := STsym
- else sym := identifier;
- end
- else if Uch = '+' then begin sym := plus; GetCh; end
- else if Uch = '[' then begin sym := lfbrack; GetCh; end
- else if Uch = ']' then begin sym := rtbrack; GetCh; end
- else begin sym := othersym; GetCh; end;
- end;
-
- {-------------NextA}
- PROCEDURE NextA; {Get the next item but also process any
- 'WORD' 'BYTE', 'DWORD', 'QWORD',etc 'PTR'}
- type sizeary = array[0..4] of string[2];
- var tmp : ptrtype;
- indx : Integer;
- const ptrary : sizeary = ('BY', 'WO', 'DW', 'QW', 'TB');
- ptrary1 : array[0..4] of string[5] =
- ('BYTE','WORD','DWORD','QWORD','TBYTE');
-
- begin
- DoNext;
- if sym = identifier then
- begin
- tmp := bptr; indx := 0;
- while (tmp < unkptr) and (Lsid <> ptrary[indx]) and (Lsid <>ptrary1[indx]) do
- begin
- tmp := Succ(tmp); indx := indx+1;
- end;
- if tmp < unkptr then
- begin ByWord := tmp; DoNext; end;
- if Str = 'PTR ' then DoNext; {ignore 'PTR'}
- end;
- end;
-
- {-------------displace_bytes}
- PROCEDURE displace_bytes(W : Integer);
- var C : Char;
- begin
- if displace then
- with SaveOfs do
- if symb then
- begin {displacement is a symbol}
- if W = 1 then C := '>' else C := '<';
- InsertStr('/'+C+sname);
- if value <> 0 then {Add it in too, don't reverse bytes}
- InsertStr('+$'+Hex2(Hi(value))+Hex2(Lo(value)));
- if W = 1 then ByteCount := ByteCount+2 else ByteCount := ByteCount+1;
- end
- else begin
- if W = 1 then InsertWord(value) else InsertByte(Lo(value));
- end;
- end;
-
- {-------------data_bytes}
- PROCEDURE data_bytes(word : Boolean);
- var C : Char;
- begin
- with DataVal do
- if symb then
- begin {data is a symbol}
- if word then C := '>' else C := '<';
- InsertStr('/'+C+sname);
- if value <> 0 then {add it in too}
- InsertStr('+$'+Hex2(Hi(value))+Hex2(Lo(value)));
- if word then ByteCount := ByteCount+2 else ByteCount := ByteCount+1;
- end
- else begin
- if word then InsertWord(value) else InsertByte(Lo(value));
- end;
- end;
-
- {-------------GetIR}
- FUNCTION GetIR : Boolean;
- var reg : indxreg;
- begin
- GetIR := False; reg := none;
- if (sym = identifier) and (Lsid[0] = Chr(2)) then
- if id2 = 'BX' then reg := bx
- else if id2 = 'SI' then reg := si
- else if id2 = 'DI' then reg := di
- else if id2 = 'BP' then reg := bp;
- if reg <> none then
- begin
- irset := irset+[reg];
- GetIR := True;
- NextA;
- end;
- end;
-
- {-------------MemReg}
- FUNCTION MemReg(var W : Integer) : Boolean;
- label 10;
-
- {Does not handle the 'reg' part of the mem/reg. Returns disp true if
- a displacement is found with w=0 for byte disp and w=1 for word
- disp. Any displacement is output in saveofs.}
-
- var
- SaveChi : Integer;
- dsp16, oldaddrs, result_MemReg : Boolean;
- begin
- SaveChi := OldChi; dsp16 := False;
- result_MemReg := False;
- oldaddrs := NoAddrs; NoAddrs := True;
- SaveOfs.value := 0; SaveOfs.symb := False; irset := [];
- while (sym <> comma) and (sym <> EOLsym) do {',' or cr terminate a MemReg}
- begin
- if sym = lfbrack then
- begin result_MemReg := True; NextA; end;
- if sym = plus then NextA;
- if (sym = disp8) or (sym = disp16) then
- with SaveOfs do
- begin
- dsp16 := dsp16 or (sym = disp16);
- if symbol then
- begin
- symb := True; sname := symname;
- end
- else value := value+nvalue;
- NextA;
- end
- else if not GetIR then
- if sym = rtbrack then NextA
- else if result_MemReg then
- begin Error(Chi, 'Comma or Line End Exp'); NextA; end
- else goto 10; {abort}
- end;
- if result_MemReg then
- begin {at least one '[' found}
- if (irset = []) or (irset = [bp]) then rmm := 6
- else if irset = [bx, si] then rmm := 0
- else if irset = [bx, di] then rmm := 1
- else if irset = [bp, si] then rmm := 2
- else if irset = [bp, di] then rmm := 3
- else if irset = [si] then rmm := 4
- else if irset = [di] then rmm := 5
- else if irset = [bx] then rmm := 7
- else Error(Chi, 'Bad Register Combination');
-
- NextA; {pass over any commas}
- with SaveOfs do
- dsp16 := dsp16 or (symb and (value <> 0)) or not bytesize(value);
- if irset = [] then
- begin displace := True; md := 0; W := 1; end {direct address}
- else if (irset = [bp]) and not dsp16 then
- begin displace := True; md := 1; W := 0; end {bp must have displ}
- else if (SaveOfs.value = 0) and not SaveOfs.symb then
- begin displace := False; md := 0; W := 3; end
- else if not dsp16 then {8 bit}
- begin displace := True; md := 1; W := 0; end
- else begin displace := True; md := 2; W := 1; end;
- modebyt := 64*md+rmm;
- end
- else
- 10: begin {not a MemReg}
- Chi := SaveChi-1; GetCh; {restore as in beginning}
- NextA;
- end;
- NoAddrs := oldaddrs;
- MemReg := result_MemReg;
- end;
-
- {-------------st_st}
- FUNCTION st_st : Boolean; {pick up st,st(i) or st(i),st or just st(i)}
- var err, rslt : Boolean;
-
- FUNCTION getsti_val : Boolean;
- var grslt : Boolean;
- begin
- NextA;
- grslt := sym = disp8;
- if grslt then
- begin
- sti_val := nvalue;
- err := ((sti_val and $f8) <> 0); {check limit of 7}
- NextA;
- end;
- getsti_val := grslt;
- end;
-
- begin
- err := False;
- rslt := sym = STsym;
- if rslt then
- begin
- if getsti_val then
- begin
- st_first := False; {st(i) is first}
- while (sym = comma) or (sym = STsym) do NextA;
- end
- else
- begin
- st_first := True; {st preceeds st(i)}
- if sym = comma then NextA;
- if sym = STsym then
- begin
- if not getsti_val then
- err := True;
- end
- else err := True;
- end;
- if err then errnull;
- end;
- st_st := rslt;
- end;
-
- {-------------fstionly}
- FUNCTION fstionly : Boolean;
- {Fl Pt instructions having only one form using st(i) operand}
- {faddp,fmulp,fsubp,fsubrp,fdivp,fdivrp,ffree,fxch -- 0..7 }
- type arraytype = array[0..7] of Integer;
- table = array[0..7, 0..5] of Char;
- var indx : Integer;
- rslt : Boolean;
- const
- stiary : arraytype =
- ($dec0, $dec8, $dee8, $dee0, $def8, $def0, $ddc0, $d9c8);
- stionlytable : table = ('FADDP ', 'FMULP ', 'FSUBP ',
- 'FSUBRP', 'FDIVP ', 'FDIVRP', 'FFREE ', 'FXCH ');
-
- begin
- rslt := matchlst(stionlytable, 6, 7, indx);
- if rslt then
- begin
- NextA;
- if not st_st then
- begin
- if sym = EOLsym then sti_val := 1
- else errincorrect;
- end;
- InsertByte($9b);
- InsertHi_Low(stiary[indx]+sti_val);
- end;
- fstionly := rslt;
- end;
-
- {-------------fmemonly}
- FUNCTION fmemonly : Boolean;
- {Fl Pt instructions having only one form using a memory operand}
- {fldenv,fldcw,fstenv,fstcw,fbstp,fbld,frstor,fsave,fstsw,
- fnsave,fnstcw,fnstenv,fnstsw--0..12 }
- type arraytype = array[0..12] of Integer;
- table = array[0..12, 0..6] of Char;
- var indx : Integer;
- rslt : Boolean;
- const
- memary : arraytype = (
- $d920, $d928, $d930, $d938, $df30, $df20, $dd20, $dd30, $dd38,
- $dd30, $d938, $d930, $dd38);
- memonlytable : table =
- ('FLDENV ', 'FLDCW ', 'FSTENV ', 'FSTCW ', 'FBSTP ', 'FBLD ',
- 'FRSTOR ', 'FSAVE ', 'FSTSW ',
- 'FNSAVE ', 'FNSTCW ', 'FNSTENV', 'FNSTSW ');
- begin
- rslt := matchlst(memonlytable, 7, 12, indx);
- if rslt then
- begin
- NextA;
- if indx < 9 then InsertByte($9b); {fwait}
- if MemReg(w1) then
- begin
- InsertHi_Low(memary[indx]+modebyt);
- displace_bytes(w1);
- end
- else errincorrect;
- end;
- fmemonly := rslt;
- end;
-
- {-------------fldtype}
- FUNCTION fldtype : Boolean;
- {Do fld,fst,fstp-- 0..2}
- type
- arraytype = array[0..2, dwptr..unkptr] of Integer;
- table = array[0..2, 0..3] of Char;
- var indx, tmp : Integer;
- rslt : Boolean;
- const
- fldarray : arraytype = (
- ($d900, $dd00, $db28, $d9c0),
- ($d910, $dd10, 0, $ddd0),
- ($d918, $dd18, $db38, $ddd8));
- fldtable : table = ('FLD ', 'FST ', 'FSTP');
- begin
- rslt := matchlst(fldtable, 4, 2, indx);
- if rslt then
- begin
- NextA;
- InsertByte($9b); {fwait}
- if ByWord >= dwptr then
- tmp := fldarray[indx, ByWord];
- if MemReg(w1) then
- begin
- if (ByWord >= dwptr) and (ByWord <= tbptr) then
- begin
- InsertHi_Low(tmp+modebyt);
- displace_bytes(w1);
- if tmp = 0 then Error(Chi, 'TBYTE not Permitted');
- end
- else Error(Chi, 'DWORD, QWORD, or TBYTE Req''d');
- end
- else if st_st then
- InsertHi_Low(tmp+sti_val)
- else errincorrect;
- end;
- fldtype := rslt;
- end;
-
- {-------------fildtype}
- FUNCTION fildtype : Boolean;
- {do fild,fist,fistp-- 0..2}
- type
- arraytype = array[0..2, wptr..qwptr] of Integer;
- table = array[0..2, 0..4] of Char;
- var indx, tmp : Integer;
- rslt : Boolean;
- const
- fildarray : arraytype = (
- ($df00, $db00, $df28),
- ($df10, $db10, 0),
- ($df18, $db18, $df38));
- fildtable : table = ('FILD ', 'FIST ', 'FISTP');
- begin
- rslt := matchlst(fildtable, 5, 2, indx);
- if rslt then
- begin
- NextA;
- if MemReg(w1) then
- begin
- if (ByWord >= wptr) and (ByWord <= qwptr) then
- begin
- InsertByte($9b); {fwait}
- tmp := fildarray[indx, ByWord];
- InsertHi_Low(tmp+modebyt);
- displace_bytes(w1);
- if tmp = 0 then Error(Chi, 'QWORD not Permitted');
- end
- else Error(Chi, 'WORD, DWORD, or QWORD Req''d');
- end
- else errincorrect;
- end;
- fildtype := rslt;
- end;
-
- {-------------faddtype}
- FUNCTION faddtype : Boolean;
- {The fadd,fmul,fcom,fcomp,fsub,fsubr,fdiv,fdivr instructions}
- var indx : Integer;
- rslt : Boolean;
- type table = array[0..7, 0..4] of Char;
- const faddtable : table = ('FADD ', 'FMUL ', 'FCOM ', 'FCOMP',
- 'FSUB ', 'FSUBR', 'FDIV ', 'FDIVR');
- begin
- rslt := False;
- if matchlst(faddtable, 5, 7, indx) then
- begin
- NoAddrs := True;
- rslt := True;
- NextA;
- InsertByte($9b); {fwait}
- if MemReg(w1) then
- begin
- if ByWord = dwptr then InsertByte($d8)
- else if ByWord = qwptr then InsertByte($dc)
- else Error(Chi, 'DWORD or QWORD Req''d');
- InsertByte(modebyt+8*indx);
- displace_bytes(w1);
- end
- else if st_st then {Must be st,st(i) or st(i),st }
- begin
- if st_first or (indx = 2 {fcom} ) or (indx = 3 {fcomp} ) then
- InsertByte($d8) else InsertByte($dc);
- modebyt := $c0+8*indx+sti_val;
- if not st_first and (indx >= 6 {fdiv} ) then
- modebyt := modebyt xor 8; {reverse fdiv,fdivr for not st_first}
- InsertByte(modebyt);
- end
- else errincorrect;
- end;
- faddtype := rslt;
- end;
-
- {-------------fiaddtype}
- FUNCTION fiaddtype : Boolean;
- {the fiadd,fimul,ficom,ficomp,fisub,fisubr,fidiv,fidivr instructions}
- type table = array[0..7, 0..5] of Char;
- var indx : Integer;
- rslt : Boolean;
- const fiaddtable : table = ('FIADD ', 'FIMUL ', 'FICOM ', 'FICOMP',
- 'FISUB ', 'FISUBR', 'FIDIV ', 'FIDIVR');
- begin
- rslt := False;
- if matchlst(fiaddtable, 6, 7, indx) then
- begin
- NoAddrs := True;
- rslt := True;
- NextA;
- if MemReg(w1) then
- begin
- InsertByte($9b); {fwait}
- if ByWord = dwptr then InsertByte($da)
- else if ByWord = wptr then InsertByte($de)
- else Error(Chi, 'WORD or DWORD Req''d');
- InsertByte(modebyt+8*indx);
- displace_bytes(w1);
- end
- else errincorrect;
- end;
- fiaddtype := rslt;
- end;
-
- {-------------fnoperand}
- FUNCTION fnoperand : Boolean;
- {do the Fl Pt no operand instructions}
- type table = array[0..32, 0..6] of Char;
- var indx : Integer;
- rslt : Boolean;
- const
- fnoptable : table = {Ordered with fnopcode}
- ('FNOP ', 'FCHS ', 'FABS ', 'FTST ', 'FXAM ',
- 'FLD1 ', 'FLDL2T ', 'FLDL2E ', 'FLDPI ', 'FLDLG2 ', 'FLDLN2 ',
- 'FLDZ ', 'F2XM1 ', 'FYL2X ', 'FPTAN ', 'FPATAN ', 'FXTRACT',
- 'FDECSTP', 'FINCSTP', 'FPREM ', 'FYL2XP1', 'FSQRT ', 'FRNDINT',
- 'FSCALE ', 'FENI ', 'FDISI ', 'FCLEX ', 'FINIT ', 'FCOMPP ',
- 'FNCLEX ', 'FNDISI ', 'FNENI ', 'FNINIT ');
-
- fnopcode : array[0..32] of Integer =
- ($d9d0, $d9e0, $d9e1, $d9e4, $d9e5, $d9e8,
- $d9e9, $d9ea, $d9eb, $d9ec, $d9ed, $d9ee,
- $d9f0, $d9f1, $d9f2, $d9f3, $d9f4, $d9f6,
- $d9f7, $d9f8, $d9f9, $d9fa, $d9fc, $d9fd,
- $dbe0, $dbe1, $dbe2, $dbe3, $ded9,
- $dbe2, $dbe1, $dbe0, $dbe3);
-
- begin
- rslt := matchlst(fnoptable, 7, 32, indx);
- if rslt then
- begin
- NextA;
- if indx < 29 then InsertByte($9b); {fwait}
- InsertHi_Low(fnopcode[indx]);
- end;
- fnoperand := rslt;
- end;
-
- {-------------register}
- FUNCTION register(var R, W : Integer) : Boolean;
- type
- regarytype = array[0..15] of array[1..2] of Char;
- const regarray : regarytype = (
- 'AL', 'CL', 'DL', 'BL', 'AH', 'CH', 'DH', 'BH',
- 'AX', 'CX', 'DX', 'BX', 'SP', 'BP', 'SI', 'DI');
- var result_reg : Boolean;
- begin
- result_reg := False;
- if (Lsid[0] = Chr(2)) and (sym = identifier) then
- begin
- R := $ffff;
- repeat
- R := R+1;
- until (R > 15) or (id2 = regarray[R]);
- result_reg := R <= 15;
- if result_reg then
- begin
- NextA;
- if sym = comma then NextA;
- end;
- W := R div 8; {w=1 for word type register}
- R := R and 7;
- end;
- register := result_reg;
- end;
-
- {-------------segregister}
- FUNCTION segregister(var R : Integer) : Boolean;
- var result_segr : Boolean;
- begin
- if (sym = identifier) and (Lsid[0] = Chr(2)) then
- begin
- result_segr := True;
- if id2 = 'ES' then R := 0
- else if id2 = 'CS' then R := 1
- else if id2 = 'SS' then R := 2
- else if id2 = 'DS' then R := 3
- else result_segr := False;
- if result_segr then
- begin
- NextA;
- if sym = comma then NextA;
- end;
- end
- else result_segr := False;
- segregister := result_segr;
- end;
-
- {-------------Data}
- FUNCTION Data(var wd : Boolean) : Boolean;
- {See if immediate data is present. Set wd if data found is word size}
- var SaveChi : Integer;
- result : Boolean;
- begin
- result := False; wd := False;
- SaveChi := OldChi;
- with DataVal do
- begin
- value := 0; symb := False;
- while (sym = disp8) or (sym = disp16) do
- begin
- result := True;
- if symbol then
- begin
- wd := wd or (sym = disp16);
- symb := True;
- sname := symname;
- end
- else value := value+nvalue;
- NextA; if sym = plus then NextA;
- end;
- result := (sym = EOLsym) and result;
- wd := wd or not bytesize(value);
- end;
- Data := result;
- if not result then
- begin
- Chi := SaveChi-1; GetCh; NextA;
- end;
- end;
-
- {-------------TwoOperands}
- FUNCTION TwoOperands : Boolean;
- {Handles codes with two operands}
- label 2;
- type instype = (mov, adc, addx, andx, cmp, orx, sbb, sub, xorx, test, xchg,
- lds, les, lea);
- nametype = array[mov..lea] of array[1..5] of Char;
- codetype = array[mov..lea] of Byte;
- shcodetype = array[mov..test] of Byte;
- var inst : instype;
- tmp : Byte;
-
- const instname : nametype = (
- 'MOV ', 'ADC ', 'ADD ', 'AND ', 'CMP ', 'OR ',
- 'SBB ', 'SUB ', 'XOR ', 'TEST ', 'XCHG ', 'LDS ',
- 'LES ', 'LEA ');
-
- immedop : codetype = ($c6, $80, $80, $80, $80, $80, $80, $80, $80, $f6, 0,
- 0, 0, 0);
- immedreg : codetype = (0, $10, 0, $20, $38, 8, $18, $28, $30, 0, 0,
- 0, 0, 0);
- memregop : codetype = ($88, $10, 0, $20, $38, 8, $18, $28, $30, $84, $86,
- $c5, $c4, $8d);
- shimmedop : shcodetype = (0, $14, 4, $24, $3c, $c, $1c, $2c, $34, $a8);
-
- begin TwoOperands := False;
- for inst := mov to lea do
- if Str = instname[inst] then
- goto 2;
- Exit; {not found}
- 2: {found}
- NoAddrs := True; {full address not acceptable}
- TwoOperands := True;
- NextA;
- if register(reg1, w1) then
- begin
- if register(reg2, w2) then
- begin {mov reg,reg}
- if inst >= lds then Error(Chi, 'Register not Permitted');
- if w1 <> w2 then Error(Chi, 'Registers Incompatible');
- if (inst = xchg) and ((w1 = 1) and ((reg1 = 0) or (reg2 = 0))) then
- InsertByte($90+reg1+reg2)
- else
- begin
- InsertByte(memregop[inst]+w1);
- InsertByte($c0+reg1+8*reg2);
- end;
- end
- else if segregister(reg2) then
- begin {mov reg,segreg}
- if (w1 = 0) or (inst <> mov) then segmerr;
- InsertByte($8c); InsertByte($c0+8*reg2+reg1);
- end
- else if Data(wordd) then
- begin {mov reg,data}
- signext := 0; {signext not presently in use}
- if inst >= xchg then Error(Chi, 'Immediate not Permitted');
- if (Ord(wordd) > w1) then datalarge;
- if (inst = mov) then
- begin
- InsertByte($b0+8*w1+reg1);
- end
- else
- if (reg1 = 0) {ax or al} then
- InsertByte(shimmedop[inst]+w1) {add ac,immed}
- else
- begin
- (* if (inst<>test) and (w1=1) and bits_7 then
- signext:=2; {the sign extension bit} *)
- InsertByte(immedop[inst]+w1+signext);
- InsertByte($c0+immedreg[inst]+reg1);
- end;
- (* Insertbyte(lo(dataval));
- if (w1>0) and (signext=0) then Insertbyte(hi(dataval)); *)
- data_bytes(w1 > 0); {output the immediate data}
- end
- else if MemReg(w2) then
- begin {mov reg,mem/reg}
- if (inst = mov) and (reg1 = 0) {ax or al} and (rmm = 6) and (md = 0) then
- begin {mov ac,mem}
- InsertByte($a0+w1);
- end
- else
- begin
- tmp := memregop[inst];
- if inst <= xchg then
- begin
- tmp := tmp+w1;
- if inst <> test then tmp := tmp or 2; {to,from bit}
- end;
- InsertByte(tmp);
- InsertByte(modebyt+8*reg1);
- end;
- displace_bytes(w2); {add on any displacement bytes}
- end
- else errnull;
- end
- else if segregister(reg1) then
- begin
- if inst <> mov then segmerr;
- InsertByte($8e);
- if register(reg2, w2) then
- begin {mov segreg,reg}
- if (w2 = 0) then wordreg;
- InsertByte($c0+8*reg1+reg2);
- end
- else if MemReg(w2) then
- begin {mov segreg,mem/reg}
- InsertByte(modebyt+8*reg1);
- displace_bytes(w2); {add any displacement bytes}
- end
- else errnull;
- end
- else if MemReg(w1) and (inst <= xchg) then
- begin
- if register(reg2, w2) then
- begin {mov mem/reg,reg}
- if (w2 > Ord(ByWord)) then Error(Chi, 'Byte Reg Exp');
- if (inst = mov) and (reg2 = 0) {ax or al} and (rmm = 6) and (md = 0) then
- begin {mov ac, mem}
- InsertByte($a2+w2);
- end
- else
- begin
- InsertByte(memregop[inst]+w2);
- InsertByte(modebyt+8*reg2);
- end;
- displace_bytes(w1);
- end
- else if segregister(reg2) then
- begin {mov mem/reg,segreg}
- if (inst <> mov) then segmerr;
- InsertByte($8c); InsertByte(modebyt+8*reg2);
- displace_bytes(w1);
- end
- else if (Data(wordd)) and (inst < xchg) then
- begin {mov mem/reg, data}
- chk_bwptr;
- if (Ord(wordd) > Ord(ByWord)) then datalarge;
- (* if (inst>=adc) and (inst<=xorx) and (byword=wptr) and bits_7 then
- signext:=2 else *) signext := 0; {the sign extension bit,
- not currently used}
- InsertByte(immedop[inst]+Ord(ByWord)+signext);
- InsertByte(modebyt+immedreg[inst]);
- displace_bytes(w1); {add displacement bytes}
- (* Insertbyte(lo(dataval));
- if (byword=wptr) and (signext=0) then Insertbyte(hi(dataval)); *)
- data_bytes(ByWord = wptr); {the immediate data}
- end
- else errnull;
- end
- else if (sym = disp8) or (sym = disp16) then
- Error(Chi, 'Immediate not Permitted')
- else errnull;
- end;
-
- {-------------OneOperand}
- FUNCTION OneOperand : Boolean;
- {Handles codes with one operand}
- type instype = (dec, inc, push, pop, nott, Neg);
- nametype = array[dec..Neg] of array[1..5] of Char;
- codetype = array[dec..Neg] of Byte;
- var inst : instype;
- pushpop : Boolean;
-
- const
- instname : nametype = (
- 'DEC ', 'INC ', 'PUSH ', 'POP ', 'NOT ', 'NEG ');
-
- regop : codetype = ($48, $40, $50, $58, 0, 0);
- segregop : codetype = (0, 0, 6, 7, 0, 0);
- memregop : codetype = ($fe, $fe, $ff, $8f, $f6, $f6);
- memregcode : codetype = ($8, 0, $30, 0, $10, $18);
-
- begin OneOperand := False;
- for inst := dec to Neg do
- if Str = instname[inst] then
- begin
- pushpop := (inst = push) or (inst = pop);
- NoAddrs := True;
- OneOperand := True;
- NextA;
- if register(reg1, w1) then
- begin
- if (w1 = 1) and (inst < nott) then
- begin {16 bit register instructions}
- InsertByte(regop[inst]+reg1);
- end
- else begin {byte register or neg,not with any reg}
- InsertByte(memregop[inst]+w1);
- InsertByte($c0+memregcode[inst]+reg1);
- if pushpop then
- wordreg;
- end
- end {if reg}
- else if segregister(reg1) then
- begin {segment reg--push,pop only}
- InsertByte(segregop[inst]+8*reg1);
- if not pushpop then segmerr
- end
- else if MemReg(w1) then
- begin {memreg (not register)}
- if not pushpop then chk_bwptr;
- InsertByte(memregop[inst] or Ord(ByWord));
- InsertByte(modebyt+memregcode[inst]);
- displace_bytes(w1);
- end
- else errincorrect;
- end; {if st}
- end;
-
- {-------------NoOperand}
- FUNCTION NoOperand : Boolean;
- {Those instructions consisting only of opcode}
- const nmbsop = 31;
- type sofield = array[0..nmbsop] of array[1..5] of Char;
- opfield = array[0..nmbsop] of Byte;
- var index : Integer;
- const
- sop : sofield = (
- 'DAA ', 'AAA ', 'NOP ', 'MOVSB', 'MOVSW', 'CMPSB', 'CMPSW',
- 'XLAT ', 'HLT ',
- 'CMC ', 'DAS ', 'AAS ', 'CBW ', 'CWD ', 'PUSHF',
- 'POPF ', 'SAHF ', 'LAHF ', 'STOSB', 'STOSW', 'LODSB', 'LODSW',
- 'SCASB', 'SCASW', 'INTO ', 'IRET ', 'CLC ', 'STC ', 'CLI ',
- 'STI ', 'CLD ', 'STD ');
- opcode : opfield = (
- $27, $37, $90, $a4, $a5, $a6, $a7, $d7, $f4,
- $f5, $2f, $3f, $98, $99, $9c, $9d, $9e, $9f, $aa, $ab, $ac, $ad,
- $ae, $af, $ce, $cf, $f8, $f9, $fa, $fb, $fc, $fd);
-
- begin NoOperand := False;
- for index := 0 to nmbsop do
- if Str = sop[index] then
- begin
- InsertByte(opcode[index]);
- NoOperand := True;
- NextA;
- Exit;
- end;
- end;
-
- {-------------prefix}
- FUNCTION prefix : Boolean;
- {process the prefix instructions}
- const nmbsop = 11;
- type field = array[0..nmbsop] of string5;
- opfield = array[0..nmbsop] of Byte;
- var index : Integer;
- const
- ops : field = (
- 'LOCK ', 'REP ', 'REPZ ',
- 'REPNZ', 'REPE ', 'REPNE', 'WAIT ', 'FWAIT',
- 'ES ', 'DS ', 'CS ', 'SS ');
- opcode : opfield = (
- $f0, $f2, $f3, $f2, $f3, $f2, $9b, $9b, $26, $3e, $2e, $36);
-
- begin prefix := False;
- for index := 0 to nmbsop do
- if Str = ops[index] then
- begin
- InsertByte(opcode[index]);
- tindex0 := tindex; {for future fix ups}
- if Uch = ':' then GetCh; {es: etc permitted with a colon}
- prefix := True;
- Exit;
- end;
- end;
-
- {-------------FindLabel}
- FUNCTION FindLabel(var B : Integer) : Boolean;
- {Find a label if it exists in the label chain}
- var found : Boolean;
- begin
- pl := firstlabel; found := False;
- while (pl <> nil) and not found do
- with pl^ do
- if symname = name then
- begin
- found := True;
- B := bytecnt;
- end
- else pl := next;
- FindLabel := found;
- end;
-
- {-------------shortjmp}
- FUNCTION shortjmp : Boolean;
- {short jump instructions}
- const numjmp = 34;
- type
- sjfield = array[0..numjmp] of array[1..5] of Char;
- opfield = array[0..numjmp] of Byte;
- var I, B : Integer;
- const
- jumps : sjfield = (
- 'JO ', 'JNO ', 'JB ', 'JNAE ', 'JNB ', 'JAE ',
- 'JE ', 'JZ ', 'JNE ', 'JNZ ', 'JBE ', 'JNA ',
- 'JNBE ', 'JA ', 'LOOPN', 'LOOPZ', 'LOOPE', 'LOOP ',
- 'JCXZ ', 'JS ', 'JNS ', 'JP ', 'JPE ', 'JNP ',
- 'JPO ', 'JL ', 'JNGE ', 'JNL ', 'JGE ', 'JLE ',
- 'JNG ', 'JNLE ', 'JG ', 'JC ', 'JNC ');
-
- opcode : opfield = (
- $70, $71, $72, $72, $73, $73, $74, $74, $75, $75, $76, $76,
- $77, $77, $e0, $e1, $e1, $e2, $e3, $78, $79, $7a, $7a, $7b,
- $7b, $7c, $7c, $7d, $7d, $7e, $7e, $7f, $7f, $72, $73);
-
- begin shortjmp := False;
- for I := 0 to numjmp do
- if Str = jumps[I] then
- begin
- InsertByte(opcode[I]);
- shortjmp := True;
- NoAddrs := True;
- NextA;
- if sym = identifier then
- begin
- if FindLabel(B) then
- begin
- Addr := B-(ByteCount+1);
- if Addr+$80 <= $ff then InsertByte(Lo(Addr))
- else Error(Chi, 'Too Far');
- end
- else
- begin {enter jump into fixups}
- New(pf);
- with pf^ do
- begin
- next := firstfix;
- if firstfix <> nil then
- firstfix^.prev := pf;
- firstfix := pf;
- prev := nil;
- jmptype := short;
- name := symname;
- fix_pt := ByteCount; indx := tindex;
- InsertByte(0); {dummy insertion}
- end;
- end;
- NextA;
- end
- else Error(Chi, 'Label Exp');
- end;
- end;
-
- {-------------ShfRot}
- FUNCTION ShfRot : Boolean;
- type
- instype = (rclx, rcrx, rolx, rorx, salx, sarx, shlx, shrx);
- nametype = array[rclx..shrx] of array[1..3] of Char;
- codetype = array[rclx..shrx] of Byte;
- var
- inst : instype;
- cl : Byte;
-
- const
- instname : nametype = (
- 'RCL', 'RCR', 'ROL', 'ROR', 'SAL', 'SAR',
- 'SHL', 'SHR');
-
- regcode : codetype = ($10, $18, 0, 8, $20, $38, $20, $28);
-
- begin ShfRot := False;
- if Lsid[0] = Chr(3) then
- for inst := rclx to shrx do
- if id3 = instname[inst] then
- begin
- NoAddrs := True; ShfRot := True;
- NextA;
- InsertByte($d0); {may get modified later}
- if register(reg1, w1) then
- InsertByte($c0+regcode[inst]+reg1)
- else if MemReg(w2) then
- begin
- chk_bwptr;
- w1 := Ord(ByWord);
- InsertByte(modebyt+regcode[inst]);
- displace_bytes(w2);
- end
- else Error(Chi, 'Reg or Mem Exp');
- if sym = comma then NextA;
- cl := 0;
- if (id3 = 'CL ') then cl := 2
- else if nvalue <> 1 then Error(Chi, 'CL or 1 Exp');
- NextA;
- modify_byte(tindex0, cl+w1); {modify the opcode}
- end;
- end;
-
- {-------------CallJmp}
- FUNCTION calljmp : Boolean;
- type instype = (call, jmp);
- codetype = array[call..jmp] of Byte;
- var
- inst : instype;
- dist : (nodist, long, shrt, near);
- tmp : Byte;
- dwtmp : ptrtype;
- B : Integer;
-
- const
- shortop : codetype = ($e8, $e9);
- longop : codetype = ($9a, $ea);
- longcode : codetype = ($18, $28);
- shortcode : codetype = ($10, $20);
-
- begin calljmp := False;
- if Str = 'CALL ' then inst := call
- else if Str = 'JMP ' then inst := jmp
- else Exit;
-
- calljmp := True;
- NextA;
- dist := nodist;
- dwtmp := ByWord; {could have passed a 'DWORD PTR' here}
- if sym = jmpdist then
- begin
- if id2 = 'FA' then dist := long
- else if id2 = 'NE' then dist := near
- else if id2 = 'SH' then dist := shrt;
- NextA;
- end;
- if (sym = address) then
- begin
- InsertByte(longop[inst]);
- InsertWord(nvalue);
- InsertWord(segm);
- end
- else if sym = identifier then
- begin
- if dist = long then Error(Chi, 'Far not Permitted with Label');
- if FindLabel(B) then
- begin
- Addr := B-(ByteCount+2);
- if inst = call then
- begin
- InsertByte($e8);
- InsertWord(Addr-1);
- end
- else
- if (Addr+$80 <= $ff) and (dist <> near) then {jmp}
- begin {short jump}
- InsertByte($eb); InsertByte(Lo(Addr));
- end
- else
- begin
- InsertByte($e9); InsertWord(Addr-1);
- end;
- end {findlabel}
- else
- begin {enter it into fixup chain}
- New(pf);
- with pf^ do
- begin
- next := firstfix;
- if firstfix <> nil then
- firstfix^.prev := pf;
- firstfix := pf;
- prev := nil;
- name := symname;
- if dist = shrt then
- begin
- jmptype := short;
- InsertByte($eb);
- fix_pt := ByteCount; indx := tindex;
- InsertByte(0); {dummy insertion}
- end
- else
- begin
- jmptype := med;
- if inst = call then InsertByte($e8) else InsertByte($e9);
- fix_pt := ByteCount; indx := tindex;
- InsertByte(0); {dummy insertion}
- indx2 := tindex;
- InsertByte(0); {another dummy byte}
- end;
- end;
- end;
- end {identifier}
- else if register(reg1, w1) then
- begin
- if w1 = 0 then wordreg;
- if dist = long then Error(Chi, 'FAR not Permitted');
- InsertByte($ff);
- InsertByte($c0+shortcode[inst]+reg1);
- end
- else if MemReg(w1) then
- begin
- if (dist = long) or (dwtmp = dwptr) then tmp := longcode[inst]
- else tmp := shortcode[inst];
- InsertByte($ff);
- InsertByte(modebyt+tmp);
- displace_bytes(w1);
- end
- else errnull;
- NextA;
- end;
-
- {-------------retrn}
- PROCEDURE retrn(far : Boolean);
- begin
- if (sym = disp16) or (sym = disp8) then
- begin
- if far then InsertByte($ca) else InsertByte($c2);
- InsertWord(nvalue);
- NextA;
- end
- else begin
- if far then InsertByte($cb) else InsertByte($c3);
- end;
- end;
-
- {-------------otherinst}
- FUNCTION otherinst : Boolean;
- label 2, 10, 20, 30;
- type
- instsym = (ret, retf, aam, aad, inn, out, mul, imul, divd, idiv, Int);
- nametype = array[ret..Int] of array[1..5] of Char;
- var index : instsym;
- tmp : Byte;
- const instname : nametype = (
- 'RET ', 'RETF ', 'AAM ', 'AAD ', 'IN ', 'OUT ', 'MUL ',
- 'IMUL ', 'DIV ', 'IDIV ', 'INT ');
-
- PROCEDURE MulDiv(B : Byte);
- var wordbit : Integer;
- begin
- InsertByte($f6);
- if register(reg2, w2) then
- begin
- InsertByte($c0+B+reg2);
- wordbit := w2;
- end
- else if MemReg(w2) then
- begin
- chk_bwptr;
- wordbit := Ord(ByWord);
- InsertByte(modebyt+B);
- displace_bytes(w2);
- end
- else Error(Chi, 'Reg or Mem Exp');
- modify_byte(tindex0, wordbit);
- end;
-
- FUNCTION dxreg : Boolean;
- begin
- dxreg := False;
- if sym = identifier then
- if id2 = 'DX' then
- begin dxreg := True; NextA; end;
- end;
-
- FUNCTION accum(var W : Integer) : Boolean;
- var result_acc : Boolean;
- {See if next is AL or AX}
- begin
- if (sym = identifier) then
- begin
- result_acc := (id3 = 'AX ') or (id3 = 'AL ');
- if result_acc then
- begin
- if Str[2] = 'X' then W := 1 else W := 0; {word vs byte register}
- NextA;
- end;
- end;
- accum := result_acc;
- end;
-
- begin
- otherinst := False;
- for index := ret to Int do
- if Str = instname[index] then goto 2;
- Exit;
-
- 2: otherinst := True; NextA;
- case index of
- ret : retrn(False);
- retf : retrn(True);
- out : begin
- if dxreg then InsertByte($ee) {out dx,ac}
- else if sym = disp8 then
- begin {out port,ac}
- InsertByte($e6);
- InsertByte(Lo(nvalue));
- NextA;
- end
- else goto 10;
- if sym = comma then NextA;
- if accum(w1) then
- modify_byte(tindex0, w1) {al or ax}
- else goto 20;
- end;
- inn : begin
- if accum(w1) then
- begin
- if sym = comma then NextA;
- if dxreg then InsertByte($ec+w1) {in ac,dx}
- else
- begin
- if sym = disp8 then
- begin {in ac,port}
- InsertByte($e4+w1);
- InsertByte(Lo(nvalue));
- NextA;
- end
- else
- 10:Error(Chi, 'DX or Port Exp');
- end
- end
- else
- 20:Error(Chi, 'AX or AL Exp');
- end;
- aam : begin
- tmp := $d4;
- goto 30;
- end;
- aad : begin
- tmp := $d5;
- 30 : InsertByte(tmp);
- InsertByte($a);
- end;
- mul : MulDiv($20);
- imul : MulDiv($28);
- divd : MulDiv($30);
- idiv : MulDiv($38);
- int : begin
- if sym = disp8 then
- begin
- if nvalue = 3 then InsertByte($cc)
- else
- begin
- InsertByte($cd);
- InsertByte(Lo(nvalue));
- end;
- NextA;
- end
- else errnull;
- end;
- end;
- end;
-
- {-------------getquoted}
- FUNCTION getquoted(var ls : bigstring) : Boolean;
- var SaveChi, k : Integer;
- term : Char;
- gq : Boolean;
- begin
- skipspaces;
- SaveChi := Chi; k := 1;
- gq := False;
- if (Uch = '''') or (Uch = '"') then
- begin
- term := Uch; GetCh;
- while (Uch <> term) and (Uch <> Chr(cr)) do
- if (Uch <> Chr(cr)) and (k <= bigstringsize) then
- begin
- ls[k] := Lch; k := k+1; GetCh;
- end;
- GetCh; {pass by term}
- gq := not(Uch in ['+', '-', '*', '/']); {else was meant to be expr}
- end;
- ls[0] := Chr(k-1);
- if not gq then
- begin Chi := SaveChi-1; GetCh; end;
- getquoted := gq;
- end;
-
- {-------------databyte}
- PROCEDURE databyte;
- var I : Integer;
- Lst : bigstring;
- begin
- repeat
- if getquoted(Lst) then
- begin
- for I := 1 to Ord(Lst[0]) do
- InsertByte(Lo(Ord(Lst[I])));
- end
- else
- if readbyte then InsertByte(byt)
- else begin errnull; end;
- skipspaces;
- until (Uch = Chr(cr)) or (Uch = ';') or aerr;
- NextA;
- end;
-
- {-------------chk_for_label}
- PROCEDURE chk_for_label;
- begin
- if not prefix then {could be prefix here}
- begin
- skipspaces;
- if (Lsid[0] > Chr(0)) and (Uch = ':') then
- begin {label found}
- GetCh; symname := Lsid;
- pl := firstlabel; {check for duplication of label}
- while pl <> nil do
- with pl^ do
- begin
- if symname = name then Error(Chi, 'Duplicate Label');
- pl := next;
- end;
- New(pl); {add the label to the label chain}
- with pl^ do
- begin
- next := firstlabel;
- firstlabel := pl;
- bytecnt := ByteCount;
- name := symname;
- end;
- pf := firstfix; {see if any fixups are required}
- while pf <> nil do
- with pf^ do
- begin
- if name = symname then
- begin {remove this fixup from chain}
- if pf = firstfix then
- firstfix := next
- else prev^.next := next;
- if next <> nil then next^.prev := prev;
- Dispose(pf);
- Addr := ByteCount-(fix_pt+1);
- if jmptype = short then
- begin
- if Addr+$80 <= $ff then modify_byte(indx, Lo(Addr))
- else Error(Chi, 'Too Far');
- end
- else
- begin {jmptype=med}
- Addr := Addr-1;
- modify_byte(indx, Lo(Addr));
- modify_byte(indx2, Hi(Addr));
- end;
- end;
- pf := next;
- end;
- getstring; {for next item to use}
- end; {label found}
- end {neither a label or a prefix}
- else getstring; {it was a prefix}
- end;
-
- {-------------interpret}
- PROCEDURE interpret;
- begin
- tindex0 := tindex; {opcode position}
- getstring;
- chk_for_label;
- while prefix do {process any prefix instructions}
- getstring;
- if Lsid[0] > Chr(0) then
- begin
- if not NoOperand then
- if not OneOperand then
- if not TwoOperands then
- if not shortjmp then
- if not calljmp then
- if not ShfRot then
- if not otherinst then
- if not faddtype then
- if not fnoperand then
- if not fiaddtype then
- if not fldtype then
- if not fmemonly then
- if not fildtype then
- if not fstionly then
- if id3 = 'DB ' then databyte else
- if Lsid = 'END' then
- begin
- TheEnd := True;
- NextA;
- end
- else Error(Chi, 'Unknown Instruction');
- end
- else NextA; {if not a string find out what}
- if sym <> EOLsym then Error(Chi, 'End of Line Exp');
- end;
-
- {-------------chk_ioerror}
- FUNCTION chk_ioerror(S : filestring): Integer;
- var ioerr : Integer;
- begin
- ioerr := IOResult;
- if ioerr = 1 then WriteLn('Can''t find ', S)
- else if ioerr <> 0 then WriteLn('I/O Error ', Hex4(ioerr));
- chk_ioerror := ioerr;
- end;
-
- {-------------PromptForInput}
- PROCEDURE PromptForInput;
- var
- inname,name : filestring;
- err : Integer;
- begin
- {$I-}
- Repeat
- Write('Source Filename [.ASM]: '); ReadLn(inname);
- if inname='' then Halt;
- DefaultExtension('ASM', inname, name);
- Assign(inn, inname); Reset(inn);
- err:=chk_ioerror(inname);
- if err>1 then Halt(1);
- until err=0;
- Write('Object Filename [', name, '.OBJ]: '); ReadLn(inname);
- if inname='' then inname:=name; {Use the same name}
- DefaultExtension('OBJ',inname,name);
- Assign(out, inname);
- ReWrite(out);
- if chk_ioerror(inname)<>0 then Halt(1);
- {$I+}
- end;
-
- {-------------CommandInput}
- PROCEDURE CommandInput;
- var
- inname,name : filestring;
-
- PROCEDURE DoHelp;
- begin
- Halt;
- end;
-
- begin
- inname:=ParamStr(1);
- if Pos('?', inname)<>0 then DoHelp;
- DefaultExtension('ASM', inname, name);
- {$I-}
- Assign(inn, inname);
- ReSet(inn);
- if chk_ioerror(inname)<>0 then Halt(1);
- if ParamCount>=2 then inname:=ParamStr(2)
- else inname:=name; {Use the old name}
- DefaultExtension('OBJ',inname,name);
- Assign(out, inname);
- ReWrite(out);
- if chk_ioerror(inname)<>0 then Halt(1);
- {$I+}
- end;
-
- {-------------main}
- begin
- Write(signon1); WriteLn(signon2);
-
- start_col := 1; TheEnd := False;
- tindex := 0;
- ByteCount := 0;
- firstlabel := nil; firstfix := nil;
- InsertStr('Inline('+^m^j);
- str_start := True;
-
- if ParamCount >= 1 then CommandInput else PromptForInput;
-
- while not EoF(inn) and not TheEnd do
- begin
- aerr := False; NoAddrs := False;
- ByWord := unkptr;
- column := 0;
- ReadLn(inn, st); Chi := 1; GetCh; sym := othersym;
- if st <> '' then
- begin
- InsertStr(' ');
- interpret;
- while column < CommentColumn do InsertChr(' ');
- InsertChr('{');
- I := 1;
- while (column < 124) and (I <= Length(st)) do
- begin
- InsertChr(st[I]);
- I := I+1;
- end;
- InsertStr('}'^m^j);
- end;
- end;
- InsertStr(');'^m^j);
- pf := firstfix; {report any fixups not made}
- while pf <> nil do
- with pf^ do
- begin
- WriteLn('Label not Found-- ', name);
- pf := next;
- end;
- for I := 0 to tindex-1 do Write(out, TextArray[I]);
- Close(out);
- Close(inn);
- end.