#ifndef NORCSID static char rcsid[] = "$Header$"; #endif #include "assert.h" #include "param.h" #include "tables.h" #include "types.h" #include #include "data.h" #include "result.h" #include "glosym.h" #include "extern.h" /* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * * Author: Hans van Staveren */ #ifndef __STDC__ extern char *sprintf(); #else /* sprintf should be declared in stdio.h, as returning an int */ #endif #define LLEAF 01 #define LDEF 02 #define RLEAF 04 #define RDEF 010 #define LLDEF LLEAF|LDEF #define RLDEF RLEAF|RDEF char opdesc[] = { 0, /* EX_TOKFIELD */ 0, /* EX_ARG */ 0, /* EX_CON */ 0, /* EX_ALLREG */ LLDEF|RLDEF, /* EX_SAMESIGN */ LLDEF|RLDEF, /* EX_SFIT */ LLDEF|RLDEF, /* EX_UFIT */ 0, /* EX_ROM */ LLDEF|RLDEF, /* EX_NCPEQ */ LLDEF|RLDEF, /* EX_SCPEQ */ LLDEF|RLDEF, /* EX_RCPEQ */ LLDEF|RLDEF, /* EX_NCPNE */ LLDEF|RLDEF, /* EX_SCPNE */ LLDEF|RLDEF, /* EX_RCPNE */ LLDEF|RLDEF, /* EX_NCPGT */ LLDEF|RLDEF, /* EX_NCPGE */ LLDEF|RLDEF, /* EX_NCPLT */ LLDEF|RLDEF, /* EX_NCPLE */ LLDEF, /* EX_OR2 */ LLDEF, /* EX_AND2 */ LLDEF|RLDEF, /* EX_PLUS */ LLDEF|RLDEF, /* EX_CAT */ LLDEF|RLDEF, /* EX_MINUS */ LLDEF|RLDEF, /* EX_TIMES */ LLDEF|RLDEF, /* EX_DIVIDE */ LLDEF|RLDEF, /* EX_MOD */ LLDEF|RLDEF, /* EX_LSHIFT */ LLDEF|RLDEF, /* EX_RSHIFT */ LLDEF, /* EX_NOT */ LLDEF, /* EX_COMP */ 0, /* EX_COST */ 0, /* EX_STRING */ LLEAF, /* EX_DEFINED */ 0, /* EX_SUBREG */ LLDEF, /* EX_TOSTRING */ LLDEF, /* EX_UMINUS */ 0, /* EX_REG */ 0, /* EX_LOWW */ 0, /* EX_HIGHW */ LLDEF, /* EX_INREG */ LLDEF, /* EX_REGVAR */ LLDEF|RLDEF, /* EX_OR */ LLDEF|RLDEF, /* EX_XOR */ LLDEF|RLDEF, /* EX_AND */ }; string salloc(),strcpy(),strcat(); string mycat(s1,s2) register string s1,s2; { register string s; if (s1==0 || *s1=='\0') return(s2); if (s2==0 || *s2=='\0') return(s1); s=salloc(strlen(s1)+strlen(s2)+1); strcpy(s,s1); strcat(s,"+"); strcat(s,s2); return(s); } string mystrcpy(s) register string s; { register string r; r=salloc(strlen(s)); strcpy(r,s); return(r); } char digstr[21][15]; string tostring(n) register word n; { char buf[25]; if (n>=-20 && n<=20 && (n&1)==0) { if (digstr[((int)n>>1)+10][0]==0) sprintf(digstr[((int)n>>1)+10],WRD_FMT,n); return(digstr[((int)n>>1)+10]); } sprintf(buf,WRD_FMT,n); return(mystrcpy(buf)); } result_t undefres= {EV_UNDEF}; result_t compute(node) register node_p node; { result_t leaf1,leaf2,result; register token_p tp; int desc; long mask,tmp; int i,tmpreg; glosym_p gp; desc=opdesc[node->ex_operator]; if (desc&LLEAF) { leaf1 = compute(&enodes[node->ex_lnode]); if (desc&LDEF && leaf1.e_typ==EV_UNDEF) return(undefres); } if (desc&RLEAF) { leaf2 = compute(&enodes[node->ex_rnode]); if (desc&RDEF && leaf2.e_typ==EV_UNDEF) return(undefres); } result.e_typ=EV_INT; switch(node->ex_operator) { default: assert(FALSE); case EX_TOKFIELD: if (node->ex_lnode==0) if (curtoken) tp = curtoken; else tp = &fakestack[stackheight-1]; else tp = &fakestack[stackheight-node->ex_lnode]; switch(result.e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) { default: assert(FALSE); case EV_INT: result.e_v.e_con = tp->t_att[node->ex_rnode-1].aw; break; case EV_ADDR: result.e_v.e_addr = tp->t_att[node->ex_rnode-1].aa; break; case EV_REG: result.e_v.e_reg = tp->t_att[node->ex_rnode-1].ar; break; } return(result); case EX_ARG: return(dollar[node->ex_lnode-1]); case EX_CON: result.e_typ = EV_INT; result.e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff); return(result); case EX_REG: result.e_typ = EV_REG; result.e_v.e_reg = node->ex_lnode; return(result); case EX_ALLREG: result.e_typ = EV_REG; result.e_v.e_reg = allreg[node->ex_lnode-1]; #if MAXMEMBERS!=0 if (node->ex_rnode!=0) result.e_v.e_reg = machregs[result.e_v.e_reg]. r_members[node->ex_rnode-1]; #endif return(result); case EX_SAMESIGN: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_typ = EV_INT; if (leaf1.e_v.e_con>=0) result.e_v.e_con= leaf2.e_v.e_con>=0; else result.e_v.e_con= leaf2.e_v.e_con<0; return(result); case EX_SFIT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); mask = 0xFFFFFFFFL; for (i=0;iex_rnode>=0 &&node->ex_rnodeex_lnode]; if (leaf2.e_typ != EV_ADDR) return(undefres); if (leaf2.e_v.e_addr.ea_off!=0) return(undefres); gp = lookglo(leaf2.e_v.e_addr.ea_str); if (gp == (glosym_p) 0) return(undefres); if ((gp->gl_rom[MAXROM]&(1<ex_rnode))==0) return(undefres); result.e_v.e_con = gp->gl_rom[node->ex_rnode]; return(result); case EX_LOWW: result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF; return(result); case EX_HIGHW: result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16; return(result); case EX_NCPEQ: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con; return(result); case EX_SCPEQ: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); result.e_v.e_con = (strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 && leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off); return(result); case EX_RCPEQ: assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG); result.e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg; return(result); case EX_NCPNE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con; return(result); case EX_SCPNE: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); result.e_v.e_con = !(strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 && leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off); return(result); case EX_RCPNE: assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG); result.e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg; return(result); case EX_NCPGT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con; return(result); case EX_NCPGE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con; return(result); case EX_NCPLT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_conex_rnode])); return(leaf1); case EX_AND2: assert(leaf1.e_typ == EV_INT); if (leaf1.e_v.e_con!=0) return(compute(&enodes[node->ex_rnode])); return(leaf1); case EX_PLUS: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con; return(result); case EX_CAT: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); result.e_typ = EV_ADDR; result.e_v.e_addr.ea_str = mycat(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str); result.e_v.e_addr.ea_off = leaf1.e_v.e_addr.ea_off+leaf2.e_v.e_addr.ea_off; return(result); case EX_MINUS: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con; return(result); case EX_OR: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con; return(result); case EX_XOR: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con; return(result); case EX_AND: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con; return(result); case EX_TIMES: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con; return(result); case EX_DIVIDE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con; return(result); case EX_MOD: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con; return(result); case EX_LSHIFT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con; return(result); case EX_RSHIFT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); result.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con; return(result); case EX_NOT: assert(leaf1.e_typ == EV_INT); result.e_v.e_con = !leaf1.e_v.e_con; return(result); case EX_COMP: assert(leaf1.e_typ == EV_INT); result.e_v.e_con = ~leaf1.e_v.e_con; return(result); case EX_STRING: result.e_typ = EV_ADDR; result.e_v.e_addr.ea_str = codestrings[node->ex_lnode]; result.e_v.e_addr.ea_off = 0; return(result); case EX_DEFINED: result.e_v.e_con=leaf1.e_typ!=EV_UNDEF; return(result); case EX_SUBREG: result.e_typ = EV_REG; if (node->ex_lnode==0) if (curtoken) tp = curtoken; else tp = &fakestack[stackheight-1]; else tp = &fakestack[stackheight-node->ex_lnode]; assert(tp->t_token == -1); tmpreg= tp->t_att[0].ar; #if MAXMEMBERS!=0 if (node->ex_rnode) tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1]; #endif result.e_v.e_reg=tmpreg; return(result); case EX_TOSTRING: assert(leaf1.e_typ == EV_INT); result.e_typ = EV_ADDR; result.e_v.e_addr.ea_str = ""; result.e_v.e_addr.ea_off = leaf1.e_v.e_con; return(result); #ifdef REGVARS case EX_INREG: assert(leaf1.e_typ == EV_INT); result.e_v.e_con = isregtyp((long) leaf1.e_v.e_con); return(result); case EX_REGVAR: assert(leaf1.e_typ == EV_INT); i = isregvar((long) leaf1.e_v.e_con); if (i<=0) return(undefres); result.e_typ = EV_REG; result.e_v.e_reg=i; return(result); #endif case EX_UMINUS: assert(leaf1.e_typ == EV_INT); result.e_v.e_con = -leaf1.e_v.e_con; return(result); } }