home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols200
/
vol224
/
c80v-2.c
< prev
next >
Wrap
Text File
|
1994-07-13
|
31KB
|
1,383 lines
/* >>>>>>> start of cc5 <<<<<<< */
/*
history...
14 Jul 84 When profiling, not generating ':'
after label equated to zero.
27 Jun 84 No longer generating ENDDATA label
at end of program (duty taken over by ZLINK).
25 Jun 84 When profiling, the equate has
the ZMAC syntax. '\l' added.
10 Oct 83 Converted DB, DW, and DS to DEFB,
DEFW, and DEFS. Added colon after ENDDATA.
1 Sept 83 calling nl() before outputting
call to ccalls().
26 Aug 83 added code to link call counts
(header, trailer)
29 Jun 83 addim() now calls outasm
rather than ot to print the literal.
7 Mar 83 prefix "&" no longer accepts function
name.
1 Feb 83 Declaring "enddata" at the end
of the allocated memory (=top of heap).
29 Jan 83 prefix "&" can return address of
function.
27 Oct 82 Generating no extra nl() after
"dstore", updating Zsp in same routines that generate
calls to floating point routines.
23 Oct 82 rewrote value-returning expr
in "fnumber".
10 Oct 82 Corrected Zsp accounting.
Moved type coersion to a subroutine. Checking operand
types for integer operations.
9 Oct 82 Automatically widening before:
+ - * / < <= == != >= >. Short-circuit evaluation of
DOUBLE tests.
6 Oct 82 Generating calls to "qfloat" rather
than "qqfloat".
11 Sept 82 Generating no POP DE instructions
for most operators.
5 Sept 82 "constant" doing explicit "dload"
for floating constants.
3 Sep 82 Accepting floating constants.
31 Aug 82 Performing monadic "-" on
floating point variables.
30 Aug 82 Automatic conversions to and
from DOUBLE on assignments. Adjusting stack after
double precision comparisons. Comparisons now yield
integers.
29 Aug 82 monadic "&" now generates
a correct variable name.
12 Aug 82 Corrected "number" to return
type correctly.
11 Aug 82 Rewrote dbltest.
9 Aug 82 Started installing floating
point comparisons.
7 Aug 82 Modified for floating point
expressions.
5 Aug 82 Converted JZ to JP Z,
Converted several calls to ot() to outasm() to
eliminate unwanted tabs. Added some comments.
3 Aug 82 Corrected immed(), removed two
unnecessary tests for >0, removed one unnecessary
8-bit mask.
1 Aug 82 generating Zilog mnemonic
output rather than Intel.
18 Jul 82 Corrected expression analyzer
per J. E. Hendrix (ddj n62 p41);
1 Jul 82 Replaced calls to "ccpchar" with
inline code, per Ron Cain, DDJ n48 p6.
Implemented backslash escape sequences for
character and string literals, per J. E. Hendrix,
DDJ n56 p6.
18 Apr 81 Preceding names by Q rather
than QZ, to shorten them.
*/
/*
** lval[0] - symbol table address, else 0 for constant
** lval[1] - type of indirect object to fetch, else 0
for static object
** lval[2] - type of pointer or array, else 0
** lval[3] - type of value calculated jrvz 8/7/82
*/
expression()
{
int lval[4]; /* jrvz 8/7/82 */
if(heir1(lval))rvalue(lval);
return lval[3]; /* return type jrvz 8/7/82 */
}
heir1(lval)
int lval[];
{
int k,lval2[4];
k=heir2(lval);
if (match("="))
{if(k==0){needlval();return 0;
}
if (lval[1])zpush();
if(heir1(lval2))rvalue(lval2);
force(lval[3],lval2[3]); /* jrvz 10/10/82 */
store(lval);
return 0;
}
else return k;
}
heir2(lval)
int lval[];
{ int k,lval2[4];
k=heir3(lval);
blanks();
if(ch()!='|')return k;
if(k)rvalue(lval);
while(1)
{if (match("|"))
{zpush();
if(heir3(lval2)) rvalue(lval2);
intcheck(lval,lval2);
/* jrvz 10/10/82 */
zor();
}
else return 0;
}
}
heir3(lval)
int lval[];
{ int k,lval2[4];
k=heir4(lval);
blanks();
if(ch()!='^')return k;
if(k)rvalue(lval);
while(1)
{if (match("^"))
{zpush();
if(heir4(lval2))rvalue(lval2);
intcheck(lval,lval2);
/* jrvz 10/10/82 */
zxor();
}
else return 0;
}
}
heir4(lval)
int lval[];
{ int k,lval2[4];
k=heir5(lval);
blanks();
if(ch()!='&')return k;
if(k)rvalue(lval);
while(1)
{if (match("&"))
{zpush();
if(heir5(lval2))rvalue(lval2);
intcheck(lval,lval2);
/* jrvz 10/10/82 */
zand();
}
else return 0;
}
}
heir5(lval)
int lval[];
{
int k,lval2[4];
k=heir6(lval);
blanks();
if((streq(line+lptr,"==")==0)&
(streq(line+lptr,"!=")==0))return k;
if(k)rvalue(lval);
while(1)
{if (match("=="))
{if(lval[3]==DOUBLE)dpush();
/* jrvz 8/9/82 */
else zpush();
if(heir6(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{deq();
lval[3]=cint;
} /* jrvz 8/9/82 */
else zeq();
}
else if (match("!="))
{if(lval[3]==DOUBLE)dpush();
/* jrvz 8/9/82 */
else zpush();
if(heir6(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dne();
lval[3]=cint;
} /* jrvz 8/9/82 */
else zne();
}
else return 0;
}
}
heir6(lval)
int lval[];
{
int k,lval2[4];
k=heir7(lval);
blanks();
if((streq(line+lptr,"<")==0)&
(streq(line+lptr,">")==0)&
(streq(line+lptr,"<=")==0)&
(streq(line+lptr,">=")==0))return k;
if(streq(line+lptr,">>"))return k;
if(streq(line+lptr,"<<"))return k;
if(k)rvalue(lval);
while(1)
{if (match("<="))
{if(lval[3]==DOUBLE)dpush();
else zpush(); /* jrvz 8/9/82 */
if(heir7(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dle();
lval[3]=cint; continue;
}
if(lval[2]|lval2[2])
{ule();
continue;
}
if(cptr=lval2[0])
if(cptr[ident]==pointer)
{ule();
continue;
}
zle();
}
else if (match(">="))
{if(lval[3]==DOUBLE)dpush();
else zpush(); /* jrvz 8/9/82 */
if(heir7(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dge();
lval[3]=cint; continue;
}
if(lval[2]|lval2[2])
{uge();
continue;
}
if(cptr=lval2[0])
if(cptr[ident]==pointer)
{uge();
continue;
}
zge();
}
else if((streq(line+lptr,"<"))&
(streq(line+lptr,"<<")==0))
{inbyte();
if(lval[3]==DOUBLE)dpush();
else zpush(); /* jrvz 8/10/82 */
if(heir7(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dlt();
lval[3]=cint; continue;
}
if(lval[2]|lval2[2])
{ult();
continue;
}
if(cptr=lval2[0])
if(cptr[ident]==pointer)
{ult();
continue;
}
zlt();
}
else if((streq(line+lptr,">"))&
(streq(line+lptr,">>")==0))
{inbyte();
if(lval[3]==DOUBLE)dpush();
else zpush(); /* jrvz 8/10/82 */
if(heir7(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dgt();
lval[3]=cint; continue;
}
if(lval[2]|lval2[2])
{ugt();
continue;
}
if(cptr=lval2[0])
if(cptr[ident]==pointer)
{ugt();
continue;
}
zgt();
}
else return 0;
}
}
/* >>>>>> start of cc6 <<<<<< */
heir7(lval)
int lval[];
{
int k,lval2[4];
k=heir8(lval);
blanks();
if((streq(line+lptr,">>")==0)&
(streq(line+lptr,"<<")==0))return k;
if(k)rvalue(lval);
while(1)
{if (match(">>"))
{zpush();
if(heir8(lval2))rvalue(lval2);
zpop();
intcheck(lval,lval2);
/* jrvz 10/10/82 */
asr();
}
else if (match("<<"))
{zpush();
if(heir8(lval2))rvalue(lval2);
intcheck(lval,lval2);
/* jrvz 10/10/82 */
asl();
}
else return 0;
}
}
heir8(lval)
int lval[];
{
int k,lval2[4];
k=heir9(lval);
blanks();
if((ch()!='+')&(ch()!='-'))return k;
if(k)rvalue(lval);
while(1)
{if (match("+"))
{if(lval[3]==DOUBLE)dpush();
/* jrvz 8/7/82 */
else zpush();
if(heir9(lval2))rvalue(lval2);
if(dbltest(lval,lval2))
scale(lval[2]); /* jrvz 8/7/82 */
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dadd();
}
else /* jrvz 8/8/82 */
{zpop();if(dbltest(lval2,lval))
{if(lval2[2]!=cchar)
{swap();scale(lval2[2]);
}
}
zadd();
result(lval,lval2);
}
}
else if (match("-"))
{if(lval[3]==DOUBLE)dpush();
else zpush();
if(heir9(lval2))rvalue(lval2);
if(dbltest(lval,lval2))
scale(lval[2]); /* jrvz 8/7/82 */
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dsub();
}
else
{if(dbltest(lval2,lval))
{swapstk();
scale(lval2[2]);
/* jrvz 8/8/82 */
swapstk();
}
zsub();
if((lval[2]==cint)
&(lval2[2]==cint))
{swap();
immed(); ol("1");
asr(); /* div by 2 */
}
else if((lval[2]==DOUBLE)
&(lval2[2]==DOUBLE))
{swap();
immed(); ol("6");
div(); /* div by 6 */
} /* jrvz 8/8/82 */
result(lval,lval2);
}
}
else return 0;
}
}
heir9(lval)
int lval[];
{
int k,lval2[4];
k=heira(lval);
blanks();
if((ch()!='*')&(ch()!='/')&
(ch()!='%'))return k;
if(k)rvalue(lval);
while(1)
{if (match("*"))
{if(lval[3]==DOUBLE) dpush();
/* jrvz 8/7/82 */
else zpush();
if(heir9(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{dmul();
}
else mult();
}
else if (match("/"))
{if(lval[3]==DOUBLE) dpush();
/* jrvz 8/7/82 */
else zpush();
if(heira(lval2))rvalue(lval2);
if(widen(lval,lval2))
/* jrvz 10/9/82 */
{ddiv();
}
/* jrvz 8/7/82 */
else
{zpop(); div();
}
}
else if (match("%"))
{zpush();
if(heira(lval2))rvalue(lval2);
zpop();
intcheck(lval,lval2);
/* jrvz 10/10/82 */
zmod();
}
else return 0;
}
}
heira(lval)
int lval[];
{
int k;
char *ptr;
if(match("++"))
{if((k=heira(lval))==0)
{needlval();
return 0;
}
if(lval[1])zpush();
rvalue(lval);
intcheck(lval,lval); /* jrvz 10/10/82 */
if(lval[2]==DOUBLE) /* jrvz 8/7/82 */
addimm("6");
else
{inc();
if(lval[2]==cint) inc();
}
store(lval);
return 0;
}
else if(match("--"))
{if((k=heira(lval))==0)
{needlval();
return 0;
}
if(lval[1])zpush();
rvalue(lval);
intcheck(lval,lval); /* jrvz 10/10/82 */
if(lval[2]==DOUBLE) /* jrvz 8/7/82 */
addimm("0-6");
else
{dec();
if(lval[2]==cint) dec();
}
store(lval);
return 0;
}
else if (match("-"))
{k=heira(lval);
if (k) rvalue(lval);
if(lval[3]==DOUBLE)dneg();
else neg();
return 0;
}
else if(match("*"))
{k=heira(lval);
if(k)rvalue(lval);
if(ptr=lval[0]) /* get type from sym table */
lval[3]=lval[1]=ptr[type];
/* jrvz 8/7/82 */
else lval[3]=lval[1]=cint;
/* ...else assume int jrvz 8/7/82 */
lval[2]=0; /* flag as not pointer or array */
return 1; /* dereferenced pointer is lvalue */
}
else if(match("&"))
{k=heira(lval);
ptr=lval[0];
if(k==0)
{error("illegal address");
return 0;
}
ptr=lval[0];
lval[2]=ptr[type];
lval[3]=cint; /* jrvz 8/7/82 */
if(lval[1])return 0;
/* global & non-array */
immed();
outname(ptr);
/* formerly outsym jrvz 8/29/82 */
nl();
lval[1]=ptr[type];
return 0;
}
else
{k=heirb(lval);
if(match("++"))
{if(k==0)
{needlval();
return 0;
}
if(lval[1])zpush();
rvalue(lval);
intcheck(lval,lval);
/* jrvz 10/10/82 */
if(lval[2]==DOUBLE) /* jrvz 8/7/82 */
{zpush();
addimm("6");
store(lval);
mainpop();
}
else
{inc();
if(lval[2]==cint) inc();
store(lval);
dec();
if(lval[2]==cint) dec();
}
return 0;
}
else if(match("--"))
{if(k==0)
{needlval();
return 0;
}
if(lval[1])zpush();
rvalue(lval);
intcheck(lval,lval);
/* jrvz 10/10/82 */
if(lval[2]==DOUBLE) /* jrvz 8/7/82 */
{zpush();
addimm("0-6");
store(lval);
mainpop();
}
else
{dec();
if(lval[2]==cint) dec();
store(lval);
inc();
if(lval[2]==cint) inc();
}
return 0;
}
else return k;
}
}
/* >>>>>> start of cc7 <<<<<< */
heirb(lval)
int *lval;
{ int k;char *ptr;
k=primary(lval);
ptr=lval[0];
blanks();
if((ch()=='[')|(ch()=='('))
while(1)
{if(match("["))
{if(ptr==0)
{error("can't subscript");
junk();
needbrack("]");
return 0;
}
else if(ptr[ident]==pointer)rvalue(lval);
else if(ptr[ident]!=array)
{error("can't subscript");
k=0;
}
zpush();
expression();
needbrack("]");
scale(ptr[type]); /* jrvz 8/8/82 */
zpop();
zadd();
lval[0]=lval[2]=0;
lval[3]=lval[1]=ptr[type];
/* jrvz 8/7/82 */
k=1;
}
else if(match("("))
{if(ptr==0)
{callfunction(0);
}
else if(ptr[ident]!=function)
{rvalue(lval);
callfunction(0);
}
else callfunction(ptr);
k=lval[0]=0;
lval[3]=ptr[type]; /* jrvz 8/7/82 */
}
else return k;
}
if(ptr==0)return k;
if(ptr[ident]==function)
{immed();
outname(ptr);
nl();
return 0;
}
return k;
}
primary(lval)
int *lval;
{ char *ptr,sname[namesize];int num[1];
int k;
lval[2]=0; /* clear pointer/array type */
if(match("("))
{k=heir1(lval);
needbrack(")");
return k;
}
if(symname(sname))
{if(ptr=findloc(sname))
{getloc(ptr);
lval[0]=ptr;
lval[3]=lval[1]=ptr[type];
/* jrvz 8/7/82 */
if(ptr[ident]==pointer)
{lval[1]=cint;
lval[2]=ptr[type];
lval[3]=cint; /* jrvz 8/7/82 */
}
if(ptr[ident]==array)
{lval[2]=ptr[type];
lval[3]=cint; /* jrvz 8/7/82 */
return 0;
}
else return 1;
}
if(ptr=findglb(sname))
if(ptr[ident]!=function)
{lval[0]=ptr;
lval[1]=0;
lval[3]=ptr[type]; /* jrvz 8/7/82 */
if(ptr[ident]!=array)
{if(ptr[ident]==pointer)
{lval[2]=ptr[type];
lval[3]=cint;
/* jrvz 8/7/82 */
}
return 1;
}
if(ptr[ident]==array)
lval[3]=cint; /* jrvz 8/30/82*/
immed();
outname(ptr);nl();
lval[1]=lval[2]=ptr[type];
return 0;
}
ptr=addglb(sname,function,cint,0);
lval[0]=ptr;
lval[1]=0;
lval[3]=cint; /* jrvz 8/7/82 */
return 0;
}
if(constant(num,&lval[3])) /* jrvz 8/7/82 */
return(lval[0]=lval[1]=0);
else
{error("invalid expression");
immed();outdec(0);nl();
junk();
return 0;
}
}
/* Complains if an operand isn't int jrvz 10/10/82 */
intcheck(v1,v2)
int v1[],v2[]; /* pointers to operand dope arrays */
{ if((v1[3]==DOUBLE)|(v2[3]==DOUBLE))
error("operands must be int");
}
/* Forces result, having type t2, to have type t1
jrvz 10/10/82 */
force(t1,t2) int t1,t2;
{ if(t1==DOUBLE)
{if(t2!=DOUBLE) callrts("qfloat");
}
else if (t2==DOUBLE)
{if(t1!=DOUBLE) callrts("qifix");
}
}
/* If only one operand is DOUBLE, converts the other one to
DOUBLE. Returns 1 if result will be DOUBLE. jrvz 10/9/82 */
widen(v1,v2) int v1[],v2[];
{ if(v2[3]==DOUBLE)
{if(v1[3]!=DOUBLE)
{dpush2();
/* push 2nd operand UNDER 1st */
mainpop();
callrts("qfloat");
callrts("dswap");
v1[3]=DOUBLE; /* type of result */
}
return 1;
}
else
{if(v1[3]==DOUBLE)
{callrts("qfloat");
return 1;
}
else return 0;
}
}
/*
** true if val1 -> int pointer or int array and
** val2 not ptr or array
*/
dbltest(val1,val2) int val1[], val2[];
{ if(val1[2]) /* rewritten jrvz 8/11/82 */
{if(val1[2]==cchar) return 0;
if(val2[2])return 0;
return 1;
}
else return 0;
}
/*
** determine type of binary operation
*/
result(lval,lval2) int lval[],lval2[];
{ if(lval[2] & lval2[2])
lval[2]=0; /* ptr-ptr => int */
else if(lval2[2]) /* ptr +- int => ptr */
{lval[0]=lval2[0];
lval[1]=lval2[1];
lval[2]=lval2[2];
}
}
store(lval)
int *lval;
{ if (lval[1]==0)putmem(lval[0]);
else putstk(lval[1]);
}
rvalue(lval)
int *lval;
{ if((lval[0] != 0) & (lval[1] == 0))
getmem(lval[0]);
else indirect(lval[1]);
}
test(label)
int label;
{
needbrack("(");
expression();
needbrack(")");
testjump(label);
}
constant(val,t)
int val[],
*t; /* type jrvz 8/7/82 */
{ if (fnumber(val)) /* jrvz 9/3/82 */
{t[0]=DOUBLE;
immed();printlabel(litlab);outbyte('+');
outdec(val[0]); nl();
callrts("dload");
return 1;
}
else if (number(val))
{t[0]=cint; immed(); /* jrvz 8/30/82 */
}
else if (pstr(val))
{t[0]=cint; immed();
}
else if (qstr(val))
{t[0]=cint;
immed();printlabel(litlab);outbyte('+');
}
else return 0;
outdec(val[0]);
nl();
return 1;
}
fnumber(val)
int val[];
{ double *dp, /* used to store the result */
sum, /* the partial result */
scale; /* scale factor for next digit */
char *start, /* copy of pointer to starting point */
*s; /* points into source code */
int k, /* flag and mask */
minus; /* negative if number is negative */
start=s=line+lptr; /* save starting point */
k=minus=1;
while(k)
{k=0;
if(*s=='+')
{++s; k=1;
}
if(*s=='-')
{++s; k=1; minus=(-minus);
}
}
while(numeric(*s))++s;
if(*s++!='.')return 0; /* not floating point */
while(numeric(*s))++s;
lptr=(s--)-line; /* save ending point */
sum=0.; /* initialize result */
while(*s!='.') /* handle digits to right of decimal */
sum=(sum+float(*(s--)-'0'))/10.;
scale=1.; /* initialize scale factor */
while(--s>=start) /* handle remaining digits */
{sum=sum+scale*float(*s-'0');
scale=scale*10.;
}
if(match("e")) /* interpret exponent */
{int neg, /* nonzero if exp is negative */
expon; /* the exponent */
if(number(&expon)==0)
{error("bad exponent");
expon=0;
}
if(expon<0)
{neg=1; expon=-expon;
}
else neg=0;
if(expon>38)
{error("overflow");
expon=0;
}
k=32; /* set a bit in the mask */
scale=1.;
/* find 10**expon by repeated squaring */
while(k)
{scale=scale*scale;
if(k&expon) scale=scale*10.;
k=k>>1;
}
if(neg) sum=sum/scale;
else sum=sum*scale;
}
if(minus<0) sum=-sum;
if(litptr+6>=litmax)
{error("string space exhausted");
return 0;
}
/* get location for result & bump litptr */
val[0]=litptr;
dp=litq+litptr;
litptr=litptr+6;
*dp=sum; /* store result */
return 1; /* report success */
}
number(val)
int val[];
{ int k,minus;char c;
k=minus=1;
while(k)
{k=0;
if (match("+")) k=1;
if (match("-"))
{minus=(-minus);k=1;
}
}
if(numeric(ch())==0)return 0;
while (numeric(ch()))
{c=inbyte();
k=k*10+(c-'0');
}
if (minus<0) k=(-k);
val[0]=k;
return 1;
}
pstr(val)
int val[];
{ int k;char c;
if (match("'"))
{k=0;
while((ch())!=39)
k=(k&255)*256 + (litchar()&127);
lptr++; /* jeh 11/10/82 */
val[0]=k;
return 1;
}
return 0;
}
qstr(val)
int val[];
{ char c;
if (match(quote)==0) return 0;
val[0]=litptr;
while (ch()!='"')
{if(ch()==0)break;
if(litptr>=litmax)
{error("string space exhausted");
while(match(quote)==0)
if(gch()==0)break;
return 1;
}
litq[litptr++]=litchar(); /* jeh 7/1/82 */
}
gch();
litq[litptr++]=0;
return 1;
}
/* Return current literal char & bump lptr jeh 7/1/82 */
litchar()
{ int i,oct;
if(ch()!=92)return gch();
if(nch()==0)return gch();
gch();
if(ch()=='b'){++lptr; return 8;} /* BS */
if(ch()=='t'){++lptr; return 9;} /* HT */
if(ch()=='l'){++lptr; return 10;} /* LF */
if(ch()=='f'){++lptr; return 12;} /* FF */
if(ch()=='n'){++lptr; return 13;} /* CR */
i=3; oct=0;
while(((i--)>0)&(ch()>='0')&(ch()<='7'))
oct=(oct<<3)+gch()-'0';
if(i==2)return gch(); else return oct;
}
/* >>>>>> start of cc8 <<<<<<< */
/* Begin a comment line for the assembler */
comment()
{ outbyte(';');
}
/* Put out assembler info before any code is generated */
header()
{ comment(); outstr(BANNER); nl();
comment(); outstr(AUTHOR); nl();
comment(); outstr(VERSION); nl();
comment(); nl();
if(mainflg){ /* do stuff needed for first */
/* ol("ORG 100h"); /* assembler file. NOT USED for ZMAC */
ol("LD HL,(6)"); /* set up stack */
ol("LD SP,HL");
callrts("ccgo");
/* set default drive for CP/M */
zcall("main");
/* call code generated by small-c */
if(profile)
{ol("global ccregis"); /* using these */
ol("global cccalls"); /* labels from */
ol("global ccleavi"); /* profiling routine */
immed(); printlabel(firstfct); nl();
callrts("cccalls");
}
zcall("exit");
/* do an exit gtf 7/16/80 */
}
}
/* Print any assembler stuff needed after all code */
trailer()
{ if(profile) {printlabel(lastfct); ol("= 0");}
/* ol("END"); */ /*...note: commented out! */
nl();
/* 6 May 80 rj errsummary() now goes to console */
comment();
outstr(" --- End of Compilation ---");
nl();
}
/* Print out a name such that it won't annoy the assembler */
/* (by matching anything reserved, like opcodes.) */
/* gtf 4/7/80 */
outname(sname)
char *sname;
{ int len, i,j;
outasm("q");
/* qz => q to shorten names (4/18/81, jrvz) */
len = strlen(sname);
if(len>(ASMPREF+ASMSUFF)){
i = ASMPREF;
len = len-ASMPREF-ASMSUFF;
while(i--) /* jrvz 8/3/82 */
outbyte(raise(*sname++));
while(len--) /* jrvz 8/3/82 */
++sname;
while(*sname)
outbyte(raise(*sname++));
}
else outasm(sname);
/* end outname */}
/* Fetch a static memory cell into the primary register */
getmem(sym)
char *sym;
{ if((sym[ident]!=pointer)&(sym[type]==cchar))
{ot("LD A,("); outname(sym+name);
outasm(")"); nl();
callrts("ccsxt");
}
else if((sym[ident]!=pointer)&(sym[type]==DOUBLE))
{immed(); outname(sym+name); nl();
callrts("dload");
} /* jrvz 8/7/82 */
else
{ot("LD HL,("); outname(sym+name); outasm(")");
nl();
}
}
/* Fetch the address of the specified symbol */
/* into the primary register */
getloc(sym)
char *sym;
{ immed();
outdec(((sym[offset]&255)+
((sym[offset+1])<<8))-
Zsp);
/* 2nd 8-bit mask removed jrvz 8/3/82 */
nl();
ol("ADD HL,SP");
}
/* Store the primary register into the specified */
/* static memory cell */
putmem(sym)
char *sym;
{ if((sym[ident]!=pointer)&(sym[type]==DOUBLE))
{immed(); outname(sym+name); nl();
callrts("dstore");
} /* jrvz 8/7/82 */
else {if((sym[ident]!=pointer)&(sym[type]==cchar))
{ol("LD A,L");
ot("LD (");
outname(sym+name); outasm("),A");
}
else
{ot("LD (");
outname(sym+name); outasm("),HL");
}
nl();
}
}
/* Store the specified object type in the primary register */
/* at the address on the top of the stack */
putstk(typeobj)
char typeobj;
{ if(typeobj==DOUBLE)
{mainpop();
callrts("dstore");
}
else
{if(typeobj==cchar)
{zpop();
ol("LD A,L"); ol("LD (DE),A");
} /* jrvz 7/1/82 */
else
{callrts("ccpint"); popped();
}
}
}
/* Fetch the specified object type indirect through the */
/* primary register into the primary register */
indirect(typeobj)
char typeobj;
{ if(typeobj==cchar)callrts("ccgchar");
else if(typeobj==DOUBLE) /* jrvz 8/7/82 */
callrts("dload");
else callrts("ccgint");
}
/* Swap the primary and secondary registers */
swap()
{ ol("EX DE,HL");
}
/* Print partial instruction to get an immediate value */
/* into the primary register */
immed()
{ ot("LD HL,");
}
/* Push the primary register onto the stack */
zpush()
{ ol("PUSH HL");
Zsp=Zsp-2;
}
/* Push the primary floating point register onto the stack
jrvz 8/7/82 */
dpush()
{ callrts("dpush");
Zsp=Zsp-6;
}
/* Push the primary floating point register, preserving
the top value jrvz 8/7/82 */
dpush2()
{ callrts("dpush2");
Zsp=Zsp-6;
}
/* Pop the top of the stack into the primary register
jrvz 10/11/82 */
mainpop()
{ ol("POP HL");
Zsp=Zsp+2;
}
/* Pop the top of the stack into the secondary register */
zpop()
{ ol("POP DE");
Zsp=Zsp+2;
}
/* Adjust the stack counter for 2 bytes popped off stack */
popped()
{ Zsp=Zsp+2;
}
/* Swap the primary register and the top of the stack */
swapstk()
{ ol("EX (SP),HL");
}
/* Call the specified subroutine name */
zcall(sname)
char *sname;
{ ot("CALL ");
outname(sname);
nl();
}
/* Call a run-time library routine */
callrts(sname)
char *sname;
{
ot("CALL ");
outasm(sname);
nl();
/*end callrts*/}
/* Return from subroutine */
zret()
{ ol("RET");
}
/* Perform subroutine call to value on top of stack */
callstk()
{ immed();
outasm("$+5");
nl();
swapstk();
ol("JP (HL)");
Zsp=Zsp-2;
}
/* Jump to specified internal label number */
jump(label)
int label;
{ ot("JP ");
printlabel(label);
nl();
}
/* Test the primary register and jump if false to label */
testjump(label)
int label;
{ ol("LD A,H");
ol("OR L");
ot("JP Z,");
printlabel(label);
nl();
}
/* Print pseudo-op to define a byte */
defbyte()
{ ot("DEFB ");
}
/*Print pseudo-op to define storage */
defstorage()
{ ot("DEFS ");
}
/* Print pseudo-op to define a word */
defword()
{ ot("DEFW ");
}
/* Modify the stack pointer to the new value indicated */
modstk(newsp)
int newsp;
{ int k;
k=newsp-Zsp;
if(k==0)return newsp;
if(k>=0)
{if(k<7)
{if(k&1)
{ol("INC SP");
--k;
}
while(k)
{ol("POP BC");
k=k-2;
}
return newsp;
}
}
if(k<0)
{if(k>-7)
{if(k&1)
{ol("DEC SP");
++k;
}
while(k)
{ol("PUSH BC");
k=k+2;
}
return newsp;
}
}
swap();
immed();outdec(k);nl();
ol("ADD HL,SP");
ol("LD SP,HL");
swap();
return newsp;
}
/* Multiply the primary register by the length of
some variable jrvz 8/7/82 */
scale(t)
int t; /* type */
{ if(t==cchar) return;
if(t==DOUBLE) sixreg();
else doublereg();
}
/* Double the primary register */
doublereg()
{ ol("ADD HL,HL");
}
/* Multiply the primary register by the length of a double
(preserve DE) jrvz 8/7/82 */
sixreg()
{ ol("LD B,H");
ol("LD C,L");
ol("ADD HL,BC");
ol("ADD HL,BC");
ol("ADD HL,HL");
}
/* Add a constant to the primary register jrvz 10/11/82 */
addimm(x) char *x;
{ ot("LD DE,"); outasm(x); nl(); zadd();
}
/* Add the primary and secondary registers
(result in primary) */
zadd()
{ ol("ADD HL,DE");
}
/* Add the primary floating point register to the
value on the stack (under the return address)
(result in primary) jrvz 8/8/82 */
dadd(){ callrts("dadd"); Zsp=Zsp+6;}
/* Subtract the primary register from the TOS */
/* (TOS = value under the return address) */
/* (results in primary) */
zsub()
{ callrts("ccsub"); popped();
}
/* Subtract the primary floating point register from the
value on the stack (under the return address)
(result in primary) jrvz 8/8/82 */
dsub()
{ callrts("dsub"); Zsp=Zsp+6;}
/* Multiply the primary and TOS */
/* (results in primary */
mult()
{ callrts("ccmult"); popped();
}
/* Multiply the primary floating point register by the value
on the stack (under the return address)
(result in primary) jrvz 8/8/82 */
dmul()
{ callrts("dmul"); Zsp=Zsp+6;}
/* Divide the secondary register by the primary */
/* (quotient in primary, remainder in secondary) */
div()
{ callrts("ccdiv");
}
/* Divide the value on the stack (under the return address)
by the primary floating point register (quotient in primary)
jrvz 8/8/82 */
ddiv()
{ callrts("ddiv"); Zsp=Zsp+6;}
/* Compute remainder (mod) of secondary register divided */
/* by the primary */
/* (remainder in primary, quotient in secondary) */
zmod()
{ div();
swap();
}
/* Inclusive 'or' the primary and the TOS */
/* (results in primary) */
zor()
{callrts("ccor"); popped();}
/* Exclusive 'or' the primary and TOS */
/* (results in primary) */
zxor()
{callrts("ccxor"); popped();}
/* 'And' the primary and TOS */
/* (results in primary) */
zand()
{callrts("ccand"); popped();}
/* Arithmetic shift right the secondary register number of */
/* times in primary (results in primary) */
asr()
{callrts("ccasr");}
/* Arithmetic left shift the TOS number of */
/* times in primary (results in primary) */
asl()
{callrts("ccasl"); popped();}
/* Form two's complement of primary register */
neg()
{callrts("ccneg");}
/* Negate the primary floating point register */
dneg()
{callrts("minusfa");}
/* Form one's complement of primary register */
com()
{callrts("cccom");}
/* Increment the primary register by one */
inc()
{ol("INC HL");}
/* Decrement the primary register by one */
dec()
{ol("DEC HL");}
/* Following are the conditional operators */
/* They compare the TOS against the primary */
/* and put a literal 1 in the primary if the condition is */
/* true, otherwise they clear the primary register */
/* Test for equal */
zeq()
{callrts("cceq"); popped();}
/* Test for not equal */
zne()
{callrts("ccne"); popped();}
/* Test for less than (signed) */
zlt()
{callrts("cclt"); popped();}
/* Test for less than or equal to (signed) */
zle()
{callrts("ccle"); popped();}
/* Test for greater than (signed) */
zgt()
{callrts("ccgt"); popped();}
/* Test for greater than or equal to (signed) */
zge()
{callrts("ccge"); popped();}
/* Test for less than (unsigned) */
ult()
{callrts("ccult"); popped();}
/* Test for less than or equal to (unsigned) */
ule()
{callrts("ccule"); popped();}
/* Test for greater than (unsigned) */
ugt()
{callrts("ccugt"); popped();}
/* Test for greater than or equal to (unsigned) */
uge()
{callrts("ccuge"); popped();}
/* The following conditional operations compare the
top of the stack (TOS) against the primary floating point
register (FA), resulting in 1 if true and 0 if false */
/* Test for floating equal */
deq()
{callrts("deq"); Zsp=Zsp+6;}
/* Test for floating not equal */
dne()
{callrts("dne"); Zsp=Zsp+6;}
/* Test for floating less than (that is, TOS < FA) */
dlt()
{callrts("dlt"); Zsp=Zsp+6;}
/* Test for floating less than or equal to */
dle()
{callrts("dle"); Zsp=Zsp+6;}
/* Test for floating greater than */
dgt()
{callrts("dgt"); Zsp=Zsp+6;}
/* Test for floating greater than or equal */
dge()
{callrts("dge"); Zsp=Zsp+6;}
/* <<<<< End of small-c compiler >>>>> */