mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
162 lines
4.3 KiB
Plaintext
162 lines
4.3 KiB
Plaintext
$title ('INSTRUCTION MODULE')
|
|
instruc:
|
|
do;
|
|
/*
|
|
This is the module to decode and produce code-
|
|
output of a single instruction, possibly preceded
|
|
by a number of PREFIX-instructions.
|
|
*/
|
|
|
|
$include (:f1:macro.lit)
|
|
$include (:f1:struc.lit)
|
|
$include (:f1:cmacd.lit)
|
|
$include (:f1:equals.lit)
|
|
$include (:f1:ermod.lit)
|
|
$include (:f1:subr1.ext)
|
|
$include (:f1:expr.ext)
|
|
$include (:f1:symb.ext)
|
|
$include (:f1:scan.ext)
|
|
$include (:f1:ermod.ext)
|
|
$include (:f1:cmsubr.ext)
|
|
$include (:f1:instr.x86)
|
|
$eject
|
|
dcl /* global variables */
|
|
bytevar based macroptr byte, /* byte within codemacro */
|
|
comtab(12) byte data /* legal codemacro commands */
|
|
(mdbn,mdbf,mdwn,mdwf,mddf,mrelb,mrelw,mmodrm1,mmodrm2,msegfix,
|
|
mnosegfix,mdbit);
|
|
$eject
|
|
|
|
|
|
/* generate instruction output code */
|
|
makecode: proc byte;
|
|
if (noerror:=searchformatch) then$do
|
|
/* matching operands, comput code */
|
|
do while (bytevar <> mendm) and noerror;
|
|
do case commandtype(bytevar,length(comtab),.comtab);
|
|
call mDBNrout;
|
|
call mDBFrout;
|
|
call mDWNrout;
|
|
call mDWFrout; /* typed during earthquake */
|
|
call mDDFrout;
|
|
call mRELBrout;
|
|
call mRELWrout;
|
|
call mMODRM1rout;
|
|
call mMODRM2rout;
|
|
call mSEGFIXrout;
|
|
call mNOSEGFIXrout;
|
|
call mDBITrout;
|
|
do; end; /* dummy, should not happen */
|
|
end$case;
|
|
end$while;
|
|
end$if;
|
|
if noerror then call emit; else call emitdummies;
|
|
return noerror;
|
|
end makecode;
|
|
|
|
/* scan all PREFIX instructions */
|
|
prefixscan: proc byte;
|
|
/* compute address of first codemacro */
|
|
findmacroaddr: proc;
|
|
dcl macrop based codemacroptr address;
|
|
firstmacroptr=macrop;
|
|
end findmacroaddr;
|
|
/* test if instruction is of PREFIX type */
|
|
prefixinstr: proc byte;
|
|
dcl ptr address,flag based ptr byte;
|
|
ptr=firstmacroptr+2;
|
|
return ((flag and prefix$on) <> 0);
|
|
end prefixinstr;
|
|
|
|
call findmacroaddr; /* compute pointer to first macro */
|
|
do while prefixinstr;
|
|
if makecode then; /* generate output code,always succed */
|
|
call clearcmindex;
|
|
if findcodemacro(acclen,.accum(0),.codemacroptr) then$do
|
|
call scan;
|
|
call findmacroaddr;
|
|
else$do
|
|
call errmsg(missinstr); /* missing instruction */
|
|
call skip$rest$of$line;
|
|
return false;
|
|
end$if;
|
|
end$while;
|
|
return true;
|
|
end prefixscan;
|
|
|
|
/* get all instruction operands */
|
|
getoperands: proc byte;
|
|
dcl moreoperands byte,pt address,oper based pt operandstruc,
|
|
exitvalue byte;
|
|
|
|
exitvalue=true;
|
|
nooper=0; /* clear no of operands */
|
|
moreoperands=not emptyline;
|
|
do while moreoperands;
|
|
moreoperands=false;
|
|
pt=.operands(nooper);
|
|
if not operand then$do
|
|
if oper.stype <> udefsymb then call errmsg(illioper);
|
|
exitvalue=false;
|
|
if skip$until(',') then moreoperands=true;
|
|
else$do
|
|
if specialtoken(',') then$do
|
|
call scan; /* skip "," */
|
|
if nooper < 3 then moreoperands=true;
|
|
end$if;
|
|
end$if;
|
|
nooper=nooper+1;
|
|
end$while;
|
|
return exitvalue;
|
|
end getoperands;
|
|
|
|
/* test if operands contain enough type information */
|
|
|
|
enough$type$info: proc byte;
|
|
dcl pt address,oper based pt operandstruc,(i,flag) byte;
|
|
flag=true;
|
|
i=0ffh;
|
|
do while (i:=i+1) < nooper;
|
|
pt=.operands(i);
|
|
if oper.stype=variable then$do
|
|
if (oper.sflag and typebit) = 0 then flag=false;
|
|
end$if;
|
|
end$while;
|
|
if flag then return true;
|
|
i=0ffh; /* one of operands lacks type info,check others */
|
|
do while (i:=i+1) < nooper;
|
|
pt=.operands(i);
|
|
if (oper.sflag and typebit) <> 0 then return true;
|
|
if (oper.stype=number) and (wrdtest(oper.offset)) then return true;
|
|
end$while;
|
|
return false;
|
|
end enough$type$info;
|
|
|
|
/* Module entry point: */
|
|
|
|
|
|
instruction: proc public; /* decode line in pass 1 and pass 2 */
|
|
call clearcmindex; /* clear buffer for output codes */
|
|
if prefixscan then$do
|
|
if getoperands then$do
|
|
if enough$type$info then$do
|
|
if makecode then$do
|
|
if not emptyline then$do
|
|
call errmsg(end$of$line$err);
|
|
end$if;
|
|
else$do
|
|
call errmsg(opmismatch);
|
|
end$if;
|
|
else$do
|
|
call errmsg(misstypeinfo);
|
|
call emitdummies;
|
|
end$if;
|
|
else$do
|
|
if makecode then; /* try to make code with bad operands */
|
|
end$if;
|
|
end$if;
|
|
call skip$rest$of$line;
|
|
end instruction;
|
|
|
|
end$module instruc;
|