diff --git a/src/cmd/new8g/ggen.go b/src/cmd/new8g/ggen.go
new file mode 100644
index 0000000..8dd469c
--- /dev/null
+++ b/src/cmd/new8g/ggen.go
@@ -0,0 +1,1297 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"cmd/internal/obj"
+	"cmd/internal/obj/i386"
+)
+import "cmd/internal/gc"
+
+func defframe(ptxt *obj.Prog) {
+	var frame uint32
+	var ax uint32
+	var p *obj.Prog
+	var lo int64
+	var hi int64
+	var l *gc.NodeList
+	var n *gc.Node
+
+	// fill in argument size, stack size
+	ptxt.To.Type = obj.TYPE_TEXTSIZE
+
+	ptxt.To.U.Argsize = int32(gc.Rnd(gc.Curfn.Type.Argwid, int64(gc.Widthptr)))
+	frame = uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
+	ptxt.To.Offset = int64(frame)
+
+	// insert code to zero ambiguously live variables
+	// so that the garbage collector only sees initialized values
+	// when it looks for pointers.
+	p = ptxt
+
+	hi = 0
+	lo = hi
+	ax = 0
+	for l = gc.Curfn.Dcl; l != nil; l = l.Next {
+		n = l.N
+		if !(n.Needzero != 0) {
+			continue
+		}
+		if n.Class != gc.PAUTO {
+			gc.Fatal("needzero class %d", n.Class)
+		}
+		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
+			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+		}
+		if lo != hi && n.Xoffset+n.Type.Width == lo-int64(2*gc.Widthptr) {
+			// merge with range we already have
+			lo = n.Xoffset
+
+			continue
+		}
+
+		// zero old range
+		p = zerorange(p, int64(frame), lo, hi, &ax)
+
+		// set new range
+		hi = n.Xoffset + n.Type.Width
+
+		lo = n.Xoffset
+	}
+
+	// zero final range
+	zerorange(p, int64(frame), lo, hi, &ax)
+}
+
+func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, ax *uint32) *obj.Prog {
+	var cnt int64
+	var i int64
+
+	cnt = hi - lo
+	if cnt == 0 {
+		return p
+	}
+	if *ax == 0 {
+		p = appendpp(p, i386.AMOVL, obj.TYPE_CONST, 0, 0, obj.TYPE_REG, i386.REG_AX, 0)
+		*ax = 1
+	}
+
+	if cnt <= int64(4*gc.Widthreg) {
+		for i = 0; i < cnt; i += int64(gc.Widthreg) {
+			p = appendpp(p, i386.AMOVL, obj.TYPE_REG, i386.REG_AX, 0, obj.TYPE_MEM, i386.REG_SP, frame+lo+i)
+		}
+	} else if !gc.Nacl && cnt <= int64(128*gc.Widthreg) {
+		p = appendpp(p, i386.ALEAL, obj.TYPE_MEM, i386.REG_SP, frame+lo, obj.TYPE_REG, i386.REG_DI, 0)
+		p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_ADDR, 0, 1*(128-cnt/int64(gc.Widthreg)))
+		p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg))
+	} else {
+		p = appendpp(p, i386.AMOVL, obj.TYPE_CONST, 0, cnt/int64(gc.Widthreg), obj.TYPE_REG, i386.REG_CX, 0)
+		p = appendpp(p, i386.ALEAL, obj.TYPE_MEM, i386.REG_SP, frame+lo, obj.TYPE_REG, i386.REG_DI, 0)
+		p = appendpp(p, i386.AREP, obj.TYPE_NONE, 0, 0, obj.TYPE_NONE, 0, 0)
+		p = appendpp(p, i386.ASTOSL, obj.TYPE_NONE, 0, 0, obj.TYPE_NONE, 0, 0)
+	}
+
+	return p
+}
+
+func appendpp(p *obj.Prog, as int, ftype int, freg int, foffset int64, ttype int, treg int, toffset int64) *obj.Prog {
+	var q *obj.Prog
+	q = gc.Ctxt.NewProg()
+	gc.Clearp(q)
+	q.As = int16(as)
+	q.Lineno = p.Lineno
+	q.From.Type = int16(ftype)
+	q.From.Reg = int16(freg)
+	q.From.Offset = foffset
+	q.To.Type = int16(ttype)
+	q.To.Reg = int16(treg)
+	q.To.Offset = toffset
+	q.Link = p.Link
+	p.Link = q
+	return q
+}
+
+func clearfat(nl *gc.Node) {
+	var w uint32
+	var c uint32
+	var q uint32
+	var n1 gc.Node
+	var z gc.Node
+	var p *obj.Prog
+
+	/* clear a fat object */
+	if gc.Debug['g'] != 0 {
+		gc.Dump("\nclearfat", nl)
+	}
+
+	w = uint32(nl.Type.Width)
+
+	// Avoid taking the address for simple enough types.
+	if componentgen(nil, nl) != 0 {
+		return
+	}
+
+	c = w % 4 // bytes
+	q = w / 4 // quads
+
+	if q < 4 {
+		// Write sequence of MOV 0, off(base) instead of using STOSL.
+		// The hope is that although the code will be slightly longer,
+		// the MOVs will have no dependencies and pipeline better
+		// than the unrolled STOSL loop.
+		// NOTE: Must use agen, not igen, so that optimizer sees address
+		// being taken. We are not writing on field boundaries.
+		regalloc(&n1, gc.Types[gc.Tptr], nil)
+
+		agen(nl, &n1)
+		n1.Op = gc.OINDREG
+		gc.Nodconst(&z, gc.Types[gc.TUINT64], 0)
+		for {
+			tmp14 := q
+			q--
+			if !(tmp14 > 0) {
+				break
+			}
+			n1.Type = z.Type
+			gins(i386.AMOVL, &z, &n1)
+			n1.Xoffset += 4
+		}
+
+		gc.Nodconst(&z, gc.Types[gc.TUINT8], 0)
+		for {
+			tmp15 := c
+			c--
+			if !(tmp15 > 0) {
+				break
+			}
+			n1.Type = z.Type
+			gins(i386.AMOVB, &z, &n1)
+			n1.Xoffset++
+		}
+
+		regfree(&n1)
+		return
+	}
+
+	gc.Nodreg(&n1, gc.Types[gc.Tptr], i386.REG_DI)
+	agen(nl, &n1)
+	gconreg(i386.AMOVL, 0, i386.REG_AX)
+
+	if q > 128 || (q >= 4 && gc.Nacl) {
+		gconreg(i386.AMOVL, int64(q), i386.REG_CX)
+		gins(i386.AREP, nil, nil)   // repeat
+		gins(i386.ASTOSL, nil, nil) // STOL AL,*(DI)+
+	} else if q >= 4 {
+		p = gins(obj.ADUFFZERO, nil, nil)
+		p.To.Type = obj.TYPE_ADDR
+		p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg))
+
+		// 1 and 128 = magic constants: see ../../runtime/asm_386.s
+		p.To.Offset = 1 * (128 - int64(q))
+	} else {
+		for q > 0 {
+			gins(i386.ASTOSL, nil, nil) // STOL AL,*(DI)+
+			q--
+		}
+	}
+
+	for c > 0 {
+		gins(i386.ASTOSB, nil, nil) // STOB AL,*(DI)+
+		c--
+	}
+}
+
+/*
+ * generate:
+ *	call f
+ *	proc=-1	normal call but no return
+ *	proc=0	normal call
+ *	proc=1	goroutine run in new proc
+ *	proc=2	defer call save away stack
+  *	proc=3	normal call to C pointer (not Go func value)
+*/
+func ginscall(f *gc.Node, proc int) {
+	var p *obj.Prog
+	var reg gc.Node
+	var r1 gc.Node
+	var con gc.Node
+	var stk gc.Node
+	var extra int32
+
+	if f.Type != nil {
+		extra = 0
+		if proc == 1 || proc == 2 {
+			extra = 2 * int32(gc.Widthptr)
+		}
+		gc.Setmaxarg(f.Type, extra)
+	}
+
+	switch proc {
+	default:
+		gc.Fatal("ginscall: bad proc %d", proc)
+
+	case 0, // normal call
+		-1: // normal call but no return
+		if f.Op == gc.ONAME && f.Class == gc.PFUNC {
+			if f == gc.Deferreturn {
+				// Deferred calls will appear to be returning to
+				// the CALL deferreturn(SB) that we are about to emit.
+				// However, the stack trace code will show the line
+				// of the instruction byte before the return PC.
+				// To avoid that being an unrelated instruction,
+				// insert an x86 NOP that we will have the right line number.
+				// x86 NOP 0x90 is really XCHG AX, AX; use that description
+				// because the NOP pseudo-instruction will be removed by
+				// the linker.
+				gc.Nodreg(&reg, gc.Types[gc.TINT], i386.REG_AX)
+
+				gins(i386.AXCHGL, &reg, &reg)
+			}
+
+			p = gins(obj.ACALL, nil, f)
+			gc.Afunclit(&p.To, f)
+			if proc == -1 || gc.Noreturn(p) != 0 {
+				gins(obj.AUNDEF, nil, nil)
+			}
+			break
+		}
+
+		gc.Nodreg(&reg, gc.Types[gc.Tptr], i386.REG_DX)
+		gc.Nodreg(&r1, gc.Types[gc.Tptr], i386.REG_BX)
+		gmove(f, &reg)
+		reg.Op = gc.OINDREG
+		gmove(&reg, &r1)
+		reg.Op = gc.OREGISTER
+		gins(obj.ACALL, &reg, &r1)
+
+	case 3: // normal call of c function pointer
+		gins(obj.ACALL, nil, f)
+
+	case 1, // call in new proc (go)
+		2: // deferred call (defer)
+		stk = gc.Node{}
+
+		stk.Op = gc.OINDREG
+		stk.Val.U.Reg = i386.REG_SP
+		stk.Xoffset = 0
+
+		// size of arguments at 0(SP)
+		gc.Nodconst(&con, gc.Types[gc.TINT32], int64(gc.Argsize(f.Type)))
+
+		gins(i386.AMOVL, &con, &stk)
+
+		// FuncVal* at 4(SP)
+		stk.Xoffset = int64(gc.Widthptr)
+
+		gins(i386.AMOVL, f, &stk)
+
+		if proc == 1 {
+			ginscall(gc.Newproc, 0)
+		} else {
+			ginscall(gc.Deferproc, 0)
+		}
+		if proc == 2 {
+			gc.Nodreg(&reg, gc.Types[gc.TINT32], i386.REG_AX)
+			gins(i386.ATESTL, &reg, &reg)
+			p = gc.Gbranch(i386.AJEQ, nil, +1)
+			cgen_ret(nil)
+			gc.Patch(p, gc.Pc)
+		}
+	}
+}
+
+/*
+ * n is call to interface method.
+ * generate res = n.
+ */
+func cgen_callinter(n *gc.Node, res *gc.Node, proc int) {
+	var i *gc.Node
+	var f *gc.Node
+	var tmpi gc.Node
+	var nodi gc.Node
+	var nodo gc.Node
+	var nodr gc.Node
+	var nodsp gc.Node
+
+	i = n.Left
+	if i.Op != gc.ODOTINTER {
+		gc.Fatal("cgen_callinter: not ODOTINTER %v", gc.Oconv(int(i.Op), 0))
+	}
+
+	f = i.Right // field
+	if f.Op != gc.ONAME {
+		gc.Fatal("cgen_callinter: not ONAME %v", gc.Oconv(int(f.Op), 0))
+	}
+
+	i = i.Left // interface
+
+	if !(i.Addable != 0) {
+		gc.Tempname(&tmpi, i.Type)
+		cgen(i, &tmpi)
+		i = &tmpi
+	}
+
+	gc.Genlist(n.List) // assign the args
+
+	// i is now addable, prepare an indirected
+	// register to hold its address.
+	igen(i, &nodi, res) // REG = &inter
+
+	gc.Nodindreg(&nodsp, gc.Types[gc.Tptr], i386.REG_SP)
+
+	nodsp.Xoffset = 0
+	if proc != 0 {
+		nodsp.Xoffset += 2 * int64(gc.Widthptr) // leave room for size & fn
+	}
+	nodi.Type = gc.Types[gc.Tptr]
+	nodi.Xoffset += int64(gc.Widthptr)
+	cgen(&nodi, &nodsp) // {0 or 8}(SP) = 4(REG) -- i.data
+
+	regalloc(&nodo, gc.Types[gc.Tptr], res)
+
+	nodi.Type = gc.Types[gc.Tptr]
+	nodi.Xoffset -= int64(gc.Widthptr)
+	cgen(&nodi, &nodo) // REG = 0(REG) -- i.tab
+	regfree(&nodi)
+
+	regalloc(&nodr, gc.Types[gc.Tptr], &nodo)
+	if n.Left.Xoffset == gc.BADWIDTH {
+		gc.Fatal("cgen_callinter: badwidth")
+	}
+	gc.Cgen_checknil(&nodo)
+	nodo.Op = gc.OINDREG
+	nodo.Xoffset = n.Left.Xoffset + 3*int64(gc.Widthptr) + 8
+
+	if proc == 0 {
+		// plain call: use direct c function pointer - more efficient
+		cgen(&nodo, &nodr) // REG = 20+offset(REG) -- i.tab->fun[f]
+		proc = 3
+	} else {
+		// go/defer. generate go func value.
+		gins(i386.ALEAL, &nodo, &nodr) // REG = &(20+offset(REG)) -- i.tab->fun[f]
+	}
+
+	nodr.Type = n.Left.Type
+	ginscall(&nodr, proc)
+
+	regfree(&nodr)
+	regfree(&nodo)
+}
+
+/*
+ * generate function call;
+ *	proc=0	normal call
+ *	proc=1	goroutine run in new proc
+ *	proc=2	defer call save away stack
+ */
+func cgen_call(n *gc.Node, proc int) {
+	var t *gc.Type
+	var nod gc.Node
+	var afun gc.Node
+
+	if n == nil {
+		return
+	}
+
+	if n.Left.Ullman >= gc.UINF {
+		// if name involves a fn call
+		// precompute the address of the fn
+		gc.Tempname(&afun, gc.Types[gc.Tptr])
+
+		cgen(n.Left, &afun)
+	}
+
+	gc.Genlist(n.List) // assign the args
+	t = n.Left.Type
+
+	// call tempname pointer
+	if n.Left.Ullman >= gc.UINF {
+		regalloc(&nod, gc.Types[gc.Tptr], nil)
+		gc.Cgen_as(&nod, &afun)
+		nod.Type = t
+		ginscall(&nod, proc)
+		regfree(&nod)
+		return
+	}
+
+	// call pointer
+	if n.Left.Op != gc.ONAME || n.Left.Class != gc.PFUNC {
+		regalloc(&nod, gc.Types[gc.Tptr], nil)
+		gc.Cgen_as(&nod, n.Left)
+		nod.Type = t
+		ginscall(&nod, proc)
+		regfree(&nod)
+		return
+	}
+
+	// call direct
+	n.Left.Method = 1
+
+	ginscall(n.Left, proc)
+}
+
+/*
+ * call to n has already been generated.
+ * generate:
+ *	res = return value from call.
+ */
+func cgen_callret(n *gc.Node, res *gc.Node) {
+	var nod gc.Node
+	var fp *gc.Type
+	var t *gc.Type
+	var flist gc.Iter
+
+	t = n.Left.Type
+	if t.Etype == gc.TPTR32 || t.Etype == gc.TPTR64 {
+		t = t.Type
+	}
+
+	fp = gc.Structfirst(&flist, gc.Getoutarg(t))
+	if fp == nil {
+		gc.Fatal("cgen_callret: nil")
+	}
+
+	nod = gc.Node{}
+	nod.Op = gc.OINDREG
+	nod.Val.U.Reg = i386.REG_SP
+	nod.Addable = 1
+
+	nod.Xoffset = fp.Width
+	nod.Type = fp.Type
+	gc.Cgen_as(res, &nod)
+}
+
+/*
+ * call to n has already been generated.
+ * generate:
+ *	res = &return value from call.
+ */
+func cgen_aret(n *gc.Node, res *gc.Node) {
+	var nod1 gc.Node
+	var nod2 gc.Node
+	var fp *gc.Type
+	var t *gc.Type
+	var flist gc.Iter
+
+	t = n.Left.Type
+	if gc.Isptr[t.Etype] != 0 {
+		t = t.Type
+	}
+
+	fp = gc.Structfirst(&flist, gc.Getoutarg(t))
+	if fp == nil {
+		gc.Fatal("cgen_aret: nil")
+	}
+
+	nod1 = gc.Node{}
+	nod1.Op = gc.OINDREG
+	nod1.Val.U.Reg = i386.REG_SP
+	nod1.Addable = 1
+
+	nod1.Xoffset = fp.Width
+	nod1.Type = fp.Type
+
+	if res.Op != gc.OREGISTER {
+		regalloc(&nod2, gc.Types[gc.Tptr], res)
+		gins(i386.ALEAL, &nod1, &nod2)
+		gins(i386.AMOVL, &nod2, res)
+		regfree(&nod2)
+	} else {
+		gins(i386.ALEAL, &nod1, res)
+	}
+}
+
+/*
+ * generate return.
+ * n->left is assignments to return values.
+ */
+func cgen_ret(n *gc.Node) {
+	var p *obj.Prog
+
+	if n != nil {
+		gc.Genlist(n.List) // copy out args
+	}
+	if gc.Hasdefer != 0 {
+		ginscall(gc.Deferreturn, 0)
+	}
+	gc.Genlist(gc.Curfn.Exit)
+	p = gins(obj.ARET, nil, nil)
+	if n != nil && n.Op == gc.ORETJMP {
+		p.To.Type = obj.TYPE_MEM
+		p.To.Name = obj.NAME_EXTERN
+		p.To.Sym = gc.Linksym(n.Left.Sym)
+	}
+}
+
+/*
+ * generate division.
+ * caller must set:
+ *	ax = allocated AX register
+ *	dx = allocated DX register
+ * generates one of:
+ *	res = nl / nr
+ *	res = nl % nr
+ * according to op.
+ */
+func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.Node) {
+	var check int
+	var n1 gc.Node
+	var t1 gc.Node
+	var t2 gc.Node
+	var t3 gc.Node
+	var t4 gc.Node
+	var n4 gc.Node
+	var nz gc.Node
+	var t *gc.Type
+	var t0 *gc.Type
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+
+	// Have to be careful about handling
+	// most negative int divided by -1 correctly.
+	// The hardware will trap.
+	// Also the byte divide instruction needs AH,
+	// which we otherwise don't have to deal with.
+	// Easiest way to avoid for int8, int16: use int32.
+	// For int32 and int64, use explicit test.
+	// Could use int64 hw for int32.
+	t = nl.Type
+
+	t0 = t
+	check = 0
+	if gc.Issigned[t.Etype] != 0 {
+		check = 1
+		if gc.Isconst(nl, gc.CTINT) != 0 && gc.Mpgetfix(nl.Val.U.Xval) != -1<<uint64(t.Width*8-1) {
+			check = 0
+		} else if gc.Isconst(nr, gc.CTINT) != 0 && gc.Mpgetfix(nr.Val.U.Xval) != -1 {
+			check = 0
+		}
+	}
+
+	if t.Width < 4 {
+		if gc.Issigned[t.Etype] != 0 {
+			t = gc.Types[gc.TINT32]
+		} else {
+			t = gc.Types[gc.TUINT32]
+		}
+		check = 0
+	}
+
+	gc.Tempname(&t1, t)
+	gc.Tempname(&t2, t)
+	if t0 != t {
+		gc.Tempname(&t3, t0)
+		gc.Tempname(&t4, t0)
+		cgen(nl, &t3)
+		cgen(nr, &t4)
+
+		// Convert.
+		gmove(&t3, &t1)
+
+		gmove(&t4, &t2)
+	} else {
+		cgen(nl, &t1)
+		cgen(nr, &t2)
+	}
+
+	if !(gc.Samereg(ax, res) != 0) && !(gc.Samereg(dx, res) != 0) {
+		regalloc(&n1, t, res)
+	} else {
+		regalloc(&n1, t, nil)
+	}
+	gmove(&t2, &n1)
+	gmove(&t1, ax)
+	p2 = nil
+	if gc.Nacl {
+		// Native Client does not relay the divide-by-zero trap
+		// to the executing program, so we must insert a check
+		// for ourselves.
+		gc.Nodconst(&n4, t, 0)
+
+		gins(optoas(gc.OCMP, t), &n1, &n4)
+		p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
+		if panicdiv == nil {
+			panicdiv = gc.Sysfunc("panicdivide")
+		}
+		ginscall(panicdiv, -1)
+		gc.Patch(p1, gc.Pc)
+	}
+
+	if check != 0 {
+		gc.Nodconst(&n4, t, -1)
+		gins(optoas(gc.OCMP, t), &n1, &n4)
+		p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
+		if op == gc.ODIV {
+			// a / (-1) is -a.
+			gins(optoas(gc.OMINUS, t), nil, ax)
+
+			gmove(ax, res)
+		} else {
+			// a % (-1) is 0.
+			gc.Nodconst(&n4, t, 0)
+
+			gmove(&n4, res)
+		}
+
+		p2 = gc.Gbranch(obj.AJMP, nil, 0)
+		gc.Patch(p1, gc.Pc)
+	}
+
+	if !(gc.Issigned[t.Etype] != 0) {
+		gc.Nodconst(&nz, t, 0)
+		gmove(&nz, dx)
+	} else {
+		gins(optoas(gc.OEXTEND, t), nil, nil)
+	}
+	gins(optoas(op, t), &n1, nil)
+	regfree(&n1)
+
+	if op == gc.ODIV {
+		gmove(ax, res)
+	} else {
+		gmove(dx, res)
+	}
+	if check != 0 {
+		gc.Patch(p2, gc.Pc)
+	}
+}
+
+func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
+	var r int
+
+	r = int(reg[dr])
+	gc.Nodreg(x, gc.Types[gc.TINT32], dr)
+
+	// save current ax and dx if they are live
+	// and not the destination
+	*oldx = gc.Node{}
+
+	if r > 0 && !(gc.Samereg(x, res) != 0) {
+		gc.Tempname(oldx, gc.Types[gc.TINT32])
+		gmove(x, oldx)
+	}
+
+	regalloc(x, t, x)
+}
+
+func restx(x *gc.Node, oldx *gc.Node) {
+	regfree(x)
+
+	if oldx.Op != 0 {
+		x.Type = gc.Types[gc.TINT32]
+		gmove(oldx, x)
+	}
+}
+
+/*
+ * generate division according to op, one of:
+ *	res = nl / nr
+ *	res = nl % nr
+ */
+func cgen_div(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	var ax gc.Node
+	var dx gc.Node
+	var oldax gc.Node
+	var olddx gc.Node
+	var t *gc.Type
+
+	if gc.Is64(nl.Type) != 0 {
+		gc.Fatal("cgen_div %v", gc.Tconv(nl.Type, 0))
+	}
+
+	if gc.Issigned[nl.Type.Etype] != 0 {
+		t = gc.Types[gc.TINT32]
+	} else {
+		t = gc.Types[gc.TUINT32]
+	}
+	savex(i386.REG_AX, &ax, &oldax, res, t)
+	savex(i386.REG_DX, &dx, &olddx, res, t)
+	dodiv(op, nl, nr, res, &ax, &dx)
+	restx(&dx, &olddx)
+	restx(&ax, &oldax)
+}
+
+/*
+ * generate shift according to op, one of:
+ *	res = nl << nr
+ *	res = nl >> nr
+ */
+func cgen_shift(op int, bounded int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	var n1 gc.Node
+	var n2 gc.Node
+	var nt gc.Node
+	var cx gc.Node
+	var oldcx gc.Node
+	var hi gc.Node
+	var lo gc.Node
+	var a int
+	var w int
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+	var sc uint64
+
+	if nl.Type.Width > 4 {
+		gc.Fatal("cgen_shift %v", gc.Tconv(nl.Type, 0))
+	}
+
+	w = int(nl.Type.Width * 8)
+
+	a = optoas(op, nl.Type)
+
+	if nr.Op == gc.OLITERAL {
+		gc.Tempname(&n2, nl.Type)
+		cgen(nl, &n2)
+		regalloc(&n1, nl.Type, res)
+		gmove(&n2, &n1)
+		sc = uint64(gc.Mpgetfix(nr.Val.U.Xval))
+		if sc >= uint64(nl.Type.Width*8) {
+			// large shift gets 2 shifts by width-1
+			gins(a, ncon(uint32(w)-1), &n1)
+
+			gins(a, ncon(uint32(w)-1), &n1)
+		} else {
+			gins(a, nr, &n1)
+		}
+		gmove(&n1, res)
+		regfree(&n1)
+		return
+	}
+
+	oldcx = gc.Node{}
+	gc.Nodreg(&cx, gc.Types[gc.TUINT32], i386.REG_CX)
+	if reg[i386.REG_CX] > 1 && !(gc.Samereg(&cx, res) != 0) {
+		gc.Tempname(&oldcx, gc.Types[gc.TUINT32])
+		gmove(&cx, &oldcx)
+	}
+
+	if nr.Type.Width > 4 {
+		gc.Tempname(&nt, nr.Type)
+		n1 = nt
+	} else {
+		gc.Nodreg(&n1, gc.Types[gc.TUINT32], i386.REG_CX)
+		regalloc(&n1, nr.Type, &n1) // to hold the shift type in CX
+	}
+
+	if gc.Samereg(&cx, res) != 0 {
+		regalloc(&n2, nl.Type, nil)
+	} else {
+		regalloc(&n2, nl.Type, res)
+	}
+	if nl.Ullman >= nr.Ullman {
+		cgen(nl, &n2)
+		cgen(nr, &n1)
+	} else {
+		cgen(nr, &n1)
+		cgen(nl, &n2)
+	}
+
+	// test and fix up large shifts
+	if bounded != 0 {
+		if nr.Type.Width > 4 {
+			// delayed reg alloc
+			gc.Nodreg(&n1, gc.Types[gc.TUINT32], i386.REG_CX)
+
+			regalloc(&n1, gc.Types[gc.TUINT32], &n1) // to hold the shift type in CX
+			split64(&nt, &lo, &hi)
+			gmove(&lo, &n1)
+			splitclean()
+		}
+	} else {
+		if nr.Type.Width > 4 {
+			// delayed reg alloc
+			gc.Nodreg(&n1, gc.Types[gc.TUINT32], i386.REG_CX)
+
+			regalloc(&n1, gc.Types[gc.TUINT32], &n1) // to hold the shift type in CX
+			split64(&nt, &lo, &hi)
+			gmove(&lo, &n1)
+			gins(optoas(gc.OCMP, gc.Types[gc.TUINT32]), &hi, ncon(0))
+			p2 = gc.Gbranch(optoas(gc.ONE, gc.Types[gc.TUINT32]), nil, +1)
+			gins(optoas(gc.OCMP, gc.Types[gc.TUINT32]), &n1, ncon(uint32(w)))
+			p1 = gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1)
+			splitclean()
+			gc.Patch(p2, gc.Pc)
+		} else {
+			gins(optoas(gc.OCMP, nr.Type), &n1, ncon(uint32(w)))
+			p1 = gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1)
+		}
+
+		if op == gc.ORSH && gc.Issigned[nl.Type.Etype] != 0 {
+			gins(a, ncon(uint32(w)-1), &n2)
+		} else {
+			gmove(ncon(0), &n2)
+		}
+
+		gc.Patch(p1, gc.Pc)
+	}
+
+	gins(a, &n1, &n2)
+
+	if oldcx.Op != 0 {
+		gmove(&oldcx, &cx)
+	}
+
+	gmove(&n2, res)
+
+	regfree(&n1)
+	regfree(&n2)
+}
+
+/*
+ * generate byte multiply:
+ *	res = nl * nr
+ * there is no 2-operand byte multiply instruction so
+ * we do a full-width multiplication and truncate afterwards.
+ */
+func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	var n1 gc.Node
+	var n2 gc.Node
+	var nt gc.Node
+	var tmp *gc.Node
+	var t *gc.Type
+	var a int
+
+	// copy from byte to full registers
+	t = gc.Types[gc.TUINT32]
+
+	if gc.Issigned[nl.Type.Etype] != 0 {
+		t = gc.Types[gc.TINT32]
+	}
+
+	// largest ullman on left.
+	if nl.Ullman < nr.Ullman {
+		tmp = nl
+		nl = nr
+		nr = tmp
+	}
+
+	gc.Tempname(&nt, nl.Type)
+	cgen(nl, &nt)
+	regalloc(&n1, t, res)
+	cgen(nr, &n1)
+	regalloc(&n2, t, nil)
+	gmove(&nt, &n2)
+	a = optoas(op, t)
+	gins(a, &n2, &n1)
+	regfree(&n2)
+	gmove(&n1, res)
+	regfree(&n1)
+}
+
+/*
+ * generate high multiply:
+ *   res = (nl*nr) >> width
+ */
+func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	var t *gc.Type
+	var a int
+	var n1 gc.Node
+	var n2 gc.Node
+	var ax gc.Node
+	var dx gc.Node
+
+	t = nl.Type
+	a = optoas(gc.OHMUL, t)
+
+	// gen nl in n1.
+	gc.Tempname(&n1, t)
+
+	cgen(nl, &n1)
+
+	// gen nr in n2.
+	regalloc(&n2, t, res)
+
+	cgen(nr, &n2)
+
+	// multiply.
+	gc.Nodreg(&ax, t, i386.REG_AX)
+
+	gmove(&n2, &ax)
+	gins(a, &n1, nil)
+	regfree(&n2)
+
+	if t.Width == 1 {
+		// byte multiply behaves differently.
+		gc.Nodreg(&ax, t, i386.REG_AH)
+
+		gc.Nodreg(&dx, t, i386.REG_DX)
+		gmove(&ax, &dx)
+	}
+
+	gc.Nodreg(&dx, t, i386.REG_DX)
+	gmove(&dx, res)
+}
+
+/*
+ * generate floating-point operation.
+ */
+func cgen_float(n *gc.Node, res *gc.Node) {
+	var nl *gc.Node
+	var n1 gc.Node
+	var n2 gc.Node
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+	var p3 *obj.Prog
+
+	nl = n.Left
+	switch n.Op {
+	case gc.OEQ,
+		gc.ONE,
+		gc.OLT,
+		gc.OLE,
+		gc.OGE:
+		p1 = gc.Gbranch(obj.AJMP, nil, 0)
+		p2 = gc.Pc
+		gmove(gc.Nodbool(1), res)
+		p3 = gc.Gbranch(obj.AJMP, nil, 0)
+		gc.Patch(p1, gc.Pc)
+		bgen(n, true, 0, p2)
+		gmove(gc.Nodbool(0), res)
+		gc.Patch(p3, gc.Pc)
+		return
+
+	case gc.OPLUS:
+		cgen(nl, res)
+		return
+
+	case gc.OCONV:
+		if gc.Eqtype(n.Type, nl.Type) || gc.Noconv(n.Type, nl.Type) != 0 {
+			cgen(nl, res)
+			return
+		}
+
+		gc.Tempname(&n2, n.Type)
+		mgen(nl, &n1, res)
+		gmove(&n1, &n2)
+		gmove(&n2, res)
+		mfree(&n1)
+		return
+	}
+
+	if gc.Use_sse != 0 {
+		cgen_floatsse(n, res)
+	} else {
+		cgen_float387(n, res)
+	}
+}
+
+// floating-point.  387 (not SSE2)
+func cgen_float387(n *gc.Node, res *gc.Node) {
+	var f0 gc.Node
+	var f1 gc.Node
+	var nl *gc.Node
+	var nr *gc.Node
+
+	nl = n.Left
+	nr = n.Right
+	gc.Nodreg(&f0, nl.Type, i386.REG_F0)
+	gc.Nodreg(&f1, n.Type, i386.REG_F0+1)
+	if nr != nil {
+		goto flt2
+	}
+
+	// unary
+	cgen(nl, &f0)
+
+	if n.Op != gc.OCONV && n.Op != gc.OPLUS {
+		gins(foptoas(int(n.Op), n.Type, 0), nil, nil)
+	}
+	gmove(&f0, res)
+	return
+
+flt2: // binary
+	if nl.Ullman >= nr.Ullman {
+		cgen(nl, &f0)
+		if nr.Addable != 0 {
+			gins(foptoas(int(n.Op), n.Type, 0), nr, &f0)
+		} else {
+			cgen(nr, &f0)
+			gins(foptoas(int(n.Op), n.Type, Fpop), &f0, &f1)
+		}
+	} else {
+		cgen(nr, &f0)
+		if nl.Addable != 0 {
+			gins(foptoas(int(n.Op), n.Type, Frev), nl, &f0)
+		} else {
+			cgen(nl, &f0)
+			gins(foptoas(int(n.Op), n.Type, Frev|Fpop), &f0, &f1)
+		}
+	}
+
+	gmove(&f0, res)
+	return
+}
+
+func cgen_floatsse(n *gc.Node, res *gc.Node) {
+	var nl *gc.Node
+	var nr *gc.Node
+	var r *gc.Node
+	var n1 gc.Node
+	var n2 gc.Node
+	var nt gc.Node
+	var a int
+
+	nl = n.Left
+	nr = n.Right
+	switch n.Op {
+	default:
+		gc.Dump("cgen_floatsse", n)
+		gc.Fatal("cgen_floatsse %v", gc.Oconv(int(n.Op), 0))
+		return
+
+	case gc.OMINUS,
+		gc.OCOM:
+		nr = gc.Nodintconst(-1)
+		gc.Convlit(&nr, n.Type)
+		a = foptoas(gc.OMUL, nl.Type, 0)
+		goto sbop
+
+		// symmetric binary
+	case gc.OADD,
+		gc.OMUL:
+		a = foptoas(int(n.Op), nl.Type, 0)
+
+		goto sbop
+
+		// asymmetric binary
+	case gc.OSUB,
+		gc.OMOD,
+		gc.ODIV:
+		a = foptoas(int(n.Op), nl.Type, 0)
+
+		goto abop
+	}
+
+sbop: // symmetric binary
+	if nl.Ullman < nr.Ullman || nl.Op == gc.OLITERAL {
+		r = nl
+		nl = nr
+		nr = r
+	}
+
+abop: // asymmetric binary
+	if nl.Ullman >= nr.Ullman {
+		gc.Tempname(&nt, nl.Type)
+		cgen(nl, &nt)
+		mgen(nr, &n2, nil)
+		regalloc(&n1, nl.Type, res)
+		gmove(&nt, &n1)
+		gins(a, &n2, &n1)
+		gmove(&n1, res)
+		regfree(&n1)
+		mfree(&n2)
+	} else {
+		regalloc(&n2, nr.Type, res)
+		cgen(nr, &n2)
+		regalloc(&n1, nl.Type, nil)
+		cgen(nl, &n1)
+		gins(a, &n2, &n1)
+		regfree(&n2)
+		gmove(&n1, res)
+		regfree(&n1)
+	}
+
+	return
+}
+
+func bgen_float(n *gc.Node, true_ int, likely int, to *obj.Prog) {
+	var et int
+	var a int
+	var nl *gc.Node
+	var nr *gc.Node
+	var r *gc.Node
+	var n1 gc.Node
+	var n2 gc.Node
+	var n3 gc.Node
+	var tmp gc.Node
+	var t1 gc.Node
+	var t2 gc.Node
+	var ax gc.Node
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+
+	nl = n.Left
+	nr = n.Right
+	a = int(n.Op)
+	if !(true_ != 0) {
+		// brcom is not valid on floats when NaN is involved.
+		p1 = gc.Gbranch(obj.AJMP, nil, 0)
+
+		p2 = gc.Gbranch(obj.AJMP, nil, 0)
+		gc.Patch(p1, gc.Pc)
+
+		// No need to avoid re-genning ninit.
+		bgen_float(n, 1, -likely, p2)
+
+		gc.Patch(gc.Gbranch(obj.AJMP, nil, 0), to)
+		gc.Patch(p2, gc.Pc)
+		return
+	}
+
+	if gc.Use_sse != 0 {
+		goto sse
+	} else {
+		goto x87
+	}
+
+x87:
+	a = gc.Brrev(a) // because the args are stacked
+	if a == gc.OGE || a == gc.OGT {
+		// only < and <= work right with NaN; reverse if needed
+		r = nr
+
+		nr = nl
+		nl = r
+		a = gc.Brrev(a)
+	}
+
+	gc.Nodreg(&tmp, nr.Type, i386.REG_F0)
+	gc.Nodreg(&n2, nr.Type, i386.REG_F0+1)
+	gc.Nodreg(&ax, gc.Types[gc.TUINT16], i386.REG_AX)
+	et = gc.Simsimtype(nr.Type)
+	if et == gc.TFLOAT64 {
+		if nl.Ullman > nr.Ullman {
+			cgen(nl, &tmp)
+			cgen(nr, &tmp)
+			gins(i386.AFXCHD, &tmp, &n2)
+		} else {
+			cgen(nr, &tmp)
+			cgen(nl, &tmp)
+		}
+
+		gins(i386.AFUCOMIP, &tmp, &n2)
+		gins(i386.AFMOVDP, &tmp, &tmp) // annoying pop but still better than STSW+SAHF
+	} else {
+		// TODO(rsc): The moves back and forth to memory
+		// here are for truncating the value to 32 bits.
+		// This handles 32-bit comparison but presumably
+		// all the other ops have the same problem.
+		// We need to figure out what the right general
+		// solution is, besides telling people to use float64.
+		gc.Tempname(&t1, gc.Types[gc.TFLOAT32])
+
+		gc.Tempname(&t2, gc.Types[gc.TFLOAT32])
+		cgen(nr, &t1)
+		cgen(nl, &t2)
+		gmove(&t2, &tmp)
+		gins(i386.AFCOMFP, &t1, &tmp)
+		gins(i386.AFSTSW, nil, &ax)
+		gins(i386.ASAHF, nil, nil)
+	}
+
+	goto ret
+
+sse:
+	if !(nl.Addable != 0) {
+		gc.Tempname(&n1, nl.Type)
+		cgen(nl, &n1)
+		nl = &n1
+	}
+
+	if !(nr.Addable != 0) {
+		gc.Tempname(&tmp, nr.Type)
+		cgen(nr, &tmp)
+		nr = &tmp
+	}
+
+	regalloc(&n2, nr.Type, nil)
+	gmove(nr, &n2)
+	nr = &n2
+
+	if nl.Op != gc.OREGISTER {
+		regalloc(&n3, nl.Type, nil)
+		gmove(nl, &n3)
+		nl = &n3
+	}
+
+	if a == gc.OGE || a == gc.OGT {
+		// only < and <= work right with NaN; reverse if needed
+		r = nr
+
+		nr = nl
+		nl = r
+		a = gc.Brrev(a)
+	}
+
+	gins(foptoas(gc.OCMP, nr.Type, 0), nl, nr)
+	if nl.Op == gc.OREGISTER {
+		regfree(nl)
+	}
+	regfree(nr)
+
+ret:
+	if a == gc.OEQ {
+		// neither NE nor P
+		p1 = gc.Gbranch(i386.AJNE, nil, -likely)
+
+		p2 = gc.Gbranch(i386.AJPS, nil, -likely)
+		gc.Patch(gc.Gbranch(obj.AJMP, nil, 0), to)
+		gc.Patch(p1, gc.Pc)
+		gc.Patch(p2, gc.Pc)
+	} else if a == gc.ONE {
+		// either NE or P
+		gc.Patch(gc.Gbranch(i386.AJNE, nil, likely), to)
+
+		gc.Patch(gc.Gbranch(i386.AJPS, nil, likely), to)
+	} else {
+		gc.Patch(gc.Gbranch(optoas(a, nr.Type), nil, likely), to)
+	}
+}
+
+// Called after regopt and peep have run.
+// Expand CHECKNIL pseudo-op into actual nil pointer check.
+func expandchecks(firstp *obj.Prog) {
+	var p *obj.Prog
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+
+	for p = firstp; p != nil; p = p.Link {
+		if p.As != obj.ACHECKNIL {
+			continue
+		}
+		if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers
+			gc.Warnl(int(p.Lineno), "generated nil check")
+		}
+
+		// check is
+		//	CMP arg, $0
+		//	JNE 2(PC) (likely)
+		//	MOV AX, 0
+		p1 = gc.Ctxt.NewProg()
+
+		p2 = gc.Ctxt.NewProg()
+		gc.Clearp(p1)
+		gc.Clearp(p2)
+		p1.Link = p2
+		p2.Link = p.Link
+		p.Link = p1
+		p1.Lineno = p.Lineno
+		p2.Lineno = p.Lineno
+		p1.Pc = 9999
+		p2.Pc = 9999
+		p.As = i386.ACMPL
+		p.To.Type = obj.TYPE_CONST
+		p.To.Offset = 0
+		p1.As = i386.AJNE
+		p1.From.Type = obj.TYPE_CONST
+		p1.From.Offset = 1 // likely
+		p1.To.Type = obj.TYPE_BRANCH
+		p1.To.U.Branch = p2.Link
+
+		// crash by write to memory address 0.
+		// if possible, since we know arg is 0, use 0(arg),
+		// which will be shorter to encode than plain 0.
+		p2.As = i386.AMOVL
+
+		p2.From.Type = obj.TYPE_REG
+		p2.From.Reg = i386.REG_AX
+		if regtyp(&p.From) != 0 {
+			p2.To.Type = obj.TYPE_MEM
+			p2.To.Reg = p.From.Reg
+		} else {
+			p2.To.Type = obj.TYPE_MEM
+		}
+		p2.To.Offset = 0
+	}
+}
