123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /*
- * (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
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "assert.h"
- #include "param.h"
- #include "tables.h"
- #include "types.h"
- #include <cgg_cg.h>
- #include "data.h"
- #include "result.h"
- #include "glosym.h"
- #include "extern.h"
- #include "salloc.h"
- #include "utils.h"
- #include "regvar.h"
- #ifdef USE_TES
- #include "label.h"
- #endif
- #include "compute.h"
- #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 */
- 0, /* EX_ISROM */
- #ifdef USE_TES
- 0, /* EX_TOPELTSIZE */
- 0, /* EX_FALLTHROUGH */
- #endif
- };
- 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)
- {
- string r;
- r=salloc(strlen(s));
- strcpy(r,s);
- return(r);
- }
- 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;i<leaf2.e_v.e_con-1;i++)
- mask &= ~(1<<i);
- tmp = leaf1.e_v.e_con&mask;
- presult->e_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;i<leaf2.e_v.e_con;i++)
- mask &= ~(1<<i);
- presult->e_v.e_con = (leaf1.e_v.e_con&mask)==0;
- return;
- case EX_ROM:
- assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
- leaf2=dollar[node->ex_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<<node->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_con<leaf2.e_v.e_con;
- return;
- case EX_NCPLE:
- 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_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 = isregvar((long) leaf1.e_v.e_con);
- if (i<=0) {
- presult->e_typ = EV_UNDEF;
- return;
- }
- presult->e_typ = EV_REG;
- presult->e_v.e_reg=i;
- return;
- #endif
- 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
- }
- }
|