Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/old/kc/cc83.c
There are no other files named cc83.c in the archive.
/* cc83.c -- Code generator TOPS-20 (contd)   (C) 1981  K. Chen */

#define	    sd   extern
#include    "cc.g"

/* --------------------------------------------- */
/*	generate code for ternary operators      */
/* --------------------------------------------- */

gternary(n)
struct NODE *n;
{
  int false, done, r, q, first, second, opt;

  false = getlabel();
  done = getlabel();
  gboolean(n->left, false, 0);
  n = n->right;
  first = r = genstmt(n->left);
  opt = optimize;
  optimize = 0;
  release (r);
  optimize = opt;
  if (first >= 16) first = regis[first];
  code6(GOTO, 0, done);
  outlab(false);
  second = q = genstmt(n->right);
  if (second >= 16) second = regis[second];
  if (first != second) {
      changereg(r, q);
      if (first) regis[first] = 1;
      release(q);
  }
  else if (second == 0) release(q);

  outlab(done);
  if (first == 0) {
      flushcode(0);
      r = getzero();
  }
  return r;
}


/* --------------------------------------------- */
/*	generate short logicals if possible      */
/* --------------------------------------------- */

genshort(n, opr, label, mode)
struct NODE *n;
{
  int op, r;
  struct NODE *l;

  if ((op = tok[n->nop].ttype) == BOOLOP || op == BOOLUN)
     gboolean(n, label, mode);
  else {
     r = genstmt(n);
     code6(opr, r, label);
     release(r);
  }
}

/* ----------------------------------------- */
/*	jump to false label if not true      */
/*	reverse sense if reverse bit set     */
/* ----------------------------------------- */

gboolean(n, false, reverse)
struct NODE *n;
{
  int r, lab, op, val;
  struct PSEUDO *p;

  switch (n->nop) {
  case NOT:
       r = genstmt(n->left);
       op = (reverse) ? LAND : LOR;
       code6(op, r, false);
       release(r);
       break;
  case LAND:
       op = n->left->nop ;
       if (op == NOT || op == LAND || op == LOR) {
	   gboolean(n->left, false, reverse);
	   gboolean(n->right, false, reverse);
       }
       else {
	   r = genstmt(n->left);
           op = (reverse) ? LOR : LAND;
           lab = (reverse) ? getlabel() : false;
           code6(LAND, r, lab);
           release(r);

	   genshort(n->right, n->nop, false, reverse);
           if (reverse) outlab(lab);
       }
       break;
  case LOR:
       lab = (reverse) ? false : getlabel();
       op = (reverse) ? LOR : LAND;
       r = genstmt(n->left);
       code6(LOR, r, lab);
       release(r);
       r = genstmt(n->right);
       code6(op, r, false);
       release(r);
       if (!reverse) outlab(lab);
       break;
  case NEQ:
  case LEQ:
  case GEQ:
  case LESS:
  case GREAT:
  case EQUAL:
       gboolop(n, reverse);
       code6(GOTO, 0, false);
       break;
  default:
       if (n->nop == ICONST) {
	   op = n->niconst;
	   if ((!op && !reverse) || (op && reverse)) {
	       code6(GOTO, 0, false);
	   }
	   return;
       }
       r = genstmt(n);
       op = (reverse) ? LOR : LAND;
       code6(op, r, false);
       release(r);
       flushcode(0);
       break;
  }
}

/* ---------------------------------- */
/*	code for == > < <= >= !=      */
/* ---------------------------------- */

gboolop(n, reverse)
struct NODE *n;
{
  int op, r1, r2;
  struct PSEUDO *p;

  r1 = genstmt(n->left);
  r2 = genstmt(n->right);
  op = n->nop;
  if (reverse) op = revop(op);

  if ((p = previous) != NULL) {
      if (p->ptype == GLOBAL && p->pop == IDENT && p->preg == r2) {
          p->pop = op;
	  p->preg = r1;
      }
      else {
	  if (p->pop == SETZ && p->ptype == ONEREG && p->preg == r2) {
	      p->ptype = IMMED;
	      p->pop = IDENT;
	      p->pvalue = 0;
          }
   	  if (p->ptype == IMMED && p->preg == r2) {
	      p->ptype = RCONST;
	      p->pop = immedop(op);
	      p->preg = r1;
	   }
	   else
	      code0(op, r1, r2);
      }
      release(r1);
      release(r2);
      return;
   }
   code0(op, r1, r2);
   release(r2);
   release(r1);
}

/* ----------------------------------- */
/*	reverse boolean operation      */
/* ----------------------------------- */

revop(op)
{
  switch (op) {
  case NEQ:
       return EQUAL;
  case EQUAL:
       return NEQ;
  case LESS:
       return GEQ;
  case GEQ:
       return LESS;
  case LEQ:
       return GREAT;
  case GREAT:
       return LEQ;
  }
}

/* ------------------------------------------------------ */
/*	return immediate version of boolean operator      */
/* ------------------------------------------------------ */

immedop(op)
{
  switch (op) {
  case NEQ:
       return CAIN;
  case EQUAL:
       return CAIE;
  case LESS:
       return CAIL;
  case GEQ:
       return CAIGE;
  case LEQ:
       return CAILE;
  case GREAT:
       return CAIG;
  }
}

directop(op)
{
  switch (op) {
  case CAIN:
       return NEQ;
  case CAIE:
       return EQUAL;
  case CAIL:
       return LESS;
  case CAIG:
       return GREAT;
  case CAILE:
       return LEQ;
  case CAIGE:
       return GEQ;
  }
}


coerce(n)
struct NODE *n;
{
  int r, s, opt;
  switch (n->nc) {
  case NOCOER:
       return genstmt(n->left);
  case PI_PC:
       r = genstmt(n->left);
       code1(HRL,r,MSBYTE);
       return r;
  case PC_PI:
       r = genstmt(n->left);
       code1(HRL,r,0);
       return r;
  case PC_PC:
       r = genstmt(n->left);
       s = getreg();
       opt = optimize;
       optimize = 0;
       code0(HRRZ, s, r);
       code8(LSHFT, s, 2);
       code8(ROT, r, 3);
       code1(AND, r, 3);
       optimize = opt;
       code0(MINUS, s, r);
       release(r);
       return s;
  default:
       fprintf(stderr, "Unknown coercion %d\n", n->nc);
       return 0;
  }
}