$title ('codemacro module 2') cm2: do; /* modified 3/26/81 R. Silberstein */ /* This is the module to build new instructions which is not present in the already existing system. */ $include (:f1:macro.lit) $include (:f1:equals.lit) $include (:f1:struc.lit) $include (:f1:cmacd.lit) $include (:f1:cm.lit) $include (:f1:symb.ext) $include (:f1:subr1.ext) $include (:f1:subr2.ext) $include (:f1:scan.ext) $include (:f1:files.ext) $include (:f1:exglob.ext) $eject /* D E C L A R A T I O N F O R "C O D E M A C R O" P A R T Extended version of ASM86 */ dcl cm$name(80) byte , codemacro$found byte , cm$n$pt address , cm$n$var based cm$n$pt byte, cm$n$lg byte , par$name(80) byte , pmpt address , cm$pm$var based pmpt byte, cm$error byte public , cm$body(100) byte , cmpt address public , cm$b$var based cmpt byte, cm$w$var based cmpt addr, cm$counter addr , global$cm$error byte public , cm$body$full byte , ant$par byte , cm$list$overflow byte public; $eject /* VARIOUS SUBROUTINES */ legal$parameter: PROC(lg,ptr,ptr2) byte public; dcl (lg,i) byte, (ptr,ptr2) address, no based ptr2 byte; i=0; do no=0 to cm$body(2)-1; if parname(i+lg) = 0 and equal(lg,ptr,.par$name(i)) then return true; do while par$name(i:=i+1) <> 0; end$while; i=i+1; end; return false; end$proc legal$parameter; legal$spec$letter: PROC(l) byte; dcl (l,i) byte; dcl table(8) byte data ('ACDEMRSX'); do i=0 to last(table); if table(i) = l then return i; end; return i; end$proc legal$spec$letter; legal$mod$letter: PROC(l) byte; dcl (l,i) byte; dcl table(4) byte data ('BWDS'); do i=0 to last(table); if table(i) = l and i < 3 then return i; if table(i) = l and i = 3 then$do if accum(2) = 'B' then return 3; end$if; end; return i; end$proc legal$mod$letter; legal$register: PROC byte; declare disp byte; if token.type <> reg then return 0; disp=0; if token.descr=byt then disp=8; if token.descr=dwrd then disp=16; return token.value + disp + 1; end$proc legal$register; legal$seg$reg: PROC byte public; if token.type <> reg then return 0; if token.descr <> dwrd then return 0; return token.value + 1; end$proc legal$seg$reg; put$b: PROC(b) public; dcl b byte; cm$counter=cm$counter+1; if cm$counter > 99 then$do cm$error=true; cm$body$full=true; return; end$if; cm$b$var=b; cmpt=cmpt+1; end$proc put$b; put$w: PROC(w) public; dcl w addr; cm$counter=cm$counter+2; if cm$counter > 99 then$do cm$error=true; cm$body$full=true; return; end$if; cm$w$var=w; cmpt=cmpt+2; end$proc put$w; update$cm$lists: PROC byte; dcl listptr address,next based listptr address; dcl ptr address; ptr=.listptr; if findcodemacro(cm$n$lg,.cm$name(0),ptr) then$do do while next <> 0; listptr=next; end$while; else$do if not new$cm$name(cm$n$lg,.cm$name(0),ptr) then return false; end$if; next=freept; if not new$cm$body(cm$counter,.cm$body(0)) then return false; return true; end$proc update$cm$lists; $eject /* level 4 in the syntax-tree of coeemacro building */ register$rout: PROC (l); dcl l byte; call put$b(l); end$proc register$rout; range$rout: PROC; put$range: PROC(time); dcl time byte; if token.type = number then$do if time = first then$do cm$b$var=cm$b$var+numberrange; cmpt=cmpt+1; end$if; if token.value > 0ffh then$do cm$error=true; /* too large number */ return; else$do call put$b(token.value); end$if; else$do if time = first then$do cm$b$var=cm$b$var+registerrange; cmpt=cmpt+1; end$if; do case legal$register; do; /* error, expecting a register spec. */ cm$error=true; return; end; call register$rout(rax); call register$rout(rcx); call register$rout(rdx); call register$rout(rbx); call register$rout(rsp); call register$rout(rbp); call register$rout(rsi); call register$rout(rdi); call register$rout(ral); call register$rout(rcl); call register$rout(rdl); call register$rout(rbl); call register$rout(rah); call register$rout(rch); call register$rout(rdh); call register$rout(rbh); call register$rout(res); call register$rout(rcs); call register$rout(rss); call register$rout(rds); end$case; end$if; call scan; end$proc put$range; s$range: PROC; cmpt=cmpt-1; cm$b$var=cm$b$var+singlerange; call put$range(first); end$proc s$range; d$range: PROC; cmpt=cmpt-1; cm$b$var=cm$b$var+doublerange; call put$range(first); if accum(0) <> comma then$do cm$error=true; return; end$if; call scan; call put$range(second); if accum(0) <> rightpar then$do cm$error=true; return; end$if; end$proc d$range; /* mainpart of range routine */ call scan; /* skip left paranthesis */ if nextch = comma then call d$range; else call s$range; call scan; end$proc range$rout; spec$letter$rout: PROC(l); dcl l byte; call put$b(l); end$proc spec$letter$rout; mod$letter$rout: PROC(l); dcl l byte; call put$b(l); end$proc mod$letter$rout; $eject /* level 3 in the syntax-tree of codemacro building */ par$descr$rout: PROC; call copy(acclen,.accum(0),.cm$pm$var); pmpt=pmpt+acclen; cm$pm$var=0; /* end of par.name */ pmpt=pmpt+1; call scan; if accum(0) <> colon then$do /* error, expected colon in parameterdecl */ cm$error=true; end$if; call scan; do case legal$spec$letter(accum(0)); call spec$letter$rout(speca); call spec$letter$rout(specc); call spec$letter$rout(specd); call spec$letter$rout(spece); call spec$letter$rout(specm); call spec$letter$rout(specr); call spec$letter$rout(specs); call spec$letter$rout(specx); do; /* error, expected specifier letter */ cm$error=true; return; end; end$case; do case legal$mod$letter(accum(1)); call mod$letter$rout(modb); call mod$letter$rout(modw); call mod$letter$rout(modd); call mod$letter$rout(modsb); call mod$letter$rout(nomod); /* no modletter */ end$case; call scan; if accum(0) = leftpar then call range$rout; cm$body(2)=cm$body(2)+1; end$proc par$descr$rout; $eject /* level 2 in the syntax-tree of codemacro building */ /* Procedure to initialize temporary storage and pointers conserning the building of codemacro */ init$cm$rout: PROC public; cm$n$pt=.cm$name(0); cmpt=.cm$body(0)+3; /* correcting for the head */ pmpt=.par$name(0); CALL FILL (0, LENGTH (CM$NAME), .CM$NAME); CALL FILL (0, LENGTH (CM$BODY), .CM$BODY); CALL FILL (0, LENGTH (PAR$NAME), .PAR$NAME); ant$par=0; cm$counter=3; cm$body$full=false; cm$list$overflow=false; end$proc init$cm$rout; name$rout: PROC byte public; if token.type <> ident then return false; call copy(acclen,.accum(0),.cm$name(0)); cm$n$lg=acclen; call scan; return true; end$proc name$rout; formal$list$rout: PROC public; do while token.type = ident; call par$descr$rout; if accum(0) <> ',' then return; /* end of parameters */ call scan; end$while; end$proc formal$list$rout; terminate$cm$rout: PROC public; if global$cm$error then$do /* error present in codemacrodef, */ /* no updating of codemacrolist */ return; end$if; if not update$cm$lists then$do cm$error=true; /* overflow, no more vacant memory */ cm$list$overflow=true; return; end$if; end$proc terminate$cm$rout; end$module cm2;