Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM-86/MPM-86 2.0 SOURCES/10/CM2.PLM
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

344 lines
8.2 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

$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;