#ifndef NORCSID static char rcsid[] = "$Id$"; #endif #include #include #include #include #include "param.h" #include "tables.h" #include "types.h" #include #include "data.h" #include "result.h" #include "glosym.h" #include "extern.h" #ifdef REGVARS #include "regvar.h" #endif #ifdef USE_TES #include "label.h" #endif /* * (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 */ #define LLEAF 01 #define LDEF 02 #define RLEAF 04 #define RDEF 010 #define LLDEF LLEAF|LDEF #define RLDEF RLEAF|RDEF static const 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 */ 0, /* EX_ISROM */ #ifdef USE_TES 0, /* EX_TOPELTSIZE */ 0, /* EX_FALLTHROUGH */ #endif }; static string mycat(string s1, string s2) { 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(string s) { register string r; r=salloc(strlen(s)); strcpy(r,s); return(r); } static char digstr[21][15]; string tostring(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)); } void compute(node_p node, result_t *presult) { result_t leaf1,leaf2; token_p tp; int desc; long mask,tmp; int i,tmpreg; glosym_p gp; presult->e_typ = EV_UNDEF; desc=opdesc[node->ex_operator]; if (desc&LLEAF) { compute(&enodes[node->ex_lnode], &leaf1); if (desc&LDEF && leaf1.e_typ==EV_UNDEF) return; } if (desc&RLEAF) { compute(&enodes[node->ex_rnode], &leaf2); if (desc&RDEF && leaf2.e_typ==EV_UNDEF) return; } presult->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(presult->e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) { default: assert(FALSE); case EV_INT: presult->e_v.e_con = tp->t_att[node->ex_rnode-1].aw; break; case EV_ADDR: presult->e_v.e_addr = tp->t_att[node->ex_rnode-1].aa; break; case EV_REG: presult->e_v.e_reg = tp->t_att[node->ex_rnode-1].ar; break; } return; case EX_ARG: *presult = dollar[node->ex_lnode-1]; return; case EX_CON: presult->e_typ = EV_INT; presult->e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff); return; case EX_REG: presult->e_typ = EV_REG; presult->e_v.e_reg = node->ex_lnode; return; case EX_ALLREG: presult->e_typ = EV_REG; presult->e_v.e_reg = allreg[node->ex_lnode-1]; #if MAXMEMBERS!=0 if (node->ex_rnode!=0) presult->e_v.e_reg = machregs[presult->e_v.e_reg]. r_members[node->ex_rnode-1]; #endif return; case EX_SAMESIGN: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_typ = EV_INT; if (leaf1.e_v.e_con>=0) presult->e_v.e_con= leaf2.e_v.e_con>=0; else presult->e_v.e_con= leaf2.e_v.e_con<0; return; case EX_SFIT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); mask = 0xFFFFFFFFL; for (i=0;ie_v.e_con = tmp==0||tmp==mask; return; case EX_UFIT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); mask = 0xFFFFFFFFL; for (i=0;ie_v.e_con = (leaf1.e_v.e_con&mask)==0; return; case EX_ROM: assert(node->ex_rnode>=0 &&node->ex_rnodeex_lnode]; presult->e_typ = EV_UNDEF; if (leaf2.e_typ != EV_ADDR) return; if (leaf2.e_v.e_addr.ea_off!=0) return; gp = lookglo(leaf2.e_v.e_addr.ea_str); if (gp == (glosym_p) 0) return; if ((gp->gl_rom[MAXROM]&(1<ex_rnode))==0) return; presult->e_typ = EV_INT; presult->e_v.e_con = gp->gl_rom[node->ex_rnode]; return; case EX_ISROM: leaf2=dollar[node->ex_lnode]; if (leaf2.e_typ != EV_ADDR) presult->e_v.e_con = 0; else presult->e_v.e_con = lookglo(leaf2.e_v.e_addr.ea_str) != 0; return; case EX_LOWW: presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF; return; case EX_HIGHW: presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16; return; case EX_NCPEQ: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con; return; case EX_SCPEQ: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); presult->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; case EX_RCPEQ: assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG); presult->e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg; return; case EX_NCPNE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con; return; case EX_SCPNE: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); presult->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; case EX_RCPNE: assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG); presult->e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg; return; case EX_NCPGT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con; return; case EX_NCPGE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con; return; case EX_NCPLT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_cone_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con; return; case EX_OR2: assert(leaf1.e_typ == EV_INT); if (leaf1.e_v.e_con==0) { compute(&enodes[node->ex_rnode], presult); } else *presult = leaf1; return; case EX_AND2: assert(leaf1.e_typ == EV_INT); if (leaf1.e_v.e_con!=0) { compute(&enodes[node->ex_rnode], presult); } else *presult = leaf1; return; case EX_PLUS: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con; return; case EX_CAT: assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR); presult->e_typ = EV_ADDR; presult->e_v.e_addr.ea_str = mycat(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str); presult->e_v.e_addr.ea_off = leaf1.e_v.e_addr.ea_off+leaf2.e_v.e_addr.ea_off; return; case EX_MINUS: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con; return; case EX_OR: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con; return; case EX_XOR: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con; return; case EX_AND: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con; return; case EX_TIMES: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con; return; case EX_DIVIDE: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con; return; case EX_MOD: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con; return; case EX_LSHIFT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con; return; case EX_RSHIFT: assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT); presult->e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con; return; case EX_NOT: assert(leaf1.e_typ == EV_INT); presult->e_v.e_con = !leaf1.e_v.e_con; return; case EX_COMP: assert(leaf1.e_typ == EV_INT); presult->e_v.e_con = ~leaf1.e_v.e_con; return; case EX_STRING: presult->e_typ = EV_ADDR; presult->e_v.e_addr.ea_str = codestrings[node->ex_lnode]; presult->e_v.e_addr.ea_off = 0; return; case EX_DEFINED: presult->e_v.e_con=leaf1.e_typ!=EV_UNDEF; return; case EX_SUBREG: presult->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 presult->e_v.e_reg=tmpreg; return; case EX_TOSTRING: assert(leaf1.e_typ == EV_INT); presult->e_typ = EV_ADDR; presult->e_v.e_addr.ea_str = ""; presult->e_v.e_addr.ea_off = leaf1.e_v.e_con; return; #ifdef REGVARS case EX_INREG: assert(leaf1.e_typ == EV_INT); presult->e_v.e_con = isregtyp((long) leaf1.e_v.e_con); return; case EX_REGVAR: assert(leaf1.e_typ == EV_INT); i = PICK_REGVAR((long) leaf1.e_v.e_con, node->ex_rnode); if (i<=0) { presult->e_typ = EV_UNDEF; return; } presult->e_typ = EV_REG; presult->e_v.e_reg=i; return; #endif /* REGVARS */ case EX_UMINUS: assert(leaf1.e_typ == EV_INT); presult->e_v.e_con = -leaf1.e_v.e_con; return; #ifdef USE_TES case EX_TOPELTSIZE: /* Hans, new */ { register label_p lbl; lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper); if (lbl != (label_p)0) { presult->e_v.e_con = lbl->lb_height; } else { presult->e_v.e_con = 0; } return; } case EX_FALLTHROUGH: /* Hans, new */ { register label_p lbl; lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper); if (lbl != (label_p)0) { presult->e_v.e_con = lbl->lb_fallthrough; } else presult->e_v.e_con = 0; return; } #endif } }