// Derived from Inferno utils/5c/txt.c
// http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "gg.h"

// TODO(kaib): Can make this bigger if we move
// the text segment up higher in 5l for all GOOS.
long unmappedzero = 4096;

void
clearp(Prog *p)
{
	p->as = AEND;
	p->reg = NREG;
	p->scond = C_SCOND_NONE;
	p->from.type = D_NONE;
	p->from.name = D_NONE;
	p->from.reg = NREG;
	p->to.type = D_NONE;
	p->to.name = D_NONE;
	p->to.reg = NREG;
	p->loc = pcloc;
	pcloc++;
}

/*
 * generate and return proc with p->as = as,
 * linked into program.  pc is next instruction.
 */
Prog*
prog(int as)
{
	Prog *p;

	p = pc;
	pc = mal(sizeof(*pc));

	clearp(pc);

	if(lineno == 0) {
		if(debug['K'])
			warn("prog: line 0");
	}

	p->as = as;
	p->lineno = lineno;
	p->link = pc;
	return p;
}

/*
 * generate a branch.
 * t is ignored.
 */
Prog*
gbranch(int as, Type *t)
{
	Prog *p;

	p = prog(as);
	p->to.type = D_BRANCH;
	p->to.branch = P;
	return p;
}

/*
 * patch previous branch to jump to to.
 */
void
patch(Prog *p, Prog *to)
{
	if(p->to.type != D_BRANCH)
		fatal("patch: not a branch");
	p->to.branch = to;
	p->to.offset = to->loc;
}

/*
 * start a new Prog list.
 */
Plist*
newplist(void)
{
	Plist *pl;

	pl = mal(sizeof(*pl));
	if(plist == nil)
		plist = pl;
	else
		plast->link = pl;
	plast = pl;

	pc = mal(sizeof(*pc));
	clearp(pc);
	pl->firstpc = pc;

	return pl;
}

void
clearstk(void)
{
	Plist *pl;
	Prog *p, *p1, *p2, *p3;
	Node dst, end, zero, con;

	if(plast->firstpc->to.offset <= 0)
		return;

	// reestablish context for inserting code
	// at beginning of function.
	pl = plast;
	p1 = pl->firstpc;
	p2 = p1->link;
	pc = mal(sizeof(*pc));
	clearp(pc);
	p1->link = pc;
	
	// zero stack frame

	// MOVW $4(SP), R1
	nodreg(&dst, types[tptr], 1);
	p = gins(AMOVW, N, &dst);
	p->from.type = D_CONST;
	p->from.reg = REGSP;
	p->from.offset = 4;

	// MOVW $n(R1), R2
	nodreg(&end, types[tptr], 2);
	p = gins(AMOVW, N, &end);
	p->from.type = D_CONST;
	p->from.reg = 1;
	p->from.offset = p1->to.offset;
	
	// MOVW $0, R3
	nodreg(&zero, types[TUINT32], 3);
	nodconst(&con, types[TUINT32], 0);
	gmove(&con, &zero);

	// L:
	//	MOVW.P R3, 0(R1) +4
	//	CMP R1, R2
	//	BNE L
	p = gins(AMOVW, &zero, &dst);
	p->to.type = D_OREG;
	p->to.offset = 4;
	p->scond |= C_PBIT;
	p3 = p;
	p = gins(ACMP, &dst, N);
	raddr(&end, p);
	patch(gbranch(ABNE, T), p3);

	// continue with original code.
	gins(ANOP, N, N)->link = p2;
	pc = P;
}	

void
gused(Node *n)
{
	gins(ANOP, n, N);	// used
}

Prog*
gjmp(Prog *to)
{
	Prog *p;

	p = gbranch(AB, T);
	if(to != P)
		patch(p, to);
	return p;
}

void
ggloblnod(Node *nam, int32 width)
{
	Prog *p;

	p = gins(AGLOBL, nam, N);
	p->lineno = nam->lineno;
	p->to.sym = S;
	p->to.type = D_CONST;
	p->to.offset = width;
}

void
ggloblsym(Sym *s, int32 width, int dupok)
{
	Prog *p;

	p = gins(AGLOBL, N, N);
	p->from.type = D_OREG;
	p->from.name = D_EXTERN;
	p->from.sym = s;
	p->to.type = D_CONST;
	p->to.name = D_NONE;
	p->to.offset = width;
	if(dupok)
		p->reg = DUPOK;
}

int
isfat(Type *t)
{
	if(t != T)
	switch(t->etype) {
	case TSTRUCT:
	case TARRAY:
	case TSTRING:
	case TINTER:	// maybe remove later
		return 1;
	}
	return 0;
}

/*
 * naddr of func generates code for address of func.
 * if using opcode that can take address implicitly,
 * call afunclit to fix up the argument.
 * also fix up direct register references to be D_OREG.
 */
void
afunclit(Addr *a)
{
	if(a->type == D_CONST && a->name == D_EXTERN || a->type == D_REG) {
		a->type = D_OREG;
	}
}

static	int	resvd[] =
{
	9,	// reserved for m
	10,	// reserved for g
};

void
ginit(void)
{
	int i;

	for(i=0; i<nelem(reg); i++)
		reg[i] = 0;
	for(i=0; i<nelem(resvd); i++)
		reg[resvd[i]]++;
}

void
gclean(void)
{
	int i;

	for(i=0; i<nelem(resvd); i++)
		reg[resvd[i]]--;

	for(i=0; i<nelem(reg); i++)
		if(reg[i])
			yyerror("reg %R left allocated\n", i);
}

int32
anyregalloc(void)
{
	int i, j;

	for(i=0; i<nelem(reg); i++) {
		if(reg[i] == 0)
			goto ok;
		for(j=0; j<nelem(resvd); j++)
			if(resvd[j] == i)
				goto ok;
		return 1;
	ok:;
	}
	return 0;
}

/*
 * allocate register of type t, leave in n.
 * if o != N, o is desired fixed register.
 * caller must regfree(n).
 */
void
regalloc(Node *n, Type *t, Node *o)
{
	int i, et, fixfree, floatfree;

	if(debug['r']) {
		fixfree = 0;
		for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
			if(reg[i] == 0)
				fixfree++;
		floatfree = 0;
		for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
			if(reg[i] == 0)
				floatfree++;
		print("regalloc fix %d float %d\n", fixfree, floatfree);
	}

	if(t == T)
		fatal("regalloc: t nil");
	et = simtype[t->etype];
	if(is64(t))
		fatal("regalloc: 64 bit type %T");

	switch(et) {
	case TINT8:
	case TUINT8:
	case TINT16:
	case TUINT16:
	case TINT32:
	case TUINT32:
	case TPTR32:
	case TBOOL:
		if(o != N && o->op == OREGISTER) {
			i = o->val.u.reg;
			if(i >= REGALLOC_R0 && i <= REGALLOC_RMAX)
				goto out;
		}
		for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
			if(reg[i] == 0)
				goto out;

		yyerror("out of fixed registers");
		goto err;

	case TFLOAT32:
	case TFLOAT64:
		if(o != N && o->op == OREGISTER) {
			i = o->val.u.reg;
			if(i >= REGALLOC_F0 && i <= REGALLOC_FMAX)
				goto out;
		}
		for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
			if(reg[i] == 0)
				goto out;
		yyerror("out of floating point registers");
		goto err;

	case TCOMPLEX64:
	case TCOMPLEX128:
		tempname(n, t);
		return;
	}
	yyerror("regalloc: unknown type %T", t);

err:
	nodreg(n, t, 0);
	return;

out:
	reg[i]++;
	nodreg(n, t, i);
}

void
regfree(Node *n)
{
	int i, fixfree, floatfree;

	if(debug['r']) {
		fixfree = 0;
		for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
			if(reg[i] == 0)
				fixfree++;
		floatfree = 0;
		for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
			if(reg[i] == 0)
				floatfree++;
		print("regalloc fix %d float %d\n", fixfree, floatfree);
	}

	if(n->op == ONAME && iscomplex[n->type->etype])
		return;
	if(n->op != OREGISTER && n->op != OINDREG)
		fatal("regfree: not a register");
	i = n->val.u.reg;
	if(i < 0 || i >= sizeof(reg))
		fatal("regfree: reg out of range");
	if(reg[i] <= 0)
		fatal("regfree: reg not allocated");
	reg[i]--;
}

/*
 * initialize n to be register r of type t.
 */
void
nodreg(Node *n, Type *t, int r)
{
	if(t == T)
		fatal("nodreg: t nil");

	memset(n, 0, sizeof(*n));
	n->op = OREGISTER;
	n->addable = 1;
	ullmancalc(n);
	n->val.u.reg = r;
	n->type = t;
}

/*
 * initialize n to be indirect of register r; n is type t.
 */
void
nodindreg(Node *n, Type *t, int r)
{
	nodreg(n, t, r);
	n->op = OINDREG;
}

Node*
nodarg(Type *t, int fp)
{
	Node *n;
	Type *first;
	Iter savet;

	// entire argument struct, not just one arg
	if(t->etype == TSTRUCT && t->funarg) {
		n = nod(ONAME, N, N);
		n->sym = lookup(".args");
		n->type = t;
		first = structfirst(&savet, &t);
		if(first == nil)
			fatal("nodarg: bad struct");
		if(first->width == BADWIDTH)
			fatal("nodarg: offset not computed for %T", t);
		n->xoffset = first->width;
		n->addable = 1;
		goto fp;
	}

	if(t->etype != TFIELD)
		fatal("nodarg: not field %T", t);

	n = nod(ONAME, N, N);
	n->type = t->type;
	n->sym = t->sym;
	if(t->width == BADWIDTH)
		fatal("nodarg: offset not computed for %T", t);
	n->xoffset = t->width;
	n->addable = 1;

fp:
	switch(fp) {
	default:
		fatal("nodarg %T %d", t, fp);

	case 0:		// output arg for calling another function
		n->op = OINDREG;
		n->val.u.reg = REGSP;
		n->xoffset += 4;
		break;

	case 1:		// input arg to current function
		n->class = PPARAM;
		break;
	}
	return n;
}

/*
 * return constant i node.
 * overwritten by next call, but useful in calls to gins.
 */
Node*
ncon(uint32 i)
{
	static Node n;

	if(n.type == T)
		nodconst(&n, types[TUINT32], 0);
	mpmovecfix(n.val.u.xval, i);
	return &n;
}

/*
 * Is this node a memory operand?
 */
int
ismem(Node *n)
{
	switch(n->op) {
	case OINDREG:
	case ONAME:
	case OPARAM:
		return 1;
	}
	return 0;
}

Node sclean[10];
int nsclean;

/*
 * n is a 64-bit value.  fill in lo and hi to refer to its 32-bit halves.
 */
void
split64(Node *n, Node *lo, Node *hi)
{
	Node n1;
	int64 i;

	if(!is64(n->type))
		fatal("split64 %T", n->type);

	sclean[nsclean].op = OEMPTY;
	if(nsclean >= nelem(sclean))
		fatal("split64 clean");
	nsclean++;
	switch(n->op) {
	default:
		if(!dotaddable(n, &n1)) {
			igen(n, &n1, N);
			sclean[nsclean-1] = n1;
		}
		n = &n1;
		goto common;
	case ONAME:
		if(n->class == PPARAMREF) {
			cgen(n->heapaddr, &n1);
			sclean[nsclean-1] = n1;
			// fall through.
			n = &n1;
		}
		goto common;
	case OINDREG:
	common:
		*lo = *n;
		*hi = *n;
		lo->type = types[TUINT32];
		if(n->type->etype == TINT64)
			hi->type = types[TINT32];
		else
			hi->type = types[TUINT32];
		hi->xoffset += 4;
		break;

	case OLITERAL:
		convconst(&n1, n->type, &n->val);
		i = mpgetfix(n1.val.u.xval);
		nodconst(lo, types[TUINT32], (uint32)i);
		i >>= 32;
		if(n->type->etype == TINT64)
			nodconst(hi, types[TINT32], (int32)i);
		else
			nodconst(hi, types[TUINT32], (uint32)i);
		break;
	}
}

void
splitclean(void)
{
	if(nsclean <= 0)
		fatal("splitclean");
	nsclean--;
	if(sclean[nsclean].op != OEMPTY)
		regfree(&sclean[nsclean]);
}

#define	CASE(a,b)	(((a)<<16)|((b)<<0))

void
gmove(Node *f, Node *t)
{
	int a, ft, tt, fa, ta;
	Type *cvt;
	Node r1, r2, flo, fhi, tlo, thi, con;
	Prog *p1;

	if(debug['M'])
		print("gmove %N -> %N\n", f, t);

	ft = simsimtype(f->type);
	tt = simsimtype(t->type);
	cvt = t->type;

	if(iscomplex[ft] || iscomplex[tt]) {
		complexmove(f, t);
		return;
	}

	// cannot have two memory operands;
	// except 64-bit, which always copies via registers anyway.
	if(!is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
		goto hard;

	// convert constant to desired type
	if(f->op == OLITERAL) {
		switch(tt) {
		default:
			convconst(&con, t->type, &f->val);
			break;

		case TINT16:
		case TINT8:
			convconst(&con, types[TINT32], &f->val);
			regalloc(&r1, con.type, t);
			gins(AMOVW, &con, &r1);
			gmove(&r1, t);
			regfree(&r1);
			return;

		case TUINT16:
		case TUINT8:
			convconst(&con, types[TUINT32], &f->val);
			regalloc(&r1, con.type, t);
			gins(AMOVW, &con, &r1);
			gmove(&r1, t);
			regfree(&r1);
			return;
		}

		f = &con;
		ft = simsimtype(con.type);

		// constants can't move directly to memory
		if(ismem(t) && !is64(t->type)) goto hard;
	}

	// value -> value copy, only one memory operand.
	// figure out the instruction to use.
	// break out of switch for one-instruction gins.
	// goto rdst for "destination must be register".
	// goto hard for "convert to cvt type first".
	// otherwise handle and return.

	switch(CASE(ft, tt)) {
	default:
		goto fatal;

	/*
	 * integer copy and truncate
	 */
	case CASE(TINT8, TINT8):	// same size
	case CASE(TUINT8, TINT8):
	case CASE(TINT16, TINT8):	// truncate
	case CASE(TUINT16, TINT8):
	case CASE(TINT32, TINT8):
	case CASE(TUINT32, TINT8):
		a = AMOVB;
		break;

	case CASE(TINT8, TUINT8):
	case CASE(TUINT8, TUINT8):
	case CASE(TINT16, TUINT8):
	case CASE(TUINT16, TUINT8):
	case CASE(TINT32, TUINT8):
	case CASE(TUINT32, TUINT8):
		a = AMOVBU;
		break;

	case CASE(TINT64, TINT8):	// truncate low word
	case CASE(TUINT64, TINT8):
		a = AMOVB;
		goto trunc64;

	case CASE(TINT64, TUINT8):
	case CASE(TUINT64, TUINT8):
		a = AMOVBU;
		goto trunc64;

	case CASE(TINT16, TINT16):	// same size
	case CASE(TUINT16, TINT16):
	case CASE(TINT32, TINT16):	// truncate
	case CASE(TUINT32, TINT16):
		a = AMOVH;
		break;

	case CASE(TINT16, TUINT16):
	case CASE(TUINT16, TUINT16):
	case CASE(TINT32, TUINT16):
	case CASE(TUINT32, TUINT16):
		a = AMOVHU;
		break;

	case CASE(TINT64, TINT16):	// truncate low word
	case CASE(TUINT64, TINT16):
		a = AMOVH;
		goto trunc64;

	case CASE(TINT64, TUINT16):
	case CASE(TUINT64, TUINT16):
		a = AMOVHU;
		goto trunc64;

	case CASE(TINT32, TINT32):	// same size
	case CASE(TINT32, TUINT32):
	case CASE(TUINT32, TINT32):
	case CASE(TUINT32, TUINT32):
		a = AMOVW;
		break;

	case CASE(TINT64, TINT32):	// truncate
	case CASE(TUINT64, TINT32):
	case CASE(TINT64, TUINT32):
	case CASE(TUINT64, TUINT32):
		split64(f, &flo, &fhi);
		regalloc(&r1, t->type, N);
		gins(AMOVW, &flo, &r1);
		gins(AMOVW, &r1, t);
		regfree(&r1);
		splitclean();
		return;

	case CASE(TINT64, TINT64):	// same size
	case CASE(TINT64, TUINT64):
	case CASE(TUINT64, TINT64):
	case CASE(TUINT64, TUINT64):
		split64(f, &flo, &fhi);
		split64(t, &tlo, &thi);
		regalloc(&r1, flo.type, N);
		regalloc(&r2, fhi.type, N);
		gins(AMOVW, &flo, &r1);
		gins(AMOVW, &fhi, &r2);
		gins(AMOVW, &r1, &tlo);
		gins(AMOVW, &r2, &thi);
		regfree(&r1);
		regfree(&r2);
		splitclean();
		splitclean();
		return;

	/*
	 * integer up-conversions
	 */
	case CASE(TINT8, TINT16):	// sign extend int8
	case CASE(TINT8, TUINT16):
	case CASE(TINT8, TINT32):
	case CASE(TINT8, TUINT32):
		a = AMOVB;
		goto rdst;
	case CASE(TINT8, TINT64):	// convert via int32
	case CASE(TINT8, TUINT64):
		cvt = types[TINT32];
		goto hard;

	case CASE(TUINT8, TINT16):	// zero extend uint8
	case CASE(TUINT8, TUINT16):
	case CASE(TUINT8, TINT32):
	case CASE(TUINT8, TUINT32):
		a = AMOVBU;
		goto rdst;
	case CASE(TUINT8, TINT64):	// convert via uint32
	case CASE(TUINT8, TUINT64):
		cvt = types[TUINT32];
		goto hard;

	case CASE(TINT16, TINT32):	// sign extend int16
	case CASE(TINT16, TUINT32):
		a = AMOVH;
		goto rdst;
	case CASE(TINT16, TINT64):	// convert via int32
	case CASE(TINT16, TUINT64):
		cvt = types[TINT32];
		goto hard;

	case CASE(TUINT16, TINT32):	// zero extend uint16
	case CASE(TUINT16, TUINT32):
		a = AMOVHU;
		goto rdst;
	case CASE(TUINT16, TINT64):	// convert via uint32
	case CASE(TUINT16, TUINT64):
		cvt = types[TUINT32];
		goto hard;

	case CASE(TINT32, TINT64):	// sign extend int32
	case CASE(TINT32, TUINT64):
		split64(t, &tlo, &thi);
		regalloc(&r1, tlo.type, N);
		regalloc(&r2, thi.type, N);
		gmove(f, &r1);
		p1 = gins(AMOVW, &r1, &r2);
		p1->from.type = D_SHIFT;
		p1->from.offset = 2 << 5 | 31 << 7 | r1.val.u.reg; // r1->31
		p1->from.reg = NREG;
//print("gmove: %P\n", p1);
		gins(AMOVW, &r1, &tlo);
		gins(AMOVW, &r2, &thi);
		regfree(&r1);
		regfree(&r2);
		splitclean();
		return;

	case CASE(TUINT32, TINT64):	// zero extend uint32
	case CASE(TUINT32, TUINT64):
		split64(t, &tlo, &thi);
		gmove(f, &tlo);
		regalloc(&r1, thi.type, N);
		gins(AMOVW, ncon(0), &r1);
		gins(AMOVW, &r1, &thi);
		regfree(&r1);
		splitclean();
		return;

	/*
	* float to integer
	*/
	case CASE(TFLOAT32, TINT8):
	case CASE(TFLOAT32, TUINT8):
	case CASE(TFLOAT32, TINT16):
	case CASE(TFLOAT32, TUINT16):
	case CASE(TFLOAT32, TINT32):
	case CASE(TFLOAT32, TUINT32):
//	case CASE(TFLOAT32, TUINT64):

	case CASE(TFLOAT64, TINT8):
	case CASE(TFLOAT64, TUINT8):
	case CASE(TFLOAT64, TINT16):
	case CASE(TFLOAT64, TUINT16):
	case CASE(TFLOAT64, TINT32):
	case CASE(TFLOAT64, TUINT32):
//	case CASE(TFLOAT64, TUINT64):
		fa = AMOVF;
		a = AMOVFW;
		if(ft == TFLOAT64) {
			fa = AMOVD;
			a = AMOVDW;
		}
		ta = AMOVW;
		switch(tt) {
		case TINT8:
			ta = AMOVB;
			break;
		case TUINT8:
			ta = AMOVBU;
			break;
		case TINT16:
			ta = AMOVH;
			break;
		case TUINT16:
			ta = AMOVHU;
			break;
		}

		regalloc(&r1, types[ft], f);
		regalloc(&r2, types[tt], t);
		gins(fa, f, &r1);	// load to fpu
		p1 = gins(a, &r1, &r1);	// convert to w
		switch(tt) {
		case TUINT8:
		case TUINT16:
		case TUINT32:
			p1->scond |= C_UBIT;
		}
		gins(AMOVW, &r1, &r2);	// copy to cpu
		gins(ta, &r2, t);	// store
		regfree(&r1);
		regfree(&r2);
		return;

	/*
	 * integer to float
	 */
	case CASE(TINT8, TFLOAT32):
	case CASE(TUINT8, TFLOAT32):
	case CASE(TINT16, TFLOAT32):
	case CASE(TUINT16, TFLOAT32):
	case CASE(TINT32, TFLOAT32):
	case CASE(TUINT32, TFLOAT32):
	case CASE(TINT8, TFLOAT64):
	case CASE(TUINT8, TFLOAT64):
	case CASE(TINT16, TFLOAT64):
	case CASE(TUINT16, TFLOAT64):
	case CASE(TINT32, TFLOAT64):
	case CASE(TUINT32, TFLOAT64):
		fa = AMOVW;
		switch(ft) {
		case TINT8:
			fa = AMOVB;
			break;
		case TUINT8:
			fa = AMOVBU;
			break;
		case TINT16:
			fa = AMOVH;
			break;
		case TUINT16:
			fa = AMOVHU;
			break;
		}
		a = AMOVWF;
		ta = AMOVF;
		if(tt == TFLOAT64) {
			a = AMOVWD;
			ta = AMOVD;
		}
		regalloc(&r1, types[ft], f);
		regalloc(&r2, types[tt], t);
		gins(fa, f, &r1);	// load to cpu
		gins(AMOVW, &r1, &r2);	// copy to fpu
		p1 = gins(a, &r2, &r2);	// convert
		switch(ft) {
		case TUINT8:
		case TUINT16:
		case TUINT32:
			p1->scond |= C_UBIT;
		}
		gins(ta, &r2, t);	// store
		regfree(&r1);
		regfree(&r2);
		return;

	case CASE(TUINT64, TFLOAT32):
	case CASE(TUINT64, TFLOAT64):
		fatal("gmove UINT64, TFLOAT not implemented");
		return;


	/*
	 * float to float
	 */
	case CASE(TFLOAT32, TFLOAT32):
		a = AMOVF;
		break;

	case CASE(TFLOAT64, TFLOAT64):
		a = AMOVD;
		break;

	case CASE(TFLOAT32, TFLOAT64):
		regalloc(&r1, types[TFLOAT64], t);
		gins(AMOVF, f, &r1);
		gins(AMOVFD, &r1, &r1);
		gins(AMOVD, &r1, t);
		regfree(&r1);
		return;

	case CASE(TFLOAT64, TFLOAT32):
		regalloc(&r1, types[TFLOAT64], t);
		gins(AMOVD, f, &r1);
		gins(AMOVDF, &r1, &r1);
		gins(AMOVF, &r1, t);
		regfree(&r1);
		return;
	}

	gins(a, f, t);
	return;

rdst:
	// TODO(kaib): we almost always require a register dest anyway, this can probably be
	// removed.
	// requires register destination
	regalloc(&r1, t->type, t);
	gins(a, f, &r1);
	gmove(&r1, t);
	regfree(&r1);
	return;

hard:
	// requires register intermediate
	regalloc(&r1, cvt, t);
	gmove(f, &r1);
	gmove(&r1, t);
	regfree(&r1);
	return;

trunc64:
	// truncate 64 bit integer
	split64(f, &flo, &fhi);
	regalloc(&r1, t->type, N);
	gins(a, &flo, &r1);
	gins(a, &r1, t);
	regfree(&r1);
	splitclean();
	return;

fatal:
	// should not happen
	fatal("gmove %N -> %N", f, t);
}

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

	if(f->op != t->op)
		return 0;

	switch(f->op) {
	case OREGISTER:
		if(f->val.u.reg != t->val.u.reg)
			break;
		return 1;
	}
	return 0;
}

/*
 * generate one instruction:
 *	as f, t
 */
Prog*
gins(int as, Node *f, Node *t)
{
//	Node nod;
//	int32 v;
	Prog *p;
	Addr af, at;

	if(f != N && f->op == OINDEX) {
		fatal("gins OINDEX not implemented");
//		regalloc(&nod, &regnode, Z);
//		v = constnode.vconst;
//		cgen(f->right, &nod);
//		constnode.vconst = v;
//		idx.reg = nod.reg;
//		regfree(&nod);
	}
	if(t != N && t->op == OINDEX) {
		fatal("gins OINDEX not implemented");
//		regalloc(&nod, &regnode, Z);
//		v = constnode.vconst;
//		cgen(t->right, &nod);
//		constnode.vconst = v;
//		idx.reg = nod.reg;
//		regfree(&nod);
	}

	memset(&af, 0, sizeof af);
	memset(&at, 0, sizeof at);
	if(f != N)
		naddr(f, &af, 1);
	if(t != N)
		naddr(t, &at, 1);	p = prog(as);
	if(f != N)
		p->from = af;
	if(t != N)
		p->to = at;
	if(debug['g'])
		print("%P\n", p);
	return p;
}

/*
 * insert n into reg slot of p
 */
void
raddr(Node *n, Prog *p)
{
	Addr a;

	naddr(n, &a, 1);
	if(a.type != D_REG && a.type != D_FREG) {
		if(n)
			fatal("bad in raddr: %O", n->op);
		else
			fatal("bad in raddr: <null>");
		p->reg = NREG;
	} else
		p->reg = a.reg;
}

/* generate a comparison
TODO(kaib): one of the args can actually be a small constant. relax the constraint and fix call sites.
 */
Prog*
gcmp(int as, Node *lhs, Node *rhs)
{
	Prog *p;

	if(lhs->op != OREGISTER || rhs->op != OREGISTER)
		fatal("bad operands to gcmp: %O %O", lhs->op, rhs->op);

	p = gins(as, rhs, N);
	raddr(lhs, p);
	return p;
}

/* generate a constant shift
 * arm encodes a shift by 32 as 0, thus asking for 0 shift is illegal.
*/
Prog*
gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs)
{
	Prog *p;

	if(sval <= 0 || sval > 32)
		fatal("bad shift value: %d", sval);

	sval = sval&0x1f;

	p = gins(as, N, rhs);
	p->from.type = D_SHIFT;
	p->from.offset = stype | sval<<7 | lhs->val.u.reg;
	return p;
}

/* generate a register shift
*/
Prog *
gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
{
	Prog *p;
	p = gins(as, N, rhs);
	p->from.type = D_SHIFT;
	p->from.offset = stype | reg->val.u.reg << 8 | 1<<4 | lhs->val.u.reg;
	return p;
}

static void
checkoffset(Addr *a, int canemitcode)
{
	Prog *p;
	Node n1;

	if(a->offset < unmappedzero)
		return;
	if(!canemitcode)
		fatal("checkoffset %#x, cannot emit code", a->offset);

	// cannot rely on unmapped nil page at 0 to catch
	// reference with large offset.  instead, emit explicit
	// test of 0(reg).
	regalloc(&n1, types[TUINTPTR], N);
	p = gins(AMOVW, N, &n1);
	p->from = *a;
	p->from.offset = 0;
	regfree(&n1);
}

/*
 * generate code to compute n;
 * make a refer to result.
 */
void
naddr(Node *n, Addr *a, int canemitcode)
{
	a->type = D_NONE;
	a->name = D_NONE;
	a->reg = NREG;
	if(n == N)
		return;

	switch(n->op) {
	default:
		fatal("naddr: bad %O %D", n->op, a);
		break;

	case OREGISTER:
		if(n->val.u.reg <= REGALLOC_RMAX) {
			a->type = D_REG;
			a->reg = n->val.u.reg;
		} else {
			a->type = D_FREG;
			a->reg = n->val.u.reg - REGALLOC_F0;
		}
		a->sym = S;
		break;

	case OINDEX:
	case OIND:
		fatal("naddr: OINDEX");
//		naddr(n->left, a);
//		if(a->type >= D_AX && a->type <= D_DI)
//			a->type += D_INDIR;
//		else
//		if(a->type == D_CONST)
//			a->type = D_NONE+D_INDIR;
//		else
//		if(a->type == D_ADDR) {
//			a->type = a->index;
//			a->index = D_NONE;
//		} else
//			goto bad;
//		if(n->op == OINDEX) {
//			a->index = idx.reg;
//			a->scale = n->scale;
//		}
//		break;

	case OINDREG:
		a->type = D_OREG;
		a->reg = n->val.u.reg;
		a->sym = n->sym;
		a->offset = n->xoffset;
		checkoffset(a, canemitcode);
		break;

	case OPARAM:
		// n->left is PHEAP ONAME for stack parameter.
		// compute address of actual parameter on stack.
		a->etype = simtype[n->left->type->etype];
		a->width = n->left->type->width;
		a->offset = n->xoffset;
		a->sym = n->left->sym;
		a->type = D_OREG;
		a->name = D_PARAM;
		break;

	case ONAME:
		a->etype = 0;
		a->width = 0;
		a->reg = NREG;
		if(n->type != T) {
			a->etype = simtype[n->type->etype];
			a->width = n->type->width;
		}
		a->pun = n->pun;
		a->offset = n->xoffset;
		a->sym = n->sym;
		if(a->sym == S)
			a->sym = lookup(".noname");
		if(n->method) {
			if(n->type != T)
			if(n->type->sym != S)
			if(n->type->sym->pkg != nil)
				a->sym = pkglookup(a->sym->name, n->type->sym->pkg);
		}

		a->type = D_OREG;
		switch(n->class) {
		default:
			fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
		case PEXTERN:
			a->name = D_EXTERN;
			break;
		case PAUTO:
			a->name = D_AUTO;
			break;
		case PPARAM:
		case PPARAMOUT:
			a->name = D_PARAM;
			break;
		case PFUNC:
			a->name = D_EXTERN;
			a->type = D_CONST;
			break;
		}
		break;

	case OLITERAL:
		switch(n->val.ctype) {
		default:
			fatal("naddr: const %lT", n->type);
			break;
		case CTFLT:
			a->type = D_FCONST;
			a->dval = mpgetflt(n->val.u.fval);
			break;
		case CTINT:
			a->sym = S;
			a->type = D_CONST;
			a->offset = mpgetfix(n->val.u.xval);
			break;
		case CTSTR:
			datagostring(n->val.u.sval, a);
			break;
		case CTBOOL:
			a->sym = S;
			a->type = D_CONST;
			a->offset = n->val.u.bval;
			break;
		case CTNIL:
			a->sym = S;
			a->type = D_CONST;
			a->offset = 0;
			break;
		}
		break;

	case OLEN:
		// len of string or slice
		naddr(n->left, a, canemitcode);
		if(a->type == D_CONST && a->offset == 0)
			break;	// len(nil)
		a->offset += Array_nel;
		if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
			checkoffset(a, canemitcode);
		break;

	case OCAP:
		// cap of string or slice
		naddr(n->left, a, canemitcode);
		if(a->type == D_CONST && a->offset == 0)
			break;	// cap(nil)
		a->offset += Array_cap;
		if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
			checkoffset(a, canemitcode);
		break;

	case OADDR:
		naddr(n->left, a, canemitcode);
		switch(a->type) {
		case D_OREG:
			a->type = D_CONST;
			break;

		case D_REG:
		case D_CONST:
			break;
		
		default:
			fatal("naddr: OADDR %d\n", a->type);
		}
	}
}

/*
 * return Axxx for Oxxx on type t.
 */
int
optoas(int op, Type *t)
{
	int a;

	if(t == T)
		fatal("optoas: t is nil");

	a = AGOK;
	switch(CASE(op, simtype[t->etype])) {
	default:
		fatal("optoas: no entry %O-%T etype %T simtype %T", op, t, types[t->etype], types[simtype[t->etype]]);
		break;

/*	case CASE(OADDR, TPTR32):
		a = ALEAL;
		break;

	case CASE(OADDR, TPTR64):
		a = ALEAQ;
		break;
*/
	// TODO(kaib): make sure the conditional branches work on all edge cases
	case CASE(OEQ, TBOOL):
	case CASE(OEQ, TINT8):
	case CASE(OEQ, TUINT8):
	case CASE(OEQ, TINT16):
	case CASE(OEQ, TUINT16):
	case CASE(OEQ, TINT32):
	case CASE(OEQ, TUINT32):
	case CASE(OEQ, TINT64):
	case CASE(OEQ, TUINT64):
	case CASE(OEQ, TPTR32):
	case CASE(OEQ, TPTR64):
	case CASE(OEQ, TFLOAT32):
	case CASE(OEQ, TFLOAT64):
		a = ABEQ;
		break;

	case CASE(ONE, TBOOL):
	case CASE(ONE, TINT8):
	case CASE(ONE, TUINT8):
	case CASE(ONE, TINT16):
	case CASE(ONE, TUINT16):
	case CASE(ONE, TINT32):
	case CASE(ONE, TUINT32):
	case CASE(ONE, TINT64):
	case CASE(ONE, TUINT64):
	case CASE(ONE, TPTR32):
	case CASE(ONE, TPTR64):
	case CASE(ONE, TFLOAT32):
	case CASE(ONE, TFLOAT64):
		a = ABNE;
		break;

	case CASE(OLT, TINT8):
	case CASE(OLT, TINT16):
	case CASE(OLT, TINT32):
	case CASE(OLT, TINT64):
	case CASE(OLT, TFLOAT32):
	case CASE(OLT, TFLOAT64):
		a = ABLT;
		break;

	case CASE(OLT, TUINT8):
	case CASE(OLT, TUINT16):
	case CASE(OLT, TUINT32):
	case CASE(OLT, TUINT64):
		a = ABLO;
		break;

	case CASE(OLE, TINT8):
	case CASE(OLE, TINT16):
	case CASE(OLE, TINT32):
	case CASE(OLE, TINT64):
	case CASE(OLE, TFLOAT32):
	case CASE(OLE, TFLOAT64):
		a = ABLE;
		break;

	case CASE(OLE, TUINT8):
	case CASE(OLE, TUINT16):
	case CASE(OLE, TUINT32):
	case CASE(OLE, TUINT64):
		a = ABLS;
		break;

	case CASE(OGT, TINT8):
	case CASE(OGT, TINT16):
	case CASE(OGT, TINT32):
	case CASE(OGT, TINT64):
	case CASE(OGT, TFLOAT32):
	case CASE(OGT, TFLOAT64):
		a = ABGT;
		break;

	case CASE(OGT, TUINT8):
	case CASE(OGT, TUINT16):
	case CASE(OGT, TUINT32):
	case CASE(OGT, TUINT64):
		a = ABHI;
		break;

	case CASE(OGE, TINT8):
	case CASE(OGE, TINT16):
	case CASE(OGE, TINT32):
	case CASE(OGE, TINT64):
	case CASE(OGE, TFLOAT32):
	case CASE(OGE, TFLOAT64):
		a = ABGE;
		break;

	case CASE(OGE, TUINT8):
	case CASE(OGE, TUINT16):
	case CASE(OGE, TUINT32):
	case CASE(OGE, TUINT64):
		a = ABHS;
		break;

	case CASE(OCMP, TBOOL):
	case CASE(OCMP, TINT8):
	case CASE(OCMP, TUINT8):
	case CASE(OCMP, TINT16):
	case CASE(OCMP, TUINT16):
	case CASE(OCMP, TINT32):
	case CASE(OCMP, TUINT32):
	case CASE(OCMP, TPTR32):
		a = ACMP;
		break;

	case CASE(OCMP, TFLOAT32):
		a = ACMPF;
		break;

	case CASE(OCMP, TFLOAT64):
		a = ACMPD;
		break;

	case CASE(OAS, TBOOL):
	case CASE(OAS, TINT8):
		a = AMOVB;
		break;

	case CASE(OAS, TUINT8):
		a = AMOVBU;
		break;

	case CASE(OAS, TINT16):
		a = AMOVH;
		break;

	case CASE(OAS, TUINT16):
		a = AMOVHU;
		break;

	case CASE(OAS, TINT32):
	case CASE(OAS, TUINT32):
	case CASE(OAS, TPTR32):
		a = AMOVW;
		break;

	case CASE(OAS, TFLOAT32):
		a = AMOVF;
		break;

	case CASE(OAS, TFLOAT64):
		a = AMOVD;
		break;

	case CASE(OADD, TINT8):
	case CASE(OADD, TUINT8):
	case CASE(OADD, TINT16):
	case CASE(OADD, TUINT16):
	case CASE(OADD, TINT32):
	case CASE(OADD, TUINT32):
	case CASE(OADD, TPTR32):
		a = AADD;
		break;

	case CASE(OADD, TFLOAT32):
		a = AADDF;
		break;

	case CASE(OADD, TFLOAT64):
		a = AADDD;
		break;

	case CASE(OSUB, TINT8):
	case CASE(OSUB, TUINT8):
	case CASE(OSUB, TINT16):
	case CASE(OSUB, TUINT16):
	case CASE(OSUB, TINT32):
	case CASE(OSUB, TUINT32):
	case CASE(OSUB, TPTR32):
		a = ASUB;
		break;

	case CASE(OSUB, TFLOAT32):
		a = ASUBF;
		break;

	case CASE(OSUB, TFLOAT64):
		a = ASUBD;
		break;

	case CASE(OAND, TINT8):
	case CASE(OAND, TUINT8):
	case CASE(OAND, TINT16):
	case CASE(OAND, TUINT16):
	case CASE(OAND, TINT32):
	case CASE(OAND, TUINT32):
	case CASE(OAND, TPTR32):
		a = AAND;
		break;

	case CASE(OOR, TINT8):
	case CASE(OOR, TUINT8):
	case CASE(OOR, TINT16):
	case CASE(OOR, TUINT16):
	case CASE(OOR, TINT32):
	case CASE(OOR, TUINT32):
	case CASE(OOR, TPTR32):
		a = AORR;
		break;

	case CASE(OXOR, TINT8):
	case CASE(OXOR, TUINT8):
	case CASE(OXOR, TINT16):
	case CASE(OXOR, TUINT16):
	case CASE(OXOR, TINT32):
	case CASE(OXOR, TUINT32):
	case CASE(OXOR, TPTR32):
		a = AEOR;
		break;

	case CASE(OLSH, TINT8):
	case CASE(OLSH, TUINT8):
	case CASE(OLSH, TINT16):
	case CASE(OLSH, TUINT16):
	case CASE(OLSH, TINT32):
	case CASE(OLSH, TUINT32):
	case CASE(OLSH, TPTR32):
		a = ASLL;
		break;

	case CASE(ORSH, TUINT8):
	case CASE(ORSH, TUINT16):
	case CASE(ORSH, TUINT32):
	case CASE(ORSH, TPTR32):
		a = ASRL;
		break;

	case CASE(ORSH, TINT8):
	case CASE(ORSH, TINT16):
	case CASE(ORSH, TINT32):
		a = ASRA;
		break;

	case CASE(OMUL, TUINT8):
	case CASE(OMUL, TUINT16):
	case CASE(OMUL, TUINT32):
	case CASE(OMUL, TPTR32):
		a = AMULU;
		break;

	case CASE(OMUL, TINT8):
	case CASE(OMUL, TINT16):
	case CASE(OMUL, TINT32):
		a = AMUL;
		break;

	case CASE(OMUL, TFLOAT32):
		a = AMULF;
		break;

	case CASE(OMUL, TFLOAT64):
		a = AMULD;
		break;

	case CASE(ODIV, TUINT8):
	case CASE(ODIV, TUINT16):
	case CASE(ODIV, TUINT32):
	case CASE(ODIV, TPTR32):
		a = ADIVU;
		break;

	case CASE(ODIV, TINT8):
	case CASE(ODIV, TINT16):
	case CASE(ODIV, TINT32):
		a = ADIV;
		break;

	case CASE(OMOD, TUINT8):
	case CASE(OMOD, TUINT16):
	case CASE(OMOD, TUINT32):
	case CASE(OMOD, TPTR32):
		a = AMODU;
		break;

	case CASE(OMOD, TINT8):
	case CASE(OMOD, TINT16):
	case CASE(OMOD, TINT32):
		a = AMOD;
		break;

//	case CASE(OEXTEND, TINT16):
//		a = ACWD;
//		break;

//	case CASE(OEXTEND, TINT32):
//		a = ACDQ;
//		break;

//	case CASE(OEXTEND, TINT64):
//		a = ACQO;
//		break;

	case CASE(ODIV, TFLOAT32):
		a = ADIVF;
		break;

	case CASE(ODIV, TFLOAT64):
		a = ADIVD;
		break;

	}
	return a;
}

enum
{
	ODynam	= 1<<0,
	OPtrto	= 1<<1,
};

static	Node	clean[20];
static	int	cleani = 0;

void
sudoclean(void)
{
	if(clean[cleani-1].op != OEMPTY)
		regfree(&clean[cleani-1]);
	if(clean[cleani-2].op != OEMPTY)
		regfree(&clean[cleani-2]);
	cleani -= 2;
}

int
dotaddable(Node *n, Node *n1)
{
	int o, oary[10];
	Node *nn;

	if(n->op != ODOT)
		return 0;

	o = dotoffset(n, oary, &nn);
	if(nn != N && nn->addable && o == 1 && oary[0] >= 0) {
		*n1 = *nn;
		n1->type = n->type;
		n1->xoffset += oary[0];
		return 1;
	}
	return 0;
}

/*
 * generate code to compute address of n,
 * a reference to a (perhaps nested) field inside
 * an array or struct.
 * return 0 on failure, 1 on success.
 * on success, leaves usable address in a.
 *
 * caller is responsible for calling sudoclean
 * after successful sudoaddable,
 * to release the register used for a.
 */
int
sudoaddable(int as, Node *n, Addr *a, int *w)
{
	int o, i;
	int oary[10];
	int64 v;
	Node n1, n2, n3, n4, *nn, *l, *r;
	Node *reg, *reg1;
	Prog *p1, *p2;
	Type *t;

	if(n->type == T)
		return 0;

	switch(n->op) {
	case OLITERAL:
		if(n->val.ctype != CTINT)
			break;
		v = mpgetfix(n->val.u.xval);
		if(v >= 32000 || v <= -32000)
			break;
		goto lit;

	case ODOT:
	case ODOTPTR:
		cleani += 2;
		reg = &clean[cleani-1];
		reg1 = &clean[cleani-2];
		reg->op = OEMPTY;
		reg1->op = OEMPTY;
		goto odot;

	case OINDEX:
		if(n->left->type->etype == TSTRING)
			return 0;
		cleani += 2;
		reg = &clean[cleani-1];
		reg1 = &clean[cleani-2];
		reg->op = OEMPTY;
		reg1->op = OEMPTY;
		goto oindex;
	}
	return 0;

lit:
	switch(as) {
	default:
		return 0;
	case AADD: case ASUB: case AAND: case AORR: case AEOR:
	case AMOVB: case AMOVBU: case AMOVH: case AMOVHU:
	case AMOVW:
		break;
	}

	cleani += 2;
	reg = &clean[cleani-1];
	reg1 = &clean[cleani-2];
	reg->op = OEMPTY;
	reg1->op = OEMPTY;
	naddr(n, a, 1);
	goto yes;

odot:
	o = dotoffset(n, oary, &nn);
	if(nn == N)
		goto no;

	if(nn->addable && o == 1 && oary[0] >= 0) {
		// directly addressable set of DOTs
		n1 = *nn;
		n1.type = n->type;
		n1.xoffset += oary[0];
		naddr(&n1, a, 1);
		goto yes;
	}

	regalloc(reg, types[tptr], N);
	n1 = *reg;
	n1.op = OINDREG;
	if(oary[0] >= 0) {
		agen(nn, reg);
		n1.xoffset = oary[0];
	} else {
		cgen(nn, reg);
		n1.xoffset = -(oary[0]+1);
	}

	for(i=1; i<o; i++) {
		if(oary[i] >= 0)
			fatal("cant happen");
		gins(AMOVW, &n1, reg);
		n1.xoffset = -(oary[i]+1);
	}

	a->type = D_NONE;
	a->name = D_NONE;
	naddr(&n1, a, 1);
	goto yes;

oindex:
	l = n->left;
	r = n->right;
	if(l->ullman >= UINF && r->ullman >= UINF)
		goto no;

	// set o to type of array
	o = 0;
	if(isptr[l->type->etype]) {
		o += OPtrto;
		if(l->type->type->etype != TARRAY)
			fatal("not ptr ary");
		if(l->type->type->bound < 0)
			o += ODynam;
	} else {
		if(l->type->etype != TARRAY)
			fatal("not ary");
		if(l->type->bound < 0)
			o += ODynam;
	}

	*w = n->type->width;
	if(isconst(r, CTINT))
		goto oindex_const;

	switch(*w) {
	default:
		goto no;
	case 1:
	case 2:
	case 4:
	case 8:
		break;
	}

	// load the array (reg)
	if(l->ullman > r->ullman) {
		regalloc(reg, types[tptr], N);
		if(o & OPtrto)
			cgen(l, reg);
		else
			agen(l, reg);
	}

	// load the index (reg1)
	t = types[TUINT32];
	if(issigned[r->type->etype])
		t = types[TINT32];
	regalloc(reg1, t, N);
	regalloc(&n3, types[TINT32], reg1);
	p2 = cgenindex(r, &n3);
	gmove(&n3, reg1);
	regfree(&n3);

	// load the array (reg)
	if(l->ullman <= r->ullman) {
		regalloc(reg, types[tptr], N);
		if(o & OPtrto)
			cgen(l, reg);
		else
			agen(l, reg);
	}

	// check bounds
	if(!debug['B']) {
		if(o & ODynam) {
			n2 = *reg;
			n2.op = OINDREG;
			n2.type = types[tptr];
			n2.xoffset = Array_nel;
		} else {
			if(l->type->width >= unmappedzero && l->op == OIND) {
				// cannot rely on page protections to
				// catch array ptr == 0, so dereference.
				n2 = *reg;
				n2.op = OINDREG;
				n2.type = types[TUINTPTR];
				n2.xoffset = 0;
				regalloc(&n3, n2.type, N);
				gins(AMOVW, &n2, &n3);
				regfree(&n3);
			}
			nodconst(&n2, types[TUINT32], l->type->bound);
			if(o & OPtrto)
				nodconst(&n2, types[TUINT32], l->type->type->bound);
		}
		regalloc(&n3, n2.type, N);
		cgen(&n2, &n3);
		gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3);
		regfree(&n3);
		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
		if(p2)
			patch(p2, pc);
		ginscall(panicindex, 0);
		patch(p1, pc);
	}

	if(o & ODynam) {
		n2 = *reg;
		n2.op = OINDREG;
		n2.type = types[tptr];
		n2.xoffset = Array_array;
		gmove(&n2, reg);
	}

	switch(*w) {
	case 1:
		gins(AADD, reg1, reg);
		break;
	case 2:
		gshift(AADD, reg1, SHIFT_LL, 1, reg);
		break;
	case 4:
		gshift(AADD, reg1, SHIFT_LL, 2, reg);
		break;
	case 8:
		gshift(AADD, reg1, SHIFT_LL, 3, reg);
		break;
	}

	naddr(reg1, a, 1);
	a->type = D_OREG;
	a->reg = reg->val.u.reg;
	a->offset = 0;

	goto yes;

oindex_const:
	// index is constant
	// can check statically and
	// can multiply by width statically

	regalloc(reg, types[tptr], N);
	if(o & OPtrto)
		cgen(l, reg);
	else
		agen(l, reg);

	v = mpgetfix(r->val.u.xval);
	if(o & ODynam) {

		if(!debug['B'] && !n->etype) {
			n1 = *reg;
			n1.op = OINDREG;
			n1.type = types[tptr];
			n1.xoffset = Array_nel;
			nodconst(&n2, types[TUINT32], v);
			regalloc(&n3, types[TUINT32], N);
			cgen(&n2, &n3);
			regalloc(&n4, n1.type, N);
			cgen(&n1, &n4);
			gcmp(optoas(OCMP, types[TUINT32]), &n4, &n3);
			regfree(&n4);
			regfree(&n3);
			p1 = gbranch(optoas(OGT, types[TUINT32]), T);
			ginscall(panicindex, 0);
			patch(p1, pc);
		}

		n1 = *reg;
		n1.op = OINDREG;
		n1.type = types[tptr];
		n1.xoffset = Array_array;
		gmove(&n1, reg);
	}

	n2 = *reg;
	n2.op = OINDREG;
	n2.xoffset = v * (*w);
	a->type = D_NONE;
	a->name = D_NONE;
	naddr(&n2, a, 1);
	goto yes;

yes:
	return 1;

no:
	sudoclean();
	return 0;
}
