<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/rsc/txt.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>&rsquo;s /usr/web/sources/contrib/rsc/txt.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include "gc.h"

void
ginit(void)
{
       int i;
       Type *t;

       thechar = '8';
       thestring = "386";
       exregoffset = 0;
       exfregoffset = 0;
       listinit();
       nstring = 0;
       mnstring = 0;
       nrathole = 0;
       pc = 0;
       breakpc = -1;
       continpc = -1;
       cases = C;
       firstp = P;
       lastp = P;
       tfield = types[TLONG];

       zprog.link = P;
       zprog.as = AGOK;
       zprog.from.type = D_NONE;
       zprog.from.index = D_NONE;
       zprog.from.scale = 0;
       zprog.to = zprog.from;

       regnode.op = OREGISTER;
       regnode.class = CEXREG;
       regnode.reg = REGTMP;
       regnode.complex = 0;
       regnode.addable = 11;
       regnode.type = types[TLONG];

       fregnode0 = regnode;
       fregnode0.reg = D_F0;
       fregnode0.type = types[TDOUBLE];

       fregnode1 = fregnode0;
       fregnode1.reg = D_F0+1;

       constnode.op = OCONST;
       constnode.class = CXXX;
       constnode.complex = 0;
       constnode.addable = 20;
       constnode.type = types[TLONG];

       fconstnode.op = OCONST;
       fconstnode.class = CXXX;
       fconstnode.complex = 0;
       fconstnode.addable = 20;
       fconstnode.type = types[TDOUBLE];

       nodsafe = new(ONAME, Z, Z);
       nodsafe-&gt;sym = slookup(".safe");
       nodsafe-&gt;type = types[TINT];
       nodsafe-&gt;etype = types[TINT]-&gt;etype;
       nodsafe-&gt;class = CAUTO;
       complex(nodsafe);

       t = typ(TARRAY, types[TCHAR]);
       symrathole = slookup(".rathole");
       symrathole-&gt;class = CGLOBL;
       symrathole-&gt;type = t;

       nodrat = new(ONAME, Z, Z);
       nodrat-&gt;sym = symrathole;
       nodrat-&gt;type = types[TIND];
       nodrat-&gt;etype = TVOID;
       nodrat-&gt;class = CGLOBL;
       complex(nodrat);
       nodrat-&gt;type = t;

       nodret = new(ONAME, Z, Z);
       nodret-&gt;sym = slookup(".ret");
       nodret-&gt;type = types[TIND];
       nodret-&gt;etype = TIND;
       nodret-&gt;class = CPARAM;
       nodret = new(OIND, nodret, Z);
       complex(nodret);

       com64init();

       for(i=0; i&lt;nelem(reg); i++) {
               reg[i] = 1;
               if(i &gt;= D_AX &amp;&amp; i &lt;= D_DI &amp;&amp; i != D_SP)
                       reg[i] = 0;
       }
}

void
gclean(void)
{
       int i;
       Sym *s;

       reg[D_SP]--;
       for(i=D_AX; i&lt;=D_DI; i++)
               if(reg[i])
                       diag(Z, "reg %R left allocated", i);
       while(mnstring)
               outstring("", 1L);
       symstring-&gt;type-&gt;width = nstring;
       symrathole-&gt;type-&gt;width = nrathole;
       for(i=0; i&lt;NHASH; i++)
       for(s = hash[i]; s != S; s = s-&gt;link) {
               if(s-&gt;type == T)
                       continue;
               if(s-&gt;type-&gt;width == 0)
                       continue;
               if(s-&gt;class != CGLOBL &amp;&amp; s-&gt;class != CSTATIC)
                       continue;
               if(s-&gt;type == types[TENUM])
                       continue;
               gpseudo(AGLOBL, s, nodconst(s-&gt;type-&gt;width));
       }
       nextpc();
       p-&gt;as = AEND;
       outcode();
}

void
nextpc(void)
{

       p = alloc(sizeof(*p));
       *p = zprog;
       p-&gt;lineno = nearln;
       pc++;
       if(firstp == P) {
               firstp = p;
               lastp = p;
               return;
       }
       lastp-&gt;link = p;
       lastp = p;
}

void
gargs(Node *n, Node *tn1, Node *tn2)
{
       long regs;
       Node fnxargs[20], *fnxp;

       regs = cursafe;

       fnxp = fnxargs;
       garg1(n, tn1, tn2, 0, &amp;fnxp);       /* compile fns to temps */

       curarg = 0;
       fnxp = fnxargs;
       garg1(n, tn1, tn2, 1, &amp;fnxp);       /* compile normal args and temps */

       cursafe = regs;
}

int nareg(void)
{
       int i, n;

       n = 0;
       for(i=D_AX; i&lt;=D_DI; i++)
               if(reg[i] == 0)
                       n++;
       return n;
}

void
garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
{
       Node nod;

       if(n == Z)
               return;
       if(n-&gt;op == OLIST) {
               garg1(n-&gt;left, tn1, tn2, f, fnxp);
               garg1(n-&gt;right, tn1, tn2, f, fnxp);
               return;
       }
       if(f == 0) {
               if(n-&gt;complex &gt;= FNX) {
                       regsalloc(*fnxp, n);
                       nod = znode;
                       nod.op = OAS;
                       nod.left = *fnxp;
                       nod.right = n;
                       nod.type = n-&gt;type;
                       cgen(&amp;nod, Z);
                       (*fnxp)++;
               }
               return;
       }
       if(typesu[n-&gt;type-&gt;etype] || typev[n-&gt;type-&gt;etype]) {
               regaalloc(tn2, n);
               if(n-&gt;complex &gt;= FNX) {
                       sugen(*fnxp, tn2, n-&gt;type-&gt;width);
                       (*fnxp)++;
               } else
                       sugen(n, tn2, n-&gt;type-&gt;width);
               return;
       }
       if(REGARG &amp;&amp; curarg == 0 &amp;&amp; typeilp[n-&gt;type-&gt;etype]) {
               regaalloc1(tn1, n);
               if(n-&gt;complex &gt;= FNX) {
                       cgen(*fnxp, tn1);
                       (*fnxp)++;
               } else
                       cgen(n, tn1);
               return;
       }
       if(vconst(n) == 0) {
               regaalloc(tn2, n);
               gmove(n, tn2);
               return;
       }
       regalloc(tn1, n, Z);
       if(n-&gt;complex &gt;= FNX) {
               cgen(*fnxp, tn1);
               (*fnxp)++;
       } else
               cgen(n, tn1);
       regaalloc(tn2, n);
       gmove(tn1, tn2);
       regfree(tn1);
}

Node*
nodconst(long v)
{
       constnode.vconst = v;
       return &amp;constnode;
}

Node*
nodfconst(double d)
{
       fconstnode.fconst = d;
       return &amp;fconstnode;
}

int
isreg(Node *n, int r)
{

       if(n-&gt;op == OREGISTER)
               if(n-&gt;reg == r)
                       return 1;
       return 0;
}

int
nodreg(Node *n, Node *nn, int r)
{

       *n = regnode;
       n-&gt;reg = r;
       if(reg[r] == 0)
               return 0;
       if(nn != Z) {
               n-&gt;type = nn-&gt;type;
               n-&gt;lineno = nn-&gt;lineno;
               if(nn-&gt;op == OREGISTER)
               if(nn-&gt;reg == r)
                       return 0;
       }
       return 1;
}

void
regret(Node *n, Node *nn)
{
       int r;

       r = REGRET;
       if(typefd[nn-&gt;type-&gt;etype])
               r = FREGRET;
       nodreg(n, nn, r);
       reg[r]++;
}

void
regalloc(Node *n, Node *tn, Node *o)
{
       int i;

       switch(tn-&gt;type-&gt;etype) {
       case TCHAR:
       case TUCHAR:
       case TSHORT:
       case TUSHORT:
       case TINT:
       case TUINT:
       case TLONG:
       case TULONG:
       case TIND:
               if(o != Z &amp;&amp; o-&gt;op == OREGISTER) {
                       i = o-&gt;reg;
                       if(i &gt;= D_AX &amp;&amp; i &lt;= D_DI)
                               goto out;
               }
               for(i=D_AX; i&lt;=D_DI; i++)
                       if(reg[i] == 0)
                               goto out;
               diag(tn, "out of fixed registers");
abort();
               goto err;

       case TFLOAT:
       case TDOUBLE:
       case TVLONG:
               i = D_F0;
               goto out;
       }
       diag(tn, "unknown type in regalloc: %T", tn-&gt;type);
err:
       i = 0;
out:
       if(i)
               reg[i]++;
       nodreg(n, tn, i);
//print("+ %R %d\n", i, reg[i]);
}

void
regialloc(Node *n, Node *tn, Node *o)
{
       Node nod;

       nod = *tn;
       nod.type = types[TIND];
       regalloc(n, &amp;nod, o);
}

void
regfree(Node *n)
{
       int i;

       i = 0;
       if(n-&gt;op != OREGISTER &amp;&amp; n-&gt;op != OINDREG)
               goto err;
       i = n-&gt;reg;
       if(i &lt; 0 || i &gt;= sizeof(reg))
               goto err;
       if(reg[i] &lt;= 0)
               goto err;
       reg[i]--;
//print("- %R %d\n", i, reg[i]);
       return;
err:
       diag(n, "error in regfree: %R", i);
}

void
regsalloc(Node *n, Node *nn)
{
       cursafe = align(cursafe, nn-&gt;type, Aaut3);
       maxargsafe = maxround(maxargsafe, cursafe+curarg);
       *n = *nodsafe;
       n-&gt;xoffset = -(stkoff + cursafe);
       n-&gt;type = nn-&gt;type;
       n-&gt;etype = nn-&gt;type-&gt;etype;
       n-&gt;lineno = nn-&gt;lineno;
}

void
regaalloc1(Node *n, Node *nn)
{
       nodreg(n, nn, REGARG);
       reg[REGARG]++;
       curarg = align(curarg, nn-&gt;type, Aarg1);
       curarg = align(curarg, nn-&gt;type, Aarg2);
       maxargsafe = maxround(maxargsafe, cursafe+curarg);
}

void
regaalloc(Node *n, Node *nn)
{
       curarg = align(curarg, nn-&gt;type, Aarg1);
       *n = *nn;
       n-&gt;op = OINDREG;
       n-&gt;reg = REGSP;
       n-&gt;xoffset = curarg;
       n-&gt;complex = 0;
       n-&gt;addable = 20;
       curarg = align(curarg, nn-&gt;type, Aarg2);
       maxargsafe = maxround(maxargsafe, cursafe+curarg);
}

void
regind(Node *n, Node *nn)
{

       if(n-&gt;op != OREGISTER) {
               diag(n, "regind not OREGISTER");
               return;
       }
       n-&gt;op = OINDREG;
       n-&gt;type = nn-&gt;type;
}

void
naddr(Node *n, Adr *a)
{
       long v;

       a-&gt;type = D_NONE;
       if(n == Z)
               return;
       switch(n-&gt;op) {
       default:
       bad:
               diag(n, "bad in naddr: %O %D", n-&gt;op, a);
//prtree(n, "naddr");
               break;

       case OREGISTER:
               a-&gt;type = n-&gt;reg;
               a-&gt;sym = S;
               break;


       case OIND:
               naddr(n-&gt;left, a);
               if(a-&gt;type &gt;= D_AX &amp;&amp; a-&gt;type &lt;= D_DI)
                       a-&gt;type += D_INDIR;
               else
               if(a-&gt;type == D_CONST)
                       a-&gt;type = D_NONE+D_INDIR;
               else
               if(a-&gt;type == D_ADDR) {
                       a-&gt;type = a-&gt;index;
                       a-&gt;index = D_NONE;
               } else
                       goto bad;
               break;

       case OINDEX:
               a-&gt;type = idx.ptr;
               if(n-&gt;left-&gt;op == OADDR || n-&gt;left-&gt;op == OCONST)
                       naddr(n-&gt;left, a);
               if(a-&gt;type &gt;= D_AX &amp;&amp; a-&gt;type &lt;= D_DI)
                       a-&gt;type += D_INDIR;
               else
               if(a-&gt;type == D_CONST)
                       a-&gt;type = D_NONE+D_INDIR;
               else
               if(a-&gt;type == D_ADDR) {
                       a-&gt;type = a-&gt;index;
                       a-&gt;index = D_NONE;
               } else
                       goto bad;
               a-&gt;index = idx.reg;
               a-&gt;scale = n-&gt;scale;
               a-&gt;offset += n-&gt;xoffset;
               break;

       case OINDREG:
               a-&gt;type = n-&gt;reg+D_INDIR;
               a-&gt;sym = S;
               a-&gt;offset = n-&gt;xoffset;
               break;

       case ONAME:
               a-&gt;etype = n-&gt;etype;
               a-&gt;type = D_STATIC;
               a-&gt;sym = n-&gt;sym;
               a-&gt;offset = n-&gt;xoffset;
               if(n-&gt;class == CSTATIC)
                       break;
               if(n-&gt;class == CEXTERN || n-&gt;class == CGLOBL) {
                       a-&gt;type = D_EXTERN;
                       break;
               }
               if(n-&gt;class == CAUTO) {
                       a-&gt;type = D_AUTO;
                       break;
               }
               if(n-&gt;class == CPARAM) {
                       a-&gt;type = D_PARAM;
                       break;
               }
               goto bad;

       case OCONST:
               if(typefd[n-&gt;type-&gt;etype]) {
                       a-&gt;type = D_FCONST;
                       a-&gt;dval = n-&gt;fconst;
                       break;
               }
               a-&gt;sym = S;
               a-&gt;type = D_CONST;
               a-&gt;offset = n-&gt;vconst;
               break;

       case OADDR:
               naddr(n-&gt;left, a);
               if(a-&gt;type &gt;= D_INDIR) {
                       a-&gt;type -= D_INDIR;
                       break;
               }
               if(a-&gt;type == D_EXTERN || a-&gt;type == D_STATIC ||
                  a-&gt;type == D_AUTO || a-&gt;type == D_PARAM)
                       if(a-&gt;index == D_NONE) {
                               a-&gt;index = a-&gt;type;
                               a-&gt;type = D_ADDR;
                               break;
                       }
               goto bad;

       case OADD:
               if(n-&gt;right-&gt;op == OCONST) {
                       v = n-&gt;right-&gt;vconst;
                       naddr(n-&gt;left, a);
               } else
               if(n-&gt;left-&gt;op == OCONST) {
                       v = n-&gt;left-&gt;vconst;
                       naddr(n-&gt;right, a);
               } else
                       goto bad;
               a-&gt;offset += v;
               break;

       }
}

#define CASE(a,b)       ((a&lt;&lt;8)|(b&lt;&lt;0))

void
gmove(Node *f, Node *t)
{
       int ft, tt, a;
       Node nod, nod1;
       Prog *p1;

       ft = f-&gt;type-&gt;etype;
       tt = t-&gt;type-&gt;etype;
       if(debug['M'])
               print("gop: %O %O[%s],%O[%s]\n", OAS,
                       f-&gt;op, tnames[ft], t-&gt;op, tnames[tt]);
       if(typefd[ft] &amp;&amp; f-&gt;op == OCONST) {
               if(f-&gt;fconst == 0)
                       gins(AFLDZ, Z, Z);
               else
               if(f-&gt;fconst == 1)
                       gins(AFLD1, Z, Z);
               else
                       gins(AFMOVD, f, &amp;fregnode0);
               gmove(&amp;fregnode0, t);
               return;
       }
/*
* load
*/
       if(f-&gt;op == ONAME || f-&gt;op == OINDREG ||
          f-&gt;op == OIND || f-&gt;op == OINDEX)
       switch(ft) {
       case TCHAR:
               a = AMOVBLSX;
               goto ld;
       case TUCHAR:
               a = AMOVBLZX;
               goto ld;
       case TSHORT:
               if(typefd[tt]) {
                       gins(AFMOVW, f, &amp;fregnode0);
                       gmove(&amp;fregnode0, t);
                       return;
               }
               a = AMOVWLSX;
               goto ld;
       case TUSHORT:
               a = AMOVWLZX;
               goto ld;
       case TINT:
       case TUINT:
       case TLONG:
       case TULONG:
       case TIND:
               if(typefd[tt]) {
                       gins(AFMOVL, f, &amp;fregnode0);
                       gmove(&amp;fregnode0, t);
                       return;
               }
               a = AMOVL;

       ld:
               regalloc(&amp;nod, f, t);
               nod.type = types[TLONG];
               gins(a, f, &amp;nod);
               gmove(&amp;nod, t);
               regfree(&amp;nod);
               return;

       case TFLOAT:
               gins(AFMOVF, f, t);
               return;
       case TDOUBLE:
               gins(AFMOVD, f, t);
               return;
       case TVLONG:
               gins(AFMOVV, f, t);
               return;
       }

/*
* store
*/
       if(t-&gt;op == ONAME || t-&gt;op == OINDREG ||
          t-&gt;op == OIND || t-&gt;op == OINDEX)
       switch(tt) {
       case TCHAR:
       case TUCHAR:
               a = AMOVB;      goto st;
       case TSHORT:
       case TUSHORT:
               a = AMOVW;      goto st;
       case TINT:
       case TUINT:
       case TLONG:
       case TULONG:
       case TIND:
               a = AMOVL;      goto st;

       st:
               if(f-&gt;op == OCONST) {
                       gins(a, f, t);
                       return;
               }
               regalloc(&amp;nod, t, f);
               gmove(f, &amp;nod);
               gins(a, &amp;nod, t);
               regfree(&amp;nod);
               return;

       case TFLOAT:
               gins(AFMOVFP, f, t);
               return;
       case TDOUBLE:
               gins(AFMOVDP, f, t);
               return;
       case TVLONG:
               gins(AFMOVVP, f, t);
               return;
       }

/*
* convert
*/
       switch(CASE(ft,tt)) {
       default:
/*
* integer to integer
********
               a = AGOK;       break;

       case CASE(      TCHAR,  TCHAR):
       case CASE(      TUCHAR, TCHAR):
       case CASE(      TSHORT, TCHAR):
       case CASE(      TUSHORT,TCHAR):
       case CASE(      TINT,   TCHAR):
       case CASE(      TUINT,  TCHAR):
       case CASE(      TLONG,  TCHAR):
       case CASE(      TULONG, TCHAR):
       case CASE(      TIND,   TCHAR):

       case CASE(      TCHAR,  TUCHAR):
       case CASE(      TUCHAR, TUCHAR):
       case CASE(      TSHORT, TUCHAR):
       case CASE(      TUSHORT,TUCHAR):
       case CASE(      TINT,   TUCHAR):
       case CASE(      TUINT,  TUCHAR):
       case CASE(      TLONG,  TUCHAR):
       case CASE(      TULONG, TUCHAR):
       case CASE(      TIND,   TUCHAR):

       case CASE(      TSHORT, TSHORT):
       case CASE(      TUSHORT,TSHORT):
       case CASE(      TINT,   TSHORT):
       case CASE(      TUINT,  TSHORT):
       case CASE(      TLONG,  TSHORT):
       case CASE(      TULONG, TSHORT):
       case CASE(      TIND,   TSHORT):

       case CASE(      TSHORT, TUSHORT):
       case CASE(      TUSHORT,TUSHORT):
       case CASE(      TINT,   TUSHORT):
       case CASE(      TUINT,  TUSHORT):
       case CASE(      TLONG,  TUSHORT):
       case CASE(      TULONG, TUSHORT):
       case CASE(      TIND,   TUSHORT):

       case CASE(      TINT,   TINT):
       case CASE(      TUINT,  TINT):
       case CASE(      TLONG,  TINT):
       case CASE(      TULONG, TINT):
       case CASE(      TIND,   TINT):

       case CASE(      TINT,   TUINT):
       case CASE(      TUINT,  TUINT):
       case CASE(      TLONG,  TUINT):
       case CASE(      TULONG, TUINT):
       case CASE(      TIND,   TUINT):

       case CASE(      TINT,   TLONG):
       case CASE(      TUINT,  TLONG):
       case CASE(      TLONG,  TLONG):
       case CASE(      TULONG, TLONG):
       case CASE(      TIND,   TLONG):

       case CASE(      TINT,   TULONG):
       case CASE(      TUINT,  TULONG):
       case CASE(      TLONG,  TULONG):
       case CASE(      TULONG, TULONG):
       case CASE(      TIND,   TULONG):

       case CASE(      TINT,   TIND):
       case CASE(      TUINT,  TIND):
       case CASE(      TLONG,  TIND):
       case CASE(      TULONG, TIND):
       case CASE(      TIND,   TIND):
*****/
               a = AMOVL;
               break;

       case CASE(      TSHORT, TINT):
       case CASE(      TSHORT, TUINT):
       case CASE(      TSHORT, TLONG):
       case CASE(      TSHORT, TULONG):
       case CASE(      TSHORT, TIND):
               a = AMOVWLSX;
               if(f-&gt;op == OCONST) {
                       f-&gt;vconst &amp;= 0xffff;
                       if(f-&gt;vconst &amp; 0x8000)
                               f-&gt;vconst |= 0xffff0000;
                       a = AMOVL;
               }
               break;

       case CASE(      TUSHORT,TINT):
       case CASE(      TUSHORT,TUINT):
       case CASE(      TUSHORT,TLONG):
       case CASE(      TUSHORT,TULONG):
       case CASE(      TUSHORT,TIND):
               a = AMOVWLZX;
               if(f-&gt;op == OCONST) {
                       f-&gt;vconst &amp;= 0xffff;
                       a = AMOVL;
               }
               break;

       case CASE(      TCHAR,  TSHORT):
       case CASE(      TCHAR,  TUSHORT):
       case CASE(      TCHAR,  TINT):
       case CASE(      TCHAR,  TUINT):
       case CASE(      TCHAR,  TLONG):
       case CASE(      TCHAR,  TULONG):
       case CASE(      TCHAR,  TIND):
               a = AMOVBLSX;
               if(f-&gt;op == OCONST) {
                       f-&gt;vconst &amp;= 0xff;
                       if(f-&gt;vconst &amp; 0x80)
                               f-&gt;vconst |= 0xffffff00;
                       a = AMOVL;
               }
               break;

       case CASE(      TUCHAR, TSHORT):
       case CASE(      TUCHAR, TUSHORT):
       case CASE(      TUCHAR, TINT):
       case CASE(      TUCHAR, TUINT):
       case CASE(      TUCHAR, TLONG):
       case CASE(      TUCHAR, TULONG):
       case CASE(      TUCHAR, TIND):
               a = AMOVBLZX;
               if(f-&gt;op == OCONST) {
                       f-&gt;vconst &amp;= 0xff;
                       a = AMOVL;
               }
               break;

/*
* float to fix
*/
       case CASE(      TFLOAT, TCHAR):
       case CASE(      TFLOAT, TUCHAR):
       case CASE(      TFLOAT, TSHORT):
       case CASE(      TFLOAT, TUSHORT):
       case CASE(      TFLOAT, TINT):
       case CASE(      TFLOAT, TLONG):
       case CASE(      TFLOAT, TIND):

       case CASE(      TDOUBLE,TCHAR):
       case CASE(      TDOUBLE,TUCHAR):
       case CASE(      TDOUBLE,TSHORT):
       case CASE(      TDOUBLE,TUSHORT):
       case CASE(      TDOUBLE,TINT):
       case CASE(      TDOUBLE,TLONG):
       case CASE(      TDOUBLE,TIND):
               if(fproundflg) {
                       regsalloc(&amp;nod, &amp;regnode);
                       gins(AFMOVLP, f, &amp;nod);
                       gmove(&amp;nod, t);
                       return;
               }
               regsalloc(&amp;nod, &amp;regnode);
               regsalloc(&amp;nod1, &amp;regnode);
               gins(AFSTCW, Z, &amp;nod1);
               nod1.xoffset += 2;
               gins(AMOVW, nodconst(0xf7f), &amp;nod1);
               gins(AFLDCW, &amp;nod1, Z);
               gins(AFMOVLP, f, &amp;nod);
               nod1.xoffset -= 2;
               gins(AFLDCW, &amp;nod1, Z);
               gmove(&amp;nod, t);
               return;

/*
* float to ulong
*/
       case CASE(      TDOUBLE,        TULONG):
       case CASE(      TFLOAT, TULONG):
       case CASE(      TDOUBLE,        TUINT):
       case CASE(      TFLOAT, TUINT):
               regsalloc(&amp;nod, &amp;regnode);
               gmove(f, &amp;fregnode0);
               gins(AFADDD, nodfconst(-2147483648.), &amp;fregnode0);
               gins(AFMOVLP, f, &amp;nod);
               gins(ASUBL, nodconst(-2147483648), &amp;nod);
               gmove(&amp;nod, t);
               return;

/*
* ulong to float
*/
       case CASE(      TULONG, TDOUBLE):
       case CASE(      TULONG, TFLOAT):
       case CASE(      TUINT,  TDOUBLE):
       case CASE(      TUINT,  TFLOAT):
               regalloc(&amp;nod, f, f);
               gmove(f, &amp;nod);
               regsalloc(&amp;nod1, &amp;regnode);
               gmove(&amp;nod, &amp;nod1);
               gins(AFMOVL, &amp;nod1, &amp;fregnode0);
               gins(ACMPL, &amp;nod, nodconst(0));
               gins(AJGE, Z, Z);
               p1 = p;
               gins(AFADDD, nodfconst(4294967296.), &amp;fregnode0);
               patch(p1, pc);
               regfree(&amp;nod);
               return;

/*
* fix to float
*/
       case CASE(      TCHAR,  TFLOAT):
       case CASE(      TUCHAR, TFLOAT):
       case CASE(      TSHORT, TFLOAT):
       case CASE(      TUSHORT,TFLOAT):
       case CASE(      TINT,   TFLOAT):
       case CASE(      TLONG,  TFLOAT):
       case CASE(      TIND,   TFLOAT):

       case CASE(      TCHAR,  TDOUBLE):
       case CASE(      TUCHAR, TDOUBLE):
       case CASE(      TSHORT, TDOUBLE):
       case CASE(      TUSHORT,TDOUBLE):
       case CASE(      TINT,   TDOUBLE):
       case CASE(      TLONG,  TDOUBLE):
       case CASE(      TIND,   TDOUBLE):
               regsalloc(&amp;nod, &amp;regnode);
               gmove(f, &amp;nod);
               gins(AFMOVL, &amp;nod, &amp;fregnode0);
               return;

/*
* float to float
*/
       case CASE(      TFLOAT, TFLOAT):
       case CASE(      TDOUBLE,TFLOAT):

       case CASE(      TFLOAT, TDOUBLE):
       case CASE(      TDOUBLE,TDOUBLE):
               a = AFMOVD;     break;
       }
       if(a == AMOVL || a == AFMOVD)
       if(samaddr(f, t))
               return;
       gins(a, f, t);
}

void
doindex(Node *n)
{
       Node nod, nod1;
       long v;

if(debug['Y'])
prtree(n, "index");

if(n-&gt;left-&gt;complex &gt;= FNX)
print("botch in doindex\n");

       regalloc(&amp;nod, &amp;regnode, Z);
       v = constnode.vconst;
       cgen(n-&gt;right, &amp;nod);
       idx.ptr = D_NONE;
       if(n-&gt;left-&gt;op == OCONST)
               idx.ptr = D_CONST;
       else if(n-&gt;left-&gt;op == OREGISTER)
//      else if(n-&gt;left-&gt;op == OREGISTER &amp;&amp; typeil[n-&gt;left-&gt;type-&gt;etype])
               idx.ptr = n-&gt;left-&gt;reg;
       else if(n-&gt;left-&gt;op != OADDR) {
               reg[D_BP]++;    // cant be used as a base
               regalloc(&amp;nod1, &amp;regnode, Z);
               cgen(n-&gt;left, &amp;nod1);
               idx.ptr = nod1.reg;
               regfree(&amp;nod1);
               reg[D_BP]--;
       }
       idx.reg = nod.reg;
       regfree(&amp;nod);
       constnode.vconst = v;
}

void
gins(int a, Node *f, Node *t)
{

       if(f != Z &amp;&amp; f-&gt;op == OINDEX)
               doindex(f);
       if(t != Z &amp;&amp; t-&gt;op == OINDEX)
               doindex(t);
       nextpc();
       p-&gt;as = a;
       if(f != Z)
               naddr(f, &amp;p-&gt;from);
       if(t != Z)
               naddr(t, &amp;p-&gt;to);
       if(debug['g'])
               print("%P\n", p);
}

void
fgopcode(int o, Node *f, Node *t, int pop, int rev)
{
       int a, et;
       Node nod;

       et = TLONG;
       if(f != Z &amp;&amp; f-&gt;type != T)
               et = f-&gt;type-&gt;etype;
       if(!typefd[et]) {
               diag(f, "fop: integer %O", o);
               return;
       }
       if(debug['M']) {
               if(t != Z &amp;&amp; t-&gt;type != T)
                       print("gop: %O %O-%s Z\n", o, f-&gt;op, tnames[et]);
               else
                       print("gop: %O %O-%s %O-%s\n", o,
                               f-&gt;op, tnames[et], t-&gt;op, tnames[t-&gt;type-&gt;etype]);
       }
       a = AGOK;
       switch(o) {

       case OASADD:
       case OADD:
               if(et == TFLOAT)
                       a = AFADDF;
               else
               if(et == TDOUBLE || et == TVLONG) {
                       a = AFADDD;
                       if(pop)
                               a = AFADDDP;
               }
               break;

       case OASSUB:
       case OSUB:
               if(et == TFLOAT) {
                       a = AFSUBF;
                       if(rev)
                               a = AFSUBRF;
               } else
               if(et == TDOUBLE || et == TVLONG) {
                       a = AFSUBD;
                       if(pop)
                               a = AFSUBDP;
                       if(rev) {
                               a = AFSUBRD;
                               if(pop)
                                       a = AFSUBRDP;
                       }
               }
               break;

       case OASMUL:
       case OMUL:
               if(et == TFLOAT)
                       a = AFMULF;
               else
               if(et == TDOUBLE || et == TVLONG) {
                       a = AFMULD;
                       if(pop)
                               a = AFMULDP;
               }
               break;

       case OASMOD:
       case OMOD:
       case OASDIV:
       case ODIV:
               if(et == TFLOAT) {
                       a = AFDIVF;
                       if(rev)
                               a = AFDIVRF;
               } else
               if(et == TDOUBLE || et == TVLONG) {
                       a = AFDIVD;
                       if(pop)
                               a = AFDIVDP;
                       if(rev) {
                               a = AFDIVRD;
                               if(pop)
                                       a = AFDIVRDP;
                       }
               }
               break;

       case OEQ:
       case ONE:
       case OLT:
       case OLE:
       case OGE:
       case OGT:
               pop += rev;
               if(et == TFLOAT) {
                       a = AFCOMF;
                       if(pop) {
                               a = AFCOMFP;
                               if(pop &gt; 1)
                                       a = AGOK;
                       }
               } else
               if(et == TDOUBLE || et == TVLONG) {
                       a = AFCOMF;
                       if(pop) {
                               a = AFCOMDP;
                               if(pop &gt; 1)
                                       a = AFCOMDPP;
                       }
               }
               gins(a, f, t);
               regalloc(&amp;nod, &amp;regnode, Z);
               if(nod.reg != D_AX) {
                       regfree(&amp;nod);
                       nod.reg = D_AX;
                       gins(APUSHL, &amp;nod, Z);
                       gins(AWAIT, Z, Z);
                       gins(AFSTSW, Z, &amp;nod);
                       gins(ASAHF, Z, Z);
                       gins(APOPL, Z, &amp;nod);
               } else {
                       gins(AWAIT, Z, Z);
                       gins(AFSTSW, Z, &amp;nod);
                       gins(ASAHF, Z, Z);
                       regfree(&amp;nod);
               }
               switch(o) {
               case OEQ:       a = AJEQ; break;
               case ONE:       a = AJNE; break;
               case OLT:       a = AJCS; break;
               case OLE:       a = AJLS; break;
               case OGE:       a = AJCC; break;
               case OGT:       a = AJHI; break;
               }
               gins(a, Z, Z);
               return;
       }
       if(a == AGOK)
               diag(Z, "bad in gopcode %O", o);
       gins(a, f, t);
}

void
gopcode(int o, Type *ty, Node *f, Node *t)
{
       int a, et;

       et = TLONG;
       if(ty != T)
               et = ty-&gt;etype;
       if(typefd[et] &amp;&amp; o != OADDR &amp;&amp; o != OFUNC) {
               diag(f, "gop: float %O", o);
               return;
       }
       if(debug['M']) {
               if(f != Z &amp;&amp; f-&gt;type != T)
                       print("gop: %O %O[%s],", o, f-&gt;op, tnames[et]);
               else
                       print("gop: %O Z,", o);
               if(t != Z &amp;&amp; t-&gt;type != T)
                       print("%O[%s]\n", t-&gt;op, tnames[t-&gt;type-&gt;etype]);
               else
                       print("Z\n");
       }
       a = AGOK;
       switch(o) {
       case OCOM:
               a = ANOTL;
               if(et == TCHAR || et == TUCHAR)
                       a = ANOTB;
               if(et == TSHORT || et == TUSHORT)
                       a = ANOTW;
               break;

       case ONEG:
               a = ANEGL;
               if(et == TCHAR || et == TUCHAR)
                       a = ANEGB;
               if(et == TSHORT || et == TUSHORT)
                       a = ANEGW;
               break;

       case OADDR:
               a = ALEAL;
               break;

       case OASADD:
       case OADD:
               a = AADDL;
               if(et == TCHAR || et == TUCHAR)
                       a = AADDB;
               if(et == TSHORT || et == TUSHORT)
                       a = AADDW;
               break;

       case OASSUB:
       case OSUB:
               a = ASUBL;
               if(et == TCHAR || et == TUCHAR)
                       a = ASUBB;
               if(et == TSHORT || et == TUSHORT)
                       a = ASUBW;
               break;

       case OASOR:
       case OOR:
               a = AORL;
               if(et == TCHAR || et == TUCHAR)
                       a = AORB;
               if(et == TSHORT || et == TUSHORT)
                       a = AORW;
               break;

       case OASAND:
       case OAND:
               a = AANDL;
               if(et == TCHAR || et == TUCHAR)
                       a = AANDB;
               if(et == TSHORT || et == TUSHORT)
                       a = AANDW;
               break;

       case OASXOR:
       case OXOR:
               a = AXORL;
               if(et == TCHAR || et == TUCHAR)
                       a = AXORB;
               if(et == TSHORT || et == TUSHORT)
                       a = AXORW;
               break;

       case OASLSHR:
       case OLSHR:
               a = ASHRL;
               if(et == TCHAR || et == TUCHAR)
                       a = ASHRB;
               if(et == TSHORT || et == TUSHORT)
                       a = ASHRW;
               break;

       case OASASHR:
       case OASHR:
               a = ASARL;
               if(et == TCHAR || et == TUCHAR)
                       a = ASARB;
               if(et == TSHORT || et == TUSHORT)
                       a = ASARW;
               break;

       case OASASHL:
       case OASHL:
               a = ASALL;
               if(et == TCHAR || et == TUCHAR)
                       a = ASALB;
               if(et == TSHORT || et == TUSHORT)
                       a = ASALW;
               break;

       case OFUNC:
               a = ACALL;
               break;

       case OASMUL:
       case OMUL:
               if(f-&gt;op == OREGISTER &amp;&amp; t != Z &amp;&amp; isreg(t, D_AX) &amp;&amp; reg[D_DX] == 0)
                       t = Z;
               a = AIMULL;
               break;

       case OASMOD:
       case OMOD:
       case OASDIV:
       case ODIV:
               a = AIDIVL;
               break;

       case OASLMUL:
       case OLMUL:
               a = AMULL;
               break;

       case OASLMOD:
       case OLMOD:
       case OASLDIV:
       case OLDIV:
               a = ADIVL;
               break;

       case OEQ:
       case ONE:
       case OLT:
       case OLE:
       case OGE:
       case OGT:
       case OLO:
       case OLS:
       case OHS:
       case OHI:
               a = ACMPL;
               if(et == TCHAR || et == TUCHAR)
                       a = ACMPB;
               if(et == TSHORT || et == TUSHORT)
                       a = ACMPW;
               gins(a, f, t);
               switch(o) {
               case OEQ:       a = AJEQ; break;
               case ONE:       a = AJNE; break;
               case OLT:       a = AJLT; break;
               case OLE:       a = AJLE; break;
               case OGE:       a = AJGE; break;
               case OGT:       a = AJGT; break;
               case OLO:       a = AJCS; break;
               case OLS:       a = AJLS; break;
               case OHS:       a = AJCC; break;
               case OHI:       a = AJHI; break;
               }
               gins(a, Z, Z);
               return;
       }
       if(a == AGOK)
               diag(Z, "bad in gopcode %O", o);
       gins(a, f, t);
}

int
samaddr(Node *f, Node *t)
{

       if(f-&gt;op != t-&gt;op)
               return 0;
       switch(f-&gt;op) {

       case OREGISTER:
               if(f-&gt;reg != t-&gt;reg)
                       break;
               return 1;
       }
       return 0;
}

void
gbranch(int o)
{
       int a;

       a = AGOK;
       switch(o) {
       case ORETURN:
               a = ARET;
               break;
       case OGOTO:
               a = AJMP;
               break;
       }
       nextpc();
       if(a == AGOK) {
               diag(Z, "bad in gbranch %O",  o);
               nextpc();
       }
       p-&gt;as = a;
}

void
patch(Prog *op, long pc)
{

       op-&gt;to.offset = pc;
       op-&gt;to.type = D_BRANCH;
}

void
gpseudo(int a, Sym *s, Node *n)
{

       nextpc();
       p-&gt;as = a;
       p-&gt;from.type = D_EXTERN;
       p-&gt;from.sym = s;
       p-&gt;from.scale = (profileflg ? 0 : NOPROF);
       if(s-&gt;class == CSTATIC)
               p-&gt;from.type = D_STATIC;
       naddr(n, &amp;p-&gt;to);
       if(a == ADATA || a == AGLOBL)
               pc--;
}

int
sconst(Node *n)
{
       long v;

       if(n-&gt;op == OCONST &amp;&amp; !typefd[n-&gt;type-&gt;etype]) {
               v = n-&gt;vconst;
               if(v &gt;= -32766L &amp;&amp; v &lt; 32766L)
                       return 1;
       }
       return 0;
}

long
exreg(Type *t)
{

       USED(t);
       return 0;
}

schar   ewidth[NTYPE] =
{
       -1,             /*[TXXX]*/
       SZ_CHAR,        /*[TCHAR]*/
       SZ_CHAR,        /*[TUCHAR]*/
       SZ_SHORT,       /*[TSHORT]*/
       SZ_SHORT,       /*[TUSHORT]*/
       SZ_INT,         /*[TINT]*/
       SZ_INT,         /*[TUINT]*/
       SZ_LONG,        /*[TLONG]*/
       SZ_LONG,        /*[TULONG]*/
       SZ_VLONG,       /*[TVLONG]*/
       SZ_VLONG,       /*[TUVLONG]*/
       SZ_FLOAT,       /*[TFLOAT]*/
       SZ_DOUBLE,      /*[TDOUBLE]*/
       SZ_IND,         /*[TIND]*/
       0,              /*[TFUNC]*/
       -1,             /*[TARRAY]*/
       0,              /*[TVOID]*/
       -1,             /*[TSTRUCT]*/
       -1,             /*[TUNION]*/
       SZ_INT,         /*[TENUM]*/
};
long    ncast[NTYPE] =
{
       0,                              /*[TXXX]*/
       BCHAR|BUCHAR,                   /*[TCHAR]*/
       BCHAR|BUCHAR,                   /*[TUCHAR]*/
       BSHORT|BUSHORT,                 /*[TSHORT]*/
       BSHORT|BUSHORT,                 /*[TUSHORT]*/
       BINT|BUINT|BLONG|BULONG|BIND,   /*[TINT]*/
       BINT|BUINT|BLONG|BULONG|BIND,   /*[TUINT]*/
       BINT|BUINT|BLONG|BULONG|BIND,   /*[TLONG]*/
       BINT|BUINT|BLONG|BULONG|BIND,   /*[TULONG]*/
       BVLONG|BUVLONG,                 /*[TVLONG]*/
       BVLONG|BUVLONG,                 /*[TUVLONG]*/
       BFLOAT,                         /*[TFLOAT]*/
       BDOUBLE,                        /*[TDOUBLE]*/
       BLONG|BULONG|BIND,              /*[TIND]*/
       0,                              /*[TFUNC]*/
       0,                              /*[TARRAY]*/
       0,                              /*[TVOID]*/
       BSTRUCT,                        /*[TSTRUCT]*/
       BUNION,                         /*[TUNION]*/
       0,                              /*[TENUM]*/
};
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:[email protected]">[email protected]</a>.</span>
</font></center>
</body>
</html>