$title ('PSEUDO INSTRUCTION MODULE-1') pseudom: do; /* modified 4/9/81 R. Silberstein modified 4/15/81 R. Silberstein modified 5/7/81 R. Silberstein modified 7/24/81 R. Silberstein modified 8/26/81 R. Silberstein modified 8/19/81 R. Silberstein */ /* This is the module to perform the decoding of all legal pseudo instructions of the assembler. There is one subroutine for each corresponding pseudoinstruction. */ $include (:f1:macro.lit) $include (:f1:struc.lit) $include (:f1:equals.lit) $include (:f1:pseud1.x86) $include (:f1:outp.lit) $include (:f1:subr2.ext) $include (:f1:print.ext) $include (:f1:scan.ext) $include (:f1:symb.ext) $include (:f1:expr.ext) $include (:f1:ermod.ext) $include (:f1:outp.ext) $include (:f1:global.ext) $eject /*************** COMMON SUBROUTINES *************/ /* routine to test if rest of line is either a comment or empty - if not, print error message - skip rest of line */ test$emptyline: proc; if not emptyline then call errmsg(end$of$line$err); call skip$rest$of$line; end test$emptyline; /* list current address in front of printline */ listcip: proc PUBLIC; if (prefixptr=0) and (pass <> 0) then$do call hex2out(cip,.prefix(1)); prefixptr=6; end$if; end list$cip; /* common routine for ORG and RS (reserve storage pseudo) */ orgrs: proc (disp,typ); dcl disp addr,typ byte,oper operandstruc at (.operands(0)); if noforwardexpr(.oper) then$do /* evaluate operand */ if oper.stype=number then$do currentsymbol.length=oper.offset; cip=disp+oper.offset*typ; /* compute new instruction pointer */ call test$emptyline; return; end$if; end$if; /* error in expression */ call errmsg(pseudooperr); call skip$rest$of$line; end orgrs; /* perform handling for CSEG,DSEG,SSEG,ESEG routines */ segmentrout: proc (p1,p2,p3,segr); dcl segr byte,(p1,p2,p3) address, currentseg based p1 addr, segspecified based p2 byte, cipsave based p3 addr, oper operandstruc at (.operands(0)), low byte at (.csegvalue),high byte at (.csegvalue+1); emit: proc; dcl datatab(4) byte data (ESvalue,CSvalue,SSvalue,DSvalue); call emitcodebyte(high,datatab(segr)); call emitcodebyte(low,datatab(segr)); call hex2out(csegvalue,.prefix(3)); /* print value on print line */ prefixptr=7; end emit; do case csegtype; /* save current segment attributes */ do; cureseg=csegvalue; espec=csegspec; escip=cip; end; /* ES */ do; curcseg=csegvalue; cspec=csegspec; cscip=cip; end; /* CS */ do; cursseg=csegvalue; sspec=csegspec; sscip=cip; end; /* SS */ do; curdseg=csegvalue; dspec=csegspec; dscip=cip; end; /* DS */ end$case; if emptyline then$do /* allow no parameter */ call skip$rest$of$line; csegvalue=0; csegtype=segr; csegspec=false; /* no segment value specified */ cip=0; return; end$if; if specialtoken('$') then$do /* allow "$" */ csegtype=segr; /* pick up previous values */ csegspec=segspecified; csegvalue=currentseg; cip=cipsave; if csegspec then call emit; call scan; /* skip $ */ call test$emptyline; return; end$if; if expression(.oper) then$do /* operand must be expression */ if oper.stype=number then$do csegvalue=oper.offset; /* pick up segment value */ csegtype=segr; csegspec=true; /* value is specified */ cip=0; call emit; call test$emptyline; return; end$if; end$if; /* must be illegal operand */ call skip$rest$of$line; call errmsg(pseudooperr); end segmentrout; /* common routine for DB,DW and DD */ DB$DW$DD$common: proc(n); dcl(n,continue) byte,lg addr; DECLARE EP BYTE; item: proc(n); /* find one element of element list */ dcl (n,i,errorprinted) byte, oper operandstruc at (.operands(0)), low byte at (.oper.offset), high byte at (.oper.offset+1), seglow byte at (.oper.segment), seghigh byte at (.oper.segment+1); emit: proc (outputbyte); dcl outputbyte byte, datatab(4) byte data (ESdata,CSdata,SSdata,DSdata); call emitcodebyte(outputbyte,datatab(csegtype)); end emit; locexpr: proc byte; if expression(.oper) then$do i=oper.stype; if (i=number) or (i=variable) or (i=lab) then return true; end$if; return false; end locexpr; DBhandle: proc; if (token.type=string) and (acclen > 1) then$do lg=lg+acclen-1; i=0ffh; do while (i:=i+1) < acclen; call emit(accum(i)); end$while; oper.stype=number; /* dummy */ call scan; /* skip string */ else$do if locexpr then$do call emit(low); else$do call emit(0); call errmsg(illexprelem); end$if; end$if; end DBhandle; DWhandle: proc; if locexpr then$do call emit(low); call emit(high); else$do call emit(0); call emit(0); call errmsg(illexprelem); end$if; end DWhandle; DDhandle: proc; if locexpr then$do if oper.stype <> number then$do if (oper.sflag and segmbit) <> 0 then$do call emit(low); call emit(high); call emit(seglow); call emit(seghigh); return; else$do call errmsg(misssegminfo); end$if; end$if; end$if; do i=0 to 3; call emit(0); end$do; /* dummy */ call errmsg(illexprelem); end DDhandle; /* ITEM main program */ lg=lg+1; do case n; call DBhandle; call DWhandle; call DDhandle; end$case; if specialtoken(',') then$do call scan; continue=true; else$do if emptyline then$do call skip$rest$of$line; else$do CALL ERRMSG (ENDOFLINEERR); CALL SKIPRESTOFLINE; end$if; end$if; end item; /* DB$DW$DD$common main program */ CALL LISTCIP; EP = FALSE; lg=0; continue=true; do while continue; errorprinted=false; continue=false; call item(n); EP = EP OR ERRORPRINTED; end$while; currentsymbol.length=lg; ERRORPRINTED = EP; /* SO SOURCE LINE IS ECHOED IF ERROR */ end DB$DW$DD$common; $eject /***************** PSEUDO SUBROUTINES **************/ DBrout: proc public; call DB$DW$DD$common(0); end DBrout; DWrout: proc public; call DB$DW$DD$common(1); end DWrout; DDrout: proc public; call DB$DW$DD$common(2); end DDrout; RSrout: proc (typ) public; dcl typ byte; call listcip; /* list current address on printline */ call orgrs(cip,typ); /* cip = cip + typ * expression */ end RSrout; CSEGrout: proc public; call segmentrout(.curcseg,.cspec,.cscip,rcs); end CSEGrout; DSEGrout: proc public; call segmentrout(.curdseg,.dspec,.dscip,rds); end DSEGrout; SSEGrout: proc public; call segmentrout(.cursseg,.sspec,.sscip,rss); end SSEGrout; ESEGrout: proc public; call segmentrout(.cureseg,.espec,.escip,res); end ESEGrout; ORGrout: proc public; call orgrs(0,byt); /* cip = 0 + expression */ end ORGrout; EQUrout: proc public; dcl oper operandstruc at (.operands(0)), macdefpt based codemacroptr address; codempossible: proc byte; return (nextch=cr or nextch=';'); end codempossible; do case pass; do; /* pass 0 */ if codempossible and findcodemacro(acclen,.accum(0),.codemacroptr) then$do currentsymbol.stype=code; call enterattributes(symbtabadr,.currentsymbol); if not newmacro(acclensave,.accumsave,macdefpt) then fullsymbtab=true; else$do nooper=0; /* find normal operand expression */ IF NOFORWARDOPER THEN$DO call enterattributes(symbtabadr,.operands(0)); call skip$rest$of$line; else$do currentsymbol.stype=udefsymb; call enterattributes(symbtabadr,.currentsymbol); call skip$rest$of$line; end$if; end$if; end; do; /* pass 1 */ if currentsymbol.stype <> code then$do /* update symbol value */ nooper=0; IF NOFORWARDOPER THEN$DO call enterattributes(symbtabadr,.operands(0)); end$if; end$if; call skip$rest$of$line; end; do; /* pass 2 - scan to produce possible errormessages */ if currentsymbol.stype=code then$do call scan; else$do nooper=0; IF NOT NOFORWARDOPER OR (CURRENTSYMBOL.STYPE = ERROR) THEN$DO call errmsg(pseudooperr); call skip$rest$of$line; /* only one error message */ else$do prefixptr=7; call hex2out(oper.offset,.prefix(3)); end$if; end$if; call test$emptyline; end; end$case; end EQUrout; end$module pseudom;