]> Cypherpunks.ru repositories - gostls13.git/commitdiff
build: merge the great pkg/ rename into dev.power64
authorAustin Clements <austin@google.com>
Wed, 22 Oct 2014 17:25:37 +0000 (13:25 -0400)
committerAustin Clements <austin@google.com>
Wed, 22 Oct 2014 17:25:37 +0000 (13:25 -0400)
This also removes pkg/runtime/traceback_lr.c, which was ported
to Go in an earlier commit and then moved to
runtime/traceback.go.

Reviewer: rsc@golang.org
          rsc: LGTM

79 files changed:
1  2 
.hgignore
src/cmd/9a/a.y
src/cmd/9a/y.tab.c
src/cmd/9c/cgen.c
src/cmd/9g/ggen.c
src/cmd/9g/gsubr.c
src/cmd/cc/pgen.c
src/cmd/dist/build.c
src/cmd/dist/buildruntime.c
src/cmd/gc/pgen.c
src/cmd/gc/plive.c
src/cmd/gc/walk.c
src/cmd/ld/data.c
src/cmd/ld/dwarf.c
src/cmd/ld/lib.c
src/debug/elf/elf.go
src/debug/elf/file.go
src/debug/elf/file_test.go
src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
src/go/build/build.go
src/go/build/syslist.go
src/hash/crc32/crc32_generic.go
src/liblink/asm9.c
src/liblink/obj9.c
src/math/abs_power64x.s
src/math/big/arith_power64x.s
src/math/stubs_power64x.s
src/os/signal/sig.s
src/reflect/all_test.go
src/reflect/asm_power64x.s
src/reflect/value.go
src/runtime/arch_power64.h
src/runtime/arch_power64le.h
src/runtime/asm_power64x.s
src/runtime/atomic_power64x.s
src/runtime/defs1_linux.go
src/runtime/defs3_linux.go
src/runtime/defs_linux.go
src/runtime/defs_linux_power64.h
src/runtime/defs_linux_power64le.h
src/runtime/gcinfo_test.go
src/runtime/heapdump.c
src/runtime/malloc.c
src/runtime/malloc.go
src/runtime/malloc.h
src/runtime/mem_linux.c
src/runtime/memclr_power64x.s
src/runtime/memmove_power64x.s
src/runtime/mgc0.c
src/runtime/mgc0.h
src/runtime/os_linux.c
src/runtime/panic.c
src/runtime/panic.go
src/runtime/panic1.go
src/runtime/proc.c
src/runtime/rt0_linux_power64.s
src/runtime/rt0_linux_power64le.s
src/runtime/signal_linux_power64.h
src/runtime/signal_linux_power64le.h
src/runtime/signal_power64x.c
src/runtime/stack.c
src/runtime/string.go
src/runtime/sys_linux_power64x.s
src/runtime/sys_power64x.c
src/runtime/thunk.s
src/sync/atomic/asm_power64x.s
src/syscall/asm_linux_power64x.s
src/syscall/mkall.sh
src/syscall/mkerrors.sh
src/syscall/syscall_linux_power64x.go
src/syscall/types_linux.go
src/syscall/zerrors_linux_power64.go
src/syscall/zerrors_linux_power64le.go
src/syscall/zsyscall_linux_power64.go
src/syscall/zsyscall_linux_power64le.go
src/syscall/zsysnum_linux_power64.go
src/syscall/zsysnum_linux_power64le.go
src/syscall/ztypes_linux_power64.go
src/syscall/ztypes_linux_power64le.go

diff --cc .hgignore
Simple merge
diff --cc src/cmd/9a/a.y
index 2e0317e061c61a8737de7cbcc0179ff0b9f6c47c,0000000000000000000000000000000000000000..41776fd3c3656d93b549f056eb6a389a2decea0f
mode 100644,000000..100644
--- /dev/null
@@@ -1,997 -1,0 +1,997 @@@
- #include "../../pkg/runtime/funcdata.h"
 +// cmd/9a/a.y from Vita Nuova.
 +//
 +//    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-2008 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-2008 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 <u.h>
 +#include <stdio.h>    /* if we don't, bison will, and a.h re-#defines getc */
 +#include <libc.h>
 +#include "a.h"
++#include "../../runtime/funcdata.h"
 +%}
 +%union
 +{
 +      Sym     *sym;
 +      vlong   lval;
 +      double  dval;
 +      char    sval[8];
 +      Addr    addr;
 +}
 +%left '|'
 +%left '^'
 +%left '&'
 +%left '<' '>'
 +%left '+' '-'
 +%left '*' '/' '%'
 +%token        <lval>  LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
 +%token        <lval>  LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
 +%token        <lval>  LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
 +%token        <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
 +%token        <lval>  LREG LFREG LR LCR LF LFPSCR
 +%token        <lval>  LLR LCTR LSPR LSPREG LSEG LMSR
 +%token        <lval>  LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
 +%token        <lval>  LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
 +%token        <dval>  LFCONST
 +%token        <sval>  LSCONST
 +%token        <sym>   LNAME LLAB LVAR
 +%type <lval>  con expr pointer offset sreg
 +%type <addr>  addr rreg regaddr name creg freg xlreg lr ctr
 +%type <addr>  imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
 +%%
 +prog:
 +|     prog line
 +
 +line:
 +      LLAB ':'
 +      {
 +              if($1->value != pc)
 +                      yyerror("redeclaration of %s", $1->name);
 +              $1->value = pc;
 +      }
 +      line
 +|     LNAME ':'
 +      {
 +              $1->type = LLAB;
 +              $1->value = pc;
 +      }
 +      line
 +|     LNAME '=' expr ';'
 +      {
 +              $1->type = LVAR;
 +              $1->value = $3;
 +      }
 +|     LVAR '=' expr ';'
 +      {
 +              if($1->value != $3)
 +                      yyerror("redeclaration of %s", $1->name);
 +              $1->value = $3;
 +      }
 +|     LSCHED ';'
 +      {
 +              nosched = $1;
 +      }
 +|     ';'
 +|     inst ';'
 +|     error ';'
 +
 +inst:
 +/*
 + * load ints and bytes
 + */
 +      LMOVW rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW addr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW regaddr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVB rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVB addr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVB regaddr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * load floats
 + */
 +|     LFMOV addr ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFMOV regaddr ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFMOV fimm ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFMOV freg ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFMOV freg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFMOV freg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * store ints and bytes
 + */
 +|     LMOVW rreg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW rreg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVB rreg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVB rreg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * store floats
 + */
 +|     LMOVW freg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW freg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * floating point status
 + */
 +|     LMOVW fpscr ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW freg ','  fpscr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW freg ',' imm ',' fpscr
 +      {
 +              outgcode($1, &$2, NREG, &$4, &$6);
 +      }
 +|     LMOVW fpscr ',' creg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW imm ',' fpscrf
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMTFSB imm ',' con
 +      {
 +              outcode($1, &$2, $4, &nullgen);
 +      }
 +/*
 + * field moves (mtcrf)
 + */
 +|     LMOVW rreg ',' imm ',' lcr
 +      {
 +              outgcode($1, &$2, NREG, &$4, &$6);
 +      }
 +|     LMOVW rreg ',' creg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW rreg ',' lcr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * integer operations
 + * logical instructions
 + * shift instructions
 + * unary instructions
 + */
 +|     LADDW rreg ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LADDW imm ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LADDW rreg ',' imm ',' rreg
 +      {
 +              outgcode($1, &$2, NREG, &$4, &$6);
 +      }
 +|     LADDW rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LADDW imm ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LLOGW rreg ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LLOGW rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LSHW rreg ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LSHW rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LSHW imm ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LSHW imm ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LABS rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LABS rreg
 +      {
 +              outcode($1, &$2, NREG, &$2);
 +      }
 +/*
 + * multiply-accumulate
 + */
 +|     LMA rreg ',' sreg ',' rreg
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +/*
 + * move immediate: macro for cau+or, addi, addis, and other combinations
 + */
 +|     LMOVW imm ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW ximm ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * condition register operations
 + */
 +|     LCROP cbit ',' cbit
 +      {
 +              outcode($1, &$2, $4.reg, &$4);
 +      }
 +|     LCROP cbit ',' con ',' cbit
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +/*
 + * condition register moves
 + * move from machine state register
 + */
 +|     LMOVW creg ',' creg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW psr ',' creg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW lcr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW psr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW xlreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW rreg ',' xlreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW creg ',' psr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVW rreg ',' psr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * branch, branch conditional
 + * branch conditional register
 + * branch conditional to count register
 + */
 +|     LBRA rel
 +      {
 +              outcode($1, &nullgen, NREG, &$2);
 +      }
 +|     LBRA addr
 +      {
 +              outcode($1, &nullgen, NREG, &$2);
 +      }
 +|     LBRA '(' xlreg ')'
 +      {
 +              outcode($1, &nullgen, NREG, &$3);
 +      }
 +|     LBRA ',' rel
 +      {
 +              outcode($1, &nullgen, NREG, &$3);
 +      }
 +|     LBRA ',' addr
 +      {
 +              outcode($1, &nullgen, NREG, &$3);
 +      }
 +|     LBRA ',' '(' xlreg ')'
 +      {
 +              outcode($1, &nullgen, NREG, &$4);
 +      }
 +|     LBRA creg ',' rel
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LBRA creg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LBRA creg ',' '(' xlreg ')'
 +      {
 +              outcode($1, &$2, NREG, &$5);
 +      }
 +|     LBRA con ',' rel
 +      {
 +              outcode($1, &nullgen, $2, &$4);
 +      }
 +|     LBRA con ',' addr
 +      {
 +              outcode($1, &nullgen, $2, &$4);
 +      }
 +|     LBRA con ',' '(' xlreg ')'
 +      {
 +              outcode($1, &nullgen, $2, &$5);
 +      }
 +|     LBRA con ',' con ',' rel
 +      {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = $2;
 +              outcode($1, &g, $4, &$6);
 +      }
 +|     LBRA con ',' con ',' addr
 +      {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = $2;
 +              outcode($1, &g, $4, &$6);
 +      }
 +|     LBRA con ',' con ',' '(' xlreg ')'
 +      {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = $2;
 +              outcode($1, &g, $4, &$7);
 +      }
 +/*
 + * conditional trap
 + */
 +|     LTRAP rreg ',' sreg
 +      {
 +              outcode($1, &$2, $4, &nullgen);
 +      }
 +|     LTRAP imm ',' sreg
 +      {
 +              outcode($1, &$2, $4, &nullgen);
 +      }
 +|     LTRAP rreg comma
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +|     LTRAP comma
 +      {
 +              outcode($1, &nullgen, NREG, &nullgen);
 +      }
 +/*
 + * floating point operate
 + */
 +|     LFCONV freg ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFADD freg ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFADD freg ',' freg ',' freg
 +      {
 +              outcode($1, &$2, $4.reg, &$6);
 +      }
 +|     LFMA freg ',' freg ',' freg ',' freg
 +      {
 +              outgcode($1, &$2, $4.reg, &$6, &$8);
 +      }
 +|     LFCMP freg ',' freg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LFCMP freg ',' freg ',' creg
 +      {
 +              outcode($1, &$2, $6.reg, &$4);
 +      }
 +/*
 + * CMP
 + */
 +|     LCMP rreg ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LCMP rreg ',' imm
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LCMP rreg ',' rreg ',' creg
 +      {
 +              outcode($1, &$2, $6.reg, &$4);
 +      }
 +|     LCMP rreg ',' imm ',' creg
 +      {
 +              outcode($1, &$2, $6.reg, &$4);
 +      }
 +/*
 + * rotate and mask
 + */
 +|     LRLWM  imm ',' rreg ',' imm ',' rreg
 +      {
 +              outgcode($1, &$2, $4.reg, &$6, &$8);
 +      }
 +|     LRLWM  imm ',' rreg ',' mask ',' rreg
 +      {
 +              outgcode($1, &$2, $4.reg, &$6, &$8);
 +      }
 +|     LRLWM  rreg ',' rreg ',' imm ',' rreg
 +      {
 +              outgcode($1, &$2, $4.reg, &$6, &$8);
 +      }
 +|     LRLWM  rreg ',' rreg ',' mask ',' rreg
 +      {
 +              outgcode($1, &$2, $4.reg, &$6, &$8);
 +      }
 +/*
 + * load/store multiple
 + */
 +|     LMOVMW addr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LMOVMW rreg ',' addr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * various indexed load/store
 + * indexed unary (eg, cache clear)
 + */
 +|     LXLD regaddr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LXLD regaddr ',' imm ',' rreg
 +      {
 +              outgcode($1, &$2, NREG, &$4, &$6);
 +      }
 +|     LXST rreg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LXST rreg ',' imm ',' regaddr
 +      {
 +              outgcode($1, &$2, NREG, &$4, &$6);
 +      }
 +|     LXMV regaddr ',' rreg
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LXMV rreg ',' regaddr
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LXOP regaddr
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +/*
 + * NOP
 + */
 +|     LNOP comma
 +      {
 +              outcode($1, &nullgen, NREG, &nullgen);
 +      }
 +|     LNOP rreg comma
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +|     LNOP freg comma
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +|     LNOP ',' rreg
 +      {
 +              outcode($1, &nullgen, NREG, &$3);
 +      }
 +|     LNOP ',' freg
 +      {
 +              outcode($1, &nullgen, NREG, &$3);
 +      }
 +|     LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +/*
 + * word
 + */
 +|     LWORD imm comma
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +|     LWORD ximm comma
 +      {
 +              outcode($1, &$2, NREG, &nullgen);
 +      }
 +/*
 + * PCDATA
 + */
 +|     LPCDAT imm ',' imm
 +      {
 +              if($2.type != D_CONST || $4.type != D_CONST)
 +                      yyerror("arguments to PCDATA must be integer constants");
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * FUNCDATA
 + */
 +|     LFUNCDAT imm ',' addr
 +      {
 +              if($2.type != D_CONST)
 +                      yyerror("index for FUNCDATA must be integer constant");
 +              if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
 +                      yyerror("value for FUNCDATA must be symbol reference");
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +/*
 + * END
 + */
 +|     LEND comma
 +      {
 +              outcode($1, &nullgen, NREG, &nullgen);
 +      }
 +/*
 + * TEXT/GLOBL
 + */
 +|     LTEXT name ',' imm
 +      {
 +              outcode($1, &$2, NREG, &$4);
 +      }
 +|     LTEXT name ',' con ',' imm
 +      {
 +              $6.offset &= 0xffffffffull;
 +              $6.offset |= (vlong)ArgsSizeUnknown << 32;
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LTEXT name ',' con ',' imm '-' con
 +      {
 +              $6.offset &= 0xffffffffull;
 +              $6.offset |= ($8 & 0xffffffffull) << 32;
 +              outcode($1, &$2, $4, &$6);
 +      }
 +/*
 + * DATA
 + */
 +|     LDATA name '/' con ',' imm
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LDATA name '/' con ',' ximm
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +|     LDATA name '/' con ',' fimm
 +      {
 +              outcode($1, &$2, $4, &$6);
 +      }
 +/*
 + * RETURN
 + */
 +|     LRETRN  comma
 +      {
 +              outcode($1, &nullgen, NREG, &nullgen);
 +      }
 +
 +rel:
 +      con '(' LPC ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_BRANCH;
 +              $$.offset = $1 + pc;
 +      }
 +|     LNAME offset
 +      {
 +              $$ = nullgen;
 +              if(pass == 2)
 +                      yyerror("undefined label: %s", $1->name);
 +              $$.type = D_BRANCH;
 +              $$.offset = $2;
 +      }
 +|     LLAB offset
 +      {
 +              $$ = nullgen;
 +              $$.type = D_BRANCH;
 +              $$.offset = $1->value + $2;
 +      }
 +
 +rreg:
 +      sreg
 +      {
 +              $$ = nullgen;
 +              $$.type = D_REG;
 +              $$.reg = $1;
 +      }
 +
 +xlreg:
 +      lr
 +|     ctr
 +
 +lr:
 +      LLR
 +      {
 +              $$ = nullgen;
 +              $$.type = D_SPR;
 +              $$.offset = $1;
 +      }
 +
 +lcr:
 +      LCR
 +      {
 +              $$ = nullgen;
 +              $$.type = D_CREG;
 +              $$.reg = NREG;  /* whole register */
 +      }
 +
 +ctr:
 +      LCTR
 +      {
 +              $$ = nullgen;
 +              $$.type = D_SPR;
 +              $$.offset = $1;
 +      }
 +
 +msr:
 +      LMSR
 +      {
 +              $$ = nullgen;
 +              $$.type = D_MSR;
 +      }
 +
 +psr:
 +      LSPREG
 +      {
 +              $$ = nullgen;
 +              $$.type = D_SPR;
 +              $$.offset = $1;
 +      }
 +|     LSPR '(' con ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = $1;
 +              $$.offset = $3;
 +      }
 +|     msr
 +
 +fpscr:
 +      LFPSCR
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FPSCR;
 +              $$.reg = NREG;
 +      }
 +
 +fpscrf:
 +      LFPSCR '(' con ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FPSCR;
 +              $$.reg = $3;
 +      }
 +
 +freg:
 +      LFREG
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FREG;
 +              $$.reg = $1;
 +      }
 +|     LF '(' con ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FREG;
 +              $$.reg = $3;
 +      }
 +
 +creg:
 +      LCREG
 +      {
 +              $$ = nullgen;
 +              $$.type = D_CREG;
 +              $$.reg = $1;
 +      }
 +|     LCR '(' con ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_CREG;
 +              $$.reg = $3;
 +      }
 +
 +
 +cbit: con
 +      {
 +              $$ = nullgen;
 +              $$.type = D_REG;
 +              $$.reg = $1;
 +      }
 +
 +mask:
 +      con ',' con
 +      {
 +              int mb, me;
 +              uint32 v;
 +
 +              $$ = nullgen;
 +              $$.type = D_CONST;
 +              mb = $1;
 +              me = $3;
 +              if(mb < 0 || mb > 31 || me < 0 || me > 31){
 +                      yyerror("illegal mask start/end value(s)");
 +                      mb = me = 0;
 +              }
 +              if(mb <= me)
 +                      v = ((uint32)~0L>>mb) & (~0L<<(31-me));
 +              else
 +                      v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
 +              $$.offset = v;
 +      }
 +
 +ximm:
 +      '$' addr
 +      {
 +              $$ = $2;
 +              $$.type = D_CONST;
 +      }
 +|     '$' LSCONST
 +      {
 +              $$ = nullgen;
 +              $$.type = D_SCONST;
 +              memcpy($$.u.sval, $2, sizeof($$.u.sval));
 +      }
 +
 +fimm:
 +      '$' LFCONST
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FCONST;
 +              $$.u.dval = $2;
 +      }
 +|     '$' '-' LFCONST
 +      {
 +              $$ = nullgen;
 +              $$.type = D_FCONST;
 +              $$.u.dval = -$3;
 +      }
 +
 +imm:  '$' con
 +      {
 +              $$ = nullgen;
 +              $$.type = D_CONST;
 +              $$.offset = $2;
 +      }
 +
 +sreg:
 +      LREG
 +|     LR '(' con ')'
 +      {
 +              if($$ < 0 || $$ >= NREG)
 +                      print("register value out of range\n");
 +              $$ = $3;
 +      }
 +
 +regaddr:
 +      '(' sreg ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.reg = $2;
 +              $$.offset = 0;
 +      }
 +|     '(' sreg '+' sreg ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.reg = $2;
 +              $$.scale = $4;
 +              $$.offset = 0;
 +      }
 +
 +addr:
 +      name
 +|     con '(' sreg ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.reg = $3;
 +              $$.offset = $1;
 +      }
 +
 +name:
 +      con '(' pointer ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.name = $3;
 +              $$.sym = nil;
 +              $$.offset = $1;
 +      }
 +|     LNAME offset '(' pointer ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.name = $4;
 +              $$.sym = linklookup(ctxt, $1->name, 0);
 +              $$.offset = $2;
 +      }
 +|     LNAME '<' '>' offset '(' LSB ')'
 +      {
 +              $$ = nullgen;
 +              $$.type = D_OREG;
 +              $$.name = D_STATIC;
 +              $$.sym = linklookup(ctxt, $1->name, 0);
 +              $$.offset = $4;
 +      }
 +
 +comma:
 +|     ','
 +
 +offset:
 +      {
 +              $$ = 0;
 +      }
 +|     '+' con
 +      {
 +              $$ = $2;
 +      }
 +|     '-' con
 +      {
 +              $$ = -$2;
 +      }
 +
 +pointer:
 +      LSB
 +|     LSP
 +|     LFP
 +
 +con:
 +      LCONST
 +|     LVAR
 +      {
 +              $$ = $1->value;
 +      }
 +|     '-' con
 +      {
 +              $$ = -$2;
 +      }
 +|     '+' con
 +      {
 +              $$ = $2;
 +      }
 +|     '~' con
 +      {
 +              $$ = ~$2;
 +      }
 +|     '(' expr ')'
 +      {
 +              $$ = $2;
 +      }
 +
 +expr:
 +      con
 +|     expr '+' expr
 +      {
 +              $$ = $1 + $3;
 +      }
 +|     expr '-' expr
 +      {
 +              $$ = $1 - $3;
 +      }
 +|     expr '*' expr
 +      {
 +              $$ = $1 * $3;
 +      }
 +|     expr '/' expr
 +      {
 +              $$ = $1 / $3;
 +      }
 +|     expr '%' expr
 +      {
 +              $$ = $1 % $3;
 +      }
 +|     expr '<' '<' expr
 +      {
 +              $$ = $1 << $4;
 +      }
 +|     expr '>' '>' expr
 +      {
 +              $$ = $1 >> $4;
 +      }
 +|     expr '&' expr
 +      {
 +              $$ = $1 & $3;
 +      }
 +|     expr '^' expr
 +      {
 +              $$ = $1 ^ $3;
 +      }
 +|     expr '|' expr
 +      {
 +              $$ = $1 | $3;
 +      }
index 9a09cf932fa77daabe52c5f9039898bb24914959,0000000000000000000000000000000000000000..e81db9924c4e0a68e8a96629d4032e1df0e90f0e
mode 100644,000000..100644
--- /dev/null
@@@ -1,3794 -1,0 +1,3794 @@@
- #include "../../pkg/runtime/funcdata.h"
 +/* A Bison parser, made by GNU Bison 2.5.  */
 +
 +/* Bison implementation for Yacc-like parsers in C
 +   
 +      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
 +   
 +   This program is free software: you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by
 +   the Free Software Foundation, either version 3 of the License, or
 +   (at your option) any later version.
 +   
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +   
 +   You should have received a copy of the GNU General Public License
 +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 +
 +/* As a special exception, you may create a larger work that contains
 +   part or all of the Bison parser skeleton and distribute that work
 +   under terms of your choice, so long as that work isn't itself a
 +   parser generator using the skeleton or a modified version thereof
 +   as a parser skeleton.  Alternatively, if you modify or redistribute
 +   the parser skeleton itself, you may (at your option) remove this
 +   special exception, which will cause the skeleton and the resulting
 +   Bison output files to be licensed under the GNU General Public
 +   License without this special exception.
 +   
 +   This special exception was added by the Free Software Foundation in
 +   version 2.2 of Bison.  */
 +
 +/* C LALR(1) parser skeleton written by Richard Stallman, by
 +   simplifying the original so-called "semantic" parser.  */
 +
 +/* All symbols defined below should begin with yy or YY, to avoid
 +   infringing on user name space.  This should be done even for local
 +   variables, as they might otherwise be expanded by user macros.
 +   There are some unavoidable exceptions within include files to
 +   define necessary library symbols; they are noted "INFRINGES ON
 +   USER NAME SPACE" below.  */
 +
 +/* Identify Bison output.  */
 +#define YYBISON 1
 +
 +/* Bison version.  */
 +#define YYBISON_VERSION "2.5"
 +
 +/* Skeleton name.  */
 +#define YYSKELETON_NAME "yacc.c"
 +
 +/* Pure parsers.  */
 +#define YYPURE 0
 +
 +/* Push parsers.  */
 +#define YYPUSH 0
 +
 +/* Pull parsers.  */
 +#define YYPULL 1
 +
 +/* Using locations.  */
 +#define YYLSP_NEEDED 0
 +
 +
 +
 +/* Copy the first part of user declarations.  */
 +
 +/* Line 268 of yacc.c  */
 +#line 30 "a.y"
 +
 +#include <u.h>
 +#include <stdio.h>    /* if we don't, bison will, and a.h re-#defines getc */
 +#include <libc.h>
 +#include "a.h"
++#include "../../runtime/funcdata.h"
 +
 +
 +/* Line 268 of yacc.c  */
 +#line 80 "y.tab.c"
 +
 +/* Enabling traces.  */
 +#ifndef YYDEBUG
 +# define YYDEBUG 0
 +#endif
 +
 +/* Enabling verbose error messages.  */
 +#ifdef YYERROR_VERBOSE
 +# undef YYERROR_VERBOSE
 +# define YYERROR_VERBOSE 1
 +#else
 +# define YYERROR_VERBOSE 0
 +#endif
 +
 +/* Enabling the token table.  */
 +#ifndef YYTOKEN_TABLE
 +# define YYTOKEN_TABLE 0
 +#endif
 +
 +
 +/* Tokens.  */
 +#ifndef YYTOKENTYPE
 +# define YYTOKENTYPE
 +   /* Put the tokens into the symbol table, so that GDB and other debuggers
 +      know about them.  */
 +   enum yytokentype {
 +     LMOVW = 258,
 +     LMOVB = 259,
 +     LABS = 260,
 +     LLOGW = 261,
 +     LSHW = 262,
 +     LADDW = 263,
 +     LCMP = 264,
 +     LCROP = 265,
 +     LBRA = 266,
 +     LFMOV = 267,
 +     LFCONV = 268,
 +     LFCMP = 269,
 +     LFADD = 270,
 +     LFMA = 271,
 +     LTRAP = 272,
 +     LXORW = 273,
 +     LNOP = 274,
 +     LEND = 275,
 +     LRETT = 276,
 +     LWORD = 277,
 +     LTEXT = 278,
 +     LDATA = 279,
 +     LRETRN = 280,
 +     LCONST = 281,
 +     LSP = 282,
 +     LSB = 283,
 +     LFP = 284,
 +     LPC = 285,
 +     LCREG = 286,
 +     LFLUSH = 287,
 +     LREG = 288,
 +     LFREG = 289,
 +     LR = 290,
 +     LCR = 291,
 +     LF = 292,
 +     LFPSCR = 293,
 +     LLR = 294,
 +     LCTR = 295,
 +     LSPR = 296,
 +     LSPREG = 297,
 +     LSEG = 298,
 +     LMSR = 299,
 +     LPCDAT = 300,
 +     LFUNCDAT = 301,
 +     LSCHED = 302,
 +     LXLD = 303,
 +     LXST = 304,
 +     LXOP = 305,
 +     LXMV = 306,
 +     LRLWM = 307,
 +     LMOVMW = 308,
 +     LMOVEM = 309,
 +     LMOVFL = 310,
 +     LMTFSB = 311,
 +     LMA = 312,
 +     LFCONST = 313,
 +     LSCONST = 314,
 +     LNAME = 315,
 +     LLAB = 316,
 +     LVAR = 317
 +   };
 +#endif
 +/* Tokens.  */
 +#define LMOVW 258
 +#define LMOVB 259
 +#define LABS 260
 +#define LLOGW 261
 +#define LSHW 262
 +#define LADDW 263
 +#define LCMP 264
 +#define LCROP 265
 +#define LBRA 266
 +#define LFMOV 267
 +#define LFCONV 268
 +#define LFCMP 269
 +#define LFADD 270
 +#define LFMA 271
 +#define LTRAP 272
 +#define LXORW 273
 +#define LNOP 274
 +#define LEND 275
 +#define LRETT 276
 +#define LWORD 277
 +#define LTEXT 278
 +#define LDATA 279
 +#define LRETRN 280
 +#define LCONST 281
 +#define LSP 282
 +#define LSB 283
 +#define LFP 284
 +#define LPC 285
 +#define LCREG 286
 +#define LFLUSH 287
 +#define LREG 288
 +#define LFREG 289
 +#define LR 290
 +#define LCR 291
 +#define LF 292
 +#define LFPSCR 293
 +#define LLR 294
 +#define LCTR 295
 +#define LSPR 296
 +#define LSPREG 297
 +#define LSEG 298
 +#define LMSR 299
 +#define LPCDAT 300
 +#define LFUNCDAT 301
 +#define LSCHED 302
 +#define LXLD 303
 +#define LXST 304
 +#define LXOP 305
 +#define LXMV 306
 +#define LRLWM 307
 +#define LMOVMW 308
 +#define LMOVEM 309
 +#define LMOVFL 310
 +#define LMTFSB 311
 +#define LMA 312
 +#define LFCONST 313
 +#define LSCONST 314
 +#define LNAME 315
 +#define LLAB 316
 +#define LVAR 317
 +
 +
 +
 +
 +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 +typedef union YYSTYPE
 +{
 +
 +/* Line 293 of yacc.c  */
 +#line 38 "a.y"
 +
 +      Sym     *sym;
 +      vlong   lval;
 +      double  dval;
 +      char    sval[8];
 +      Addr    addr;
 +
 +
 +
 +/* Line 293 of yacc.c  */
 +#line 250 "y.tab.c"
 +} YYSTYPE;
 +# define YYSTYPE_IS_TRIVIAL 1
 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 +# define YYSTYPE_IS_DECLARED 1
 +#endif
 +
 +
 +/* Copy the second part of user declarations.  */
 +
 +
 +/* Line 343 of yacc.c  */
 +#line 262 "y.tab.c"
 +
 +#ifdef short
 +# undef short
 +#endif
 +
 +#ifdef YYTYPE_UINT8
 +typedef YYTYPE_UINT8 yytype_uint8;
 +#else
 +typedef unsigned char yytype_uint8;
 +#endif
 +
 +#ifdef YYTYPE_INT8
 +typedef YYTYPE_INT8 yytype_int8;
 +#elif (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +typedef signed char yytype_int8;
 +#else
 +typedef short int yytype_int8;
 +#endif
 +
 +#ifdef YYTYPE_UINT16
 +typedef YYTYPE_UINT16 yytype_uint16;
 +#else
 +typedef unsigned short int yytype_uint16;
 +#endif
 +
 +#ifdef YYTYPE_INT16
 +typedef YYTYPE_INT16 yytype_int16;
 +#else
 +typedef short int yytype_int16;
 +#endif
 +
 +#ifndef YYSIZE_T
 +# ifdef __SIZE_TYPE__
 +#  define YYSIZE_T __SIZE_TYPE__
 +# elif defined size_t
 +#  define YYSIZE_T size_t
 +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 +#  define YYSIZE_T size_t
 +# else
 +#  define YYSIZE_T unsigned int
 +# endif
 +#endif
 +
 +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 +
 +#ifndef YY_
 +# if defined YYENABLE_NLS && YYENABLE_NLS
 +#  if ENABLE_NLS
 +#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 +#   define YY_(msgid) dgettext ("bison-runtime", msgid)
 +#  endif
 +# endif
 +# ifndef YY_
 +#  define YY_(msgid) msgid
 +# endif
 +#endif
 +
 +/* Suppress unused-variable warnings by "using" E.  */
 +#if ! defined lint || defined __GNUC__
 +# define YYUSE(e) ((void) (e))
 +#else
 +# define YYUSE(e) /* empty */
 +#endif
 +
 +/* Identity function, used to suppress warnings about constant conditions.  */
 +#ifndef lint
 +# define YYID(n) (n)
 +#else
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static int
 +YYID (int yyi)
 +#else
 +static int
 +YYID (yyi)
 +    int yyi;
 +#endif
 +{
 +  return yyi;
 +}
 +#endif
 +
 +#if ! defined yyoverflow || YYERROR_VERBOSE
 +
 +/* The parser invokes alloca or malloc; define the necessary symbols.  */
 +
 +# ifdef YYSTACK_USE_ALLOCA
 +#  if YYSTACK_USE_ALLOCA
 +#   ifdef __GNUC__
 +#    define YYSTACK_ALLOC __builtin_alloca
 +#   elif defined __BUILTIN_VA_ARG_INCR
 +#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
 +#   elif defined _AIX
 +#    define YYSTACK_ALLOC __alloca
 +#   elif defined _MSC_VER
 +#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
 +#    define alloca _alloca
 +#   else
 +#    define YYSTACK_ALLOC alloca
 +#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
 +#     ifndef EXIT_SUCCESS
 +#      define EXIT_SUCCESS 0
 +#     endif
 +#    endif
 +#   endif
 +#  endif
 +# endif
 +
 +# ifdef YYSTACK_ALLOC
 +   /* Pacify GCC's `empty if-body' warning.  */
 +#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
 +#  ifndef YYSTACK_ALLOC_MAXIMUM
 +    /* The OS might guarantee only one guard page at the bottom of the stack,
 +       and a page size can be as small as 4096 bytes.  So we cannot safely
 +       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
 +       to allow for a few compiler-allocated temporary stack slots.  */
 +#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
 +#  endif
 +# else
 +#  define YYSTACK_ALLOC YYMALLOC
 +#  define YYSTACK_FREE YYFREE
 +#  ifndef YYSTACK_ALLOC_MAXIMUM
 +#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 +#  endif
 +#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
 +       && ! ((defined YYMALLOC || defined malloc) \
 +           && (defined YYFREE || defined free)))
 +#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
 +#   ifndef EXIT_SUCCESS
 +#    define EXIT_SUCCESS 0
 +#   endif
 +#  endif
 +#  ifndef YYMALLOC
 +#   define YYMALLOC malloc
 +#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 +#   endif
 +#  endif
 +#  ifndef YYFREE
 +#   define YYFREE free
 +#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +void free (void *); /* INFRINGES ON USER NAME SPACE */
 +#   endif
 +#  endif
 +# endif
 +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
 +
 +
 +#if (! defined yyoverflow \
 +     && (! defined __cplusplus \
 +       || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 +
 +/* A type that is properly aligned for any stack member.  */
 +union yyalloc
 +{
 +  yytype_int16 yyss_alloc;
 +  YYSTYPE yyvs_alloc;
 +};
 +
 +/* The size of the maximum gap between one aligned stack and the next.  */
 +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
 +
 +/* The size of an array large to enough to hold all stacks, each with
 +   N elements.  */
 +# define YYSTACK_BYTES(N) \
 +     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
 +      + YYSTACK_GAP_MAXIMUM)
 +
 +# define YYCOPY_NEEDED 1
 +
 +/* Relocate STACK from its old location to the new one.  The
 +   local variables YYSIZE and YYSTACKSIZE give the old and new number of
 +   elements in the stack, and YYPTR gives the new location of the
 +   stack.  Advance YYPTR to a properly aligned location for the next
 +   stack.  */
 +# define YYSTACK_RELOCATE(Stack_alloc, Stack)                         \
 +    do                                                                        \
 +      {                                                                       \
 +      YYSIZE_T yynewbytes;                                            \
 +      YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
 +      Stack = &yyptr->Stack_alloc;                                    \
 +      yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
 +      yyptr += yynewbytes / sizeof (*yyptr);                          \
 +      }                                                                       \
 +    while (YYID (0))
 +
 +#endif
 +
 +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
 +/* Copy COUNT objects from FROM to TO.  The source and destination do
 +   not overlap.  */
 +# ifndef YYCOPY
 +#  if defined __GNUC__ && 1 < __GNUC__
 +#   define YYCOPY(To, From, Count) \
 +      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
 +#  else
 +#   define YYCOPY(To, From, Count)            \
 +      do                                      \
 +      {                                       \
 +        YYSIZE_T yyi;                         \
 +        for (yyi = 0; yyi < (Count); yyi++)   \
 +          (To)[yyi] = (From)[yyi];            \
 +      }                                       \
 +      while (YYID (0))
 +#  endif
 +# endif
 +#endif /* !YYCOPY_NEEDED */
 +
 +/* YYFINAL -- State number of the termination state.  */
 +#define YYFINAL  2
 +/* YYLAST -- Last index in YYTABLE.  */
 +#define YYLAST   836
 +
 +/* YYNTOKENS -- Number of terminals.  */
 +#define YYNTOKENS  81
 +/* YYNNTS -- Number of nonterminals.  */
 +#define YYNNTS  32
 +/* YYNRULES -- Number of rules.  */
 +#define YYNRULES  186
 +/* YYNRULES -- Number of states.  */
 +#define YYNSTATES  459
 +
 +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 +#define YYUNDEFTOK  2
 +#define YYMAXUTOK   317
 +
 +#define YYTRANSLATE(YYX)                                              \
 +  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 +
 +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
 +static const yytype_uint8 yytranslate[] =
 +{
 +       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,    79,    12,     5,     2,
 +      77,    78,    10,     8,    76,     9,     2,    11,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,    73,    75,
 +       6,    74,     7,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     3,     2,    80,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
 +       2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
 +      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
 +      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
 +      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
 +      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
 +      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
 +      65,    66,    67,    68,    69,    70,    71,    72
 +};
 +
 +#if YYDEBUG
 +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 +   YYRHS.  */
 +static const yytype_uint16 yyprhs[] =
 +{
 +       0,     0,     3,     4,     7,     8,    13,    14,    19,    24,
 +      29,    32,    34,    37,    40,    45,    50,    55,    60,    65,
 +      70,    75,    80,    85,    90,    95,   100,   105,   110,   115,
 +     120,   125,   130,   135,   140,   147,   152,   157,   162,   169,
 +     174,   179,   186,   193,   200,   205,   210,   217,   222,   229,
 +     234,   241,   246,   251,   254,   261,   266,   271,   276,   283,
 +     288,   293,   298,   303,   308,   313,   318,   323,   326,   329,
 +     334,   338,   342,   348,   353,   358,   365,   370,   375,   382,
 +     389,   396,   405,   410,   415,   419,   422,   427,   432,   439,
 +     448,   453,   460,   465,   470,   477,   484,   493,   502,   511,
 +     520,   525,   530,   535,   542,   547,   554,   559,   564,   567,
 +     570,   574,   578,   582,   586,   589,   593,   597,   602,   607,
 +     610,   615,   622,   631,   638,   645,   652,   655,   660,   663,
 +     666,   668,   670,   672,   674,   676,   678,   680,   682,   687,
 +     689,   691,   696,   698,   703,   705,   710,   712,   716,   719,
 +     722,   725,   729,   732,   734,   739,   743,   749,   751,   756,
 +     761,   767,   775,   776,   778,   779,   782,   785,   787,   789,
 +     791,   793,   795,   798,   801,   804,   808,   810,   814,   818,
 +     822,   826,   830,   835,   840,   844,   848
 +};
 +
 +/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 +static const yytype_int8 yyrhs[] =
 +{
 +      82,     0,    -1,    -1,    82,    83,    -1,    -1,    71,    73,
 +      84,    83,    -1,    -1,    70,    73,    85,    83,    -1,    70,
 +      74,   112,    75,    -1,    72,    74,   112,    75,    -1,    57,
 +      75,    -1,    75,    -1,    86,    75,    -1,     1,    75,    -1,
 +      13,    88,    76,    88,    -1,    13,   106,    76,    88,    -1,
 +      13,   105,    76,    88,    -1,    14,    88,    76,    88,    -1,
 +      14,   106,    76,    88,    -1,    14,   105,    76,    88,    -1,
 +      22,   106,    76,    97,    -1,    22,   105,    76,    97,    -1,
 +      22,   102,    76,    97,    -1,    22,    97,    76,    97,    -1,
 +      22,    97,    76,   106,    -1,    22,    97,    76,   105,    -1,
 +      13,    88,    76,   106,    -1,    13,    88,    76,   105,    -1,
 +      14,    88,    76,   106,    -1,    14,    88,    76,   105,    -1,
 +      13,    97,    76,   106,    -1,    13,    97,    76,   105,    -1,
 +      13,    95,    76,    97,    -1,    13,    97,    76,    95,    -1,
 +      13,    97,    76,   103,    76,    95,    -1,    13,    95,    76,
 +      98,    -1,    13,   103,    76,    96,    -1,    66,   103,    76,
 +     111,    -1,    13,    88,    76,   103,    76,    91,    -1,    13,
 +      88,    76,    98,    -1,    13,    88,    76,    91,    -1,    18,
 +      88,    76,   104,    76,    88,    -1,    18,   103,    76,   104,
 +      76,    88,    -1,    18,    88,    76,   103,    76,    88,    -1,
 +      18,    88,    76,    88,    -1,    18,   103,    76,    88,    -1,
 +      16,    88,    76,   104,    76,    88,    -1,    16,    88,    76,
 +      88,    -1,    17,    88,    76,   104,    76,    88,    -1,    17,
 +      88,    76,    88,    -1,    17,   103,    76,   104,    76,    88,
 +      -1,    17,   103,    76,    88,    -1,    15,    88,    76,    88,
 +      -1,    15,    88,    -1,    67,    88,    76,   104,    76,    88,
 +      -1,    13,   103,    76,    88,    -1,    13,   101,    76,    88,
 +      -1,    20,    99,    76,    99,    -1,    20,    99,    76,   111,
 +      76,    99,    -1,    13,    98,    76,    98,    -1,    13,    94,
 +      76,    98,    -1,    13,    91,    76,    88,    -1,    13,    94,
 +      76,    88,    -1,    13,    89,    76,    88,    -1,    13,    88,
 +      76,    89,    -1,    13,    98,    76,    94,    -1,    13,    88,
 +      76,    94,    -1,    21,    87,    -1,    21,   106,    -1,    21,
 +      77,    89,    78,    -1,    21,    76,    87,    -1,    21,    76,
 +     106,    -1,    21,    76,    77,    89,    78,    -1,    21,    98,
 +      76,    87,    -1,    21,    98,    76,   106,    -1,    21,    98,
 +      76,    77,    89,    78,    -1,    21,   111,    76,    87,    -1,
 +      21,   111,    76,   106,    -1,    21,   111,    76,    77,    89,
 +      78,    -1,    21,   111,    76,   111,    76,    87,    -1,    21,
 +     111,    76,   111,    76,   106,    -1,    21,   111,    76,   111,
 +      76,    77,    89,    78,    -1,    27,    88,    76,   104,    -1,
 +      27,   103,    76,   104,    -1,    27,    88,   108,    -1,    27,
 +     108,    -1,    23,    97,    76,    97,    -1,    25,    97,    76,
 +      97,    -1,    25,    97,    76,    97,    76,    97,    -1,    26,
 +      97,    76,    97,    76,    97,    76,    97,    -1,    24,    97,
 +      76,    97,    -1,    24,    97,    76,    97,    76,    98,    -1,
 +      19,    88,    76,    88,    -1,    19,    88,    76,   103,    -1,
 +      19,    88,    76,    88,    76,    98,    -1,    19,    88,    76,
 +     103,    76,    98,    -1,    62,   103,    76,    88,    76,   103,
 +      76,    88,    -1,    62,   103,    76,    88,    76,   100,    76,
 +      88,    -1,    62,    88,    76,    88,    76,   103,    76,    88,
 +      -1,    62,    88,    76,    88,    76,   100,    76,    88,    -1,
 +      63,   106,    76,    88,    -1,    63,    88,    76,   106,    -1,
 +      58,   105,    76,    88,    -1,    58,   105,    76,   103,    76,
 +      88,    -1,    59,    88,    76,   105,    -1,    59,    88,    76,
 +     103,    76,   105,    -1,    61,   105,    76,    88,    -1,    61,
 +      88,    76,   105,    -1,    60,   105,    -1,    29,   108,    -1,
 +      29,    88,   108,    -1,    29,    97,   108,    -1,    29,    76,
 +      88,    -1,    29,    76,    97,    -1,    29,   103,    -1,    32,
 +     103,   108,    -1,    32,   101,   108,    -1,    55,   103,    76,
 +     103,    -1,    56,   103,    76,   106,    -1,    30,   108,    -1,
 +      33,   107,    76,   103,    -1,    33,   107,    76,   111,    76,
 +     103,    -1,    33,   107,    76,   111,    76,   103,     9,   111,
 +      -1,    34,   107,    11,   111,    76,   103,    -1,    34,   107,
 +      11,   111,    76,   101,    -1,    34,   107,    11,   111,    76,
 +     102,    -1,    35,   108,    -1,   111,    77,    40,    78,    -1,
 +      70,   109,    -1,    71,   109,    -1,   104,    -1,    90,    -1,
 +      92,    -1,    49,    -1,    46,    -1,    50,    -1,    54,    -1,
 +      52,    -1,    51,    77,   111,    78,    -1,    93,    -1,    48,
 +      -1,    48,    77,   111,    78,    -1,    44,    -1,    47,    77,
 +     111,    78,    -1,    41,    -1,    46,    77,   111,    78,    -1,
 +     111,    -1,   111,    76,   111,    -1,    79,   106,    -1,    79,
 +      69,    -1,    79,    68,    -1,    79,     9,    68,    -1,    79,
 +     111,    -1,    43,    -1,    45,    77,   111,    78,    -1,    77,
 +     104,    78,    -1,    77,   104,     8,   104,    78,    -1,   107,
 +      -1,   111,    77,   104,    78,    -1,   111,    77,   110,    78,
 +      -1,    70,   109,    77,   110,    78,    -1,    70,     6,     7,
 +     109,    77,    38,    78,    -1,    -1,    76,    -1,    -1,     8,
 +     111,    -1,     9,   111,    -1,    38,    -1,    37,    -1,    39,
 +      -1,    36,    -1,    72,    -1,     9,   111,    -1,     8,   111,
 +      -1,    80,   111,    -1,    77,   112,    78,    -1,   111,    -1,
 +     112,     8,   112,    -1,   112,     9,   112,    -1,   112,    10,
 +     112,    -1,   112,    11,   112,    -1,   112,    12,   112,    -1,
 +     112,     6,     6,   112,    -1,   112,     7,     7,   112,    -1,
 +     112,     5,   112,    -1,   112,     4,   112,    -1,   112,     3,
 +     112,    -1
 +};
 +
 +/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 +static const yytype_uint16 yyrline[] =
 +{
 +       0,    66,    66,    67,    71,    70,    78,    77,    83,    88,
 +      94,    98,    99,   100,   106,   110,   114,   118,   122,   126,
 +     133,   137,   141,   145,   149,   153,   160,   164,   168,   172,
 +     179,   183,   190,   194,   198,   202,   206,   210,   217,   221,
 +     225,   235,   239,   243,   247,   251,   255,   259,   263,   267,
 +     271,   275,   279,   283,   290,   297,   301,   308,   312,   320,
 +     324,   328,   332,   336,   340,   344,   348,   357,   361,   365,
 +     369,   373,   377,   381,   385,   389,   393,   397,   401,   405,
 +     413,   421,   432,   436,   440,   444,   451,   455,   459,   463,
 +     467,   471,   478,   482,   486,   490,   497,   501,   505,   509,
 +     516,   520,   528,   532,   536,   540,   544,   548,   552,   559,
 +     563,   567,   571,   575,   579,   586,   590,   597,   606,   617,
 +     624,   628,   634,   643,   647,   651,   658,   664,   670,   678,
 +     686,   694,   695,   698,   706,   714,   722,   729,   735,   741,
 +     744,   752,   760,   766,   774,   780,   788,   796,   817,   822,
 +     830,   836,   843,   851,   852,   860,   867,   877,   878,   887,
 +     895,   903,   912,   913,   916,   919,   923,   929,   930,   931,
 +     934,   935,   939,   943,   947,   951,   957,   958,   962,   966,
 +     970,   974,   978,   982,   986,   990,   994
 +};
 +#endif
 +
 +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
 +   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 +static const char *const yytname[] =
 +{
 +  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
 +  "'-'", "'*'", "'/'", "'%'", "LMOVW", "LMOVB", "LABS", "LLOGW", "LSHW",
 +  "LADDW", "LCMP", "LCROP", "LBRA", "LFMOV", "LFCONV", "LFCMP", "LFADD",
 +  "LFMA", "LTRAP", "LXORW", "LNOP", "LEND", "LRETT", "LWORD", "LTEXT",
 +  "LDATA", "LRETRN", "LCONST", "LSP", "LSB", "LFP", "LPC", "LCREG",
 +  "LFLUSH", "LREG", "LFREG", "LR", "LCR", "LF", "LFPSCR", "LLR", "LCTR",
 +  "LSPR", "LSPREG", "LSEG", "LMSR", "LPCDAT", "LFUNCDAT", "LSCHED", "LXLD",
 +  "LXST", "LXOP", "LXMV", "LRLWM", "LMOVMW", "LMOVEM", "LMOVFL", "LMTFSB",
 +  "LMA", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='",
 +  "';'", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "line",
 +  "$@1", "$@2", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr",
 +  "psr", "fpscr", "fpscrf", "freg", "creg", "cbit", "mask", "ximm", "fimm",
 +  "imm", "sreg", "regaddr", "addr", "name", "comma", "offset", "pointer",
 +  "con", "expr", 0
 +};
 +#endif
 +
 +# ifdef YYPRINT
 +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
 +   token YYLEX-NUM.  */
 +static const yytype_uint16 yytoknum[] =
 +{
 +       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
 +      42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
 +     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
 +     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
 +     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
 +     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
 +     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
 +     315,   316,   317,    58,    61,    59,    44,    40,    41,    36,
 +     126
 +};
 +# endif
 +
 +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 +static const yytype_uint8 yyr1[] =
 +{
 +       0,    81,    82,    82,    84,    83,    85,    83,    83,    83,
 +      83,    83,    83,    83,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
 +      86,    86,    86,    86,    86,    86,    86,    87,    87,    87,
 +      88,    89,    89,    90,    91,    92,    93,    94,    94,    94,
 +      95,    96,    97,    97,    98,    98,    99,   100,   101,   101,
 +     102,   102,   103,   104,   104,   105,   105,   106,   106,   107,
 +     107,   107,   108,   108,   109,   109,   109,   110,   110,   110,
 +     111,   111,   111,   111,   111,   111,   112,   112,   112,   112,
 +     112,   112,   112,   112,   112,   112,   112
 +};
 +
 +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 +static const yytype_uint8 yyr2[] =
 +{
 +       0,     2,     0,     2,     0,     4,     0,     4,     4,     4,
 +       2,     1,     2,     2,     4,     4,     4,     4,     4,     4,
 +       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
 +       4,     4,     4,     4,     6,     4,     4,     4,     6,     4,
 +       4,     6,     6,     6,     4,     4,     6,     4,     6,     4,
 +       6,     4,     4,     2,     6,     4,     4,     4,     6,     4,
 +       4,     4,     4,     4,     4,     4,     4,     2,     2,     4,
 +       3,     3,     5,     4,     4,     6,     4,     4,     6,     6,
 +       6,     8,     4,     4,     3,     2,     4,     4,     6,     8,
 +       4,     6,     4,     4,     6,     6,     8,     8,     8,     8,
 +       4,     4,     4,     6,     4,     6,     4,     4,     2,     2,
 +       3,     3,     3,     3,     2,     3,     3,     4,     4,     2,
 +       4,     6,     8,     6,     6,     6,     2,     4,     2,     2,
 +       1,     1,     1,     1,     1,     1,     1,     1,     4,     1,
 +       1,     4,     1,     4,     1,     4,     1,     3,     2,     2,
 +       2,     3,     2,     1,     4,     3,     5,     1,     4,     4,
 +       5,     7,     0,     1,     0,     2,     2,     1,     1,     1,
 +       1,     1,     2,     2,     2,     3,     1,     3,     3,     3,
 +       3,     3,     4,     4,     3,     3,     3
 +};
 +
 +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
 +   Performed when YYTABLE doesn't specify something else to do.  Zero
 +   means the default is an error.  */
 +static const yytype_uint8 yydefact[] =
 +{
 +       2,     0,     1,     0,     0,     0,     0,     0,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,     0,   162,   162,
 +     162,     0,     0,     0,   162,     0,     0,     0,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,    11,
 +       3,     0,    13,     0,     0,   170,   144,   153,   142,     0,
 +     134,     0,   140,   133,   135,     0,   137,   136,   164,   171,
 +       0,     0,     0,     0,     0,   131,     0,   132,   139,     0,
 +       0,     0,     0,     0,     0,   130,     0,     0,   157,     0,
 +       0,     0,     0,    53,     0,     0,     0,     0,     0,     0,
 +       0,     0,     0,   146,     0,   164,   164,     0,     0,    67,
 +       0,    68,     0,     0,     0,     0,     0,     0,     0,     0,
 +       0,     0,   163,   162,     0,    85,   163,   162,   162,   114,
 +     109,   119,   162,   162,     0,     0,     0,   126,     0,     0,
 +      10,     0,     0,     0,   108,     0,     0,     0,     0,     0,
 +       0,     0,     0,     6,     0,     4,     0,    12,   173,   172,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,   176,
 +       0,   149,   148,   152,   174,     0,     0,     0,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 +       0,     0,   152,     0,     0,     0,     0,     0,     0,   128,
 +     129,     0,    70,    71,     0,     0,     0,     0,     0,     0,
 +     150,     0,     0,     0,     0,     0,     0,     0,     0,   163,
 +      84,     0,   112,   113,   110,   111,   116,   115,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 +       0,   164,   165,   166,     0,     0,   155,     0,     0,     0,
 +       0,     0,     0,     0,     0,     0,     0,   175,    14,    64,
 +      40,    66,    39,     0,    27,    26,    63,    61,    62,    60,
 +      32,    35,    33,     0,    31,    30,    65,    59,    56,     0,
 +      55,    36,    16,    15,   168,   167,   169,     0,     0,    17,
 +      29,    28,    19,    18,    52,    47,   130,    49,   130,    51,
 +     130,    44,     0,   130,    45,   130,    92,    93,    57,   146,
 +       0,    69,     0,    73,    74,     0,    76,    77,     0,     0,
 +     151,    23,    25,    24,    22,    21,    20,    86,    90,    87,
 +       0,    82,    83,   120,     0,     0,   117,   118,   102,     0,
 +       0,   104,   107,   106,     0,     0,   101,   100,    37,     0,
 +       7,     8,     5,     9,   154,   145,   143,   138,     0,     0,
 +       0,   186,   185,   184,     0,     0,   177,   178,   179,   180,
 +     181,     0,     0,     0,   158,   159,     0,     0,     0,     0,
 +       0,     0,     0,     0,     0,    72,     0,     0,     0,   127,
 +       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 +       0,   160,   156,   182,   183,   134,    38,    34,     0,    46,
 +      48,    50,    43,    41,    42,    94,    95,    58,    75,    78,
 +       0,    79,    80,    91,    88,     0,   121,     0,   124,   125,
 +     123,   103,   105,     0,     0,     0,     0,     0,    54,     0,
 +     141,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 +     161,    81,    89,   122,    99,    98,   147,    97,    96
 +};
 +
 +/* YYDEFGOTO[NTERM-NUM].  */
 +static const yytype_int16 yydefgoto[] =
 +{
 +      -1,     1,    40,   235,   233,    41,    99,    63,    64,    65,
 +      66,    67,    68,    69,    70,   281,    71,    72,    92,   433,
 +      73,   105,    74,    75,    76,   162,    78,   115,   157,   288,
 +     159,   160
 +};
 +
 +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 +   STATE-NUM.  */
 +#define YYPACT_NINF -178
 +static const yytype_int16 yypact[] =
 +{
 +    -178,   471,  -178,   -66,   567,   640,    32,    32,   -26,   -26,
 +      32,   756,   626,    24,    55,    55,    55,    55,   -14,    73,
 +     -60,   -54,   743,   743,   -60,   -44,   -44,   -32,   -23,    32,
 +     -23,    -1,   -26,   644,   -44,    32,    35,    17,   -10,  -178,
 +    -178,    48,  -178,   756,   756,  -178,  -178,  -178,  -178,     4,
 +      63,    88,  -178,  -178,  -178,    94,  -178,  -178,   130,  -178,
 +     710,   508,   756,   101,   114,  -178,   117,  -178,  -178,   123,
 +     128,   140,   155,   166,   170,  -178,   172,   177,  -178,   174,
 +     181,   190,   192,   193,   202,   756,   203,   206,   208,   220,
 +     221,   756,   224,  -178,    63,   130,   175,   700,    42,  -178,
 +     229,  -178,   143,     6,   232,   235,   238,   240,   245,   246,
 +     255,   257,  -178,   259,   262,  -178,   285,   -60,   -60,  -178,
 +    -178,  -178,   -60,   -60,   265,   268,   306,  -178,   270,   271,
 +    -178,    32,   272,   301,  -178,   302,   315,   316,   317,   319,
 +     320,   321,   324,  -178,   756,  -178,   756,  -178,  -178,  -178,
 +     756,   756,   756,   756,   394,   756,   756,   328,    15,  -178,
 +     347,  -178,  -178,   174,  -178,   614,    32,    32,    86,    26,
 +     665,   258,    32,    -9,    32,    32,    18,   640,    32,    32,
 +      32,    32,  -178,    32,    32,   -26,    32,   -26,   756,   328,
 +    -178,    42,  -178,  -178,   330,   332,   714,   725,   157,   340,
 +    -178,   696,    55,    55,    55,    55,    55,    55,    55,    32,
 +    -178,    32,  -178,  -178,  -178,  -178,  -178,  -178,   390,   106,
 +     756,   -44,   743,   -26,    49,   -23,    32,    32,    32,   743,
 +      32,   756,    32,   534,   357,   534,   377,   335,   337,   338,
 +     339,   175,  -178,  -178,   106,    32,  -178,   756,   756,   756,
 +     406,   411,   756,   756,   756,   756,   756,  -178,  -178,  -178,
 +    -178,  -178,  -178,   343,  -178,  -178,  -178,  -178,  -178,  -178,
 +    -178,  -178,  -178,   351,  -178,  -178,  -178,  -178,  -178,   352,
 +    -178,  -178,  -178,  -178,  -178,  -178,  -178,   350,   353,  -178,
 +    -178,  -178,  -178,  -178,  -178,  -178,   361,  -178,   362,  -178,
 +     363,  -178,   366,   369,  -178,   370,   371,   372,  -178,   373,
 +     375,  -178,    42,  -178,  -178,    42,  -178,  -178,   184,   376,
 +    -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,   374,   379,
 +     380,  -178,  -178,  -178,   381,   382,  -178,  -178,  -178,   383,
 +     388,  -178,  -178,  -178,   389,   392,  -178,  -178,  -178,   397,
 +    -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,   398,   396,
 +     399,   620,   513,   147,   756,   756,   216,   216,  -178,  -178,
 +    -178,   405,   418,   756,  -178,  -178,    32,    32,    32,    32,
 +      32,    32,    59,    59,   756,  -178,   403,   404,   739,  -178,
 +      59,    55,    55,   -44,   420,    32,   -23,   390,   390,    32,
 +     438,  -178,  -178,   283,   283,  -178,  -178,  -178,   424,  -178,
 +    -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,
 +      42,  -178,  -178,  -178,  -178,   431,   499,   334,  -178,  -178,
 +    -178,  -178,  -178,   436,   439,   460,   463,   464,  -178,   467,
 +    -178,   484,    55,   756,   721,    32,    32,   756,    32,    32,
 +    -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178,  -178
 +};
 +
 +/* YYPGOTO[NTERM-NUM].  */
 +static const yytype_int16 yypgoto[] =
 +{
 +    -178,  -178,     8,  -178,  -178,  -178,   -90,    -5,   -76,  -178,
 +    -157,  -178,  -178,  -153,  -160,  -178,    69,    40,  -177,   167,
 +     -15,   176,   116,   104,    82,    33,   241,   127,   -75,   327,
 +      36,    71
 +};
 +
 +/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 +   positive, shift that token.  If negative, reduce the rule which
 +   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 +#define YYTABLE_NINF -1
 +static const yytype_uint16 yytable[] =
 +{
 +      80,    83,    84,    86,    88,    90,   122,   192,   260,    42,
 +     272,   308,   261,   113,   117,   199,   112,    47,   276,    49,
 +     189,   190,   195,   245,   133,    61,   135,   137,   139,    47,
 +     142,    49,    43,    44,    47,    85,    49,    77,    82,   279,
 +      79,    79,    47,   130,    49,   101,   107,    93,   102,    79,
 +      43,    44,   100,    85,   131,   284,   285,   286,   125,   125,
 +      45,    47,   112,    49,   146,    85,   140,    46,    48,    79,
 +      48,    51,    94,    51,   200,    47,   131,    49,    45,   148,
 +     149,   150,   104,   108,   109,   110,   111,    81,   118,   259,
 +     145,    53,    54,   246,    58,   106,    59,   163,   164,    48,
 +      46,    60,    51,   103,    62,    94,   313,   316,   143,   144,
 +     132,   212,   134,   136,    59,   310,    47,    48,    49,    91,
 +      51,   182,    62,   147,    87,    89,   131,    46,    85,    47,
 +     193,    49,    94,   194,   114,   119,   154,   123,   155,   156,
 +     151,   128,   129,   284,   285,   286,   120,   121,   138,   116,
 +     141,   127,    85,   250,   251,   252,   253,   254,   255,   256,
 +     258,   266,   267,   268,   158,   152,   358,   278,   280,   282,
 +     283,   153,   289,   292,   293,   294,   295,   165,   297,   299,
 +     301,   304,   306,   155,   156,   213,   237,   238,   239,   240,
 +     166,   242,   243,   167,   284,   285,   286,   319,   265,   168,
 +      47,    79,    49,   275,   169,   262,    79,   417,   269,   271,
 +     291,   277,   407,    79,   406,   234,   170,   236,   338,   197,
 +     198,   343,   344,   345,   309,   347,   254,   255,   256,   314,
 +     317,   171,   194,   318,   323,   158,   386,    79,   270,   387,
 +     210,   350,   172,   352,   214,   215,   173,   264,   174,   216,
 +     217,   176,   274,   175,   334,   337,   335,   177,    79,   290,
 +     388,   198,   346,   124,   126,    79,   178,   348,   179,   180,
 +     321,   324,   325,   326,   327,   328,   329,   330,   181,   183,
 +     287,   263,   184,   322,   185,   296,   273,   298,   300,   303,
 +     305,   252,   253,   254,   255,   256,   186,   187,   421,    46,
 +     188,   302,   287,   307,    94,   196,   341,   342,   201,    55,
 +      56,   202,    57,   331,   203,   332,   204,   220,   361,   362,
 +     363,   205,   206,   366,   367,   368,   369,   370,    47,    48,
 +      49,   207,    51,   208,   333,   209,   349,   336,   211,   339,
 +     340,   218,    43,   444,   441,   219,   221,   222,   223,   360,
 +     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
 +     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
 +      45,   409,   410,   411,   412,   413,   414,   224,   225,   428,
 +     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
 +     431,   226,   227,   228,   438,   229,   230,   231,    43,    44,
 +     232,   241,   200,   161,    58,   244,    59,   198,   320,   408,
 +     311,    91,   364,   354,    62,   355,   356,   357,   365,   371,
 +      93,   422,   415,   416,   194,   257,    45,   372,   374,   373,
 +     423,   375,   351,   435,   435,   403,   404,   376,   377,   378,
 +     454,   455,   379,   457,   458,   380,   381,   382,   383,   384,
 +     390,   405,   353,   385,   389,   391,   392,   393,   394,   395,
 +     424,   425,    59,   163,   396,   397,    52,    91,   398,    85,
 +      62,     2,     3,   399,   401,   400,   439,   402,   432,   453,
 +     149,   418,   419,   456,     4,     5,     6,     7,     8,     9,
 +      10,    11,    12,    13,    14,    15,    16,    17,    18,   427,
 +      19,    20,   440,    21,    22,    23,    24,   442,   443,   426,
 +     430,   452,   445,   434,   437,   446,    43,    44,   249,   250,
 +     251,   252,   253,   254,   255,   256,    25,    26,    27,    28,
 +      29,    30,    31,    32,    33,     3,   447,    34,    35,   448,
 +     449,    36,    37,    38,    45,   450,    39,     4,     5,     6,
 +       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
 +      17,    18,   451,    19,    20,   436,    21,    22,    23,    24,
 +     429,   359,     0,     0,     0,    43,    44,   161,    58,     0,
 +      59,     0,     0,     0,     0,    91,     0,     0,    62,    25,
 +      26,    27,    28,    29,    30,    31,    32,    33,     0,     0,
 +      34,    35,     0,    45,    36,    37,    38,     0,    46,    39,
 +      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
 +       0,    57,    43,    44,   248,   249,   250,   251,   252,   253,
 +     254,   255,   256,     0,    43,    44,     0,    58,     0,    59,
 +       0,     0,     0,     0,    60,     0,    61,    62,    43,    44,
 +      45,     0,    43,    44,     0,    46,     0,    47,     0,    49,
 +      50,     0,    45,    53,    54,    55,    56,    46,    57,     0,
 +       0,     0,    94,    43,    44,     0,    45,     0,     0,     0,
 +      45,     0,     0,    47,    58,    49,    59,    47,     0,    49,
 +       0,    60,     0,    85,    62,     0,    95,    96,    59,     0,
 +       0,    45,    97,    98,    43,    44,    62,     0,    43,    44,
 +      58,     0,    59,    52,    58,     0,    59,    60,    43,    44,
 +      62,    91,    43,    44,    62,     0,     0,     0,     0,    43,
 +      44,     0,    45,    43,    44,    58,    45,    59,     0,     0,
 +      48,     0,    60,    51,    85,    62,    45,    43,    44,     0,
 +      45,    43,    44,    47,     0,    49,     0,    45,     0,     0,
 +       0,    45,     0,     0,    43,    44,    58,     0,    59,     0,
 +      95,    96,    59,    60,     0,    45,    62,   191,     0,    45,
 +      62,     0,    59,     0,    95,    96,    59,    91,     0,   320,
 +      62,   312,    45,    59,    62,    95,    96,    59,    91,     0,
 +       0,    62,   315,     0,     0,    62,     0,     0,     0,    95,
 +      96,    59,     0,    58,     0,    59,   420,     0,     0,    62,
 +      91,     0,     0,    62,     0,     0,     0,     0,    59,     0,
 +       0,     0,     0,    91,     0,     0,    62
 +};
 +
 +#define yypact_value_is_default(yystate) \
 +  ((yystate) == (-178))
 +
 +#define yytable_value_is_error(yytable_value) \
 +  YYID (0)
 +
 +static const yytype_int16 yycheck[] =
 +{
 +       5,     6,     7,     8,     9,    10,    21,    97,   165,    75,
 +     170,   188,   165,    18,    19,     9,    76,    43,   171,    45,
 +      95,    96,    98,     8,    29,    79,    31,    32,    33,    43,
 +      35,    45,     8,     9,    43,    79,    45,     4,     5,    48,
 +       4,     5,    43,    75,    45,    12,    13,    11,    12,    13,
 +       8,     9,    12,    79,    77,    37,    38,    39,    22,    23,
 +      36,    43,    76,    45,    74,    79,    33,    41,    44,    33,
 +      44,    47,    46,    47,    68,    43,    77,    45,    36,    43,
 +      44,    77,    13,    14,    15,    16,    17,     5,    19,   165,
 +      73,    49,    50,    78,    70,    13,    72,    61,    62,    44,
 +      41,    77,    47,    79,    80,    46,   196,   197,    73,    74,
 +      28,   116,    30,    31,    72,   191,    43,    44,    45,    77,
 +      47,    85,    80,    75,     8,     9,    77,    41,    79,    43,
 +      97,    45,    46,    97,    18,    19,     6,    21,     8,     9,
 +      77,    25,    26,    37,    38,    39,    19,    20,    32,    76,
 +      34,    24,    79,     6,     7,     8,     9,    10,    11,    12,
 +     165,   166,   167,   168,    60,    77,   241,   172,   173,   174,
 +     175,    77,   177,   178,   179,   180,   181,    76,   183,   184,
 +     185,   186,   187,     8,     9,   116,   150,   151,   152,   153,
 +      76,   155,   156,    76,    37,    38,    39,    40,   165,    76,
 +      43,   165,    45,   170,    76,   165,   170,   384,   168,   169,
 +     177,   171,   372,   177,   371,   144,    76,   146,   223,    76,
 +      77,   226,   227,   228,   188,   230,    10,    11,    12,   196,
 +     197,    76,   196,   197,   201,   131,   312,   201,   169,   315,
 +     113,   233,    76,   235,   117,   118,    76,   165,    76,   122,
 +     123,    77,   170,    76,   218,   222,   220,    76,   222,   177,
 +      76,    77,   229,    22,    23,   229,    76,   231,    76,    76,
 +     201,   202,   203,   204,   205,   206,   207,   208,    76,    76,
 +     176,   165,    76,   201,    76,   181,   170,   183,   184,   185,
 +     186,     8,     9,    10,    11,    12,    76,    76,   388,    41,
 +      76,   185,   198,   187,    46,    76,   224,   225,    76,    51,
 +      52,    76,    54,   209,    76,   211,    76,    11,   247,   248,
 +     249,    76,    76,   252,   253,   254,   255,   256,    43,    44,
 +      45,    76,    47,    76,   218,    76,   232,   221,    76,   223,
 +     224,    76,     8,     9,   420,    77,    76,    76,    76,   245,
 +       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
 +       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
 +      36,   376,   377,   378,   379,   380,   381,    76,    76,   394,
 +       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
 +     395,    76,    76,    76,   399,    76,    76,    76,     8,     9,
 +      76,     7,    68,    69,    70,    77,    72,    77,    68,   373,
 +      78,    77,     6,    78,    80,    78,    78,    78,     7,    76,
 +     384,   388,   382,   383,   388,    78,    36,    76,    78,    77,
 +     390,    78,    75,   397,   398,   364,   365,    76,    76,    76,
 +     445,   446,    76,   448,   449,    76,    76,    76,    76,    76,
 +      76,    46,    75,    78,    78,    76,    76,    76,    76,    76,
 +     391,   392,    72,   427,    76,    76,    48,    77,    76,    79,
 +      80,     0,     1,    76,    78,    77,    38,    78,   396,   443,
 +     444,    78,    78,   447,    13,    14,    15,    16,    17,    18,
 +      19,    20,    21,    22,    23,    24,    25,    26,    27,    79,
 +      29,    30,    78,    32,    33,    34,    35,    76,     9,   393,
 +     394,   442,    76,   397,   398,    76,     8,     9,     5,     6,
 +       7,     8,     9,    10,    11,    12,    55,    56,    57,    58,
 +      59,    60,    61,    62,    63,     1,    76,    66,    67,    76,
 +      76,    70,    71,    72,    36,    78,    75,    13,    14,    15,
 +      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
 +      26,    27,    78,    29,    30,   398,    32,    33,    34,    35,
 +     394,   244,    -1,    -1,    -1,     8,     9,    69,    70,    -1,
 +      72,    -1,    -1,    -1,    -1,    77,    -1,    -1,    80,    55,
 +      56,    57,    58,    59,    60,    61,    62,    63,    -1,    -1,
 +      66,    67,    -1,    36,    70,    71,    72,    -1,    41,    75,
 +      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
 +      -1,    54,     8,     9,     4,     5,     6,     7,     8,     9,
 +      10,    11,    12,    -1,     8,     9,    -1,    70,    -1,    72,
 +      -1,    -1,    -1,    -1,    77,    -1,    79,    80,     8,     9,
 +      36,    -1,     8,     9,    -1,    41,    -1,    43,    -1,    45,
 +      46,    -1,    36,    49,    50,    51,    52,    41,    54,    -1,
 +      -1,    -1,    46,     8,     9,    -1,    36,    -1,    -1,    -1,
 +      36,    -1,    -1,    43,    70,    45,    72,    43,    -1,    45,
 +      -1,    77,    -1,    79,    80,    -1,    70,    71,    72,    -1,
 +      -1,    36,    76,    77,     8,     9,    80,    -1,     8,     9,
 +      70,    -1,    72,    48,    70,    -1,    72,    77,     8,     9,
 +      80,    77,     8,     9,    80,    -1,    -1,    -1,    -1,     8,
 +       9,    -1,    36,     8,     9,    70,    36,    72,    -1,    -1,
 +      44,    -1,    77,    47,    79,    80,    36,     8,     9,    -1,
 +      36,     8,     9,    43,    -1,    45,    -1,    36,    -1,    -1,
 +      -1,    36,    -1,    -1,     8,     9,    70,    -1,    72,    -1,
 +      70,    71,    72,    77,    -1,    36,    80,    77,    -1,    36,
 +      80,    -1,    72,    -1,    70,    71,    72,    77,    -1,    68,
 +      80,    77,    36,    72,    80,    70,    71,    72,    77,    -1,
 +      -1,    80,    77,    -1,    -1,    80,    -1,    -1,    -1,    70,
 +      71,    72,    -1,    70,    -1,    72,    77,    -1,    -1,    80,
 +      77,    -1,    -1,    80,    -1,    -1,    -1,    -1,    72,    -1,
 +      -1,    -1,    -1,    77,    -1,    -1,    80
 +};
 +
 +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 +   symbol of state STATE-NUM.  */
 +static const yytype_uint8 yystos[] =
 +{
 +       0,    82,     0,     1,    13,    14,    15,    16,    17,    18,
 +      19,    20,    21,    22,    23,    24,    25,    26,    27,    29,
 +      30,    32,    33,    34,    35,    55,    56,    57,    58,    59,
 +      60,    61,    62,    63,    66,    67,    70,    71,    72,    75,
 +      83,    86,    75,     8,     9,    36,    41,    43,    44,    45,
 +      46,    47,    48,    49,    50,    51,    52,    54,    70,    72,
 +      77,    79,    80,    88,    89,    90,    91,    92,    93,    94,
 +      95,    97,    98,   101,   103,   104,   105,   106,   107,   111,
 +      88,   105,   106,    88,    88,    79,    88,   103,    88,   103,
 +      88,    77,    99,   111,    46,    70,    71,    76,    77,    87,
 +      98,   106,   111,    79,    97,   102,   105,   106,    97,    97,
 +      97,    97,    76,    88,   103,   108,    76,    88,    97,   103,
 +     108,   108,   101,   103,   107,   111,   107,   108,   103,   103,
 +      75,    77,   105,    88,   105,    88,   105,    88,   103,    88,
 +     106,   103,    88,    73,    74,    73,    74,    75,   111,   111,
 +      77,    77,    77,    77,     6,     8,     9,   109,   104,   111,
 +     112,    69,   106,   111,   111,    76,    76,    76,    76,    76,
 +      76,    76,    76,    76,    76,    76,    77,    76,    76,    76,
 +      76,    76,   111,    76,    76,    76,    76,    76,    76,   109,
 +     109,    77,    87,   106,   111,    89,    76,    76,    77,     9,
 +      68,    76,    76,    76,    76,    76,    76,    76,    76,    76,
 +     108,    76,    88,    97,   108,   108,   108,   108,    76,    77,
 +      11,    76,    76,    76,    76,    76,    76,    76,    76,    76,
 +      76,    76,    76,    85,   112,    84,   112,   111,   111,   111,
 +     111,     7,   111,   111,    77,     8,    78,     3,     4,     5,
 +       6,     7,     8,     9,    10,    11,    12,    78,    88,    89,
 +      91,    94,    98,   103,   105,   106,    88,    88,    88,    98,
 +      97,    98,    95,   103,   105,   106,    94,    98,    88,    48,
 +      88,    96,    88,    88,    37,    38,    39,   104,   110,    88,
 +     105,   106,    88,    88,    88,    88,   104,    88,   104,    88,
 +     104,    88,   103,   104,    88,   104,    88,   103,    99,   111,
 +      89,    78,    77,    87,   106,    77,    87,   106,   111,    40,
 +      68,    97,   105,   106,    97,    97,    97,    97,    97,    97,
 +      97,   104,   104,   103,   111,   111,   103,   106,    88,   103,
 +     103,   105,   105,    88,    88,    88,   106,    88,   111,   104,
 +      83,    75,    83,    75,    78,    78,    78,    78,   109,   110,
 +     104,   112,   112,   112,     6,     7,   112,   112,   112,   112,
 +     112,    76,    76,    77,    78,    78,    76,    76,    76,    76,
 +      76,    76,    76,    76,    76,    78,    89,    89,    76,    78,
 +      76,    76,    76,    76,    76,    76,    76,    76,    76,    76,
 +      77,    78,    78,   112,   112,    46,    91,    95,   111,    88,
 +      88,    88,    88,    88,    88,    98,    98,    99,    78,    78,
 +      77,    87,   106,    98,    97,    97,   103,    79,   101,   102,
 +     103,    88,   105,   100,   103,   111,   100,   103,    88,    38,
 +      78,    89,    76,     9,     9,    76,    76,    76,    76,    76,
 +      78,    78,    97,   111,    88,    88,   111,    88,    88
 +};
 +
 +#define yyerrok               (yyerrstatus = 0)
 +#define yyclearin     (yychar = YYEMPTY)
 +#define YYEMPTY               (-2)
 +#define YYEOF         0
 +
 +#define YYACCEPT      goto yyacceptlab
 +#define YYABORT               goto yyabortlab
 +#define YYERROR               goto yyerrorlab
 +
 +
 +/* Like YYERROR except do call yyerror.  This remains here temporarily
 +   to ease the transition to the new meaning of YYERROR, for GCC.
 +   Once GCC version 2 has supplanted version 1, this can go.  However,
 +   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
 +   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
 +   discussed.  */
 +
 +#define YYFAIL                goto yyerrlab
 +#if defined YYFAIL
 +  /* This is here to suppress warnings from the GCC cpp's
 +     -Wunused-macros.  Normally we don't worry about that warning, but
 +     some users do, and we want to make it easy for users to remove
 +     YYFAIL uses, which will produce warnings from Bison 2.5.  */
 +#endif
 +
 +#define YYRECOVERING()  (!!yyerrstatus)
 +
 +#define YYBACKUP(Token, Value)                                        \
 +do                                                            \
 +  if (yychar == YYEMPTY && yylen == 1)                                \
 +    {                                                         \
 +      yychar = (Token);                                               \
 +      yylval = (Value);                                               \
 +      YYPOPSTACK (1);                                         \
 +      goto yybackup;                                          \
 +    }                                                         \
 +  else                                                                \
 +    {                                                         \
 +      yyerror (YY_("syntax error: cannot back up")); \
 +      YYERROR;                                                        \
 +    }                                                         \
 +while (YYID (0))
 +
 +
 +#define YYTERROR      1
 +#define YYERRCODE     256
 +
 +
 +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
 +   If N is 0, then set CURRENT to the empty location which ends
 +   the previous symbol: RHS[0] (always defined).  */
 +
 +#define YYRHSLOC(Rhs, K) ((Rhs)[K])
 +#ifndef YYLLOC_DEFAULT
 +# define YYLLOC_DEFAULT(Current, Rhs, N)                              \
 +    do                                                                        \
 +      if (YYID (N))                                                    \
 +      {                                                               \
 +        (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
 +        (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
 +        (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
 +        (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
 +      }                                                               \
 +      else                                                            \
 +      {                                                               \
 +        (Current).first_line   = (Current).last_line   =              \
 +          YYRHSLOC (Rhs, 0).last_line;                                \
 +        (Current).first_column = (Current).last_column =              \
 +          YYRHSLOC (Rhs, 0).last_column;                              \
 +      }                                                               \
 +    while (YYID (0))
 +#endif
 +
 +
 +/* This macro is provided for backward compatibility. */
 +
 +#ifndef YY_LOCATION_PRINT
 +# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 +#endif
 +
 +
 +/* YYLEX -- calling `yylex' with the right arguments.  */
 +
 +#ifdef YYLEX_PARAM
 +# define YYLEX yylex (YYLEX_PARAM)
 +#else
 +# define YYLEX yylex ()
 +#endif
 +
 +/* Enable debugging if requested.  */
 +#if YYDEBUG
 +
 +# ifndef YYFPRINTF
 +#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
 +#  define YYFPRINTF fprintf
 +# endif
 +
 +# define YYDPRINTF(Args)                      \
 +do {                                          \
 +  if (yydebug)                                        \
 +    YYFPRINTF Args;                           \
 +} while (YYID (0))
 +
 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                          \
 +do {                                                                    \
 +  if (yydebug)                                                                  \
 +    {                                                                   \
 +      YYFPRINTF (stderr, "%s ", Title);                                         \
 +      yy_symbol_print (stderr,                                                  \
 +                Type, Value); \
 +      YYFPRINTF (stderr, "\n");                                                 \
 +    }                                                                   \
 +} while (YYID (0))
 +
 +
 +/*--------------------------------.
 +| Print this symbol on YYOUTPUT.  |
 +`--------------------------------*/
 +
 +/*ARGSUSED*/
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static void
 +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
 +#else
 +static void
 +yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 +    FILE *yyoutput;
 +    int yytype;
 +    YYSTYPE const * const yyvaluep;
 +#endif
 +{
 +  if (!yyvaluep)
 +    return;
 +# ifdef YYPRINT
 +  if (yytype < YYNTOKENS)
 +    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
 +# else
 +  YYUSE (yyoutput);
 +# endif
 +  switch (yytype)
 +    {
 +      default:
 +      break;
 +    }
 +}
 +
 +
 +/*--------------------------------.
 +| Print this symbol on YYOUTPUT.  |
 +`--------------------------------*/
 +
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static void
 +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
 +#else
 +static void
 +yy_symbol_print (yyoutput, yytype, yyvaluep)
 +    FILE *yyoutput;
 +    int yytype;
 +    YYSTYPE const * const yyvaluep;
 +#endif
 +{
 +  if (yytype < YYNTOKENS)
 +    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
 +  else
 +    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 +
 +  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
 +  YYFPRINTF (yyoutput, ")");
 +}
 +
 +/*------------------------------------------------------------------.
 +| yy_stack_print -- Print the state stack from its BOTTOM up to its |
 +| TOP (included).                                                   |
 +`------------------------------------------------------------------*/
 +
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static void
 +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 +#else
 +static void
 +yy_stack_print (yybottom, yytop)
 +    yytype_int16 *yybottom;
 +    yytype_int16 *yytop;
 +#endif
 +{
 +  YYFPRINTF (stderr, "Stack now");
 +  for (; yybottom <= yytop; yybottom++)
 +    {
 +      int yybot = *yybottom;
 +      YYFPRINTF (stderr, " %d", yybot);
 +    }
 +  YYFPRINTF (stderr, "\n");
 +}
 +
 +# define YY_STACK_PRINT(Bottom, Top)                          \
 +do {                                                          \
 +  if (yydebug)                                                        \
 +    yy_stack_print ((Bottom), (Top));                         \
 +} while (YYID (0))
 +
 +
 +/*------------------------------------------------.
 +| Report that the YYRULE is going to be reduced.  |
 +`------------------------------------------------*/
 +
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static void
 +yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
 +#else
 +static void
 +yy_reduce_print (yyvsp, yyrule)
 +    YYSTYPE *yyvsp;
 +    int yyrule;
 +#endif
 +{
 +  int yynrhs = yyr2[yyrule];
 +  int yyi;
 +  unsigned long int yylno = yyrline[yyrule];
 +  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
 +           yyrule - 1, yylno);
 +  /* The symbols being reduced.  */
 +  for (yyi = 0; yyi < yynrhs; yyi++)
 +    {
 +      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
 +      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
 +                     &(yyvsp[(yyi + 1) - (yynrhs)])
 +                                     );
 +      YYFPRINTF (stderr, "\n");
 +    }
 +}
 +
 +# define YY_REDUCE_PRINT(Rule)                \
 +do {                                  \
 +  if (yydebug)                                \
 +    yy_reduce_print (yyvsp, Rule); \
 +} while (YYID (0))
 +
 +/* Nonzero means print parse trace.  It is left uninitialized so that
 +   multiple parsers can coexist.  */
 +int yydebug;
 +#else /* !YYDEBUG */
 +# define YYDPRINTF(Args)
 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
 +# define YY_STACK_PRINT(Bottom, Top)
 +# define YY_REDUCE_PRINT(Rule)
 +#endif /* !YYDEBUG */
 +
 +
 +/* YYINITDEPTH -- initial size of the parser's stacks.  */
 +#ifndef       YYINITDEPTH
 +# define YYINITDEPTH 200
 +#endif
 +
 +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
 +   if the built-in stack extension method is used).
 +
 +   Do not make this value too large; the results are undefined if
 +   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
 +   evaluated with infinite-precision integer arithmetic.  */
 +
 +#ifndef YYMAXDEPTH
 +# define YYMAXDEPTH 10000
 +#endif
 +
 +
 +#if YYERROR_VERBOSE
 +
 +# ifndef yystrlen
 +#  if defined __GLIBC__ && defined _STRING_H
 +#   define yystrlen strlen
 +#  else
 +/* Return the length of YYSTR.  */
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static YYSIZE_T
 +yystrlen (const char *yystr)
 +#else
 +static YYSIZE_T
 +yystrlen (yystr)
 +    const char *yystr;
 +#endif
 +{
 +  YYSIZE_T yylen;
 +  for (yylen = 0; yystr[yylen]; yylen++)
 +    continue;
 +  return yylen;
 +}
 +#  endif
 +# endif
 +
 +# ifndef yystpcpy
 +#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
 +#   define yystpcpy stpcpy
 +#  else
 +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
 +   YYDEST.  */
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static char *
 +yystpcpy (char *yydest, const char *yysrc)
 +#else
 +static char *
 +yystpcpy (yydest, yysrc)
 +    char *yydest;
 +    const char *yysrc;
 +#endif
 +{
 +  char *yyd = yydest;
 +  const char *yys = yysrc;
 +
 +  while ((*yyd++ = *yys++) != '\0')
 +    continue;
 +
 +  return yyd - 1;
 +}
 +#  endif
 +# endif
 +
 +# ifndef yytnamerr
 +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
 +   quotes and backslashes, so that it's suitable for yyerror.  The
 +   heuristic is that double-quoting is unnecessary unless the string
 +   contains an apostrophe, a comma, or backslash (other than
 +   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
 +   null, do not copy; instead, return the length of what the result
 +   would have been.  */
 +static YYSIZE_T
 +yytnamerr (char *yyres, const char *yystr)
 +{
 +  if (*yystr == '"')
 +    {
 +      YYSIZE_T yyn = 0;
 +      char const *yyp = yystr;
 +
 +      for (;;)
 +      switch (*++yyp)
 +        {
 +        case '\'':
 +        case ',':
 +          goto do_not_strip_quotes;
 +
 +        case '\\':
 +          if (*++yyp != '\\')
 +            goto do_not_strip_quotes;
 +          /* Fall through.  */
 +        default:
 +          if (yyres)
 +            yyres[yyn] = *yyp;
 +          yyn++;
 +          break;
 +
 +        case '"':
 +          if (yyres)
 +            yyres[yyn] = '\0';
 +          return yyn;
 +        }
 +    do_not_strip_quotes: ;
 +    }
 +
 +  if (! yyres)
 +    return yystrlen (yystr);
 +
 +  return yystpcpy (yyres, yystr) - yyres;
 +}
 +# endif
 +
 +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
 +   about the unexpected token YYTOKEN for the state stack whose top is
 +   YYSSP.
 +
 +   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
 +   not large enough to hold the message.  In that case, also set
 +   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
 +   required number of bytes is too large to store.  */
 +static int
 +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 +                yytype_int16 *yyssp, int yytoken)
 +{
 +  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
 +  YYSIZE_T yysize = yysize0;
 +  YYSIZE_T yysize1;
 +  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
 +  /* Internationalized format string. */
 +  const char *yyformat = 0;
 +  /* Arguments of yyformat. */
 +  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
 +  /* Number of reported tokens (one for the "unexpected", one per
 +     "expected"). */
 +  int yycount = 0;
 +
 +  /* There are many possibilities here to consider:
 +     - Assume YYFAIL is not used.  It's too flawed to consider.  See
 +       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
 +       for details.  YYERROR is fine as it does not invoke this
 +       function.
 +     - If this state is a consistent state with a default action, then
 +       the only way this function was invoked is if the default action
 +       is an error action.  In that case, don't check for expected
 +       tokens because there are none.
 +     - The only way there can be no lookahead present (in yychar) is if
 +       this state is a consistent state with a default action.  Thus,
 +       detecting the absence of a lookahead is sufficient to determine
 +       that there is no unexpected or expected token to report.  In that
 +       case, just report a simple "syntax error".
 +     - Don't assume there isn't a lookahead just because this state is a
 +       consistent state with a default action.  There might have been a
 +       previous inconsistent state, consistent state with a non-default
 +       action, or user semantic action that manipulated yychar.
 +     - Of course, the expected token list depends on states to have
 +       correct lookahead information, and it depends on the parser not
 +       to perform extra reductions after fetching a lookahead from the
 +       scanner and before detecting a syntax error.  Thus, state merging
 +       (from LALR or IELR) and default reductions corrupt the expected
 +       token list.  However, the list is correct for canonical LR with
 +       one exception: it will still contain any token that will not be
 +       accepted due to an error action in a later state.
 +  */
 +  if (yytoken != YYEMPTY)
 +    {
 +      int yyn = yypact[*yyssp];
 +      yyarg[yycount++] = yytname[yytoken];
 +      if (!yypact_value_is_default (yyn))
 +        {
 +          /* Start YYX at -YYN if negative to avoid negative indexes in
 +             YYCHECK.  In other words, skip the first -YYN actions for
 +             this state because they are default actions.  */
 +          int yyxbegin = yyn < 0 ? -yyn : 0;
 +          /* Stay within bounds of both yycheck and yytname.  */
 +          int yychecklim = YYLAST - yyn + 1;
 +          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
 +          int yyx;
 +
 +          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
 +            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
 +                && !yytable_value_is_error (yytable[yyx + yyn]))
 +              {
 +                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
 +                  {
 +                    yycount = 1;
 +                    yysize = yysize0;
 +                    break;
 +                  }
 +                yyarg[yycount++] = yytname[yyx];
 +                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
 +                if (! (yysize <= yysize1
 +                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
 +                  return 2;
 +                yysize = yysize1;
 +              }
 +        }
 +    }
 +
 +  switch (yycount)
 +    {
 +# define YYCASE_(N, S)                      \
 +      case N:                               \
 +        yyformat = S;                       \
 +      break
 +      YYCASE_(0, YY_("syntax error"));
 +      YYCASE_(1, YY_("syntax error, unexpected %s"));
 +      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
 +      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
 +      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
 +      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
 +# undef YYCASE_
 +    }
 +
 +  yysize1 = yysize + yystrlen (yyformat);
 +  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
 +    return 2;
 +  yysize = yysize1;
 +
 +  if (*yymsg_alloc < yysize)
 +    {
 +      *yymsg_alloc = 2 * yysize;
 +      if (! (yysize <= *yymsg_alloc
 +             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
 +        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
 +      return 1;
 +    }
 +
 +  /* Avoid sprintf, as that infringes on the user's name space.
 +     Don't have undefined behavior even if the translation
 +     produced a string with the wrong number of "%s"s.  */
 +  {
 +    char *yyp = *yymsg;
 +    int yyi = 0;
 +    while ((*yyp = *yyformat) != '\0')
 +      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
 +        {
 +          yyp += yytnamerr (yyp, yyarg[yyi++]);
 +          yyformat += 2;
 +        }
 +      else
 +        {
 +          yyp++;
 +          yyformat++;
 +        }
 +  }
 +  return 0;
 +}
 +#endif /* YYERROR_VERBOSE */
 +
 +/*-----------------------------------------------.
 +| Release the memory associated to this symbol.  |
 +`-----------------------------------------------*/
 +
 +/*ARGSUSED*/
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +static void
 +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
 +#else
 +static void
 +yydestruct (yymsg, yytype, yyvaluep)
 +    const char *yymsg;
 +    int yytype;
 +    YYSTYPE *yyvaluep;
 +#endif
 +{
 +  YYUSE (yyvaluep);
 +
 +  if (!yymsg)
 +    yymsg = "Deleting";
 +  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 +
 +  switch (yytype)
 +    {
 +
 +      default:
 +      break;
 +    }
 +}
 +
 +
 +/* Prevent warnings from -Wmissing-prototypes.  */
 +#ifdef YYPARSE_PARAM
 +#if defined __STDC__ || defined __cplusplus
 +int yyparse (void *YYPARSE_PARAM);
 +#else
 +int yyparse ();
 +#endif
 +#else /* ! YYPARSE_PARAM */
 +#if defined __STDC__ || defined __cplusplus
 +int yyparse (void);
 +#else
 +int yyparse ();
 +#endif
 +#endif /* ! YYPARSE_PARAM */
 +
 +
 +/* The lookahead symbol.  */
 +int yychar;
 +
 +/* The semantic value of the lookahead symbol.  */
 +YYSTYPE yylval;
 +
 +/* Number of syntax errors so far.  */
 +int yynerrs;
 +
 +
 +/*----------.
 +| yyparse.  |
 +`----------*/
 +
 +#ifdef YYPARSE_PARAM
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +int
 +yyparse (void *YYPARSE_PARAM)
 +#else
 +int
 +yyparse (YYPARSE_PARAM)
 +    void *YYPARSE_PARAM;
 +#endif
 +#else /* ! YYPARSE_PARAM */
 +#if (defined __STDC__ || defined __C99__FUNC__ \
 +     || defined __cplusplus || defined _MSC_VER)
 +int
 +yyparse (void)
 +#else
 +int
 +yyparse ()
 +
 +#endif
 +#endif
 +{
 +    int yystate;
 +    /* Number of tokens to shift before error messages enabled.  */
 +    int yyerrstatus;
 +
 +    /* The stacks and their tools:
 +       `yyss': related to states.
 +       `yyvs': related to semantic values.
 +
 +       Refer to the stacks thru separate pointers, to allow yyoverflow
 +       to reallocate them elsewhere.  */
 +
 +    /* The state stack.  */
 +    yytype_int16 yyssa[YYINITDEPTH];
 +    yytype_int16 *yyss;
 +    yytype_int16 *yyssp;
 +
 +    /* The semantic value stack.  */
 +    YYSTYPE yyvsa[YYINITDEPTH];
 +    YYSTYPE *yyvs;
 +    YYSTYPE *yyvsp;
 +
 +    YYSIZE_T yystacksize;
 +
 +  int yyn;
 +  int yyresult;
 +  /* Lookahead token as an internal (translated) token number.  */
 +  int yytoken;
 +  /* The variables used to return semantic value and location from the
 +     action routines.  */
 +  YYSTYPE yyval;
 +
 +#if YYERROR_VERBOSE
 +  /* Buffer for error messages, and its allocated size.  */
 +  char yymsgbuf[128];
 +  char *yymsg = yymsgbuf;
 +  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
 +#endif
 +
 +#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 +
 +  /* The number of symbols on the RHS of the reduced rule.
 +     Keep to zero when no symbol should be popped.  */
 +  int yylen = 0;
 +
 +  yytoken = 0;
 +  yyss = yyssa;
 +  yyvs = yyvsa;
 +  yystacksize = YYINITDEPTH;
 +
 +  YYDPRINTF ((stderr, "Starting parse\n"));
 +
 +  yystate = 0;
 +  yyerrstatus = 0;
 +  yynerrs = 0;
 +  yychar = YYEMPTY; /* Cause a token to be read.  */
 +
 +  /* Initialize stack pointers.
 +     Waste one element of value and location stack
 +     so that they stay on the same level as the state stack.
 +     The wasted elements are never initialized.  */
 +  yyssp = yyss;
 +  yyvsp = yyvs;
 +
 +  goto yysetstate;
 +
 +/*------------------------------------------------------------.
 +| yynewstate -- Push a new state, which is found in yystate.  |
 +`------------------------------------------------------------*/
 + yynewstate:
 +  /* In all cases, when you get here, the value and location stacks
 +     have just been pushed.  So pushing a state here evens the stacks.  */
 +  yyssp++;
 +
 + yysetstate:
 +  *yyssp = yystate;
 +
 +  if (yyss + yystacksize - 1 <= yyssp)
 +    {
 +      /* Get the current used size of the three stacks, in elements.  */
 +      YYSIZE_T yysize = yyssp - yyss + 1;
 +
 +#ifdef yyoverflow
 +      {
 +      /* Give user a chance to reallocate the stack.  Use copies of
 +         these so that the &'s don't force the real ones into
 +         memory.  */
 +      YYSTYPE *yyvs1 = yyvs;
 +      yytype_int16 *yyss1 = yyss;
 +
 +      /* Each stack pointer address is followed by the size of the
 +         data in use in that stack, in bytes.  This used to be a
 +         conditional around just the two extra args, but that might
 +         be undefined if yyoverflow is a macro.  */
 +      yyoverflow (YY_("memory exhausted"),
 +                  &yyss1, yysize * sizeof (*yyssp),
 +                  &yyvs1, yysize * sizeof (*yyvsp),
 +                  &yystacksize);
 +
 +      yyss = yyss1;
 +      yyvs = yyvs1;
 +      }
 +#else /* no yyoverflow */
 +# ifndef YYSTACK_RELOCATE
 +      goto yyexhaustedlab;
 +# else
 +      /* Extend the stack our own way.  */
 +      if (YYMAXDEPTH <= yystacksize)
 +      goto yyexhaustedlab;
 +      yystacksize *= 2;
 +      if (YYMAXDEPTH < yystacksize)
 +      yystacksize = YYMAXDEPTH;
 +
 +      {
 +      yytype_int16 *yyss1 = yyss;
 +      union yyalloc *yyptr =
 +        (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 +      if (! yyptr)
 +        goto yyexhaustedlab;
 +      YYSTACK_RELOCATE (yyss_alloc, yyss);
 +      YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 +#  undef YYSTACK_RELOCATE
 +      if (yyss1 != yyssa)
 +        YYSTACK_FREE (yyss1);
 +      }
 +# endif
 +#endif /* no yyoverflow */
 +
 +      yyssp = yyss + yysize - 1;
 +      yyvsp = yyvs + yysize - 1;
 +
 +      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 +                (unsigned long int) yystacksize));
 +
 +      if (yyss + yystacksize - 1 <= yyssp)
 +      YYABORT;
 +    }
 +
 +  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 +
 +  if (yystate == YYFINAL)
 +    YYACCEPT;
 +
 +  goto yybackup;
 +
 +/*-----------.
 +| yybackup.  |
 +`-----------*/
 +yybackup:
 +
 +  /* Do appropriate processing given the current state.  Read a
 +     lookahead token if we need one and don't already have one.  */
 +
 +  /* First try to decide what to do without reference to lookahead token.  */
 +  yyn = yypact[yystate];
 +  if (yypact_value_is_default (yyn))
 +    goto yydefault;
 +
 +  /* Not known => get a lookahead token if don't already have one.  */
 +
 +  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
 +  if (yychar == YYEMPTY)
 +    {
 +      YYDPRINTF ((stderr, "Reading a token: "));
 +      yychar = YYLEX;
 +    }
 +
 +  if (yychar <= YYEOF)
 +    {
 +      yychar = yytoken = YYEOF;
 +      YYDPRINTF ((stderr, "Now at end of input.\n"));
 +    }
 +  else
 +    {
 +      yytoken = YYTRANSLATE (yychar);
 +      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
 +    }
 +
 +  /* If the proper action on seeing token YYTOKEN is to reduce or to
 +     detect an error, take that action.  */
 +  yyn += yytoken;
 +  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
 +    goto yydefault;
 +  yyn = yytable[yyn];
 +  if (yyn <= 0)
 +    {
 +      if (yytable_value_is_error (yyn))
 +        goto yyerrlab;
 +      yyn = -yyn;
 +      goto yyreduce;
 +    }
 +
 +  /* Count tokens shifted since error; after three, turn off error
 +     status.  */
 +  if (yyerrstatus)
 +    yyerrstatus--;
 +
 +  /* Shift the lookahead token.  */
 +  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 +
 +  /* Discard the shifted token.  */
 +  yychar = YYEMPTY;
 +
 +  yystate = yyn;
 +  *++yyvsp = yylval;
 +
 +  goto yynewstate;
 +
 +
 +/*-----------------------------------------------------------.
 +| yydefault -- do the default action for the current state.  |
 +`-----------------------------------------------------------*/
 +yydefault:
 +  yyn = yydefact[yystate];
 +  if (yyn == 0)
 +    goto yyerrlab;
 +  goto yyreduce;
 +
 +
 +/*-----------------------------.
 +| yyreduce -- Do a reduction.  |
 +`-----------------------------*/
 +yyreduce:
 +  /* yyn is the number of a rule to reduce with.  */
 +  yylen = yyr2[yyn];
 +
 +  /* If YYLEN is nonzero, implement the default value of the action:
 +     `$$ = $1'.
 +
 +     Otherwise, the following line sets YYVAL to garbage.
 +     This behavior is undocumented and Bison
 +     users should not rely upon it.  Assigning to YYVAL
 +     unconditionally makes the parser a bit smaller, and it avoids a
 +     GCC warning that YYVAL may be used uninitialized.  */
 +  yyval = yyvsp[1-yylen];
 +
 +
 +  YY_REDUCE_PRINT (yyn);
 +  switch (yyn)
 +    {
 +        case 4:
 +
 +/* Line 1806 of yacc.c  */
 +#line 71 "a.y"
 +    {
 +              if((yyvsp[(1) - (2)].sym)->value != pc)
 +                      yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name);
 +              (yyvsp[(1) - (2)].sym)->value = pc;
 +      }
 +    break;
 +
 +  case 6:
 +
 +/* Line 1806 of yacc.c  */
 +#line 78 "a.y"
 +    {
 +              (yyvsp[(1) - (2)].sym)->type = LLAB;
 +              (yyvsp[(1) - (2)].sym)->value = pc;
 +      }
 +    break;
 +
 +  case 8:
 +
 +/* Line 1806 of yacc.c  */
 +#line 84 "a.y"
 +    {
 +              (yyvsp[(1) - (4)].sym)->type = LVAR;
 +              (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 9:
 +
 +/* Line 1806 of yacc.c  */
 +#line 89 "a.y"
 +    {
 +              if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval))
 +                      yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name);
 +              (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 10:
 +
 +/* Line 1806 of yacc.c  */
 +#line 95 "a.y"
 +    {
 +              nosched = (yyvsp[(1) - (2)].lval);
 +      }
 +    break;
 +
 +  case 14:
 +
 +/* Line 1806 of yacc.c  */
 +#line 107 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 15:
 +
 +/* Line 1806 of yacc.c  */
 +#line 111 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 16:
 +
 +/* Line 1806 of yacc.c  */
 +#line 115 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 17:
 +
 +/* Line 1806 of yacc.c  */
 +#line 119 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 18:
 +
 +/* Line 1806 of yacc.c  */
 +#line 123 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 19:
 +
 +/* Line 1806 of yacc.c  */
 +#line 127 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 20:
 +
 +/* Line 1806 of yacc.c  */
 +#line 134 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 21:
 +
 +/* Line 1806 of yacc.c  */
 +#line 138 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 22:
 +
 +/* Line 1806 of yacc.c  */
 +#line 142 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 23:
 +
 +/* Line 1806 of yacc.c  */
 +#line 146 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 24:
 +
 +/* Line 1806 of yacc.c  */
 +#line 150 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 25:
 +
 +/* Line 1806 of yacc.c  */
 +#line 154 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 26:
 +
 +/* Line 1806 of yacc.c  */
 +#line 161 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 27:
 +
 +/* Line 1806 of yacc.c  */
 +#line 165 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 28:
 +
 +/* Line 1806 of yacc.c  */
 +#line 169 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 29:
 +
 +/* Line 1806 of yacc.c  */
 +#line 173 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 30:
 +
 +/* Line 1806 of yacc.c  */
 +#line 180 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 31:
 +
 +/* Line 1806 of yacc.c  */
 +#line 184 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 32:
 +
 +/* Line 1806 of yacc.c  */
 +#line 191 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 33:
 +
 +/* Line 1806 of yacc.c  */
 +#line 195 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 34:
 +
 +/* Line 1806 of yacc.c  */
 +#line 199 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 35:
 +
 +/* Line 1806 of yacc.c  */
 +#line 203 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 36:
 +
 +/* Line 1806 of yacc.c  */
 +#line 207 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 37:
 +
 +/* Line 1806 of yacc.c  */
 +#line 211 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
 +      }
 +    break;
 +
 +  case 38:
 +
 +/* Line 1806 of yacc.c  */
 +#line 218 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 39:
 +
 +/* Line 1806 of yacc.c  */
 +#line 222 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 40:
 +
 +/* Line 1806 of yacc.c  */
 +#line 226 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 41:
 +
 +/* Line 1806 of yacc.c  */
 +#line 236 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 42:
 +
 +/* Line 1806 of yacc.c  */
 +#line 240 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 43:
 +
 +/* Line 1806 of yacc.c  */
 +#line 244 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 44:
 +
 +/* Line 1806 of yacc.c  */
 +#line 248 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 45:
 +
 +/* Line 1806 of yacc.c  */
 +#line 252 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 46:
 +
 +/* Line 1806 of yacc.c  */
 +#line 256 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 47:
 +
 +/* Line 1806 of yacc.c  */
 +#line 260 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 48:
 +
 +/* Line 1806 of yacc.c  */
 +#line 264 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 49:
 +
 +/* Line 1806 of yacc.c  */
 +#line 268 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 50:
 +
 +/* Line 1806 of yacc.c  */
 +#line 272 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 51:
 +
 +/* Line 1806 of yacc.c  */
 +#line 276 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 52:
 +
 +/* Line 1806 of yacc.c  */
 +#line 280 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 53:
 +
 +/* Line 1806 of yacc.c  */
 +#line 284 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr));
 +      }
 +    break;
 +
 +  case 54:
 +
 +/* Line 1806 of yacc.c  */
 +#line 291 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 55:
 +
 +/* Line 1806 of yacc.c  */
 +#line 298 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 56:
 +
 +/* Line 1806 of yacc.c  */
 +#line 302 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 57:
 +
 +/* Line 1806 of yacc.c  */
 +#line 309 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 58:
 +
 +/* Line 1806 of yacc.c  */
 +#line 313 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 59:
 +
 +/* Line 1806 of yacc.c  */
 +#line 321 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 60:
 +
 +/* Line 1806 of yacc.c  */
 +#line 325 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 61:
 +
 +/* Line 1806 of yacc.c  */
 +#line 329 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 62:
 +
 +/* Line 1806 of yacc.c  */
 +#line 333 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 63:
 +
 +/* Line 1806 of yacc.c  */
 +#line 337 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 64:
 +
 +/* Line 1806 of yacc.c  */
 +#line 341 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 65:
 +
 +/* Line 1806 of yacc.c  */
 +#line 345 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 66:
 +
 +/* Line 1806 of yacc.c  */
 +#line 349 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 67:
 +
 +/* Line 1806 of yacc.c  */
 +#line 358 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
 +      }
 +    break;
 +
 +  case 68:
 +
 +/* Line 1806 of yacc.c  */
 +#line 362 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
 +      }
 +    break;
 +
 +  case 69:
 +
 +/* Line 1806 of yacc.c  */
 +#line 366 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr));
 +      }
 +    break;
 +
 +  case 70:
 +
 +/* Line 1806 of yacc.c  */
 +#line 370 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
 +      }
 +    break;
 +
 +  case 71:
 +
 +/* Line 1806 of yacc.c  */
 +#line 374 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
 +      }
 +    break;
 +
 +  case 72:
 +
 +/* Line 1806 of yacc.c  */
 +#line 378 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr));
 +      }
 +    break;
 +
 +  case 73:
 +
 +/* Line 1806 of yacc.c  */
 +#line 382 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 74:
 +
 +/* Line 1806 of yacc.c  */
 +#line 386 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 75:
 +
 +/* Line 1806 of yacc.c  */
 +#line 390 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr));
 +      }
 +    break;
 +
 +  case 76:
 +
 +/* Line 1806 of yacc.c  */
 +#line 394 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 77:
 +
 +/* Line 1806 of yacc.c  */
 +#line 398 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 78:
 +
 +/* Line 1806 of yacc.c  */
 +#line 402 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
 +      }
 +    break;
 +
 +  case 79:
 +
 +/* Line 1806 of yacc.c  */
 +#line 406 "a.y"
 +    {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = (yyvsp[(2) - (6)].lval);
 +              outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 80:
 +
 +/* Line 1806 of yacc.c  */
 +#line 414 "a.y"
 +    {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = (yyvsp[(2) - (6)].lval);
 +              outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 81:
 +
 +/* Line 1806 of yacc.c  */
 +#line 422 "a.y"
 +    {
 +              Addr g;
 +              g = nullgen;
 +              g.type = D_CONST;
 +              g.offset = (yyvsp[(2) - (8)].lval);
 +              outcode((yyvsp[(1) - (8)].lval), &g, (yyvsp[(4) - (8)].lval), &(yyvsp[(7) - (8)].addr));
 +      }
 +    break;
 +
 +  case 82:
 +
 +/* Line 1806 of yacc.c  */
 +#line 433 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
 +      }
 +    break;
 +
 +  case 83:
 +
 +/* Line 1806 of yacc.c  */
 +#line 437 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
 +      }
 +    break;
 +
 +  case 84:
 +
 +/* Line 1806 of yacc.c  */
 +#line 441 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 85:
 +
 +/* Line 1806 of yacc.c  */
 +#line 445 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 86:
 +
 +/* Line 1806 of yacc.c  */
 +#line 452 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 87:
 +
 +/* Line 1806 of yacc.c  */
 +#line 456 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 88:
 +
 +/* Line 1806 of yacc.c  */
 +#line 460 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 89:
 +
 +/* Line 1806 of yacc.c  */
 +#line 464 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
 +      }
 +    break;
 +
 +  case 90:
 +
 +/* Line 1806 of yacc.c  */
 +#line 468 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 91:
 +
 +/* Line 1806 of yacc.c  */
 +#line 472 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
 +      }
 +    break;
 +
 +  case 92:
 +
 +/* Line 1806 of yacc.c  */
 +#line 479 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 93:
 +
 +/* Line 1806 of yacc.c  */
 +#line 483 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 94:
 +
 +/* Line 1806 of yacc.c  */
 +#line 487 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
 +      }
 +    break;
 +
 +  case 95:
 +
 +/* Line 1806 of yacc.c  */
 +#line 491 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
 +      }
 +    break;
 +
 +  case 96:
 +
 +/* Line 1806 of yacc.c  */
 +#line 498 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
 +      }
 +    break;
 +
 +  case 97:
 +
 +/* Line 1806 of yacc.c  */
 +#line 502 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
 +      }
 +    break;
 +
 +  case 98:
 +
 +/* Line 1806 of yacc.c  */
 +#line 506 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
 +      }
 +    break;
 +
 +  case 99:
 +
 +/* Line 1806 of yacc.c  */
 +#line 510 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
 +      }
 +    break;
 +
 +  case 100:
 +
 +/* Line 1806 of yacc.c  */
 +#line 517 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 101:
 +
 +/* Line 1806 of yacc.c  */
 +#line 521 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 102:
 +
 +/* Line 1806 of yacc.c  */
 +#line 529 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 103:
 +
 +/* Line 1806 of yacc.c  */
 +#line 533 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 104:
 +
 +/* Line 1806 of yacc.c  */
 +#line 537 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 105:
 +
 +/* Line 1806 of yacc.c  */
 +#line 541 "a.y"
 +    {
 +              outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 106:
 +
 +/* Line 1806 of yacc.c  */
 +#line 545 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 107:
 +
 +/* Line 1806 of yacc.c  */
 +#line 549 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 108:
 +
 +/* Line 1806 of yacc.c  */
 +#line 553 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 109:
 +
 +/* Line 1806 of yacc.c  */
 +#line 560 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 110:
 +
 +/* Line 1806 of yacc.c  */
 +#line 564 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 111:
 +
 +/* Line 1806 of yacc.c  */
 +#line 568 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 112:
 +
 +/* Line 1806 of yacc.c  */
 +#line 572 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
 +      }
 +    break;
 +
 +  case 113:
 +
 +/* Line 1806 of yacc.c  */
 +#line 576 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
 +      }
 +    break;
 +
 +  case 114:
 +
 +/* Line 1806 of yacc.c  */
 +#line 580 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 115:
 +
 +/* Line 1806 of yacc.c  */
 +#line 587 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 116:
 +
 +/* Line 1806 of yacc.c  */
 +#line 591 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 117:
 +
 +/* Line 1806 of yacc.c  */
 +#line 598 "a.y"
 +    {
 +              if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST)
 +                      yyerror("arguments to PCDATA must be integer constants");
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 118:
 +
 +/* Line 1806 of yacc.c  */
 +#line 607 "a.y"
 +    {
 +              if((yyvsp[(2) - (4)].addr).type != D_CONST)
 +                      yyerror("index for FUNCDATA must be integer constant");
 +              if((yyvsp[(4) - (4)].addr).type != D_EXTERN && (yyvsp[(4) - (4)].addr).type != D_STATIC && (yyvsp[(4) - (4)].addr).type != D_OREG)
 +                      yyerror("value for FUNCDATA must be symbol reference");
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 119:
 +
 +/* Line 1806 of yacc.c  */
 +#line 618 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 120:
 +
 +/* Line 1806 of yacc.c  */
 +#line 625 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
 +      }
 +    break;
 +
 +  case 121:
 +
 +/* Line 1806 of yacc.c  */
 +#line 629 "a.y"
 +    {
 +              (yyvsp[(6) - (6)].addr).offset &= 0xffffffffull;
 +              (yyvsp[(6) - (6)].addr).offset |= (vlong)ArgsSizeUnknown << 32;
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 122:
 +
 +/* Line 1806 of yacc.c  */
 +#line 635 "a.y"
 +    {
 +              (yyvsp[(6) - (8)].addr).offset &= 0xffffffffull;
 +              (yyvsp[(6) - (8)].addr).offset |= ((yyvsp[(8) - (8)].lval) & 0xffffffffull) << 32;
 +              outcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr));
 +      }
 +    break;
 +
 +  case 123:
 +
 +/* Line 1806 of yacc.c  */
 +#line 644 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 124:
 +
 +/* Line 1806 of yacc.c  */
 +#line 648 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 125:
 +
 +/* Line 1806 of yacc.c  */
 +#line 652 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
 +      }
 +    break;
 +
 +  case 126:
 +
 +/* Line 1806 of yacc.c  */
 +#line 659 "a.y"
 +    {
 +              outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
 +      }
 +    break;
 +
 +  case 127:
 +
 +/* Line 1806 of yacc.c  */
 +#line 665 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_BRANCH;
 +              (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
 +      }
 +    break;
 +
 +  case 128:
 +
 +/* Line 1806 of yacc.c  */
 +#line 671 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              if(pass == 2)
 +                      yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name);
 +              (yyval.addr).type = D_BRANCH;
 +              (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 129:
 +
 +/* Line 1806 of yacc.c  */
 +#line 679 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_BRANCH;
 +              (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 130:
 +
 +/* Line 1806 of yacc.c  */
 +#line 687 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_REG;
 +              (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 133:
 +
 +/* Line 1806 of yacc.c  */
 +#line 699 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_SPR;
 +              (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 134:
 +
 +/* Line 1806 of yacc.c  */
 +#line 707 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_CREG;
 +              (yyval.addr).reg = NREG;        /* whole register */
 +      }
 +    break;
 +
 +  case 135:
 +
 +/* Line 1806 of yacc.c  */
 +#line 715 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_SPR;
 +              (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 136:
 +
 +/* Line 1806 of yacc.c  */
 +#line 723 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_MSR;
 +      }
 +    break;
 +
 +  case 137:
 +
 +/* Line 1806 of yacc.c  */
 +#line 730 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_SPR;
 +              (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 138:
 +
 +/* Line 1806 of yacc.c  */
 +#line 736 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = (yyvsp[(1) - (4)].lval);
 +              (yyval.addr).offset = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 140:
 +
 +/* Line 1806 of yacc.c  */
 +#line 745 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FPSCR;
 +              (yyval.addr).reg = NREG;
 +      }
 +    break;
 +
 +  case 141:
 +
 +/* Line 1806 of yacc.c  */
 +#line 753 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FPSCR;
 +              (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 142:
 +
 +/* Line 1806 of yacc.c  */
 +#line 761 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FREG;
 +              (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 143:
 +
 +/* Line 1806 of yacc.c  */
 +#line 767 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FREG;
 +              (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 144:
 +
 +/* Line 1806 of yacc.c  */
 +#line 775 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_CREG;
 +              (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 145:
 +
 +/* Line 1806 of yacc.c  */
 +#line 781 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_CREG;
 +              (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 146:
 +
 +/* Line 1806 of yacc.c  */
 +#line 789 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_REG;
 +              (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
 +      }
 +    break;
 +
 +  case 147:
 +
 +/* Line 1806 of yacc.c  */
 +#line 797 "a.y"
 +    {
 +              int mb, me;
 +              uint32 v;
 +
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_CONST;
 +              mb = (yyvsp[(1) - (3)].lval);
 +              me = (yyvsp[(3) - (3)].lval);
 +              if(mb < 0 || mb > 31 || me < 0 || me > 31){
 +                      yyerror("illegal mask start/end value(s)");
 +                      mb = me = 0;
 +              }
 +              if(mb <= me)
 +                      v = ((uint32)~0L>>mb) & (~0L<<(31-me));
 +              else
 +                      v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
 +              (yyval.addr).offset = v;
 +      }
 +    break;
 +
 +  case 148:
 +
 +/* Line 1806 of yacc.c  */
 +#line 818 "a.y"
 +    {
 +              (yyval.addr) = (yyvsp[(2) - (2)].addr);
 +              (yyval.addr).type = D_CONST;
 +      }
 +    break;
 +
 +  case 149:
 +
 +/* Line 1806 of yacc.c  */
 +#line 823 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_SCONST;
 +              memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
 +      }
 +    break;
 +
 +  case 150:
 +
 +/* Line 1806 of yacc.c  */
 +#line 831 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FCONST;
 +              (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
 +      }
 +    break;
 +
 +  case 151:
 +
 +/* Line 1806 of yacc.c  */
 +#line 837 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_FCONST;
 +              (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
 +      }
 +    break;
 +
 +  case 152:
 +
 +/* Line 1806 of yacc.c  */
 +#line 844 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_CONST;
 +              (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 154:
 +
 +/* Line 1806 of yacc.c  */
 +#line 853 "a.y"
 +    {
 +              if((yyval.lval) < 0 || (yyval.lval) >= NREG)
 +                      print("register value out of range\n");
 +              (yyval.lval) = (yyvsp[(3) - (4)].lval);
 +      }
 +    break;
 +
 +  case 155:
 +
 +/* Line 1806 of yacc.c  */
 +#line 861 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
 +              (yyval.addr).offset = 0;
 +      }
 +    break;
 +
 +  case 156:
 +
 +/* Line 1806 of yacc.c  */
 +#line 868 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).reg = (yyvsp[(2) - (5)].lval);
 +              (yyval.addr).scale = (yyvsp[(4) - (5)].lval);
 +              (yyval.addr).offset = 0;
 +      }
 +    break;
 +
 +  case 158:
 +
 +/* Line 1806 of yacc.c  */
 +#line 879 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
 +              (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
 +      }
 +    break;
 +
 +  case 159:
 +
 +/* Line 1806 of yacc.c  */
 +#line 888 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).name = (yyvsp[(3) - (4)].lval);
 +              (yyval.addr).sym = nil;
 +              (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
 +      }
 +    break;
 +
 +  case 160:
 +
 +/* Line 1806 of yacc.c  */
 +#line 896 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).name = (yyvsp[(4) - (5)].lval);
 +              (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
 +              (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
 +      }
 +    break;
 +
 +  case 161:
 +
 +/* Line 1806 of yacc.c  */
 +#line 904 "a.y"
 +    {
 +              (yyval.addr) = nullgen;
 +              (yyval.addr).type = D_OREG;
 +              (yyval.addr).name = D_STATIC;
 +              (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 0);
 +              (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
 +      }
 +    break;
 +
 +  case 164:
 +
 +/* Line 1806 of yacc.c  */
 +#line 916 "a.y"
 +    {
 +              (yyval.lval) = 0;
 +      }
 +    break;
 +
 +  case 165:
 +
 +/* Line 1806 of yacc.c  */
 +#line 920 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 166:
 +
 +/* Line 1806 of yacc.c  */
 +#line 924 "a.y"
 +    {
 +              (yyval.lval) = -(yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 171:
 +
 +/* Line 1806 of yacc.c  */
 +#line 936 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
 +      }
 +    break;
 +
 +  case 172:
 +
 +/* Line 1806 of yacc.c  */
 +#line 940 "a.y"
 +    {
 +              (yyval.lval) = -(yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 173:
 +
 +/* Line 1806 of yacc.c  */
 +#line 944 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 174:
 +
 +/* Line 1806 of yacc.c  */
 +#line 948 "a.y"
 +    {
 +              (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
 +      }
 +    break;
 +
 +  case 175:
 +
 +/* Line 1806 of yacc.c  */
 +#line 952 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(2) - (3)].lval);
 +      }
 +    break;
 +
 +  case 177:
 +
 +/* Line 1806 of yacc.c  */
 +#line 959 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 178:
 +
 +/* Line 1806 of yacc.c  */
 +#line 963 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 179:
 +
 +/* Line 1806 of yacc.c  */
 +#line 967 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 180:
 +
 +/* Line 1806 of yacc.c  */
 +#line 971 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 181:
 +
 +/* Line 1806 of yacc.c  */
 +#line 975 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 182:
 +
 +/* Line 1806 of yacc.c  */
 +#line 979 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
 +      }
 +    break;
 +
 +  case 183:
 +
 +/* Line 1806 of yacc.c  */
 +#line 983 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
 +      }
 +    break;
 +
 +  case 184:
 +
 +/* Line 1806 of yacc.c  */
 +#line 987 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 185:
 +
 +/* Line 1806 of yacc.c  */
 +#line 991 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +  case 186:
 +
 +/* Line 1806 of yacc.c  */
 +#line 995 "a.y"
 +    {
 +              (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
 +      }
 +    break;
 +
 +
 +
 +/* Line 1806 of yacc.c  */
 +#line 3566 "y.tab.c"
 +      default: break;
 +    }
 +  /* User semantic actions sometimes alter yychar, and that requires
 +     that yytoken be updated with the new translation.  We take the
 +     approach of translating immediately before every use of yytoken.
 +     One alternative is translating here after every semantic action,
 +     but that translation would be missed if the semantic action invokes
 +     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
 +     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
 +     incorrect destructor might then be invoked immediately.  In the
 +     case of YYERROR or YYBACKUP, subsequent parser actions might lead
 +     to an incorrect destructor call or verbose syntax error message
 +     before the lookahead is translated.  */
 +  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 +
 +  YYPOPSTACK (yylen);
 +  yylen = 0;
 +  YY_STACK_PRINT (yyss, yyssp);
 +
 +  *++yyvsp = yyval;
 +
 +  /* Now `shift' the result of the reduction.  Determine what state
 +     that goes to, based on the state we popped back to and the rule
 +     number reduced by.  */
 +
 +  yyn = yyr1[yyn];
 +
 +  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
 +  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
 +    yystate = yytable[yystate];
 +  else
 +    yystate = yydefgoto[yyn - YYNTOKENS];
 +
 +  goto yynewstate;
 +
 +
 +/*------------------------------------.
 +| yyerrlab -- here on detecting error |
 +`------------------------------------*/
 +yyerrlab:
 +  /* Make sure we have latest lookahead translation.  See comments at
 +     user semantic actions for why this is necessary.  */
 +  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
 +
 +  /* If not already recovering from an error, report this error.  */
 +  if (!yyerrstatus)
 +    {
 +      ++yynerrs;
 +#if ! YYERROR_VERBOSE
 +      yyerror (YY_("syntax error"));
 +#else
 +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
 +                                        yyssp, yytoken)
 +      {
 +        char const *yymsgp = YY_("syntax error");
 +        int yysyntax_error_status;
 +        yysyntax_error_status = YYSYNTAX_ERROR;
 +        if (yysyntax_error_status == 0)
 +          yymsgp = yymsg;
 +        else if (yysyntax_error_status == 1)
 +          {
 +            if (yymsg != yymsgbuf)
 +              YYSTACK_FREE (yymsg);
 +            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
 +            if (!yymsg)
 +              {
 +                yymsg = yymsgbuf;
 +                yymsg_alloc = sizeof yymsgbuf;
 +                yysyntax_error_status = 2;
 +              }
 +            else
 +              {
 +                yysyntax_error_status = YYSYNTAX_ERROR;
 +                yymsgp = yymsg;
 +              }
 +          }
 +        yyerror (yymsgp);
 +        if (yysyntax_error_status == 2)
 +          goto yyexhaustedlab;
 +      }
 +# undef YYSYNTAX_ERROR
 +#endif
 +    }
 +
 +
 +
 +  if (yyerrstatus == 3)
 +    {
 +      /* If just tried and failed to reuse lookahead token after an
 +       error, discard it.  */
 +
 +      if (yychar <= YYEOF)
 +      {
 +        /* Return failure if at end of input.  */
 +        if (yychar == YYEOF)
 +          YYABORT;
 +      }
 +      else
 +      {
 +        yydestruct ("Error: discarding",
 +                    yytoken, &yylval);
 +        yychar = YYEMPTY;
 +      }
 +    }
 +
 +  /* Else will try to reuse lookahead token after shifting the error
 +     token.  */
 +  goto yyerrlab1;
 +
 +
 +/*---------------------------------------------------.
 +| yyerrorlab -- error raised explicitly by YYERROR.  |
 +`---------------------------------------------------*/
 +yyerrorlab:
 +
 +  /* Pacify compilers like GCC when the user code never invokes
 +     YYERROR and the label yyerrorlab therefore never appears in user
 +     code.  */
 +  if (/*CONSTCOND*/ 0)
 +     goto yyerrorlab;
 +
 +  /* Do not reclaim the symbols of the rule which action triggered
 +     this YYERROR.  */
 +  YYPOPSTACK (yylen);
 +  yylen = 0;
 +  YY_STACK_PRINT (yyss, yyssp);
 +  yystate = *yyssp;
 +  goto yyerrlab1;
 +
 +
 +/*-------------------------------------------------------------.
 +| yyerrlab1 -- common code for both syntax error and YYERROR.  |
 +`-------------------------------------------------------------*/
 +yyerrlab1:
 +  yyerrstatus = 3;    /* Each real token shifted decrements this.  */
 +
 +  for (;;)
 +    {
 +      yyn = yypact[yystate];
 +      if (!yypact_value_is_default (yyn))
 +      {
 +        yyn += YYTERROR;
 +        if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
 +          {
 +            yyn = yytable[yyn];
 +            if (0 < yyn)
 +              break;
 +          }
 +      }
 +
 +      /* Pop the current state because it cannot handle the error token.  */
 +      if (yyssp == yyss)
 +      YYABORT;
 +
 +
 +      yydestruct ("Error: popping",
 +                yystos[yystate], yyvsp);
 +      YYPOPSTACK (1);
 +      yystate = *yyssp;
 +      YY_STACK_PRINT (yyss, yyssp);
 +    }
 +
 +  *++yyvsp = yylval;
 +
 +
 +  /* Shift the error token.  */
 +  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
 +
 +  yystate = yyn;
 +  goto yynewstate;
 +
 +
 +/*-------------------------------------.
 +| yyacceptlab -- YYACCEPT comes here.  |
 +`-------------------------------------*/
 +yyacceptlab:
 +  yyresult = 0;
 +  goto yyreturn;
 +
 +/*-----------------------------------.
 +| yyabortlab -- YYABORT comes here.  |
 +`-----------------------------------*/
 +yyabortlab:
 +  yyresult = 1;
 +  goto yyreturn;
 +
 +#if !defined(yyoverflow) || YYERROR_VERBOSE
 +/*-------------------------------------------------.
 +| yyexhaustedlab -- memory exhaustion comes here.  |
 +`-------------------------------------------------*/
 +yyexhaustedlab:
 +  yyerror (YY_("memory exhausted"));
 +  yyresult = 2;
 +  /* Fall through.  */
 +#endif
 +
 +yyreturn:
 +  if (yychar != YYEMPTY)
 +    {
 +      /* Make sure we have latest lookahead translation.  See comments at
 +         user semantic actions for why this is necessary.  */
 +      yytoken = YYTRANSLATE (yychar);
 +      yydestruct ("Cleanup: discarding lookahead",
 +                  yytoken, &yylval);
 +    }
 +  /* Do not reclaim the symbols of the rule which action triggered
 +     this YYABORT or YYACCEPT.  */
 +  YYPOPSTACK (yylen);
 +  YY_STACK_PRINT (yyss, yyssp);
 +  while (yyssp != yyss)
 +    {
 +      yydestruct ("Cleanup: popping",
 +                yystos[*yyssp], yyvsp);
 +      YYPOPSTACK (1);
 +    }
 +#ifndef yyoverflow
 +  if (yyss != yyssa)
 +    YYSTACK_FREE (yyss);
 +#endif
 +#if YYERROR_VERBOSE
 +  if (yymsg != yymsgbuf)
 +    YYSTACK_FREE (yymsg);
 +#endif
 +  /* Make sure YYID is used.  */
 +  return YYID (yyresult);
 +}
 +
 +
 +
index aeedc60c06525da006f1cbdfb4c137960a0dcc6d,0000000000000000000000000000000000000000..d756af93bb06882ba8cdd23a1f0e6403601dced3
mode 100644,000000..100644
--- /dev/null
@@@ -1,1151 -1,0 +1,1151 @@@
- #include "../../pkg/runtime/funcdata.h"
 +// cmd/9c/cgen.c from Vita Nuova.
 +//
 +//    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-2008 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-2008 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 "gc.h"
++#include "../../runtime/funcdata.h"
 +
 +void
 +cgen(Node *n, Node *nn)
 +{
 +      Node *l, *r;
 +      Prog *p1;
 +      Node nod, nod1, nod2, nod3, nod4;
 +      int o;
 +      int32 v, curs;
 +
 +      if(debug['g']) {
 +              prtree(nn, "cgen lhs");
 +              prtree(n, "cgen");
 +      }
 +      if(n == Z || n->type == T)
 +              return;
 +      if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
 +              sugen(n, nn, n->type->width);
 +              return;
 +      }
 +      l = n->left;
 +      r = n->right;
 +      o = n->op;
 +      if(n->addable >= INDEXED) {
 +              if(nn == Z) {
 +                      switch(o) {
 +                      default:
 +                              nullwarn(Z, Z);
 +                              break;
 +                      case OINDEX:
 +                              nullwarn(l, r);
 +                              break;
 +                      }
 +                      return;
 +              }
 +              gmove(n, nn);
 +              return;
 +      }
 +      curs = cursafe;
 +
 +      if(n->complex >= FNX)
 +      if(l->complex >= FNX)
 +      if(r != Z && r->complex >= FNX)
 +      switch(o) {
 +      default:
 +              regret(&nod, r, 0, 0);
 +              cgen(r, &nod);
 +
 +              regsalloc(&nod1, r);
 +              gopcode(OAS, &nod, Z, &nod1);
 +
 +              regfree(&nod);
 +              nod = *n;
 +              nod.right = &nod1;
 +              cgen(&nod, nn);
 +              return;
 +
 +      case OFUNC:
 +      case OCOMMA:
 +      case OANDAND:
 +      case OOROR:
 +      case OCOND:
 +      case ODOT:
 +              break;
 +      }
 +
 +      switch(o) {
 +      default:
 +              diag(n, "unknown op in cgen: %O", o);
 +              break;
 +
 +      case OAS:
 +              if(l->op == OBIT)
 +                      goto bitas;
 +              if(l->addable >= INDEXED) {
 +                      if(nn != Z || r->addable < INDEXED) {
 +                              regalloc(&nod, r, nn);
 +                              cgen(r, &nod);
 +                              gmove(&nod, l);
 +                              regfree(&nod);
 +                      } else
 +                              gmove(r, l);
 +                      break;
 +              }
 +              if(l->complex >= r->complex) {
 +                      reglcgen(&nod1, l, Z);
 +                      if(r->addable >= INDEXED) {
 +                              gmove(r, &nod1);
 +                              if(nn != Z)
 +                                      gmove(r, nn);
 +                              regfree(&nod1);
 +                              break;
 +                      }
 +                      regalloc(&nod, r, nn);
 +                      cgen(r, &nod);
 +              } else {
 +                      regalloc(&nod, r, nn);
 +                      cgen(r, &nod);
 +                      reglcgen(&nod1, l, Z);
 +              }
 +              gmove(&nod, &nod1);
 +              regfree(&nod);
 +              regfree(&nod1);
 +              break;
 +
 +      bitas:
 +              n = l->left;
 +              regalloc(&nod, r, nn);
 +              if(l->complex >= r->complex) {
 +                      reglcgen(&nod1, n, Z);
 +                      cgen(r, &nod);
 +              } else {
 +                      cgen(r, &nod);
 +                      reglcgen(&nod1, n, Z);
 +              }
 +              regalloc(&nod2, n, Z);
 +              gopcode(OAS, &nod1, Z, &nod2);
 +              bitstore(l, &nod, &nod1, &nod2, nn);
 +              break;
 +
 +      case OBIT:
 +              if(nn == Z) {
 +                      nullwarn(l, Z);
 +                      break;
 +              }
 +              bitload(n, &nod, Z, Z, nn);
 +              gopcode(OAS, &nod, Z, nn);
 +              regfree(&nod);
 +              break;
 +
 +      case OXOR:
 +              if(nn != Z)
 +              if(r->op == OCONST && r->vconst == -1){
 +                      cgen(l, nn);
 +                      gopcode(OCOM, nn, Z, nn);
 +                      break;
 +              }
 +
 +      case OADD:
 +      case OSUB:
 +      case OAND:
 +      case OOR:
 +      case OLSHR:
 +      case OASHL:
 +      case OASHR:
 +              /*
 +               * immediate operands
 +               */
 +              if(nn != Z &&
 +                 r->op == OCONST &&
 +                 !typefd[n->type->etype] &&
 +                 immconst(r)) {
 +                      cgen(l, nn);
 +                      if(r->vconst == 0)
 +                      if(o != OAND)
 +                              break;
 +                      if(nn != Z)
 +                              gopcode(o, r, Z, nn);
 +                      break;
 +              }
 +
 +      case OMUL:
 +      case OLMUL:
 +      case OLDIV:
 +      case OLMOD:
 +      case ODIV:
 +      case OMOD:
 +              if(nn == Z) {
 +                      nullwarn(l, r);
 +                      break;
 +              }
 +              if(o == OMUL || o == OLMUL) {
 +                      if(mulcon(n, nn))
 +                              break;
 +                      if(debug['M'])
 +                              print("%L multiply\n", n->lineno);
 +              }
 +              if(l->complex >= r->complex) {
 +                      regalloc(&nod, l, nn);
 +                      cgen(l, &nod);
 +                      regalloc(&nod1, l, Z);          /* note: l used for type, so shifts work! */
 +                      cgen(r, &nod1);
 +                      gopcode(o, &nod1, Z, &nod);
 +              } else {
 +                      regalloc(&nod, l, nn);          /* note: l used for type, so shifts work! */
 +                      cgen(r, &nod);
 +                      regalloc(&nod1, l, Z);
 +                      cgen(l, &nod1);
 +                      gopcode(o, &nod, &nod1, &nod);
 +              }
 +              gopcode(OAS, &nod, Z, nn);
 +              regfree(&nod);
 +              regfree(&nod1);
 +              break;
 +
 +      case OASLSHR:
 +      case OASASHL:
 +      case OASASHR:
 +      case OASAND:
 +      case OASADD:
 +      case OASSUB:
 +      case OASXOR:
 +      case OASOR:
 +              if(l->op == OBIT)
 +                      goto asbitop;
 +              if(r->op == OCONST &&
 +                 !typefd[n->type->etype] &&
 +                 immconst(r)) {
 +                      if(l->addable < INDEXED)
 +                              reglcgen(&nod2, l, Z);
 +                      else
 +                              nod2 = *l;
 +                      regalloc(&nod, l, nn);          /* note: l used for type, so shifts work! */
 +                      gopcode(OAS, &nod2, Z, &nod);
 +                      gopcode(o, r, Z, &nod);
 +                      gopcode(OAS, &nod, Z, &nod2);
 +      
 +                      regfree(&nod);
 +                      if(l->addable < INDEXED)
 +                              regfree(&nod2);
 +                      break;
 +              }
 +
 +      case OASLMUL:
 +      case OASLDIV:
 +      case OASLMOD:
 +      case OASMUL:
 +      case OASDIV:
 +      case OASMOD:
 +              if(l->op == OBIT)
 +                      goto asbitop;
 +              if(l->complex >= r->complex) {
 +                      if(l->addable < INDEXED)
 +                              reglcgen(&nod2, l, Z);
 +                      else
 +                              nod2 = *l;
 +                      regalloc(&nod, n, nn);
 +                      cgen(r, &nod);
 +              } else {
 +                      regalloc(&nod, n, nn);
 +                      cgen(r, &nod);
 +                      if(l->addable < INDEXED)
 +                              reglcgen(&nod2, l, Z);
 +                      else
 +                              nod2 = *l;
 +              }
 +              regalloc(&nod1, n, Z);
 +              gopcode(OAS, &nod2, Z, &nod1);
 +              if(nod1.type->etype != nod.type->etype){
 +                      regalloc(&nod3, &nod, Z);
 +                      gmove(&nod1, &nod3);
 +                      regfree(&nod1);
 +                      nod1 = nod3;
 +              }
 +              gopcode(o, &nod, &nod1, &nod);
 +              gmove(&nod, &nod2);
 +              if(nn != Z)
 +                      gmove(&nod, nn);
 +              regfree(&nod);
 +              regfree(&nod1);
 +              if(l->addable < INDEXED)
 +                      regfree(&nod2);
 +              break;
 +
 +      asbitop:
 +              regalloc(&nod4, n, nn);
 +              regalloc(&nod3, r, Z);
 +              if(l->complex >= r->complex) {
 +                      bitload(l, &nod, &nod1, &nod2, &nod4);
 +                      cgen(r, &nod3);
 +              } else {
 +                      cgen(r, &nod3);
 +                      bitload(l, &nod, &nod1, &nod2, &nod4);
 +              }
 +              gmove(&nod, &nod4);
 +              gopcode(n->op, &nod3, Z, &nod4);
 +              regfree(&nod3);
 +              gmove(&nod4, &nod);
 +              regfree(&nod4);
 +              bitstore(l, &nod, &nod1, &nod2, nn);
 +              break;
 +
 +      case OADDR:
 +              if(nn == Z) {
 +                      nullwarn(l, Z);
 +                      break;
 +              }
 +              lcgen(l, nn);
 +              break;
 +
 +      case OFUNC:
 +              if(l->complex >= FNX) {
 +                      if(l->op != OIND)
 +                              diag(n, "bad function call");
 +
 +                      regret(&nod, l->left, 0, 0);
 +                      cgen(l->left, &nod);
 +                      regsalloc(&nod1, l->left);
 +                      gopcode(OAS, &nod, Z, &nod1);
 +                      regfree(&nod);
 +
 +                      nod = *n;
 +                      nod.left = &nod2;
 +                      nod2 = *l;
 +                      nod2.left = &nod1;
 +                      nod2.complex = 1;
 +                      cgen(&nod, nn);
 +
 +                      return;
 +              }
 +              if(REGARG >= 0)
 +                      o = reg[REGARG];
 +              gargs(r, &nod, &nod1);
 +              gpcdata(PCDATA_ArgSize, curarg);
 +              if(l->addable < INDEXED) {
 +                      reglcgen(&nod, l, Z);
 +                      gopcode(OFUNC, Z, Z, &nod);
 +                      regfree(&nod);
 +              } else
 +                      gopcode(OFUNC, Z, Z, l);
 +              gpcdata(PCDATA_ArgSize, -1);
 +              if(REGARG>=0)
 +                      if(o != reg[REGARG])
 +                              reg[REGARG]--;
 +              regret(&nod, n, l->type, 1); // update maxarg if nothing else
 +              gpcdata(PCDATA_ArgSize, curarg);
 +              gpcdata(PCDATA_ArgSize, -1);
 +              if(nn != Z)
 +                      gopcode(OAS, &nod, Z, nn);
 +              if(nod.op == OREGISTER)
 +                      regfree(&nod);
 +              break;
 +
 +      case OIND:
 +              if(nn == Z) {
 +                      cgen(l, nn);
 +                      break;
 +              }
 +              regialloc(&nod, n, nn);
 +              r = l;
 +              while(r->op == OADD)
 +                      r = r->right;
 +              if(sconst(r)) {
 +                      v = r->vconst;
 +                      r->vconst = 0;
 +                      cgen(l, &nod);
 +                      nod.xoffset += v;
 +                      r->vconst = v;
 +              } else
 +                      cgen(l, &nod);
 +              regind(&nod, n);
 +              gopcode(OAS, &nod, Z, nn);
 +              regfree(&nod);
 +              break;
 +
 +      case OEQ:
 +      case ONE:
 +      case OLE:
 +      case OLT:
 +      case OGE:
 +      case OGT:
 +      case OLO:
 +      case OLS:
 +      case OHI:
 +      case OHS:
 +              if(nn == Z) {
 +                      nullwarn(l, r);
 +                      break;
 +              }
 +              boolgen(n, 1, nn);
 +              break;
 +
 +      case OANDAND:
 +      case OOROR:
 +              boolgen(n, 1, nn);
 +              if(nn == Z)
 +                      patch(p, pc);
 +              break;
 +
 +      case ONOT:
 +              if(nn == Z) {
 +                      nullwarn(l, Z);
 +                      break;
 +              }
 +              boolgen(n, 1, nn);
 +              break;
 +
 +      case OCOMMA:
 +              cgen(l, Z);
 +              cgen(r, nn);
 +              break;
 +
 +      case OCAST:
 +              if(nn == Z) {
 +                      nullwarn(l, Z);
 +                      break;
 +              }
 +              /*
 +               * convert from types l->n->nn
 +               */
 +              if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
 +                      /* both null, gen l->nn */
 +                      cgen(l, nn);
 +                      break;
 +              }
 +              regalloc(&nod, l, nn);
 +              cgen(l, &nod);
 +              regalloc(&nod1, n, &nod);
 +              gopcode(OAS, &nod, Z, &nod1);
 +              gopcode(OAS, &nod1, Z, nn);
 +              regfree(&nod1);
 +              regfree(&nod);
 +              break;
 +
 +      case ODOT:
 +              sugen(l, nodrat, l->type->width);
 +              if(nn != Z) {
 +                      warn(n, "non-interruptable temporary");
 +                      nod = *nodrat;
 +                      if(!r || r->op != OCONST) {
 +                              diag(n, "DOT and no offset");
 +                              break;
 +                      }
 +                      nod.xoffset += (int32)r->vconst;
 +                      nod.type = n->type;
 +                      cgen(&nod, nn);
 +              }
 +              break;
 +
 +      case OCOND:
 +              bcgen(l, 1);
 +              p1 = p;
 +              cgen(r->left, nn);
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              p1 = p;
 +              cgen(r->right, nn);
 +              patch(p1, pc);
 +              break;
 +
 +      case OPOSTINC:
 +      case OPOSTDEC:
 +              v = 1;
 +              if(l->type->etype == TIND)
 +                      v = l->type->link->width;
 +              if(o == OPOSTDEC)
 +                      v = -v;
 +              if(l->op == OBIT)
 +                      goto bitinc;
 +              if(nn == Z)
 +                      goto pre;
 +
 +              if(l->addable < INDEXED)
 +                      reglcgen(&nod2, l, Z);
 +              else
 +                      nod2 = *l;
 +
 +              regalloc(&nod, l, nn);
 +              gopcode(OAS, &nod2, Z, &nod);
 +              regalloc(&nod1, l, Z);
 +              if(typefd[l->type->etype]) {
 +                      regalloc(&nod3, l, Z);
 +                      if(v < 0) {
 +                              gopcode(OAS, nodfconst(-v), Z, &nod3);
 +                              gopcode(OSUB, &nod3, &nod, &nod1);
 +                      } else {
 +                              gopcode(OAS, nodfconst(v), Z, &nod3);
 +                              gopcode(OADD, &nod3, &nod, &nod1);
 +                      }
 +                      regfree(&nod3);
 +              } else
 +                      gopcode(OADD, nodconst(v), &nod, &nod1);
 +              gopcode(OAS, &nod1, Z, &nod2);
 +
 +              regfree(&nod);
 +              regfree(&nod1);
 +              if(l->addable < INDEXED)
 +                      regfree(&nod2);
 +              break;
 +
 +      case OPREINC:
 +      case OPREDEC:
 +              v = 1;
 +              if(l->type->etype == TIND)
 +                      v = l->type->link->width;
 +              if(o == OPREDEC)
 +                      v = -v;
 +              if(l->op == OBIT)
 +                      goto bitinc;
 +
 +      pre:
 +              if(l->addable < INDEXED)
 +                      reglcgen(&nod2, l, Z);
 +              else
 +                      nod2 = *l;
 +
 +              regalloc(&nod, l, nn);
 +              gopcode(OAS, &nod2, Z, &nod);
 +              if(typefd[l->type->etype]) {
 +                      regalloc(&nod3, l, Z);
 +                      if(v < 0) {
 +                              gopcode(OAS, nodfconst(-v), Z, &nod3);
 +                              gopcode(OSUB, &nod3, Z, &nod);
 +                      } else {
 +                              gopcode(OAS, nodfconst(v), Z, &nod3);
 +                              gopcode(OADD, &nod3, Z, &nod);
 +                      }
 +                      regfree(&nod3);
 +              } else
 +                      gopcode(OADD, nodconst(v), Z, &nod);
 +              gopcode(OAS, &nod, Z, &nod2);
 +              if(nn && l->op == ONAME)        /* in x=++i, emit USED(i) */
 +                      gins(ANOP, l, Z);
 +
 +              regfree(&nod);
 +              if(l->addable < INDEXED)
 +                      regfree(&nod2);
 +              break;
 +
 +      bitinc:
 +              if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
 +                      bitload(l, &nod, &nod1, &nod2, Z);
 +                      gopcode(OAS, &nod, Z, nn);
 +                      gopcode(OADD, nodconst(v), Z, &nod);
 +                      bitstore(l, &nod, &nod1, &nod2, Z);
 +                      break;
 +              }
 +              bitload(l, &nod, &nod1, &nod2, nn);
 +              gopcode(OADD, nodconst(v), Z, &nod);
 +              bitstore(l, &nod, &nod1, &nod2, nn);
 +              break;
 +      }
 +      cursafe = curs;
 +}
 +
 +void
 +reglcgen(Node *t, Node *n, Node *nn)
 +{
 +      Node *r;
 +      int32 v;
 +
 +      regialloc(t, n, nn);
 +      if(n->op == OIND) {
 +              r = n->left;
 +              while(r->op == OADD)
 +                      r = r->right;
 +              if(sconst(r)) {
 +                      v = r->vconst;
 +                      r->vconst = 0;
 +                      lcgen(n, t);
 +                      t->xoffset += v;
 +                      r->vconst = v;
 +                      regind(t, n);
 +                      return;
 +              }
 +      }
 +      lcgen(n, t);
 +      regind(t, n);
 +}
 +
 +void
 +lcgen(Node *n, Node *nn)
 +{
 +      Prog *p1;
 +      Node nod;
 +
 +      if(debug['g']) {
 +              prtree(nn, "lcgen lhs");
 +              prtree(n, "lcgen");
 +      }
 +      if(n == Z || n->type == T)
 +              return;
 +      if(nn == Z) {
 +              nn = &nod;
 +              regalloc(&nod, n, Z);
 +      }
 +      switch(n->op) {
 +      default:
 +              if(n->addable < INDEXED) {
 +                      diag(n, "unknown op in lcgen: %O", n->op);
 +                      break;
 +              }
 +              nod = *n;
 +              nod.op = OADDR;
 +              nod.left = n;
 +              nod.right = Z;
 +              nod.type = types[TIND];
 +              gopcode(OAS, &nod, Z, nn);
 +              break;
 +
 +      case OCOMMA:
 +              cgen(n->left, n->left);
 +              lcgen(n->right, nn);
 +              break;
 +
 +      case OIND:
 +              cgen(n->left, nn);
 +              break;
 +
 +      case OCOND:
 +              bcgen(n->left, 1);
 +              p1 = p;
 +              lcgen(n->right->left, nn);
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              p1 = p;
 +              lcgen(n->right->right, nn);
 +              patch(p1, pc);
 +              break;
 +      }
 +}
 +
 +void
 +bcgen(Node *n, int true)
 +{
 +
 +      if(n->type == T)
 +              gbranch(OGOTO);
 +      else
 +              boolgen(n, true, Z);
 +}
 +
 +void
 +boolgen(Node *n, int true, Node *nn)
 +{
 +      int o;
 +      Prog *p1, *p2;
 +      Node *l, *r, nod, nod1;
 +      int32 curs;
 +
 +      if(debug['g']) {
 +              prtree(nn, "boolgen lhs");
 +              prtree(n, "boolgen");
 +      }
 +      curs = cursafe;
 +      l = n->left;
 +      r = n->right;
 +      switch(n->op) {
 +
 +      default:
 +              if(n->op == OCONST) {
 +                      o = vconst(n);
 +                      if(!true)
 +                              o = !o;
 +                      gbranch(OGOTO);
 +                      if(o) {
 +                              p1 = p;
 +                              gbranch(OGOTO);
 +                              patch(p1, pc);
 +                      }
 +                      goto com;
 +              }
 +              regalloc(&nod, n, nn);
 +              cgen(n, &nod);
 +              o = ONE;
 +              if(true)
 +                      o = comrel[relindex(o)];
 +              if(typefd[n->type->etype]) {
 +                      nodreg(&nod1, n, NREG+FREGZERO);
 +                      gopcode(o, &nod, Z, &nod1);
 +              } else
 +                      gopcode(o, &nod, Z, nodconst(0));
 +              regfree(&nod);
 +              goto com;
 +
 +      case OCOMMA:
 +              cgen(l, Z);
 +              boolgen(r, true, nn);
 +              break;
 +
 +      case ONOT:
 +              boolgen(l, !true, nn);
 +              break;
 +
 +      case OCOND:
 +              bcgen(l, 1);
 +              p1 = p;
 +              bcgen(r->left, true);
 +              p2 = p;
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              p1 = p;
 +              bcgen(r->right, !true);
 +              patch(p2, pc);
 +              p2 = p;
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              patch(p2, pc);
 +              goto com;
 +
 +      case OANDAND:
 +              if(!true)
 +                      goto caseor;
 +
 +      caseand:
 +              bcgen(l, true);
 +              p1 = p;
 +              bcgen(r, !true);
 +              p2 = p;
 +              patch(p1, pc);
 +              gbranch(OGOTO);
 +              patch(p2, pc);
 +              goto com;
 +
 +      case OOROR:
 +              if(!true)
 +                      goto caseand;
 +
 +      caseor:
 +              bcgen(l, !true);
 +              p1 = p;
 +              bcgen(r, !true);
 +              p2 = p;
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              patch(p2, pc);
 +              goto com;
 +
 +      case OEQ:
 +      case ONE:
 +      case OLE:
 +      case OLT:
 +      case OGE:
 +      case OGT:
 +      case OHI:
 +      case OHS:
 +      case OLO:
 +      case OLS:
 +              o = n->op;
 +              if(true)
 +                      o = comrel[relindex(o)];
 +              if(l->complex >= FNX && r->complex >= FNX) {
 +                      regret(&nod, r, 0, 0);
 +                      cgen(r, &nod);
 +                      regsalloc(&nod1, r);
 +                      gopcode(OAS, &nod, Z, &nod1);
 +                      regfree(&nod);
 +                      nod = *n;
 +                      nod.right = &nod1;
 +                      boolgen(&nod, true, nn);
 +                      break;
 +              }
 +              if(sconst(r)) {
 +                      regalloc(&nod, l, nn);
 +                      cgen(l, &nod);
 +                      gopcode(o, &nod, Z, r);
 +                      regfree(&nod);
 +                      goto com;
 +              }
 +              if(l->complex >= r->complex) {
 +                      regalloc(&nod1, l, nn);
 +                      cgen(l, &nod1);
 +                      regalloc(&nod, r, Z);
 +                      cgen(r, &nod);
 +              } else {
 +                      regalloc(&nod, r, nn);
 +                      cgen(r, &nod);
 +                      regalloc(&nod1, l, Z);
 +                      cgen(l, &nod1);
 +              }
 +              gopcode(o, &nod1, Z, &nod);
 +              regfree(&nod);
 +              regfree(&nod1);
 +
 +      com:
 +              if(nn != Z) {
 +                      p1 = p;
 +                      gopcode(OAS, nodconst(1L), Z, nn);
 +                      gbranch(OGOTO);
 +                      p2 = p;
 +                      patch(p1, pc);
 +                      gopcode(OAS, nodconst(0L), Z, nn);
 +                      patch(p2, pc);
 +              }
 +              break;
 +      }
 +      cursafe = curs;
 +}
 +
 +void
 +sugen(Node *n, Node *nn, int32 w)
 +{
 +      Prog *p1;
 +      Node nod0, nod1, nod2, nod3, nod4, *l, *r;
 +      Type *t;
 +      int32 pc1;
 +      int i, m, c;
 +
 +      if(n == Z || n->type == T)
 +              return;
 +      if(debug['g']) {
 +              prtree(nn, "sugen lhs");
 +              prtree(n, "sugen");
 +      }
 +      if(nn == nodrat)
 +              if(w > nrathole)
 +                      nrathole = w;
 +      switch(n->op) {
 +      case OIND:
 +              if(nn == Z) {
 +                      nullwarn(n->left, Z);
 +                      break;
 +              }
 +
 +      default:
 +              goto copy;
 +
 +      case OCONST:
 +              if(n->type && typev[n->type->etype]) {
 +                      if(nn == Z) {
 +                              nullwarn(n->left, Z);
 +                              break;
 +                      }
 +
 +                      t = nn->type;
 +                      nn->type = types[TLONG];
 +                      reglcgen(&nod1, nn, Z);
 +                      nn->type = t;
 +
 +                      if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
 +                              gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
 +                      else
 +                              gopcode(OAS, nod32const(n->vconst), Z, &nod1);
 +                      nod1.xoffset += SZ_LONG;
 +                      if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
 +                              gopcode(OAS, nod32const(n->vconst), Z, &nod1);
 +                      else
 +                              gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
 +
 +                      regfree(&nod1);
 +                      break;
 +              }
 +              goto copy;
 +
 +      case ODOT:
 +              l = n->left;
 +              sugen(l, nodrat, l->type->width);
 +              if(nn != Z) {
 +                      warn(n, "non-interruptable temporary");
 +                      nod1 = *nodrat;
 +                      r = n->right;
 +                      if(!r || r->op != OCONST) {
 +                              diag(n, "DOT and no offset");
 +                              break;
 +                      }
 +                      nod1.xoffset += (int32)r->vconst;
 +                      nod1.type = n->type;
 +                      sugen(&nod1, nn, w);
 +              }
 +              break;
 +
 +      case OSTRUCT:
 +              /*
 +               * rewrite so lhs has no side effects
 +               */
 +              if(nn != Z && side(nn)) {
 +                      nod1 = *n;
 +                      nod1.type = typ(TIND, n->type);
 +                      regalloc(&nod2, &nod1, Z);
 +                      lcgen(nn, &nod2);
 +                      regsalloc(&nod0, &nod1);
 +                      gopcode(OAS, &nod2, Z, &nod0);
 +                      regfree(&nod2);
 +
 +                      nod1 = *n;
 +                      nod1.op = OIND;
 +                      nod1.left = &nod0;
 +                      nod1.right = Z;
 +                      nod1.complex = 1;
 +
 +                      sugen(n, &nod1, w);
 +                      return;
 +              }
 +
 +              r = n->left;
 +              for(t = n->type->link; t != T; t = t->down) {
 +                      l = r;
 +                      if(r->op == OLIST) {
 +                              l = r->left;
 +                              r = r->right;
 +                      }
 +                      if(nn == Z) {
 +                              cgen(l, nn);
 +                              continue;
 +                      }
 +                      /*
 +                       * hand craft *(&nn + o) = l
 +                       */
 +                      nod0 = znode;
 +                      nod0.op = OAS;
 +                      nod0.type = t;
 +                      nod0.left = &nod1;
 +                      nod0.right = l;
 +
 +                      nod1 = znode;
 +                      nod1.op = OIND;
 +                      nod1.type = t;
 +                      nod1.left = &nod2;
 +
 +                      nod2 = znode;
 +                      nod2.op = OADD;
 +                      nod2.type = typ(TIND, t);
 +                      nod2.left = &nod3;
 +                      nod2.right = &nod4;
 +
 +                      nod3 = znode;
 +                      nod3.op = OADDR;
 +                      nod3.type = nod2.type;
 +                      nod3.left = nn;
 +
 +                      nod4 = znode;
 +                      nod4.op = OCONST;
 +                      nod4.type = nod2.type;
 +                      nod4.vconst = t->offset;
 +
 +                      ccom(&nod0);
 +                      acom(&nod0);
 +                      xcom(&nod0);
 +                      nod0.addable = 0;
 +
 +                      /* prtree(&nod0, "hand craft"); /* */
 +                      cgen(&nod0, Z);
 +              }
 +              break;
 +
 +      case OAS:
 +              if(nn == Z) {
 +                      if(n->addable < INDEXED)
 +                              sugen(n->right, n->left, w);
 +                      break;
 +              }
 +              /* BOTCH -- functions can clobber rathole */
 +              sugen(n->right, nodrat, w);
 +              warn(n, "non-interruptable temporary");
 +              sugen(nodrat, n->left, w);
 +              sugen(nodrat, nn, w);
 +              break;
 +
 +      case OFUNC:
 +              if(!hasdotdotdot(n->left->type)) {
 +                      cgen(n, Z);
 +                      if(nn != Z) {
 +                              curarg -= n->type->width;
 +                              regret(&nod1, n, n->left->type, 1);
 +                              if(nn->complex >= FNX) {
 +                                      regsalloc(&nod2, n);
 +                                      cgen(&nod1, &nod2);
 +                                      nod1 = nod2;
 +                              }
 +                              cgen(&nod1, nn);
 +                      }
 +                      break;
 +              }
 +              if(nn == Z) {
 +                      sugen(n, nodrat, w);
 +                      break;
 +              }
 +              if(nn->op != OIND) {
 +                      nn = new1(OADDR, nn, Z);
 +                      nn->type = types[TIND];
 +                      nn->addable = 0;
 +              } else
 +                      nn = nn->left;
 +              n = new(OFUNC, n->left, new(OLIST, nn, n->right));
 +              n->type = types[TVOID];
 +              n->left->type = types[TVOID];
 +              cgen(n, Z);
 +              break;
 +
 +      case OCOND:
 +              bcgen(n->left, 1);
 +              p1 = p;
 +              sugen(n->right->left, nn, w);
 +              gbranch(OGOTO);
 +              patch(p1, pc);
 +              p1 = p;
 +              sugen(n->right->right, nn, w);
 +              patch(p1, pc);
 +              break;
 +
 +      case OCOMMA:
 +              cgen(n->left, Z);
 +              sugen(n->right, nn, w);
 +              break;
 +      }
 +      return;
 +
 +copy:
 +      if(nn == Z)
 +              return;
 +      if(n->complex >= FNX && nn->complex >= FNX) {
 +              t = nn->type;
 +              nn->type = types[TLONG];
 +              regialloc(&nod1, nn, Z);
 +              lcgen(nn, &nod1);
 +              regsalloc(&nod2, nn);
 +              nn->type = t;
 +
 +              gopcode(OAS, &nod1, Z, &nod2);
 +              regfree(&nod1);
 +
 +              nod2.type = typ(TIND, t);
 +
 +              nod1 = nod2;
 +              nod1.op = OIND;
 +              nod1.left = &nod2;
 +              nod1.right = Z;
 +              nod1.complex = 1;
 +              nod1.type = t;
 +
 +              sugen(n, &nod1, w);
 +              return;
 +      }
 +
 +      if(n->complex > nn->complex) {
 +              t = n->type;
 +              n->type = types[TLONG];
 +              reglcgen(&nod1, n, Z);
 +              n->type = t;
 +
 +              t = nn->type;
 +              nn->type = types[TLONG];
 +              reglcgen(&nod2, nn, Z);
 +              nn->type = t;
 +      } else {
 +              t = nn->type;
 +              nn->type = types[TLONG];
 +              reglcgen(&nod2, nn, Z);
 +              nn->type = t;
 +
 +              t = n->type;
 +              n->type = types[TLONG];
 +              reglcgen(&nod1, n, Z);
 +              n->type = t;
 +      }
 +
 +      w /= SZ_LONG;
 +      if(w <= 5) {
 +              layout(&nod1, &nod2, w, 0, Z);
 +              goto out;
 +      }
 +
 +      /*
 +       * minimize space for unrolling loop
 +       * 3,4,5 times. (6 or more is never minimum)
 +       * if small structure, try 2 also.
 +       */
 +      c = 0; /* set */
 +      m = 100;
 +      i = 3;
 +      if(w <= 15)
 +              i = 2;
 +      for(; i<=5; i++)
 +              if(i + w%i <= m) {
 +                      c = i;
 +                      m = c + w%c;
 +              }
 +
 +      regalloc(&nod3, &regnode, Z);
 +      layout(&nod1, &nod2, w%c, w/c, &nod3);
 +      
 +      pc1 = pc;
 +      layout(&nod1, &nod2, c, 0, Z);
 +
 +      gopcode(OSUB, nodconst(1L), Z, &nod3);
 +      nod1.op = OREGISTER;
 +      gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
 +      nod2.op = OREGISTER;
 +      gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
 +      
 +      gopcode(OGT, &nod3, Z, nodconst(0));
 +      patch(p, pc1);
 +
 +      regfree(&nod3);
 +out:
 +      regfree(&nod1);
 +      regfree(&nod2);
 +}
 +
 +void
 +layout(Node *f, Node *t, int c, int cv, Node *cn)
 +{
 +      Node t1, t2;
 +
 +      while(c > 3) {
 +              layout(f, t, 2, 0, Z);
 +              c -= 2;
 +      }
 +
 +      regalloc(&t1, &regnode, Z);
 +      regalloc(&t2, &regnode, Z);
 +      if(c > 0) {
 +              gopcode(OAS, f, Z, &t1);
 +              f->xoffset += SZ_LONG;
 +      }
 +      if(cn != Z)
 +              gopcode(OAS, nodconst(cv), Z, cn);
 +      if(c > 1) {
 +              gopcode(OAS, f, Z, &t2);
 +              f->xoffset += SZ_LONG;
 +      }
 +      if(c > 0) {
 +              gopcode(OAS, &t1, Z, t);
 +              t->xoffset += SZ_LONG;
 +      }
 +      if(c > 2) {
 +              gopcode(OAS, f, Z, &t1);
 +              f->xoffset += SZ_LONG;
 +      }
 +      if(c > 1) {
 +              gopcode(OAS, &t2, Z, t);
 +              t->xoffset += SZ_LONG;
 +      }
 +      if(c > 2) {
 +              gopcode(OAS, &t1, Z, t);
 +              t->xoffset += SZ_LONG;
 +      }
 +      regfree(&t1);
 +      regfree(&t2);
 +}
index 09f51536a52c9b6f2fe4809aef1580112473b7e9,0000000000000000000000000000000000000000..708a9392c9b5dcbb3f935478c0391dd3dc8cfbb8
mode 100644,000000..100644
--- /dev/null
@@@ -1,1053 -1,0 +1,1053 @@@
-               // 4 and 128 = magic constants: see ../../pkg/runtime/asm_power64x.s
 +// 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.
 +
 +#undef        EXTERN
 +#define       EXTERN
 +#include <u.h>
 +#include <libc.h>
 +#include "gg.h"
 +#include "opt.h"
 +
 +static Prog *appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset);
 +static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi);
 +
 +void
 +defframe(Prog *ptxt)
 +{
 +      uint32 frame;
 +      Prog *p;
 +      vlong hi, lo;
 +      NodeList *l;
 +      Node *n;
 +
 +      // fill in argument size
 +      ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
 +
 +      // fill in final stack size
 +      ptxt->to.offset <<= 32;
 +      frame = rnd(stksize+maxarg, widthreg);
 +      ptxt->to.offset |= frame;
 +      
 +      // insert code to zero ambiguously live variables
 +      // so that the garbage collector only sees initialized values
 +      // when it looks for pointers.
 +      p = ptxt;
 +      lo = hi = 0;
 +      // iterate through declarations - they are sorted in decreasing xoffset order.
 +      for(l=curfn->dcl; l != nil; l = l->next) {
 +              n = l->n;
 +              if(!n->needzero)
 +                      continue;
 +              if(n->class != PAUTO)
 +                      fatal("needzero class %d", n->class);
 +              if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
 +                      fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
 +
 +              if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthreg) {
 +                      // merge with range we already have
 +                      lo = n->xoffset;
 +                      continue;
 +              }
 +              // zero old range
 +              p = zerorange(p, frame, lo, hi);
 +
 +              // set new range
 +              hi = n->xoffset + n->type->width;
 +              lo = n->xoffset;
 +      }
 +      // zero final range
 +      zerorange(p, frame, lo, hi);
 +}
 +
 +static Prog*
 +zerorange(Prog *p, vlong frame, vlong lo, vlong hi)
 +{
 +      vlong cnt, i;
 +      Prog *p1;
 +      Node *f;
 +
 +      cnt = hi - lo;
 +      if(cnt == 0)
 +              return p;
 +      if(cnt < 4*widthptr) {
 +              for(i = 0; i < cnt; i += widthptr)
 +                      p = appendpp(p, AMOVD, D_REG, REGZERO, 0, D_OREG, REGSP, 8+frame+lo+i);
 +      } else if(cnt <= 128*widthptr) {
 +              p = appendpp(p, AADD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGRT1, 0);
 +              p->reg = REGSP;
 +              p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
 +              f = sysfunc("duffzero");
 +              naddr(f, &p->to, 1);
 +              afunclit(&p->to, f);
 +              p->to.offset = 4*(128-cnt/widthptr);
 +      } else {
 +              p = appendpp(p, AMOVD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGTMP, 0);
 +              p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT1, 0);
 +              p->reg = REGSP;
 +              p = appendpp(p, AMOVD, D_CONST, NREG, cnt, D_REG, REGTMP, 0);
 +              p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT2, 0);
 +              p->reg = REGRT1;
 +              p1 = p = appendpp(p, AMOVDU, D_REG, REGZERO, 0, D_OREG, REGRT1, widthptr);
 +              p = appendpp(p, ACMP, D_REG, REGRT1, 0, D_REG, REGRT2, 0);
 +              p = appendpp(p, ABNE, D_NONE, NREG, 0, D_BRANCH, NREG, 0);
 +              patch(p, p1);
 +      }
 +      return p;
 +}
 +
 +static Prog*
 +appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)
 +{
 +      Prog *q;
 +      q = mal(sizeof(*q));
 +      clearp(q);
 +      q->as = as;
 +      q->lineno = p->lineno;
 +      q->from.type = ftype;
 +      q->from.reg = freg;
 +      q->from.offset = foffset;
 +      q->to.type = ttype;
 +      q->to.reg = treg;
 +      q->to.offset = toffset;
 +      q->link = p->link;
 +      p->link = q;
 +      return q;
 +}
 +
 +// Sweep the prog list to mark any used nodes.
 +void
 +markautoused(Prog *p)
 +{
 +      for (; p; p = p->link) {
 +              if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
 +                      continue;
 +
 +              if (p->from.node)
 +                      p->from.node->used = 1;
 +
 +              if (p->to.node)
 +                      p->to.node->used = 1;
 +      }
 +}
 +
 +// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
 +void
 +fixautoused(Prog *p)
 +{
 +      Prog **lp;
 +
 +      for (lp=&p; (p=*lp) != P; ) {
 +              if (p->as == ATYPE && p->from.node && p->from.name == D_AUTO && !p->from.node->used) {
 +                      *lp = p->link;
 +                      continue;
 +              }
 +              if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
 +                      // Cannot remove VARDEF instruction, because - unlike TYPE handled above -
 +                      // VARDEFs are interspersed with other code, and a jump might be using the
 +                      // VARDEF as a target. Replace with a no-op instead. A later pass will remove
 +                      // the no-ops.
 +                      p->to.type = D_NONE;
 +                      p->to.node = N;
 +                      p->as = ANOP;
 +                      continue;
 +              }
 +              if (p->from.name == D_AUTO && p->from.node)
 +                      p->from.offset += p->from.node->stkdelta;
 +
 +              if (p->to.name == D_AUTO && p->to.node)
 +                      p->to.offset += p->to.node->stkdelta;
 +
 +              lp = &p->link;
 +      }
 +}
 +
 +/*
 + * generate: BL reg, f
 + * where both reg and f are registers.
 + * On power, f must be moved to CTR first.
 + */
 +static void
 +ginsBL(Node *reg, Node *f)
 +{
 +      Prog *p;
 +      p = gins(AMOVD, f, N);
 +      p->to.type = D_SPR;
 +      p->to.offset = D_CTR;
 +      p = gins(ABL, reg, N);
 +      p->to.type = D_SPR;
 +      p->to.offset = D_CTR;
 +}
 +
 +/*
 + * 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)
 + */
 +void
 +ginscall(Node *f, int proc)
 +{
 +      int32 arg;
 +      Prog *p;
 +      Node reg, con, reg2;
 +      Node r1;
 +
 +      if(f->type != T)
 +              setmaxarg(f->type);
 +
 +      arg = -1;
 +      // Most functions have a fixed-size argument block, so traceback uses that during unwind.
 +      // Not all, though: there are some variadic functions in package runtime,
 +      // and for those we emit call-specific metadata recorded by caller.
 +      // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub),
 +      // so we do this for all indirect calls as well.
 +      if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) {
 +              arg = f->type->argwid;
 +              if(proc == 1 || proc == 2)
 +                      arg += 3*widthptr;
 +      }
 +
 +      if(arg != -1)
 +              gargsize(arg);
 +
 +      switch(proc) {
 +      default:
 +              fatal("ginscall: bad proc %d", proc);
 +              break;
 +
 +      case 0: // normal call
 +      case -1:        // normal call but no return
 +              if(f->op == ONAME && f->class == PFUNC) {
 +                      if(f == 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 a Power64 NOP that we will have the right line number.
 +                              // Power64 NOP is really or r0, r0, r0; use that description
 +                              // because the NOP pseudo-instruction would be removed by
 +                              // the linker.
 +                              nodreg(&reg, types[TINT], D_R0);
 +                              gins(AOR, &reg, &reg);
 +                      }
 +                      p = gins(ABL, N, f);
 +                      afunclit(&p->to, f);
 +                      if(proc == -1 || noreturn(p))
 +                              gins(AUNDEF, N, N);
 +                      break;
 +              }
 +              nodreg(&reg, types[tptr], D_R0+REGENV);
 +              nodreg(&r1, types[tptr], D_R0+3);
 +              gmove(f, &reg);
 +              reg.op = OINDREG;
 +              gmove(&reg, &r1);
 +              reg.op = OREGISTER;
 +              ginsBL(&reg, &r1);
 +              break;
 +      
 +      case 3: // normal call of c function pointer
 +              ginsBL(N, f);
 +              break;
 +
 +      case 1: // call in new proc (go)
 +      case 2: // deferred call (defer)
 +              nodconst(&con, types[TINT64], argsize(f->type));
 +              nodreg(&reg, types[TINT64], D_R0+3);
 +              nodreg(&reg2, types[TINT64], D_R0+4);
 +              gmove(f, &reg);
 +
 +              p = gins(ASUB, N, N);
 +              p->from.type = D_CONST;
 +              p->from.offset = 3 * 8;
 +              p->to.type = D_REG;
 +              p->to.reg = REGSP;
 +
 +              gmove(&con, &reg2);
 +              p = gins(AMOVW, &reg2, N);
 +              p->to.type = D_OREG;
 +              p->to.reg = REGSP;
 +              p->to.offset = 8;
 +
 +              p = gins(AMOVD, &reg, N);
 +              p->to.type = D_OREG;
 +              p->to.reg = REGSP;
 +              p->to.offset = 16;
 +
 +              if(proc == 1)
 +                      ginscall(newproc, 0);
 +              else {
 +                      if(!hasdefer)
 +                              fatal("hasdefer=0 but has defer");
 +                      ginscall(deferproc, 0);
 +              }
 +
 +              p = gins(AADD, N, N);
 +              p->from.type = D_CONST;
 +              p->from.offset = 3 * 8;
 +              p->to.type = D_REG;
 +              p->to.reg = REGSP;
 +
 +              if(proc == 2) {
 +                      nodreg(&reg, types[TINT64], D_R0+3);
 +                      p = gins(ACMP, &reg, N);
 +                      p->to.type = D_REG;
 +                      p->to.reg = D_R0;
 +                      p = gbranch(ABEQ, T, +1);
 +                      cgen_ret(N);
 +                      patch(p, pc);
 +              }
 +              break;
 +      }
 +
 +      if(arg != -1)
 +              gargsize(-1);
 +}
 +
 +/*
 + * n is call to interface method.
 + * generate res = n.
 + */
 +void
 +cgen_callinter(Node *n, Node *res, int proc)
 +{
 +      Node *i, *f;
 +      Node tmpi, nodi, nodo, nodr, nodsp;
 +      Prog *p;
 +
 +      i = n->left;
 +      if(i->op != ODOTINTER)
 +              fatal("cgen_callinter: not ODOTINTER %O", i->op);
 +
 +      f = i->right;           // field
 +      if(f->op != ONAME)
 +              fatal("cgen_callinter: not ONAME %O", f->op);
 +
 +      i = i->left;            // interface
 +
 +      if(!i->addable) {
 +              tempname(&tmpi, i->type);
 +              cgen(i, &tmpi);
 +              i = &tmpi;
 +      }
 +
 +      genlist(n->list);               // assign the args
 +
 +      // i is now addable, prepare an indirected
 +      // register to hold its address.
 +      igen(i, &nodi, res);            // REG = &inter
 +
 +      nodindreg(&nodsp, types[tptr], D_R0+REGSP);
 +      nodsp.xoffset = widthptr;
 +      nodi.type = types[tptr];
 +      nodi.xoffset += widthptr;
 +      cgen(&nodi, &nodsp);    // 0(SP) = 8(REG) -- i.data
 +
 +      regalloc(&nodo, types[tptr], res);
 +      nodi.type = types[tptr];
 +      nodi.xoffset -= widthptr;
 +      cgen(&nodi, &nodo);     // REG = 0(REG) -- i.tab
 +      regfree(&nodi);
 +
 +      regalloc(&nodr, types[tptr], &nodo);
 +      if(n->left->xoffset == BADWIDTH)
 +              fatal("cgen_callinter: badwidth");
 +      cgen_checknil(&nodo); // in case offset is huge
 +      nodo.op = OINDREG;
 +      nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
 +      if(proc == 0) {
 +              // plain call: use direct c function pointer - more efficient
 +              cgen(&nodo, &nodr);     // REG = 32+offset(REG) -- i.tab->fun[f]
 +              proc = 3;
 +      } else {
 +              // go/defer. generate go func value.
 +              p = gins(AMOVD, &nodo, &nodr);  // REG = &(32+offset(REG)) -- i.tab->fun[f]
 +              p->from.type = D_CONST;
 +      }
 +
 +      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
 + */
 +void
 +cgen_call(Node *n, int proc)
 +{
 +      Type *t;
 +      Node nod, afun;
 +
 +      if(n == N)
 +              return;
 +
 +      if(n->left->ullman >= UINF) {
 +              // if name involves a fn call
 +              // precompute the address of the fn
 +              tempname(&afun, types[tptr]);
 +              cgen(n->left, &afun);
 +      }
 +
 +      genlist(n->list);               // assign the args
 +      t = n->left->type;
 +
 +      // call tempname pointer
 +      if(n->left->ullman >= UINF) {
 +              regalloc(&nod, types[tptr], N);
 +              cgen_as(&nod, &afun);
 +              nod.type = t;
 +              ginscall(&nod, proc);
 +              regfree(&nod);
 +              return;
 +      }
 +
 +      // call pointer
 +      if(n->left->op != ONAME || n->left->class != PFUNC) {
 +              regalloc(&nod, types[tptr], N);
 +              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.
 + */
 +void
 +cgen_callret(Node *n, Node *res)
 +{
 +      Node nod;
 +      Type *fp, *t;
 +      Iter flist;
 +
 +      t = n->left->type;
 +      if(t->etype == TPTR32 || t->etype == TPTR64)
 +              t = t->type;
 +
 +      fp = structfirst(&flist, getoutarg(t));
 +      if(fp == T)
 +              fatal("cgen_callret: nil");
 +
 +      memset(&nod, 0, sizeof(nod));
 +      nod.op = OINDREG;
 +      nod.val.u.reg = D_R0+REGSP;
 +      nod.addable = 1;
 +
 +      nod.xoffset = fp->width + widthptr; // +widthptr: saved LR at 0(R1)
 +      nod.type = fp->type;
 +      cgen_as(res, &nod);
 +}
 +
 +/*
 + * call to n has already been generated.
 + * generate:
 + *    res = &return value from call.
 + */
 +void
 +cgen_aret(Node *n, Node *res)
 +{
 +      Node nod1, nod2;
 +      Type *fp, *t;
 +      Iter flist;
 +
 +      t = n->left->type;
 +      if(isptr[t->etype])
 +              t = t->type;
 +
 +      fp = structfirst(&flist, getoutarg(t));
 +      if(fp == T)
 +              fatal("cgen_aret: nil");
 +
 +      memset(&nod1, 0, sizeof(nod1));
 +      nod1.op = OINDREG;
 +      nod1.val.u.reg = D_R0 + REGSP;
 +      nod1.addable = 1;
 +
 +      nod1.xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
 +      nod1.type = fp->type;
 +
 +      if(res->op != OREGISTER) {
 +              regalloc(&nod2, types[tptr], res);
 +              agen(&nod1, &nod2);
 +              gins(AMOVD, &nod2, res);
 +              regfree(&nod2);
 +      } else
 +              agen(&nod1, res);
 +}
 +
 +/*
 + * generate return.
 + * n->left is assignments to return values.
 + */
 +void
 +cgen_ret(Node *n)
 +{
 +      Prog *p;
 +
 +      if(n != N)
 +              genlist(n->list);               // copy out args
 +      if(hasdefer)
 +              ginscall(deferreturn, 0);
 +      genlist(curfn->exit);
 +      p = gins(ARET, N, N);
 +      if(n != N && n->op == ORETJMP) {
 +              p->to.name = D_EXTERN;
 +              p->to.type = D_CONST;
 +              p->to.sym = linksym(n->left->sym);
 +      }
 +}
 +
 +void
 +cgen_asop(Node *n)
 +{
 +      USED(n);
 +      fatal("cgen_asop"); // no longer used
 +}
 +
 +int
 +samereg(Node *a, Node *b)
 +{
 +      if(a == N || b == N)
 +              return 0;
 +      if(a->op != OREGISTER)
 +              return 0;
 +      if(b->op != OREGISTER)
 +              return 0;
 +      if(a->val.u.reg != b->val.u.reg)
 +              return 0;
 +      return 1;
 +}
 +
 +/*
 + * generate division.
 + * generates one of:
 + *    res = nl / nr
 + *    res = nl % nr
 + * according to op.
 + */
 +void
 +dodiv(int op, Node *nl, Node *nr, Node *res)
 +{
 +      int a, check;
 +      Type *t, *t0;
 +      Node tl, tr, tl2, tr2, nm1, nz, tm;
 +      Prog *p1, *p2;
 +
 +      // Have to be careful about handling
 +      // most negative int divided by -1 correctly.
 +      // The hardware will generate undefined result.
 +      // Also need to explicitly trap on division on zero,
 +      // the hardware will silently generate undefined result.
 +      // DIVW will leave unpredicable result in higher 32-bit,
 +      // so always use DIVD/DIVDU.
 +      t = nl->type;
 +      t0 = t;
 +      check = 0;
 +      if(issigned[t->etype]) {
 +              check = 1;
 +              if(isconst(nl, CTINT) && mpgetfix(nl->val.u.xval) != -(1ULL<<(t->width*8-1)))
 +                      check = 0;
 +              else if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) != -1)
 +                      check = 0;
 +      }
 +      if(t->width < 8) {
 +              if(issigned[t->etype])
 +                      t = types[TINT64];
 +              else
 +                      t = types[TUINT64];
 +              check = 0;
 +      }
 +
 +      a = optoas(ODIV, t);
 +
 +      regalloc(&tl, t0, N);
 +      regalloc(&tr, t0, N);
 +      if(nl->ullman >= nr->ullman) {
 +              cgen(nl, &tl);
 +              cgen(nr, &tr);
 +      } else {
 +              cgen(nr, &tr);
 +              cgen(nl, &tl);
 +      }
 +      if(t != t0) {
 +              // Convert
 +              tl2 = tl;
 +              tr2 = tr;
 +              tl.type = t;
 +              tr.type = t;
 +              gmove(&tl2, &tl);
 +              gmove(&tr2, &tr);
 +      }
 +
 +      // Handle divide-by-zero panic.
 +      p1 = gins(optoas(OCMP, t), &tr, N);
 +      p1->to.type = D_REG;
 +      p1->to.reg = REGZERO;
 +      p1 = gbranch(optoas(ONE, t), T, +1);
 +      if(panicdiv == N)
 +              panicdiv = sysfunc("panicdivide");
 +      ginscall(panicdiv, -1);
 +      patch(p1, pc);
 +
 +      if(check) {
 +              nodconst(&nm1, t, -1);
 +              gins(optoas(OCMP, t), &tr, &nm1);
 +              p1 = gbranch(optoas(ONE, t), T, +1);
 +              if(op == ODIV) {
 +                      // a / (-1) is -a.
 +                      gins(optoas(OMINUS, t), N, &tl);
 +                      gmove(&tl, res);
 +              } else {
 +                      // a % (-1) is 0.
 +                      nodconst(&nz, t, 0);
 +                      gmove(&nz, res);
 +              }
 +              p2 = gbranch(AJMP, T, 0);
 +              patch(p1, pc);
 +      }
 +      p1 = gins(a, &tr, &tl);
 +      if(op == ODIV) {
 +              regfree(&tr);
 +              gmove(&tl, res);
 +      } else {
 +              // A%B = A-(A/B*B)
 +              regalloc(&tm, t, N);
 +              // patch div to use the 3 register form
 +              // TODO(minux): add gins3?
 +              p1->reg = p1->to.reg;
 +              p1->to.reg = tm.val.u.reg;
 +              gins(optoas(OMUL, t), &tr, &tm);
 +              regfree(&tr);
 +              gins(optoas(OSUB, t), &tm, &tl);
 +              regfree(&tm);
 +              gmove(&tl, res);
 +      }
 +      regfree(&tl);
 +      if(check)
 +              patch(p2, pc);
 +}
 +
 +/*
 + * generate division according to op, one of:
 + *    res = nl / nr
 + *    res = nl % nr
 + */
 +void
 +cgen_div(int op, Node *nl, Node *nr, Node *res)
 +{
 +      Node n1, n2, n3;
 +      int w, a;
 +      Magic m;
 +
 +      // TODO(minux): enable division by magic multiply (also need to fix longmod below)
 +      //if(nr->op != OLITERAL)
 +              goto longdiv;
 +      w = nl->type->width*8;
 +
 +      // Front end handled 32-bit division. We only need to handle 64-bit.
 +      // try to do division by multiply by (2^w)/d
 +      // see hacker's delight chapter 10
 +      switch(simtype[nl->type->etype]) {
 +      default:
 +              goto longdiv;
 +
 +      case TUINT64:
 +              m.w = w;
 +              m.ud = mpgetfix(nr->val.u.xval);
 +              umagic(&m);
 +              if(m.bad)
 +                      break;
 +              if(op == OMOD)
 +                      goto longmod;
 +
 +              cgenr(nl, &n1, N);
 +              nodconst(&n2, nl->type, m.um);
 +              regalloc(&n3, nl->type, res);
 +              cgen_hmul(&n1, &n2, &n3);
 +
 +              if(m.ua) {
 +                      // need to add numerator accounting for overflow
 +                      gins(optoas(OADD, nl->type), &n1, &n3);
 +                      nodconst(&n2, nl->type, 1);
 +                      gins(optoas(ORROTC, nl->type), &n2, &n3);
 +                      nodconst(&n2, nl->type, m.s-1);
 +                      gins(optoas(ORSH, nl->type), &n2, &n3);
 +              } else {
 +                      nodconst(&n2, nl->type, m.s);
 +                      gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx
 +              }
 +
 +              gmove(&n3, res);
 +              regfree(&n1);
 +              regfree(&n3);
 +              return;
 +
 +      case TINT64:
 +              m.w = w;
 +              m.sd = mpgetfix(nr->val.u.xval);
 +              smagic(&m);
 +              if(m.bad)
 +                      break;
 +              if(op == OMOD)
 +                      goto longmod;
 +
 +              cgenr(nl, &n1, res);
 +              nodconst(&n2, nl->type, m.sm);
 +              regalloc(&n3, nl->type, N);
 +              cgen_hmul(&n1, &n2, &n3);
 +
 +              if(m.sm < 0) {
 +                      // need to add numerator
 +                      gins(optoas(OADD, nl->type), &n1, &n3);
 +              }
 +
 +              nodconst(&n2, nl->type, m.s);
 +              gins(optoas(ORSH, nl->type), &n2, &n3); // shift n3
 +
 +              nodconst(&n2, nl->type, w-1);
 +              gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg
 +              gins(optoas(OSUB, nl->type), &n1, &n3); // added
 +
 +              if(m.sd < 0) {
 +                      // this could probably be removed
 +                      // by factoring it into the multiplier
 +                      gins(optoas(OMINUS, nl->type), N, &n3);
 +              }
 +
 +              gmove(&n3, res);
 +              regfree(&n1);
 +              regfree(&n3);
 +              return;
 +      }
 +      goto longdiv;
 +
 +longdiv:
 +      // division and mod using (slow) hardware instruction
 +      dodiv(op, nl, nr, res);
 +      return;
 +
 +longmod:
 +      // mod using formula A%B = A-(A/B*B) but
 +      // we know that there is a fast algorithm for A/B
 +      regalloc(&n1, nl->type, res);
 +      cgen(nl, &n1);
 +      regalloc(&n2, nl->type, N);
 +      cgen_div(ODIV, &n1, nr, &n2);
 +      a = optoas(OMUL, nl->type);
 +      if(w == 8) {
 +              // use 2-operand 16-bit multiply
 +              // because there is no 2-operand 8-bit multiply
 +              //a = AIMULW;
 +      }
 +      if(!smallintconst(nr)) {
 +              regalloc(&n3, nl->type, N);
 +              cgen(nr, &n3);
 +              gins(a, &n3, &n2);
 +              regfree(&n3);
 +      } else
 +              gins(a, nr, &n2);
 +      gins(optoas(OSUB, nl->type), &n2, &n1);
 +      gmove(&n1, res);
 +      regfree(&n1);
 +      regfree(&n2);
 +}
 +
 +/*
 + * generate high multiply:
 + *   res = (nl*nr) >> width
 + */
 +void
 +cgen_hmul(Node *nl, Node *nr, Node *res)
 +{
 +      int w;
 +      Node n1, n2, *tmp;
 +      Type *t;
 +      Prog *p;
 +
 +      // largest ullman on left.
 +      if(nl->ullman < nr->ullman) {
 +              tmp = nl;
 +              nl = nr;
 +              nr = tmp;
 +      }
 +      t = nl->type;
 +      w = t->width * 8;
 +      cgenr(nl, &n1, res);
 +      cgenr(nr, &n2, N);
 +      switch(simtype[t->etype]) {
 +      case TINT8:
 +      case TINT16:
 +      case TINT32:
 +              gins(optoas(OMUL, t), &n2, &n1);
 +              p = gins(ASRAD, N, &n1);
 +              p->from.type = D_CONST;
 +              p->from.offset = w;
 +              break;
 +      case TUINT8:
 +      case TUINT16:
 +      case TUINT32:
 +              gins(optoas(OMUL, t), &n2, &n1);
 +              p = gins(ASRD, N, &n1);
 +              p->from.type = D_CONST;
 +              p->from.offset = w;
 +              break;
 +      case TINT64:
 +      case TUINT64:
 +              if(issigned[t->etype])
 +                      p = gins(AMULHD, &n2, &n1);
 +              else
 +                      p = gins(AMULHDU, &n2, &n1);
 +              break;
 +      default:
 +              fatal("cgen_hmul %T", t);
 +              break;
 +      }
 +      cgen(&n1, res);
 +      regfree(&n1);
 +      regfree(&n2);
 +}
 +
 +/*
 + * generate shift according to op, one of:
 + *    res = nl << nr
 + *    res = nl >> nr
 + */
 +void
 +cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
 +{
 +      Node n1, n2, n3, n4, n5;
 +      int a;
 +      Prog *p1;
 +      uvlong sc;
 +      Type *tcount;
 +
 +      a = optoas(op, nl->type);
 +
 +      if(nr->op == OLITERAL) {
 +              regalloc(&n1, nl->type, res);
 +              cgen(nl, &n1);
 +              sc = mpgetfix(nr->val.u.xval);
 +              if(sc >= nl->type->width*8) {
 +                      // large shift gets 2 shifts by width-1
 +                      nodconst(&n3, types[TUINT32], nl->type->width*8-1);
 +                      gins(a, &n3, &n1);
 +                      gins(a, &n3, &n1);
 +              } else
 +                      gins(a, nr, &n1);
 +              gmove(&n1, res);
 +              regfree(&n1);
 +              goto ret;
 +      }
 +
 +      if(nl->ullman >= UINF) {
 +              tempname(&n4, nl->type);
 +              cgen(nl, &n4);
 +              nl = &n4;
 +      }
 +      if(nr->ullman >= UINF) {
 +              tempname(&n5, nr->type);
 +              cgen(nr, &n5);
 +              nr = &n5;
 +      }
 +
 +      // Allow either uint32 or uint64 as shift type,
 +      // to avoid unnecessary conversion from uint32 to uint64
 +      // just to do the comparison.
 +      tcount = types[simtype[nr->type->etype]];
 +      if(tcount->etype < TUINT32)
 +              tcount = types[TUINT32];
 +
 +      regalloc(&n1, nr->type, N);             // to hold the shift type in CX
 +      regalloc(&n3, tcount, &n1);     // to clear high bits of CX
 +
 +      regalloc(&n2, nl->type, res);
 +      if(nl->ullman >= nr->ullman) {
 +              cgen(nl, &n2);
 +              cgen(nr, &n1);
 +              gmove(&n1, &n3);
 +      } else {
 +              cgen(nr, &n1);
 +              gmove(&n1, &n3);
 +              cgen(nl, &n2);
 +      }
 +      regfree(&n3);
 +
 +      // test and fix up large shifts
 +      if(!bounded) {
 +              nodconst(&n3, tcount, nl->type->width*8);
 +              gins(optoas(OCMP, tcount), &n1, &n3);
 +              p1 = gbranch(optoas(OLT, tcount), T, +1);
 +              if(op == ORSH && issigned[nl->type->etype]) {
 +                      nodconst(&n3, types[TUINT32], nl->type->width*8-1);
 +                      gins(a, &n3, &n2);
 +              } else {
 +                      nodconst(&n3, nl->type, 0);
 +                      gmove(&n3, &n2);
 +              }
 +              patch(p1, pc);
 +      }
 +
 +      gins(a, &n1, &n2);
 +
 +      gmove(&n2, res);
 +
 +      regfree(&n1);
 +      regfree(&n2);
 +
 +ret:
 +      ;
 +}
 +
 +void
 +clearfat(Node *nl)
 +{
 +      uint64 w, c, q, t;
 +      Node dst, end, r0, *f;
 +      Prog *p, *pl;
 +
 +      /* clear a fat object */
 +      if(debug['g']) {
 +              print("clearfat %N (%T, size: %lld)\n", nl, nl->type, nl->type->width);
 +      }
 +
 +      w = nl->type->width;
 +      // Avoid taking the address for simple enough types.
 +      //if(componentgen(N, nl))
 +      //      return;
 +
 +      c = w % 8;      // bytes
 +      q = w / 8;      // dwords
 +
 +      if(reg[REGRT1] > 0)
 +              fatal("R%d in use during clearfat", REGRT1);
 +
 +      nodreg(&r0, types[TUINT64], 0); // r0 is always zero
 +      nodreg(&dst, types[tptr], D_R0+REGRT1);
 +      reg[REGRT1]++;
 +      agen(nl, &dst);
 +
 +      if(q > 128) {
 +              p = gins(ASUB, N, &dst);
 +              p->from.type = D_CONST;
 +              p->from.offset = 8;
 +
 +              regalloc(&end, types[tptr], N);
 +              p = gins(AMOVD, &dst, &end);
 +              p->from.type = D_CONST;
 +              p->from.offset = q*8;
 +
 +              p = gins(AMOVDU, &r0, &dst);
 +              p->to.type = D_OREG;
 +              p->to.offset = 8;
 +              pl = p;
 +
 +              p = gins(ACMP, &dst, &end);
 +              patch(gbranch(ABNE, T, 0), pl);
 +
 +              regfree(&end);
 +      } else if(q >= 4) {
 +              p = gins(ASUB, N, &dst);
 +              p->from.type = D_CONST;
 +              p->from.offset = 8;
 +              f = sysfunc("duffzero");
 +              p = gins(ADUFFZERO, N, f);
 +              afunclit(&p->to, f);
++              // 4 and 128 = magic constants: see ../../runtime/asm_power64x.s
 +              p->to.offset = 4*(128-q);
 +      } else
 +      for(t = 0; t < q; t++) {
 +              p = gins(AMOVD, &r0, &dst);
 +              p->to.type = D_OREG;
 +              p->to.offset = 8*t;
 +      }
 +
 +      for(t = 0; t < c; t++) {
 +              p = gins(AMOVB, &r0, &dst);
 +              p->to.type = D_OREG;
 +              p->to.offset = t;
 +      }
 +      reg[REGRT1]--;
 +}
 +
 +// Called after regopt and peep have run.
 +// Expand CHECKNIL pseudo-op into actual nil pointer check.
 +void
 +expandchecks(Prog *firstp)
 +{
 +      Prog *p, *p1, *p2;
 +
 +      for(p = firstp; p != P; p = p->link) {
 +              if(debug_checknil && ctxt->debugvlog)
 +                      print("expandchecks: %P\n", p);
 +              if(p->as != ACHECKNIL)
 +                      continue;
 +              if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
 +                      warnl(p->lineno, "generated nil check");
 +              if(p->from.type != D_REG)
 +                      fatal("invalid nil check %P\n", p);
 +              /*
 +              // check is
 +              //      TD $4, R0, arg (R0 is always zero)
 +              // eqv. to:
 +              //      tdeq r0, arg
 +              // NOTE: this needs special runtime support to make SIGTRAP recoverable.
 +              reg = p->from.reg;
 +              p->as = ATD;
 +              p->from = p->to = p->from3 = zprog.from;
 +              p->from.type = D_CONST;
 +              p->from.offset = 4;
 +              p->from.reg = NREG;
 +              p->reg = 0;
 +              p->to.type = D_REG;
 +              p->to.reg = reg;
 +              */
 +              // check is
 +              //      CMP arg, R0
 +              //      BNE 2(PC) [likely]
 +              //      MOVD R0, 0(R0)
 +              p1 = mal(sizeof *p1);
 +              p2 = mal(sizeof *p2);
 +              clearp(p1);
 +              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 = ACMP;
 +              p->to.type = D_REG;
 +              p->to.reg = REGZERO;
 +              p1->as = ABNE;
 +              //p1->from.type = D_CONST;
 +              //p1->from.offset = 1; // likely
 +              p1->to.type = D_BRANCH;
 +              p1->to.u.branch = p2->link;
 +              // crash by write to memory address 0.
 +              p2->as = AMOVD;
 +              p2->from.type = D_REG;
 +              p2->from.reg = 0;
 +              p2->to.type = D_OREG;
 +              p2->to.reg = 0;
 +              p2->to.offset = 0;
 +      }
 +}
index b194cfd9eef0fe3656e405169154cd9a25ffc566,0000000000000000000000000000000000000000..a84056bbef9fcb6a24e0bb138d4bb8e1fe03cb2a
mode 100644,000000..100644
--- /dev/null
@@@ -1,1715 -1,0 +1,1715 @@@
- #include "../../pkg/runtime/funcdata.h"
 +// Derived from Inferno utils/6c/txt.c
 +// http://code.google.com/p/inferno-os/source/browse/utils/6c/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 <u.h>
 +#include <libc.h>
 +#include "gg.h"
- // At the same time, can raise StackBig in ../../pkg/runtime/stack.h.
++#include "../../runtime/funcdata.h"
 +
 +// TODO(rsc): Can make this bigger if we move
 +// the text segment up higher in 6l for all GOOS.
++// At the same time, can raise StackBig in ../../runtime/stack.h.
 +vlong unmappedzero = 4096;
 +
 +void
 +clearp(Prog *p)
 +{
 +      *p = zprog;
 +      p->as = AEND;
 +      p->pc = pcloc;
 +      pcloc++;
 +}
 +
 +static int ddumped;
 +static Prog *dfirst;
 +static Prog *dpc;
 +
 +/*
 + * generate and return proc with p->as = as,
 + * linked into program. pc is next instruction.
 + */
 +Prog*
 +prog(int as)
 +{
 +      Prog *p;
 +
 +      if(as == ADATA || as == AGLOBL) {
 +              if(ddumped)
 +                      fatal("already dumped data");
 +              if(dpc == nil) {
 +                      dpc = mal(sizeof(*dpc));
 +                      dfirst = dpc;
 +              }
 +              p = dpc;
 +              dpc = mal(sizeof(*dpc));
 +              p->link = dpc;
 +              p->reg = 0; // used for flags
 +      } else {
 +              p = pc;
 +              pc = mal(sizeof(*pc));
 +              clearp(pc);
 +              p->link = pc;
 +      }
 +
 +      if(lineno == 0) {
 +              if(debug['K'])
 +                      warn("prog: line 0");
 +      }
 +
 +      p->as = as;
 +      p->lineno = lineno;
 +      return p;
 +}
 +
 +void
 +dumpdata(void)
 +{
 +      ddumped = 1;
 +      if(dfirst == nil)
 +              return;
 +      newplist();
 +      *pc = *dfirst;
 +      pc = dpc;
 +      clearp(pc);
 +}
 +
 +/*
 + * generate a branch.
 + * t is ignored.
 + * likely values are for branch prediction:
 + *    -1 unlikely
 + *    0 no opinion
 + *    +1 likely
 + */
 +Prog*
 +gbranch(int as, Type *t, int likely)
 +{
 +      Prog *p;
 +      
 +      USED(t);
 +
 +      p = prog(as);
 +      p->to.type = D_BRANCH;
 +      p->to.u.branch = P;
 +      // TODO(minux): Enable this code.
 +      // Note: liblink used Bcc CR0, label form, so we need another way
 +      // to set likely/unlikely flag. Also note the y bit is not exactly
 +      // likely/unlikely bit.
 +      if(0 && as != ABR && likely != 0) {
 +              p->from.type = D_CONST;
 +              p->from.offset = likely > 0;
 +      }
 +      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.u.branch = to;
 +      p->to.offset = to->pc;
 +}
 +
 +Prog*
 +unpatch(Prog *p)
 +{
 +      Prog *q;
 +
 +      if(p->to.type != D_BRANCH)
 +              fatal("unpatch: not a branch");
 +      q = p->to.u.branch;
 +      p->to.u.branch = P;
 +      p->to.offset = 0;
 +      return q;
 +}
 +
 +/*
 + * start a new Prog list.
 + */
 +Plist*
 +newplist(void)
 +{
 +      Plist *pl;
 +
 +      pl = linknewplist(ctxt);
 +
 +      pc = mal(sizeof(*pc));
 +      clearp(pc);
 +      pl->firstpc = pc;
 +
 +      return pl;
 +}
 +
 +void
 +gused(Node *n)
 +{
 +      gins(ANOP, n, N);       // used
 +}
 +
 +Prog*
 +gjmp(Prog *to)
 +{
 +      Prog *p;
 +
 +      p = gbranch(ABR, T, 0);
 +      if(to != P)
 +              patch(p, to);
 +      return p;
 +}
 +
 +void
 +ggloblnod(Node *nam)
 +{
 +      Prog *p;
 +
 +      p = gins(AGLOBL, nam, N);
 +      p->lineno = nam->lineno;
 +      p->from.sym->gotype = linksym(ngotype(nam));
 +      p->to.sym = nil;
 +      p->to.type = D_CONST;
 +      p->to.offset = nam->type->width;
 +      if(nam->readonly)
 +              p->reg = RODATA;
 +      if(nam->type != T && !haspointers(nam->type))
 +              p->reg |= NOPTR;
 +}
 +
 +void
 +gtrack(Sym *s)
 +{
 +      Prog *p;
 +      
 +      p = gins(AUSEFIELD, N, N);
 +      p->from.type = D_OREG;
 +      p->from.name = D_EXTERN;
 +      p->from.sym = linksym(s);
 +}
 +
 +void
 +gargsize(vlong size)
 +{
 +      Node n1, n2;
 +      
 +      nodconst(&n1, types[TINT32], PCDATA_ArgSize);
 +      nodconst(&n2, types[TINT32], size);
 +      gins(APCDATA, &n1, &n2);
 +}
 +
 +void
 +ggloblsym(Sym *s, int32 width, int8 flags)
 +{
 +      Prog *p;
 +
 +      p = gins(AGLOBL, N, N);
 +      p->from.type = D_OREG;
 +      p->from.name = D_EXTERN;
 +      p->from.sym = linksym(s);
 +      p->to.type = D_CONST;
 +      p->to.name = D_NONE;
 +      p->to.offset = width;
 +      p->reg = flags;
 +}
 +
 +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.
 + */
 +void
 +afunclit(Addr *a, Node *n)
 +{
 +      if(a->type == D_CONST && a->name == D_EXTERN) {
 +              a->type = D_OREG;
 +              a->sym = linksym(n->sym);
 +      }
 +}
 +
 +static        int     resvd[] =
 +{
 +      REGZERO,
 +      REGSP,  // reserved for SP, XXX: not reserved in 9c.
 +      30,     // for g
 +      REGTMP, // REGTMP
 +      FREGCVI+NREG,
 +      FREGZERO+NREG,
 +      FREGHALF+NREG,
 +      FREGONE+NREG,
 +      FREGTWO+NREG,
 +};
 +
 +void
 +ginit(void)
 +{
 +      int i;
 +
 +      for(i=0; i<nelem(reg); i++)
 +              reg[i] = 1;
 +      for(i=0; i<NREG; i++)
 +              reg[i] = 0;
 +      for(i=NREG; i<NREG+NREG; i++)
 +              reg[i] = 0;
 +
 +      for(i=0; i<nelem(resvd); i++)
 +              reg[resvd[i]]++;
 +}
 +
 +static        uintptr regpc[nelem(reg)];
 +
 +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, %p\n", i, regpc[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;
 +      int fixfree, fltfree;
 +
 +      if(t == T)
 +              fatal("regalloc: t nil");
 +      et = simtype[t->etype];
 +
 +      if(debug['r']) {
 +              fixfree = 0;
 +              fltfree = 0;
 +              for(i = D_R0; i < D_F0+NREG; i++)
 +                      if(reg[i] == 0) {
 +                              if(i < D_F0)
 +                                      fixfree++;
 +                              else
 +                                      fltfree++;
 +                      }
 +              print("regalloc fix %d flt %d free\n", fixfree, fltfree);
 +      }
 +
 +      switch(et) {
 +      case TINT8:
 +      case TUINT8:
 +      case TINT16:
 +      case TUINT16:
 +      case TINT32:
 +      case TUINT32:
 +      case TINT64:
 +      case TUINT64:
 +      case TPTR32:
 +      case TPTR64:
 +      case TBOOL:
 +              if(o != N && o->op == OREGISTER) {
 +                      i = o->val.u.reg;
 +                      if(i >= D_R0+REGMIN && i <= D_R0+REGMAX)
 +                              goto out;
 +              }
 +              for(i=D_R0+REGMIN; i<=D_R0+REGMAX; i++)
 +                      if(reg[i] == 0) {
 +                              regpc[i] = (uintptr)getcallerpc(&n);
 +                              goto out;
 +                      }
 +              flusherrors();
 +              for(i=D_R0; i<D_R0+NREG; i++)
 +                      print("R%d %p\n", i, regpc[i]);
 +              fatal("out of fixed registers");
 +
 +      case TFLOAT32:
 +      case TFLOAT64:
 +              if(o != N && o->op == OREGISTER) {
 +                      i = o->val.u.reg;
 +                      if(i >= D_F0+FREGMIN && i <= D_F0+FREGMAX)
 +                              goto out;
 +              }
 +              for(i=D_F0+FREGMIN; i<=D_F0+FREGMAX; i++)
 +                      if(reg[i] == 0) {
 +                              regpc[i] = (uintptr)getcallerpc(&n);
 +                              goto out;
 +                      }
 +              flusherrors();
 +              for(i=D_F0; i<D_F0+NREG; i++)
 +                      print("F%d %p\n", i, regpc[i]);
 +              fatal("out of floating registers");
 +
 +      case TCOMPLEX64:
 +      case TCOMPLEX128:
 +              tempname(n, t);
 +              return;
 +      }
 +      fatal("regalloc: unknown type %T", t);
 +      return;
 +
 +out:
 +      reg[i]++;
 +      nodreg(n, t, i);
 +}
 +
 +void
 +regfree(Node *n)
 +{
 +      int i;
 +
 +      if(n->op == ONAME)
 +              return;
 +      if(n->op != OREGISTER && n->op != OINDREG)
 +              fatal("regfree: not a register");
 +      i = n->val.u.reg;
 +      if(i == D_R0 + REGSP)
 +              return;
 +      if(i < 0 || i >= nelem(reg))
 +              fatal("regfree: reg out of range");
 +      if(reg[i] <= 0)
 +              fatal("regfree: reg not allocated");
 +      reg[i]--;
 +      if(reg[i] == 0)
 +              regpc[i] = 0;
 +}
 +
 +/*
 + * 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;
 +      NodeList *l;
 +      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);
 +      
 +      if(fp == 1) {
 +              for(l=curfn->dcl; l; l=l->next) {
 +                      n = l->n;
 +                      if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
 +                              return n;
 +              }
 +      }
 +
 +      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;
 +      n->orig = t->nname;
 +
 +fp:
 +      // Rewrite argument named _ to __,
 +      // or else the assignment to _ will be
 +      // discarded during code generation.
 +      if(isblank(n))
 +              n->sym = lookup("__");
 +
 +      switch(fp) {
 +      default:
 +              fatal("nodarg %T %d", t, fp);
 +
 +      case 0:         // output arg for calling another function
 +              n->op = OINDREG;
 +              n->val.u.reg = D_R0+REGSP;
 +              n->xoffset += 8;
 +              break;
 +
 +      case 1:         // input arg to current function
 +              n->class = PPARAM;
 +              break;
 +
 +      case 2:         // offset output arg
 +fatal("shouldn't be used");
 +              n->op = OINDREG;
 +              n->val.u.reg = D_R0 + REGSP;
 +              n->xoffset += types[tptr]->width;
 +              break;
 +      }
 +      n->typecheck = 1;
 +      return n;
 +}
 +
 +/*
 + * generate
 + *    as $c, n
 + */
 +void
 +ginscon(int as, vlong c, Node *n2)
 +{
 +      Node n1, ntmp;
 +
 +      nodconst(&n1, types[TINT64], c);
 +
 +      if(as != AMOVD && (c < -BIG || c > BIG)) {
 +              // cannot have more than 16-bit of immediate in ADD, etc.
 +              // instead, MOV into register first.
 +              regalloc(&ntmp, types[TINT64], N);
 +              gins(AMOVD, &n1, &ntmp);
 +              gins(as, &ntmp, n2);
 +              regfree(&ntmp);
 +              return;
 +      }
 +      gins(as, &n1, n2);
 +}
 +
 +/*
 + * generate
 + *    as n, $c (CMP/CMPU)
 + */
 +void
 +ginscon2(int as, Node *n2, vlong c)
 +{
 +      Node n1, ntmp;
 +
 +      nodconst(&n1, types[TINT64], c);
 +
 +      switch(as) {
 +      default:
 +              fatal("ginscon2");
 +      case ACMP:
 +              if(-BIG <= c && c <= BIG) {
 +                      gins(as, n2, &n1);
 +                      return;
 +              }
 +              break;
 +      case ACMPU:
 +              if(0 <= c && c <= 2*BIG) {
 +                      gins(as, n2, &n1);
 +                      return;
 +              }
 +              break;
 +      }
 +      // MOV n1 into register first
 +      regalloc(&ntmp, types[TINT64], N);
 +      gins(AMOVD, &n1, &ntmp);
 +      gins(as, n2, &ntmp);
 +      regfree(&ntmp);
 +}
 +
 +#define       CASE(a,b)       (((a)<<16)|((b)<<0))
 +/*c2go int CASE(int, int); */
 +
 +/*
 + * Is this node a memory operand?
 + */
 +int
 +ismem(Node *n)
 +{
 +      switch(n->op) {
 +      case OITAB:
 +      case OSPTR:
 +      case OLEN:
 +      case OCAP:
 +      case OINDREG:
 +      case ONAME:
 +      case OPARAM:
 +      case OCLOSUREVAR:
 +      case OADDR:
 +              return 1;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * set up nodes representing 2^63
 + */
 +Node bigi;
 +Node bigf;
 +
 +void
 +bignodes(void)
 +{
 +      static int did;
 +
 +      if(did)
 +              return;
 +      did = 1;
 +
 +      nodconst(&bigi, types[TUINT64], 1);
 +      mpshiftfix(bigi.val.u.xval, 63);
 +
 +      bigf = bigi;
 +      bigf.type = types[TFLOAT64];
 +      bigf.val.ctype = CTFLT;
 +      bigf.val.u.fval = mal(sizeof *bigf.val.u.fval);
 +      mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval);
 +}
 +
 +/*
 + * generate move:
 + *    t = f
 + * hard part is conversions.
 + */
 +void
 +gmove(Node *f, Node *t)
 +{
 +      int a, ft, tt;
 +      Type *cvt;
 +      Node r1, r2, r3, con;
 +      Prog *p1, *p2;
 +
 +      if(debug['M'])
 +              print("gmove %lN -> %lN\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
 +      if(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 TINT32:
 +              case TINT16:
 +              case TINT8:
 +                      convconst(&con, types[TINT64], &f->val);
 +                      regalloc(&r1, con.type, t);
 +                      gins(AMOVD, &con, &r1);
 +                      gmove(&r1, t);
 +                      regfree(&r1);
 +                      return;
 +
 +              case TUINT32:
 +              case TUINT16:
 +              case TUINT8:
 +                      convconst(&con, types[TUINT64], &f->val);
 +                      regalloc(&r1, con.type, t);
 +                      gins(AMOVD, &con, &r1);
 +                      gmove(&r1, t);
 +                      regfree(&r1);
 +                      return;
 +              }
 +
 +              f = &con;
 +              ft = tt;        // so big switch will choose a simple mov
 +
 +              // constants can't move directly to memory.
 +              if(ismem(t)) {
 +                      goto hard;
 +                      // float constants come from memory.
 +                      //if(isfloat[tt])
 +                      //      goto hard;
 +
 +                      // 64-bit immediates are also from memory.
 +                      //if(isint[tt])
 +                      //      goto hard;
 +                      //// 64-bit immediates are really 32-bit sign-extended
 +                      //// unless moving into a register.
 +                      //if(isint[tt]) {
 +                      //      if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
 +                      //              goto hard;
 +                      //      if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
 +                      //              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:
 +              fatal("gmove %lT -> %lT", f->type, t->type);
 +
 +      /*
 +       * 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):
 +      case CASE(TINT64, TINT8):
 +      case CASE(TUINT64, TINT8):
 +              a = AMOVB;
 +              break;
 +
 +      case CASE(TINT8, TUINT8):       // same size
 +      case CASE(TUINT8, TUINT8):
 +      case CASE(TINT16, TUINT8):      // truncate
 +      case CASE(TUINT16, TUINT8):
 +      case CASE(TINT32, TUINT8):
 +      case CASE(TUINT32, TUINT8):
 +      case CASE(TINT64, TUINT8):
 +      case CASE(TUINT64, TUINT8):
 +              a = AMOVBZ;
 +              break;
 +
 +      case CASE(TINT16, TINT16):      // same size
 +      case CASE(TUINT16, TINT16):
 +      case CASE(TINT32, TINT16):      // truncate
 +      case CASE(TUINT32, TINT16):
 +      case CASE(TINT64, TINT16):
 +      case CASE(TUINT64, TINT16):
 +              a = AMOVH;
 +              break;
 +
 +      case CASE(TINT16, TUINT16):     // same size
 +      case CASE(TUINT16, TUINT16):
 +      case CASE(TINT32, TUINT16):     // truncate
 +      case CASE(TUINT32, TUINT16):
 +      case CASE(TINT64, TUINT16):
 +      case CASE(TUINT64, TUINT16):
 +              a = AMOVHZ;
 +              break;
 +
 +      case CASE(TINT32, TINT32):      // same size
 +      case CASE(TUINT32, TINT32):
 +      case CASE(TINT64, TINT32):      // truncate
 +      case CASE(TUINT64, TINT32):
 +              a = AMOVW;
 +              break;
 +
 +      case CASE(TINT32, TUINT32):     // same size
 +      case CASE(TUINT32, TUINT32):
 +      case CASE(TINT64, TUINT32):
 +      case CASE(TUINT64, TUINT32):
 +              a = AMOVWZ;
 +              break;
 +
 +      case CASE(TINT64, TINT64):      // same size
 +      case CASE(TINT64, TUINT64):
 +      case CASE(TUINT64, TINT64):
 +      case CASE(TUINT64, TUINT64):
 +              a = AMOVD;
 +              break;
 +
 +      /*
 +       * integer up-conversions
 +       */
 +      case CASE(TINT8, TINT16):       // sign extend int8
 +      case CASE(TINT8, TUINT16):
 +      case CASE(TINT8, TINT32):
 +      case CASE(TINT8, TUINT32):
 +      case CASE(TINT8, TINT64):
 +      case CASE(TINT8, TUINT64):
 +              a = AMOVB;
 +              goto rdst;
 +
 +      case CASE(TUINT8, TINT16):      // zero extend uint8
 +      case CASE(TUINT8, TUINT16):
 +      case CASE(TUINT8, TINT32):
 +      case CASE(TUINT8, TUINT32):
 +      case CASE(TUINT8, TINT64):
 +      case CASE(TUINT8, TUINT64):
 +              a = AMOVBZ;
 +              goto rdst;
 +
 +      case CASE(TINT16, TINT32):      // sign extend int16
 +      case CASE(TINT16, TUINT32):
 +      case CASE(TINT16, TINT64):
 +      case CASE(TINT16, TUINT64):
 +              a = AMOVH;
 +              goto rdst;
 +
 +      case CASE(TUINT16, TINT32):     // zero extend uint16
 +      case CASE(TUINT16, TUINT32):
 +      case CASE(TUINT16, TINT64):
 +      case CASE(TUINT16, TUINT64):
 +              a = AMOVHZ;
 +              goto rdst;
 +
 +      case CASE(TINT32, TINT64):      // sign extend int32
 +      case CASE(TINT32, TUINT64):
 +              a = AMOVW;
 +              goto rdst;
 +
 +      case CASE(TUINT32, TINT64):     // zero extend uint32
 +      case CASE(TUINT32, TUINT64):
 +              a = AMOVWZ;
 +              goto rdst;
 +
 +      /*
 +      * float to integer
 +      */
 +      case CASE(TFLOAT32, TINT32):
 +      case CASE(TFLOAT64, TINT32):
 +      case CASE(TFLOAT32, TINT64):
 +      case CASE(TFLOAT64, TINT64):
 +      case CASE(TFLOAT32, TINT16):
 +      case CASE(TFLOAT32, TINT8):
 +      case CASE(TFLOAT32, TUINT16):
 +      case CASE(TFLOAT32, TUINT8):
 +      case CASE(TFLOAT64, TINT16):
 +      case CASE(TFLOAT64, TINT8):
 +      case CASE(TFLOAT64, TUINT16):
 +      case CASE(TFLOAT64, TUINT8):
 +      case CASE(TFLOAT32, TUINT32):
 +      case CASE(TFLOAT64, TUINT32):
 +      case CASE(TFLOAT32, TUINT64):
 +      case CASE(TFLOAT64, TUINT64):
 +              //warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
 +              //return;
 +              // algorithm is:
 +              //      if small enough, use native float64 -> int64 conversion.
 +              //      otherwise, subtract 2^63, convert, and add it back.
 +              bignodes();
 +              regalloc(&r1, types[ft], f);
 +              gmove(f, &r1);
 +              if(tt == TUINT64) {
 +                      regalloc(&r2, types[TFLOAT64], N);
 +                      gmove(&bigf, &r2);
 +                      gins(AFCMPU, &r1, &r2);
 +                      p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1);
 +                      gins(AFSUB, &r2, &r1);
 +                      patch(p1, pc);
 +                      regfree(&r2);
 +              }
 +              regalloc(&r2, types[TFLOAT64], N);
 +              regalloc(&r3, types[TINT64], t);
 +              gins(AFCTIDZ, &r1, &r2);
 +              p1 = gins(AFMOVD, &r2, N);
 +              p1->to.type = D_OREG;
 +              p1->to.reg = REGSP;
 +              p1->to.offset = -8;
 +              p1 = gins(AMOVD, N, &r3);
 +              p1->from.type = D_OREG;
 +              p1->from.reg = REGSP;
 +              p1->from.offset = -8;
 +              regfree(&r2);
 +              regfree(&r1);
 +              if(tt == TUINT64) {
 +                      p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again
 +                      nodreg(&r1, types[TINT64], D_R0+REGTMP);
 +                      gins(AMOVD, &bigi, &r1);
 +                      gins(AADD, &r1, &r3);
 +                      patch(p1, pc);
 +              }
 +              gmove(&r3, t);
 +              regfree(&r3);
 +              return;
 +
 +      /*
 +       * integer to float
 +       */
 +      case CASE(TINT32, TFLOAT32):
 +      case CASE(TINT32, TFLOAT64):
 +      case CASE(TINT64, TFLOAT32):
 +      case CASE(TINT64, TFLOAT64):
 +      case CASE(TINT16, TFLOAT32):
 +      case CASE(TINT16, TFLOAT64):
 +      case CASE(TINT8, TFLOAT32):
 +      case CASE(TINT8, TFLOAT64):
 +      case CASE(TUINT16, TFLOAT32):
 +      case CASE(TUINT16, TFLOAT64):
 +      case CASE(TUINT8, TFLOAT32):
 +      case CASE(TUINT8, TFLOAT64):
 +      case CASE(TUINT32, TFLOAT32):
 +      case CASE(TUINT32, TFLOAT64):
 +      case CASE(TUINT64, TFLOAT32):
 +      case CASE(TUINT64, TFLOAT64):
 +              //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
 +              //return;
 +              // algorithm is:
 +              //      if small enough, use native int64 -> uint64 conversion.
 +              //      otherwise, halve (rounding to odd?), convert, and double.
 +              bignodes();
 +              regalloc(&r1, types[TINT64], N);
 +              gmove(f, &r1);
 +              if(ft == TUINT64) {
 +                      nodreg(&r2, types[TUINT64], D_R0+REGTMP);
 +                      gmove(&bigi, &r2);
 +                      gins(ACMPU, &r1, &r2);
 +                      p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
 +                      p2 = gins(ASRD, N, &r1);
 +                      p2->from.type = D_CONST;
 +                      p2->from.offset = 1;
 +                      patch(p1, pc);
 +              }
 +              regalloc(&r2, types[TFLOAT64], t);
 +              p1 = gins(AMOVD, &r1, N);
 +              p1->to.type = D_OREG;
 +              p1->to.reg = REGSP;
 +              p1->to.offset = -8;
 +              p1 = gins(AFMOVD, N, &r2);
 +              p1->from.type = D_OREG;
 +              p1->from.reg = REGSP;
 +              p1->from.offset = -8;
 +              gins(AFCFID, &r2, &r2);
 +              regfree(&r1);
 +              if(ft == TUINT64) {
 +                      p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again
 +                      nodreg(&r1, types[TFLOAT64], D_F0+FREGTWO);
 +                      gins(AFMUL, &r1, &r2);
 +                      patch(p1, pc);
 +              }
 +              gmove(&r2, t);
 +              regfree(&r2);
 +              return;
 +
 +      /*
 +       * float to float
 +       */
 +      case CASE(TFLOAT32, TFLOAT32):
 +              a = AFMOVS;
 +              break;
 +
 +      case CASE(TFLOAT64, TFLOAT64):
 +              a = AFMOVD;
 +              break;
 +
 +      case CASE(TFLOAT32, TFLOAT64):
 +              a = AFMOVS;
 +              goto rdst;
 +
 +      case CASE(TFLOAT64, TFLOAT32):
 +              a = AFRSP;
 +              goto rdst;
 +      }
 +
 +      gins(a, f, t);
 +      return;
 +
 +rdst:
 +      // 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;
 +}
 +
 +/*
 + * generate one instruction:
 + *    as f, t
 + */
 +Prog*
 +gins(int as, Node *f, Node *t)
 +{
 +      //int32 w;
 +      Prog *p;
 +      Addr af, at;
 +
 +      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(as == ATEXT)
 +              p->reg = 0;
 +      if(debug['g'])
 +              print("%P\n", p);
 +
 +      // TODO(minux): enable these.
 +      // right now it fails on MOVD $type."".TypeAssertionError(SB) [width=1], R7 [width=8]
 +      /*
 +      w = 0;
 +      switch(as) {
 +      case AMOVB:
 +      case AMOVBU:
 +      case AMOVBZ:
 +      case AMOVBZU:
 +              w = 1;
 +              break;
 +      case AMOVH:
 +      case AMOVHU:
 +      case AMOVHZ:
 +      case AMOVHZU:
 +              w = 2;
 +              break;
 +      case AMOVW:
 +      case AMOVWU:
 +      case AMOVWZ:
 +      case AMOVWZU:
 +              w = 4;
 +              break;
 +      case AMOVD:
 +      case AMOVDU:
 +              w = 8;
 +              break;
 +      }
 +      if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) {
 +              dump("f", f);
 +              dump("t", t);
 +              fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
 +      }
 +      */
 +
 +      return p;
 +}
 +
 +void
 +fixlargeoffset(Node *n)
 +{
 +      Node a;
 +
 +      if(n == N)
 +              return;
 +      if(n->op != OINDREG)
 +              return;
 +      if(n->val.u.reg == D_R0+REGSP) // stack offset cannot be large
 +              return;
 +      if(n->xoffset != (int32)n->xoffset) {
 +              // TODO(minux): offset too large, move into R31 and add to R31 instead.
 +              // this is used only in test/fixedbugs/issue6036.go.
 +              print("offset too large: %N\n", n);
 +              noimpl;
 +              a = *n;
 +              a.op = OREGISTER;
 +              a.type = types[tptr];
 +              a.xoffset = 0;
 +              cgen_checknil(&a);
 +              ginscon(optoas(OADD, types[tptr]), n->xoffset, &a);
 +              n->xoffset = 0;
 +      }
 +}
 +
 +/*
 + * generate code to compute n;
 + * make a refer to result.
 + */
 +void
 +naddr(Node *n, Addr *a, int canemitcode)
 +{
 +      Sym *s;
 +
 +      a->type = D_NONE;
 +      a->name = D_NONE;
 +      a->reg = NREG;
 +      a->gotype = nil;
 +      a->node = N;
 +      a->etype = 0;
 +      a->width = 0;
 +      if(n == N)
 +              return;
 +
 +      if(n->type != T && n->type->etype != TIDEAL) {
 +              dowidth(n->type);
 +              a->width = n->type->width;
 +      }
 +
 +      switch(n->op) {
 +      default:
 +              fatal("naddr: bad %O %D", n->op, a);
 +              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->offset = n->xoffset;
 +              s = n->sym;
 +              a->node = n->orig;
 +              //if(a->node >= (Node*)&n)
 +              //      fatal("stack node");
 +              if(s == S)
 +                      s = lookup(".noname");
 +              if(n->method) {
 +                      if(n->type != T)
 +                      if(n->type->sym != S)
 +                      if(n->type->sym->pkg != nil)
 +                              s = pkglookup(s->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;
 +                      a->width = widthptr;
 +                      s = funcsym(s);
 +                      break;
 +              }
 +              a->sym = linksym(s);
 +              break;
 +
 +      case OLITERAL:
 +              switch(n->val.ctype) {
 +              default:
 +                      fatal("naddr: const %lT", n->type);
 +                      break;
 +              case CTFLT:
 +                      a->type = D_FCONST;
 +                      a->u.dval = mpgetflt(n->val.u.fval);
 +                      break;
 +              case CTINT:
 +              case CTRUNE:
 +                      a->sym = nil;
 +                      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 = nil;
 +                      a->type = D_CONST;
 +                      a->offset = n->val.u.bval;
 +                      break;
 +              case CTNIL:
 +                      a->sym = nil;
 +                      a->type = D_CONST;
 +                      a->offset = 0;
 +                      break;
 +              }
 +              break;
 +
 +      case OREGISTER:
 +              if(n->val.u.reg < D_F0) {
 +                      a->type = D_REG;
 +                      a->reg = n->val.u.reg;
 +              } else {
 +                      a->type = D_FREG;
 +                      a->reg = n->val.u.reg - D_F0;
 +              }
 +              a->sym = nil;
 +              break;
 +
 +      case OINDREG:
 +              a->type = D_OREG;
 +              a->reg = n->val.u.reg;
 +              a->sym = linksym(n->sym);
 +              a->offset = n->xoffset;
 +              if(a->offset != (int32)a->offset)
 +                      yyerror("offset %lld too large for OINDREG", a->offset);
 +              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 = linksym(n->left->sym);
 +              a->type = D_OREG;
 +              a->name = D_PARAM;
 +              a->node = n->left->orig;
 +              break;
 +
 +      case OCLOSUREVAR:
 +              if(!curfn->needctxt)
 +                      fatal("closurevar without needctxt");
 +              a->type = D_OREG;
 +              a->reg = REGENV;
 +              a->offset = n->xoffset;
 +              a->sym = nil;
 +              break;
 +
 +      case OCFUNC:
 +              naddr(n->left, a, canemitcode);
 +              a->sym = linksym(n->left->sym);
 +              break;
 +
 +      case OITAB:
 +              // itable of interface value
 +              naddr(n->left, a, canemitcode);
 +              a->etype = simtype[tptr];
 +              if(a->type == D_CONST && a->offset == 0)
 +                      break;  // len(nil)
 +              break;
 +
 +      case OSPTR:
 +              // pointer in a string or slice
 +              naddr(n->left, a, canemitcode);
 +              if(a->type == D_CONST && a->offset == 0)
 +                      break;  // ptr(nil)
 +              a->etype = simtype[tptr];
 +              a->offset += Array_array;
 +              a->width = widthptr;
 +              break;
 +
 +      case OLEN:
 +              // len of string or slice
 +              naddr(n->left, a, canemitcode);
 +              a->etype = simtype[TINT];
 +              if(a->type == D_CONST && a->offset == 0)
 +                      break;  // len(nil)
 +              a->offset += Array_nel;
 +              break;
 +
 +      case OCAP:
 +              // cap of string or slice
 +              naddr(n->left, a, canemitcode);
 +              a->etype = simtype[TINT];
 +              if(a->type == D_CONST && a->offset == 0)
 +                      break;  // cap(nil)
 +              a->offset += Array_cap;
 +              break;
 +
 +      case OADDR:
 +              naddr(n->left, a, canemitcode);
 +              a->etype = tptr;
 +              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 for op=%O type=%T", op, t);
 +              break;
 +
 +      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):  // ACMP
 +      case CASE(OLT, TINT16):
 +      case CASE(OLT, TINT32):
 +      case CASE(OLT, TINT64):
 +      case CASE(OLT, TUINT8): // ACMPU
 +      case CASE(OLT, TUINT16):
 +      case CASE(OLT, TUINT32):
 +      case CASE(OLT, TUINT64):
 +      case CASE(OLT, TFLOAT32): // AFCMPU
 +      case CASE(OLT, TFLOAT64):
 +              a = ABLT;
 +              break;
 +
 +      case CASE(OLE, TINT8):  // ACMP
 +      case CASE(OLE, TINT16):
 +      case CASE(OLE, TINT32):
 +      case CASE(OLE, TINT64):
 +      case CASE(OLE, TUINT8): // ACMPU
 +      case CASE(OLE, TUINT16):
 +      case CASE(OLE, TUINT32):
 +      case CASE(OLE, TUINT64):
 +      case CASE(OLE, TFLOAT32): // AFCMPU
 +      case CASE(OLE, TFLOAT64):
 +              a = ABLE;
 +              break;
 +
 +      case CASE(OGT, TINT8):
 +      case CASE(OGT, TINT16):
 +      case CASE(OGT, TINT32):
 +      case CASE(OGT, TINT64):
 +      case CASE(OGT, TUINT8):
 +      case CASE(OGT, TUINT16):
 +      case CASE(OGT, TUINT32):
 +      case CASE(OGT, TUINT64):
 +      case CASE(OGT, TFLOAT32):
 +      case CASE(OGT, TFLOAT64):
 +              a = ABGT;
 +              break;
 +
 +      case CASE(OGE, TINT8):
 +      case CASE(OGE, TINT16):
 +      case CASE(OGE, TINT32):
 +      case CASE(OGE, TINT64):
 +      case CASE(OGE, TUINT8):
 +      case CASE(OGE, TUINT16):
 +      case CASE(OGE, TUINT32):
 +      case CASE(OGE, TUINT64):
 +      case CASE(OGE, TFLOAT32):
 +      case CASE(OGE, TFLOAT64):
 +              a = ABGE;
 +              break;
 +
 +      case CASE(OCMP, TBOOL):
 +      case CASE(OCMP, TINT8):
 +      case CASE(OCMP, TINT16):
 +      case CASE(OCMP, TINT32):
 +      case CASE(OCMP, TPTR32):
 +      case CASE(OCMP, TINT64):
 +              a = ACMP;
 +              break;
 +
 +      case CASE(OCMP, TUINT8):
 +      case CASE(OCMP, TUINT16):
 +      case CASE(OCMP, TUINT32):
 +      case CASE(OCMP, TUINT64):
 +      case CASE(OCMP, TPTR64):
 +              a = ACMPU;
 +              break;
 +
 +      case CASE(OCMP, TFLOAT32):
 +      case CASE(OCMP, TFLOAT64):
 +              a = AFCMPU;
 +              break;
 +
 +      case CASE(OAS, TBOOL):
 +      case CASE(OAS, TINT8):
 +              a = AMOVB;
 +              break;
 +
 +      case CASE(OAS, TUINT8):
 +              a = AMOVBZ;
 +              break;
 +
 +      case CASE(OAS, TINT16):
 +              a = AMOVH;
 +              break;
 +
 +      case CASE(OAS, TUINT16):
 +              a = AMOVHZ;
 +              break;
 +
 +      case CASE(OAS, TINT32):
 +              a = AMOVW;
 +              break;
 +
 +      case CASE(OAS, TUINT32):
 +      case CASE(OAS, TPTR32):
 +              a = AMOVWZ;
 +              break;
 +
 +      case CASE(OAS, TINT64):
 +      case CASE(OAS, TUINT64):
 +      case CASE(OAS, TPTR64):
 +              a = AMOVD;
 +              break;
 +
 +      case CASE(OAS, TFLOAT32):
 +              a = AFMOVS;
 +              break;
 +
 +      case CASE(OAS, TFLOAT64):
 +              a = AFMOVD;
 +              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):
 +      case CASE(OADD, TINT64):
 +      case CASE(OADD, TUINT64):
 +      case CASE(OADD, TPTR64):
 +              a = AADD;
 +              break;
 +
 +      case CASE(OADD, TFLOAT32):
 +              a = AFADDS;
 +              break;
 +
 +      case CASE(OADD, TFLOAT64):
 +              a = AFADD;
 +              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):
 +      case CASE(OSUB, TINT64):
 +      case CASE(OSUB, TUINT64):
 +      case CASE(OSUB, TPTR64):
 +              a = ASUB;
 +              break;
 +
 +      case CASE(OSUB, TFLOAT32):
 +              a = AFSUBS;
 +              break;
 +
 +      case CASE(OSUB, TFLOAT64):
 +              a = AFSUB;
 +              break;
 +
 +      case CASE(OMINUS, TINT8):
 +      case CASE(OMINUS, TUINT8):
 +      case CASE(OMINUS, TINT16):
 +      case CASE(OMINUS, TUINT16):
 +      case CASE(OMINUS, TINT32):
 +      case CASE(OMINUS, TUINT32):
 +      case CASE(OMINUS, TPTR32):
 +      case CASE(OMINUS, TINT64):
 +      case CASE(OMINUS, TUINT64):
 +      case CASE(OMINUS, TPTR64):
 +              a = ANEG;
 +              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):
 +      case CASE(OAND, TINT64):
 +      case CASE(OAND, TUINT64):
 +      case CASE(OAND, TPTR64):
 +              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):
 +      case CASE(OOR, TINT64):
 +      case CASE(OOR, TUINT64):
 +      case CASE(OOR, TPTR64):
 +              a = AOR;
 +              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):
 +      case CASE(OXOR, TINT64):
 +      case CASE(OXOR, TUINT64):
 +      case CASE(OXOR, TPTR64):
 +              a = AXOR;
 +              break;
 +
 +      // TODO(minux): handle rotates
 +      //case CASE(OLROT, TINT8):
 +      //case CASE(OLROT, TUINT8):
 +      //case CASE(OLROT, TINT16):
 +      //case CASE(OLROT, TUINT16):
 +      //case CASE(OLROT, TINT32):
 +      //case CASE(OLROT, TUINT32):
 +      //case CASE(OLROT, TPTR32):
 +      //case CASE(OLROT, TINT64):
 +      //case CASE(OLROT, TUINT64):
 +      //case CASE(OLROT, TPTR64):
 +      //      a = 0//???; RLDC?
 +      //      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):
 +      case CASE(OLSH, TINT64):
 +      case CASE(OLSH, TUINT64):
 +      case CASE(OLSH, TPTR64):
 +              a = ASLD;
 +              break;
 +
 +      case CASE(ORSH, TUINT8):
 +      case CASE(ORSH, TUINT16):
 +      case CASE(ORSH, TUINT32):
 +      case CASE(ORSH, TPTR32):
 +      case CASE(ORSH, TUINT64):
 +      case CASE(ORSH, TPTR64):
 +              a = ASRD;
 +              break;
 +
 +      case CASE(ORSH, TINT8):
 +      case CASE(ORSH, TINT16):
 +      case CASE(ORSH, TINT32):
 +      case CASE(ORSH, TINT64):
 +              a = ASRAD;
 +              break;
 +
 +      // TODO(minux): handle rotates
 +      //case CASE(ORROTC, TINT8):
 +      //case CASE(ORROTC, TUINT8):
 +      //case CASE(ORROTC, TINT16):
 +      //case CASE(ORROTC, TUINT16):
 +      //case CASE(ORROTC, TINT32):
 +      //case CASE(ORROTC, TUINT32):
 +      //case CASE(ORROTC, TINT64):
 +      //case CASE(ORROTC, TUINT64):
 +      //      a = 0//??? RLDC??
 +      //      break;
 +
 +      case CASE(OHMUL, TINT64):
 +              a = AMULHD;
 +              break;
 +      case CASE(OHMUL, TUINT64):
 +      case CASE(OHMUL, TPTR64):
 +              a = AMULHDU;
 +              break;
 +
 +      case CASE(OMUL, TINT8):
 +      case CASE(OMUL, TINT16):
 +      case CASE(OMUL, TINT32):
 +      case CASE(OMUL, TINT64):
 +              a = AMULLD;
 +              break;
 +
 +      case CASE(OMUL, TUINT8):
 +      case CASE(OMUL, TUINT16):
 +      case CASE(OMUL, TUINT32):
 +      case CASE(OMUL, TPTR32):
 +              // don't use word multiply, the high 32-bit are undefined.
 +              // fallthrough
 +      case CASE(OMUL, TUINT64):
 +      case CASE(OMUL, TPTR64):
 +              a = AMULLD; // for 64-bit multiplies, signedness doesn't matter.
 +              break;
 +
 +      case CASE(OMUL, TFLOAT32):
 +              a = AFMULS;
 +              break;
 +
 +      case CASE(OMUL, TFLOAT64):
 +              a = AFMUL;
 +              break;
 +
 +      case CASE(ODIV, TINT8):
 +      case CASE(ODIV, TINT16):
 +      case CASE(ODIV, TINT32):
 +      case CASE(ODIV, TINT64):
 +              a = ADIVD;
 +              break;
 +
 +      case CASE(ODIV, TUINT8):
 +      case CASE(ODIV, TUINT16):
 +      case CASE(ODIV, TUINT32):
 +      case CASE(ODIV, TPTR32):
 +      case CASE(ODIV, TUINT64):
 +      case CASE(ODIV, TPTR64):
 +              a = ADIVDU;
 +              break;
 +
 +      case CASE(ODIV, TFLOAT32):
 +              a = AFDIVS;
 +              break;
 +
 +      case CASE(ODIV, TFLOAT64):
 +              a = AFDIV;
 +              break;
 +
 +      }
 +      return a;
 +}
 +
 +enum
 +{
 +      ODynam          = 1<<0,
 +      OAddable        = 1<<1,
 +};
 +
 +int
 +xgen(Node *n, Node *a, int o)
 +{
 +      // TODO(minux)
 +      USED(n); USED(a); USED(o);
 +      return -1;
 +}
 +
 +void
 +sudoclean(void)
 +{
 +      return;
 +}
 +
 +/*
 + * 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)
 +{
 +      // TODO(minux)
 +      USED(as); USED(n); USED(a);
 +      return 0;
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index dad7445486e8897ad351ec2c8fad09f0d8ee494d,0000000000000000000000000000000000000000..dad7445486e8897ad351ec2c8fad09f0d8ee494d
mode 100644,000000..100644
Binary files differ
Simple merge
Simple merge
Simple merge
index 56582fe27d02c680d239e06cbf1ec5debae5c512,0000000000000000000000000000000000000000..47d515e0544bf15f4e22ca375be637dfc2eca75c
mode 100644,000000..100644
--- /dev/null
@@@ -1,2819 -1,0 +1,2819 @@@
- #include "../pkg/runtime/stack.h"
 +// cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
 +//
 +//    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-2008 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-2008 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.
 +
 +// Instruction layout.
 +
 +#include <u.h>
 +#include <libc.h>
 +#include <bio.h>
 +#include <link.h>
 +#include "../cmd/9l/9.out.h"
++#include "../runtime/stack.h"
 +
 +enum {
 +      FuncAlign = 8,
 +};
 +
 +enum {
 +      r0iszero = 1,
 +};
 +
 +typedef       struct  Optab   Optab;
 +
 +struct        Optab
 +{
 +      short   as;
 +      uchar   a1;
 +      uchar   a2;
 +      uchar   a3;
 +      uchar   a4;
 +      char    type;
 +      char    size;
 +      char    param;
 +};
 +
 +static Optab  optab[] = {
 +      { ATEXT,        C_LEXT, C_NONE, C_NONE,         C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_LEXT, C_REG, C_NONE,  C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_LEXT, C_NONE, C_LCON,         C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_LEXT, C_REG, C_LCON,  C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_ADDR, C_NONE, C_NONE,         C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_ADDR, C_REG, C_NONE,  C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_ADDR, C_NONE, C_LCON,         C_LCON,          0, 0, 0 },
 +      { ATEXT,        C_ADDR, C_REG, C_LCON,  C_LCON,          0, 0, 0 },
 +
 +      /* move register */
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_REG,           1, 4, 0 },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_REG,          12, 4, 0 },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_REG,          13, 4, 0 },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_REG,           12, 4, 0 },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_REG,           13, 4, 0 },
 +
 +      { AADD,         C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
 +      { AADD,         C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
 +      { AADD,         C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
 +      { AADD,         C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
 +      { AADD,         C_UCON, C_REG, C_NONE,  C_REG,          20, 4, 0 },
 +      { AADD,         C_UCON, C_NONE, C_NONE,         C_REG,          20, 4, 0 },
 +      { AADD,         C_LCON, C_REG, C_NONE,  C_REG,          22, 12, 0 },
 +      { AADD,         C_LCON, C_NONE, C_NONE,         C_REG,          22, 12, 0 },
 +
 +      { AADDC,        C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
 +      { AADDC,        C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
 +      { AADDC,        C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
 +      { AADDC,        C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
 +      { AADDC,        C_LCON, C_REG, C_NONE,  C_REG,          22, 12, 0 },
 +      { AADDC,        C_LCON, C_NONE, C_NONE,         C_REG,          22, 12, 0 },
 +
 +      { AAND,         C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },      /* logical, no literal */
 +      { AAND,         C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
 +      { AANDCC,       C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },
 +      { AANDCC,       C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
 +
 +      { AANDCC,       C_ANDCON,C_NONE, C_NONE, C_REG,         58, 4, 0 },
 +      { AANDCC,       C_ANDCON,C_REG, C_NONE,         C_REG,          58, 4, 0 },
 +      { AANDCC,       C_UCON, C_NONE, C_NONE,         C_REG,          59, 4, 0 },
 +      { AANDCC,       C_UCON, C_REG, C_NONE,  C_REG,          59, 4, 0 },
 +      { AANDCC,       C_LCON, C_NONE, C_NONE,         C_REG,          23, 12, 0 },
 +      { AANDCC,       C_LCON, C_REG, C_NONE,  C_REG,          23, 12, 0 },
 +
 +      { AMULLW,       C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
 +      { AMULLW,       C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
 +      { AMULLW,       C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
 +      { AMULLW,       C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
 +      { AMULLW,       C_ANDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
 +      { AMULLW,       C_ANDCON,       C_NONE, C_NONE, C_REG,   4, 4, 0 },
 +      { AMULLW,       C_LCON, C_REG,  C_NONE, C_REG,          22, 12, 0},
 +      { AMULLW,       C_LCON, C_NONE, C_NONE, C_REG,          22, 12, 0},
 +
 +      { ASUBC,        C_REG,  C_REG, C_NONE,  C_REG,           10, 4, 0 },
 +      { ASUBC,        C_REG,  C_NONE, C_NONE,         C_REG,           10, 4, 0 },
 +      { ASUBC,        C_REG,  C_NONE, C_ADDCON,       C_REG,   27, 4, 0 },
 +      { ASUBC,        C_REG,  C_NONE, C_LCON, C_REG,          28, 12, 0},
 +
 +      { AOR,          C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },      /* logical, literal not cc (or/xor) */
 +      { AOR,          C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
 +      { AOR,          C_ANDCON, C_NONE, C_NONE,  C_REG,       58, 4, 0 },
 +      { AOR,          C_ANDCON, C_REG, C_NONE,  C_REG,                58, 4, 0 },
 +      { AOR,          C_UCON, C_NONE, C_NONE,  C_REG,         59, 4, 0 },
 +      { AOR,          C_UCON, C_REG, C_NONE,  C_REG,          59, 4, 0 },
 +      { AOR,          C_LCON, C_NONE, C_NONE,         C_REG,          23, 12, 0 },
 +      { AOR,          C_LCON, C_REG, C_NONE,  C_REG,          23, 12, 0 },
 +
 +      { ADIVW,        C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },     /* op r1[,r2],r3 */
 +      { ADIVW,        C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
 +      { ASUB, C_REG,  C_REG, C_NONE,  C_REG,           10, 4, 0 },    /* op r2[,r1],r3 */
 +      { ASUB, C_REG,  C_NONE, C_NONE,         C_REG,           10, 4, 0 },
 +
 +      { ASLW, C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
 +      { ASLW, C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
 +      { ASLD, C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
 +      { ASLD, C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
 +      { ASLD, C_SCON, C_REG, C_NONE,  C_REG,          25, 4, 0 },
 +      { ASLD, C_SCON, C_NONE, C_NONE, C_REG,          25, 4, 0 },
 +      { ASLW, C_SCON, C_REG, C_NONE,  C_REG,          57, 4, 0 },
 +      { ASLW, C_SCON, C_NONE, C_NONE,         C_REG,          57, 4, 0 },
 +
 +      { ASRAW,        C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
 +      { ASRAW,        C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
 +      { ASRAW,        C_SCON, C_REG, C_NONE,  C_REG,          56, 4, 0 },
 +      { ASRAW,        C_SCON, C_NONE, C_NONE,         C_REG,          56, 4, 0 },
 +      { ASRAD,        C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
 +      { ASRAD,        C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
 +      { ASRAD,        C_SCON, C_REG, C_NONE,  C_REG,          56, 4, 0 },
 +      { ASRAD,        C_SCON, C_NONE, C_NONE,         C_REG,          56, 4, 0 },
 +
 +      { ARLWMI,       C_SCON, C_REG, C_LCON,  C_REG,          62, 4, 0 },
 +      { ARLWMI,       C_REG,  C_REG, C_LCON,  C_REG,          63, 4, 0 },
 +      { ARLDMI,       C_SCON, C_REG, C_LCON,  C_REG,          30, 4, 0 },
 +
 +      { ARLDC,        C_SCON, C_REG, C_LCON,  C_REG,          29, 4, 0 },
 +      { ARLDCL,       C_SCON, C_REG, C_LCON,  C_REG,          29, 4, 0 },
 +      { ARLDCL,       C_REG,  C_REG,  C_LCON, C_REG,          14, 4, 0 },
 +      { ARLDCL, C_REG,        C_NONE, C_LCON, C_REG,          14, 4, 0 },
 +
 +      { AFADD,        C_FREG, C_NONE, C_NONE,         C_FREG,          2, 4, 0 },
 +      { AFADD,        C_FREG, C_REG, C_NONE,  C_FREG,          2, 4, 0 },
 +      { AFABS,        C_FREG, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
 +      { AFABS,        C_NONE, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
 +
 +      { AFMADD,       C_FREG, C_REG, C_FREG,  C_FREG,          34, 4, 0 },
 +      { AFMUL,        C_FREG, C_NONE, C_NONE,         C_FREG,          32, 4, 0 },
 +      { AFMUL,        C_FREG, C_REG, C_NONE,  C_FREG,          32, 4, 0 },
 +
 +      /* store, short offset */
 +      { AMOVD,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVW,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVWZ,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVBZ,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVBZU,      C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVB,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVBU,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVBZU,      C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +      { AMOVBU,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
 +
 +      /* load, short offset */
 +      { AMOVD,        C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
 +      { AMOVW,        C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
 +      { AMOVWZ,       C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
 +      { AMOVBZ,       C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
 +      { AMOVBZU,      C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
 +      { AMOVB,        C_ZOREG,C_REG, C_NONE,  C_REG,          9, 8, REGZERO },
 +      { AMOVBU,       C_ZOREG,C_REG, C_NONE,  C_REG,          9, 8, REGZERO },
 +      { AMOVD,        C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
 +      { AMOVW,        C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
 +      { AMOVWZ,       C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
 +      { AMOVBZ,       C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
 +      { AMOVB,        C_SEXT, C_NONE, C_NONE,         C_REG,          9, 8, REGSB },
 +      { AMOVD,        C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
 +      { AMOVW,        C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
 +      { AMOVWZ,       C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
 +      { AMOVBZ,       C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
 +      { AMOVB,        C_SAUTO,C_NONE, C_NONE,         C_REG,          9, 8, REGSP },
 +      { AMOVD,        C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
 +      { AMOVW,        C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
 +      { AMOVWZ,       C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
 +      { AMOVBZ,       C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
 +      { AMOVBZU,      C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
 +      { AMOVB,        C_SOREG,C_NONE, C_NONE,         C_REG,          9, 8, REGZERO },
 +      { AMOVBU,       C_SOREG,C_NONE, C_NONE,         C_REG,          9, 8, REGZERO },
 +
 +      /* store, long offset */
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +      { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +      { AMOVB,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +
 +      /* load, long offset */
 +      { AMOVD,        C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
 +      { AMOVW,        C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
 +      { AMOVWZ,       C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
 +      { AMOVBZ,       C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
 +      { AMOVB,        C_LEXT, C_NONE, C_NONE,         C_REG,          37, 12, REGSB },
 +      { AMOVD,        C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
 +      { AMOVW,        C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
 +      { AMOVWZ,       C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
 +      { AMOVBZ,       C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
 +      { AMOVB,        C_LAUTO,C_NONE, C_NONE,         C_REG,          37, 12, REGSP },
 +      { AMOVD,        C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
 +      { AMOVW,        C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
 +      { AMOVWZ,       C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
 +      { AMOVBZ,       C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
 +      { AMOVB,        C_LOREG,C_NONE, C_NONE,         C_REG,          37, 12, REGZERO },
 +      { AMOVD,        C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
 +      { AMOVW,        C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
 +      { AMOVWZ,       C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
 +      { AMOVBZ,       C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
 +      { AMOVB,        C_ADDR, C_NONE, C_NONE,         C_REG,          76, 12, 0 },
 +
 +      /* load constant */
 +      { AMOVD,        C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB },
 +      { AMOVD,        C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
 +      { AMOVD,        C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
 +      { AMOVD,        C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
 +      { AMOVD,        C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
 +      { AMOVW,        C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB }, /* TO DO: check */
 +      { AMOVW,        C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
 +      { AMOVW,        C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
 +      { AMOVW,        C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
 +      { AMOVW,        C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
 +      { AMOVWZ,       C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB }, /* TO DO: check */
 +      { AMOVWZ,       C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
 +      { AMOVWZ,       C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
 +      { AMOVWZ,       C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
 +      { AMOVWZ,       C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
 +
 +      /* load unsigned/long constants (TO DO: check) */
 +      { AMOVD,        C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
 +      { AMOVD,        C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
 +      { AMOVW,        C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
 +      { AMOVW,        C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
 +      { AMOVWZ,       C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
 +      { AMOVWZ,       C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
 +
 +      { AMOVHBR,      C_ZOREG,        C_REG, C_NONE, C_REG,           45, 4, 0 },
 +      { AMOVHBR,      C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0 },
 +      { AMOVHBR,      C_REG,  C_REG, C_NONE,  C_ZOREG,                44, 4, 0 },
 +      { AMOVHBR,      C_REG,  C_NONE, C_NONE, C_ZOREG,                44, 4, 0 },
 +
 +      { ASYSCALL,     C_NONE, C_NONE, C_NONE,         C_NONE,          5, 4, 0 },
 +      { ASYSCALL,     C_REG,  C_NONE, C_NONE,         C_NONE,          77, 12, 0 },
 +      { ASYSCALL,     C_SCON, C_NONE, C_NONE,         C_NONE,          77, 12, 0 },
 +
 +      { ABEQ,         C_NONE, C_NONE, C_NONE,         C_SBRA,         16, 4, 0 },
 +      { ABEQ,         C_CREG, C_NONE, C_NONE,         C_SBRA,         16, 4, 0 },
 +
 +      { ABR,          C_NONE, C_NONE, C_NONE,         C_LBRA,         11, 4, 0 },
 +
 +      { ABC,          C_SCON, C_REG, C_NONE,  C_SBRA,         16, 4, 0 },
 +      { ABC,          C_SCON, C_REG, C_NONE,  C_LBRA,         17, 4, 0 },
 +
 +      { ABR,          C_NONE, C_NONE, C_NONE,         C_LR,           18, 4, 0 },
 +      { ABR,          C_NONE, C_NONE, C_NONE,         C_CTR,          18, 4, 0 },
 +      { ABR,          C_REG,  C_NONE, C_NONE,         C_CTR,          18, 4, 0 },
 +      { ABR,          C_NONE, C_NONE, C_NONE,         C_ZOREG,                15, 8, 0 },
 +
 +      { ABC,          C_NONE, C_REG, C_NONE,  C_LR,           18, 4, 0 },
 +      { ABC,          C_NONE, C_REG, C_NONE,  C_CTR,          18, 4, 0 },
 +      { ABC,          C_SCON, C_REG, C_NONE,  C_LR,           18, 4, 0 },
 +      { ABC,          C_SCON, C_REG, C_NONE,  C_CTR,          18, 4, 0 },
 +      { ABC,          C_NONE, C_NONE, C_NONE,         C_ZOREG,                15, 8, 0 },
 +
 +      { AFMOVD,       C_SEXT, C_NONE, C_NONE,         C_FREG,         8, 4, REGSB },
 +      { AFMOVD,       C_SAUTO,C_NONE, C_NONE,         C_FREG,         8, 4, REGSP },
 +      { AFMOVD,       C_SOREG,C_NONE, C_NONE,         C_FREG,         8, 4, REGZERO },
 +
 +      { AFMOVD,       C_LEXT, C_NONE, C_NONE,         C_FREG,         36, 8, REGSB },
 +      { AFMOVD,       C_LAUTO,C_NONE, C_NONE,         C_FREG,         36, 8, REGSP },
 +      { AFMOVD,       C_LOREG,C_NONE, C_NONE,         C_FREG,         36, 8, REGZERO },
 +      { AFMOVD,       C_ADDR, C_NONE, C_NONE,         C_FREG,         75, 8, 0 },
 +
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SEXT,         7, 4, REGSB },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SAUTO,        7, 4, REGSP },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SOREG,        7, 4, REGZERO },
 +
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
 +      { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
 +
 +      { ASYNC,                C_NONE, C_NONE, C_NONE,         C_NONE,         46, 4, 0 },
 +      { AWORD,        C_LCON, C_NONE, C_NONE,         C_NONE,         40, 4, 0 },
 +      { ADWORD,       C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 },
 +      { ADWORD,       C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 },
 +
 +      { AADDME,       C_REG,  C_NONE, C_NONE,         C_REG,          47, 4, 0 },
 +
 +      { AEXTSB,       C_REG,  C_NONE, C_NONE,         C_REG,          48, 4, 0 },
 +      { AEXTSB,       C_NONE, C_NONE, C_NONE,         C_REG,          48, 4, 0 },
 +
 +      { ANEG,         C_REG,  C_NONE, C_NONE,         C_REG,          47, 4, 0 },
 +      { ANEG,         C_NONE, C_NONE, C_NONE,         C_REG,          47, 4, 0 },
 +
 +      { AREM,         C_REG,  C_NONE, C_NONE,         C_REG,          50, 12, 0 },
 +      { AREM,         C_REG,  C_REG, C_NONE,  C_REG,          50, 12, 0 },
 +      { AREMD,                C_REG,  C_NONE, C_NONE,         C_REG,          51, 12, 0 },
 +      { AREMD,                C_REG,  C_REG, C_NONE,  C_REG,          51, 12, 0 },
 +
 +      { AMTFSB0,      C_SCON, C_NONE, C_NONE,         C_NONE,         52, 4, 0 },
 +      { AMOVFL, C_FPSCR, C_NONE, C_NONE,      C_FREG,         53, 4, 0 },
 +      { AMOVFL, C_FREG, C_NONE, C_NONE,       C_FPSCR,                64, 4, 0 },
 +      { AMOVFL, C_FREG, C_NONE, C_LCON,       C_FPSCR,                64, 4, 0 },
 +      { AMOVFL,       C_LCON, C_NONE, C_NONE, C_FPSCR,                65, 4, 0 },
 +
 +      { AMOVD,        C_MSR,  C_NONE, C_NONE,         C_REG,          54, 4, 0 },             /* mfmsr */
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_MSR,          54, 4, 0 },             /* mtmsrd */
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_MSR,          54, 4, 0 },             /* mtmsr */
 +
 +      /* 64-bit special registers */
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LR,           66, 4, 0 },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
 +      { AMOVD,        C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
 +      { AMOVD,        C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +      { AMOVD,        C_LR,   C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +      { AMOVD,        C_CTR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +      { AMOVD,        C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +
 +      /* 32-bit special registers (gloss over sign-extension or not?) */
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
 +      { AMOVW,        C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
 +      { AMOVW,        C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +      { AMOVW,        C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
 +      { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
 +      { AMOVWZ,       C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +      { AMOVWZ,       C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
 +
 +      { AMOVFL,       C_FPSCR, C_NONE, C_NONE,        C_CREG,         73, 4, 0 },
 +      { AMOVFL,       C_CREG, C_NONE, C_NONE,         C_CREG,         67, 4, 0 },
 +      { AMOVW,        C_CREG, C_NONE, C_NONE,         C_REG,          68, 4, 0 },
 +      { AMOVWZ,       C_CREG, C_NONE, C_NONE,         C_REG,          68, 4, 0 },
 +      { AMOVFL,       C_REG, C_NONE, C_LCON, C_CREG,          69, 4, 0 },
 +      { AMOVFL,       C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
 +      { AMOVW,        C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
 +      { AMOVWZ,       C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
 +
 +      { ACMP, C_REG,  C_NONE, C_NONE,         C_REG,  70, 4, 0 },
 +      { ACMP, C_REG,  C_REG, C_NONE,  C_REG,  70, 4, 0 },
 +      { ACMP, C_REG,  C_NONE, C_NONE, C_ADDCON,       71, 4, 0 },
 +      { ACMP, C_REG,  C_REG, C_NONE,  C_ADDCON,       71, 4, 0 },
 +
 +      { ACMPU,        C_REG,  C_NONE, C_NONE,         C_REG,  70, 4, 0 },
 +      { ACMPU,        C_REG,  C_REG, C_NONE,  C_REG,  70, 4, 0 },
 +      { ACMPU,        C_REG,  C_NONE, C_NONE, C_ANDCON,       71, 4, 0 },
 +      { ACMPU,        C_REG,  C_REG, C_NONE,  C_ANDCON,       71, 4, 0 },
 +
 +      { AFCMPO,       C_FREG, C_NONE, C_NONE,         C_FREG, 70, 4, 0 },
 +      { AFCMPO,       C_FREG, C_REG, C_NONE,  C_FREG, 70, 4, 0 },
 +
 +      { ATW,          C_LCON, C_REG, C_NONE,  C_REG,          60, 4, 0 },
 +      { ATW,          C_LCON, C_REG, C_NONE,  C_ADDCON,       61, 4, 0 },
 +
 +      { ADCBF,        C_ZOREG, C_NONE, C_NONE,  C_NONE,       43, 4, 0 },
 +      { ADCBF,        C_ZOREG, C_REG, C_NONE,  C_NONE,        43, 4, 0 },
 +
 +      { AECOWX,       C_REG,  C_REG, C_NONE,  C_ZOREG,        44, 4, 0 },
 +      { AECIWX,       C_ZOREG, C_REG, C_NONE,  C_REG,         45, 4, 0 },
 +      { AECOWX,       C_REG,  C_NONE, C_NONE,         C_ZOREG,        44, 4, 0 },
 +      { AECIWX,       C_ZOREG, C_NONE, C_NONE,  C_REG,                45, 4, 0 },
 +
 +      { AEIEIO,       C_NONE, C_NONE, C_NONE,         C_NONE,         46, 4, 0 },
 +      { ATLBIE,       C_REG, C_NONE, C_NONE,          C_NONE,         49, 4, 0 },
 +      { ATLBIE,       C_SCON, C_NONE, C_NONE, C_REG,  49, 4, 0 },
 +      { ASLBMFEE, C_REG, C_NONE, C_NONE,      C_REG,  55, 4, 0 },
 +      { ASLBMTE, C_REG, C_NONE, C_NONE,       C_REG,  55, 4, 0 },
 +
 +      { ASTSW,        C_REG,  C_NONE, C_NONE,         C_ZOREG,        44, 4, 0 },
 +      { ASTSW,        C_REG,  C_NONE, C_LCON,         C_ZOREG,        41, 4, 0 },
 +      { ALSW, C_ZOREG, C_NONE, C_NONE,  C_REG,                45, 4, 0 },
 +      { ALSW, C_ZOREG, C_NONE, C_LCON,  C_REG,                42, 4, 0 },
 +
 +      { AUNDEF,       C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0 },
 +      { AUSEFIELD,    C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
 +      { APCDATA,      C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0 },
 +      { AFUNCDATA,    C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0 },
 +
 +      { ADUFFZERO,    C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 },  // same as ABR/ABL
 +      { ADUFFCOPY,    C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 },  // same as ABR/ABL
 +
 +      { ANOP,         C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
 +
 +      { AXXX,         C_NONE, C_NONE, C_NONE,         C_NONE,          0, 4, 0 },
 +};
 +
 +static int ocmp(const void *, const void *);
 +static int cmp(int, int);
 +static void buildop(Link*);
 +static void prasm(Prog *);
 +static int isint32(vlong);
 +static int isuint32(uvlong);
 +static int aclass(Link*, Addr*);
 +static Optab* oplook(Link*, Prog*);
 +static void asmout(Link*, Prog*, Optab*, int32*);
 +static vlong vregoff(Link*, Addr*);
 +static int32 regoff(Link*, Addr*);
 +static int32 oprrr(Link*, int);
 +static int32 opirr(Link*, int);
 +static int32 opload(Link*, int);
 +static int32 opstore(Link*, int);
 +static int32 oploadx(Link*, int);
 +static int32 opstorex(Link*, int);
 +static int getmask(uchar*, uint32);
 +static void maskgen(Link*, Prog*, uchar*, uint32);
 +static int getmask64(uchar*, uvlong);
 +static void maskgen64(Link*, Prog*, uchar*, uvlong);
 +static uint32 loadu32(int, vlong);
 +static void addaddrreloc(Link*, LSym*, int*, int*);
 +
 +static struct
 +{
 +      Optab*  start;
 +      Optab*  stop;
 +} oprange[ALAST];
 +
 +static char   xcmp[C_NCLASS][C_NCLASS];
 +
 +
 +void
 +span9(Link *ctxt, LSym *cursym)
 +{
 +      Prog *p, *q;
 +      Optab *o;
 +      int m, bflag;
 +      vlong c, otxt;
 +      int32 out[6], i, j;
 +      uchar *bp, *cast;
 +
 +      p = cursym->text;
 +      if(p == nil || p->link == nil) // handle external functions and ELF section symbols
 +              return;
 +      ctxt->cursym = cursym;
 +      ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8;
 +
 +      if(oprange[AANDN].start == nil)
 +              buildop(ctxt);
 +
 +      bflag = 0;
 +      c = 0;  
 +      p->pc = c;
 +
 +      for(p = p->link; p != nil; p = p->link) {
 +              ctxt->curp = p;
 +              p->pc = c;
 +              o = oplook(ctxt, p);
 +              m = o->size;
 +              if(m == 0) {
 +                      if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
 +                              ctxt->diag("zero-width instruction\n%P", p);
 +                      continue;
 +              }
 +              c += m;
 +      }
 +      cursym->size = c;
 +
 +      /*
 +       * if any procedure is large enough to
 +       * generate a large SBRA branch, then
 +       * generate extra passes putting branches
 +       * around jmps to fix. this is rare.
 +       */
 +      bflag = 1;
 +      while(bflag) {
 +              if(ctxt->debugvlog)
 +                      Bprint(ctxt->bso, "%5.2f span1\n", cputime());
 +              bflag = 0;
 +              c = 0;
 +              for(p = cursym->text->link; p != nil; p = p->link) {
 +                      p->pc = c;
 +                      o = oplook(ctxt, p);
 +
 +                      // very large conditional branches
 +                      if((o->type == 16 || o->type == 17) && p->pcond) {
 +                              otxt = p->pcond->pc - c;
 +                              if(otxt < -(1L<<15)+10 || otxt >= (1L<<15)-10) {
 +                                      q = ctxt->arch->prg();
 +                                      q->link = p->link;
 +                                      p->link = q;
 +                                      q->as = ABR;
 +                                      q->to.type = D_BRANCH;
 +                                      q->pcond = p->pcond;
 +                                      p->pcond = q;
 +                                      q = ctxt->arch->prg();
 +                                      q->link = p->link;
 +                                      p->link = q;
 +                                      q->as = ABR;
 +                                      q->to.type = D_BRANCH;
 +                                      q->pcond = q->link->link;
 +                                      //addnop(p->link);
 +                                      //addnop(p);
 +                                      bflag = 1;
 +                              }
 +                      }
 +
 +                      m = o->size;
 +                      if(m == 0) {
 +                              if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
 +                                      ctxt->diag("zero-width instruction\n%P", p);
 +                              continue;
 +                      }
 +                      c += m;
 +              }
 +              cursym->size = c;
 +      }
 +
 +      c += -c&(FuncAlign-1);
 +      cursym->size = c;
 +
 +      /*
 +       * lay out the code, emitting code and data relocations.
 +       */
 +      if(ctxt->tlsg == nil)
 +              ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
 +
 +      symgrow(ctxt, cursym, cursym->size);
 +
 +      bp = cursym->p;
 +      for(p = cursym->text->link; p != nil; p = p->link) {
 +              ctxt->pc = p->pc;
 +              ctxt->curp = p;
 +              o = oplook(ctxt, p);
 +              if(o->size > 4*nelem(out))
 +                      sysfatal("out array in span9 is too small, need at least %d for %P", o->size/4, p);
 +              asmout(ctxt, p, o, out);
 +              for(i=0; i<o->size/4; i++) {
 +                      cast = (uchar*)&out[i];
 +                      for(j=0; j<4; j++)
 +                              *bp++ = cast[inuxi4[j]];
 +              }
 +      }
 +}
 +
 +static int
 +isint32(vlong v)
 +{
 +      return (int32)v == v;
 +}
 +
 +static int
 +isuint32(uvlong v)
 +{
 +      return (uint32)v == v;
 +}
 +
 +static int
 +aclass(Link *ctxt, Addr *a)
 +{
 +      LSym *s;
 +
 +      switch(a->type) {
 +      case D_NONE:
 +              return C_NONE;
 +
 +      case D_REG:
 +              return C_REG;
 +
 +      case D_FREG:
 +              return C_FREG;
 +
 +      case D_CREG:
 +              return C_CREG;
 +
 +      case D_SPR:
 +              if(a->offset == D_LR)
 +                      return C_LR;
 +              if(a->offset == D_XER)
 +                      return C_XER;
 +              if(a->offset == D_CTR)
 +                      return C_CTR;
 +              return C_SPR;
 +
 +      case D_DCR:
 +              return C_SPR;
 +
 +      case D_FPSCR:
 +              return C_FPSCR;
 +
 +      case D_MSR:
 +              return C_MSR;
 +
 +      case D_OREG:
 +              switch(a->name) {
 +              case D_EXTERN:
 +              case D_STATIC:
 +                      if(a->sym == nil)
 +                              break;
 +                      ctxt->instoffset = a->offset;
 +                      if(a->sym != nil) // use relocation
 +                              return C_ADDR;
 +                      return C_LEXT;
 +              case D_AUTO:
 +                      ctxt->instoffset = ctxt->autosize + a->offset;
 +                      if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
 +                              return C_SAUTO;
 +                      return C_LAUTO;
 +              case D_PARAM:
 +                      ctxt->instoffset = ctxt->autosize + a->offset + 8L;
 +                      if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
 +                              return C_SAUTO;
 +                      return C_LAUTO;
 +              case D_NONE:
 +                      ctxt->instoffset = a->offset;
 +                      if(ctxt->instoffset == 0)
 +                              return C_ZOREG;
 +                      if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
 +                              return C_SOREG;
 +                      return C_LOREG;
 +              }
 +              return C_GOK;
 +
 +      case D_OPT:
 +              ctxt->instoffset = a->offset & 31L;
 +              if(a->name == D_NONE)
 +                      return C_SCON;
 +              return C_GOK;
 +
 +      case D_CONST:
 +              switch(a->name) {
 +              case D_NONE:
 +                      ctxt->instoffset = a->offset;
 +                      if(a->reg != NREG) {
 +                              if(-BIG <= ctxt->instoffset && ctxt->instoffset <= BIG)
 +                                      return C_SACON;
 +                              return C_LACON;
 +                      }
 +              consize:
 +                      if(ctxt->instoffset >= 0) {
 +                              if(ctxt->instoffset == 0)
 +                                      return C_ZCON;
 +                              if(ctxt->instoffset <= 0x7fff)
 +                                      return C_SCON;
 +                              if(ctxt->instoffset <= 0xffff)
 +                                      return C_ANDCON;
 +                              if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset))      /* && (instoffset & (1<<31)) == 0) */
 +                                      return C_UCON;
 +                              if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset))
 +                                      return C_LCON;
 +                              return C_DCON;
 +                      }
 +                      if(ctxt->instoffset >= -0x8000)
 +                              return C_ADDCON;
 +                      if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset))
 +                              return C_UCON;
 +                      if(isint32(ctxt->instoffset))
 +                              return C_LCON;
 +                      return C_DCON;
 +
 +              case D_EXTERN:
 +              case D_STATIC:
 +                      s = a->sym;
 +                      if(s == nil)
 +                              break;
 +                      if(s->type == SCONST) {
 +                              ctxt->instoffset = s->value + a->offset;
 +                              goto consize;
 +                      }
 +                      ctxt->instoffset = s->value + a->offset;
 +                      /* not sure why this barfs */
 +                      return C_LCON;
 +
 +              case D_AUTO:
 +                      ctxt->instoffset = ctxt->autosize + a->offset;
 +                      if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
 +                              return C_SACON;
 +                      return C_LACON;
 +
 +              case D_PARAM:
 +                      ctxt->instoffset = ctxt->autosize + a->offset + 8L;
 +                      if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
 +                              return C_SACON;
 +                      return C_LACON;
 +              }
 +              return C_GOK;
 +
 +      case D_BRANCH:
 +              return C_SBRA;
 +      }
 +      return C_GOK;
 +}
 +
 +static void
 +prasm(Prog *p)
 +{
 +      print("%P\n", p);
 +}
 +
 +static Optab*
 +oplook(Link *ctxt, Prog *p)
 +{
 +      int a1, a2, a3, a4, r;
 +      char *c1, *c3, *c4;
 +      Optab *o, *e;
 +
 +      a1 = p->optab;
 +      if(a1)
 +              return optab+(a1-1);
 +      a1 = p->from.class;
 +      if(a1 == 0) {
 +              a1 = aclass(ctxt, &p->from) + 1;
 +              p->from.class = a1;
 +      }
 +      a1--;
 +      a3 = p->from3.class;
 +      if(a3 == 0) {
 +              a3 = aclass(ctxt, &p->from3) + 1;
 +              p->from3.class = a3;
 +      }
 +      a3--;
 +      a4 = p->to.class;
 +      if(a4 == 0) {
 +              a4 = aclass(ctxt, &p->to) + 1;
 +              p->to.class = a4;
 +      }
 +      a4--;
 +      a2 = C_NONE;
 +      if(p->reg != NREG)
 +              a2 = C_REG;
 +//print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
 +      r = p->as;
 +      o = oprange[r].start;
 +      if(o == 0)
 +              o = oprange[r].stop; /* just generate an error */
 +      e = oprange[r].stop;
 +      c1 = xcmp[a1];
 +      c3 = xcmp[a3];
 +      c4 = xcmp[a4];
 +      for(; o<e; o++)
 +              if(o->a2 == a2)
 +              if(c1[o->a1])
 +              if(c3[o->a3])
 +              if(c4[o->a4]) {
 +                      p->optab = (o-optab)+1;
 +                      return o;
 +              }
 +      ctxt->diag("illegal combination %A %^ %^ %^ %^",
 +              p->as, a1, a2, a3, a4);
 +      prasm(p);
 +      if(o == 0)
 +              o = optab;
 +      return o;
 +}
 +
 +static int
 +cmp(int a, int b)
 +{
 +
 +      if(a == b)
 +              return 1;
 +      switch(a) {
 +      case C_LCON:
 +              if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON)
 +                      return 1;
 +              break;
 +      case C_ADDCON:
 +              if(b == C_ZCON || b == C_SCON)
 +                      return 1;
 +              break;
 +      case C_ANDCON:
 +              if(b == C_ZCON || b == C_SCON)
 +                      return 1;
 +              break;
 +      case C_SPR:
 +              if(b == C_LR || b == C_XER || b == C_CTR)
 +                      return 1;
 +              break;
 +      case C_UCON:
 +              if(b == C_ZCON)
 +                      return 1;
 +              break;
 +      case C_SCON:
 +              if(b == C_ZCON)
 +                      return 1;
 +              break;
 +      case C_LACON:
 +              if(b == C_SACON)
 +                      return 1;
 +              break;
 +      case C_LBRA:
 +              if(b == C_SBRA)
 +                      return 1;
 +              break;
 +      case C_LEXT:
 +              if(b == C_SEXT)
 +                      return 1;
 +              break;
 +      case C_LAUTO:
 +              if(b == C_SAUTO)
 +                      return 1;
 +              break;
 +      case C_REG:
 +              if(b == C_ZCON)
 +                      return r0iszero;
 +              break;
 +      case C_LOREG:
 +              if(b == C_ZOREG || b == C_SOREG)
 +                      return 1;
 +              break;
 +      case C_SOREG:
 +              if(b == C_ZOREG)
 +                      return 1;
 +              break;
 +
 +      case C_ANY:
 +              return 1;
 +      }
 +      return 0;
 +}
 +
 +static int
 +ocmp(const void *a1, const void *a2)
 +{
 +      const Optab *p1, *p2;
 +      int n;
 +
 +      p1 = a1;
 +      p2 = a2;
 +      n = p1->as - p2->as;
 +      if(n)
 +              return n;
 +      n = p1->a1 - p2->a1;
 +      if(n)
 +              return n;
 +      n = p1->a2 - p2->a2;
 +      if(n)
 +              return n;
 +      n = p1->a3 - p2->a3;
 +      if(n)
 +              return n;
 +      n = p1->a4 - p2->a4;
 +      if(n)
 +              return n;
 +      return 0;
 +}
 +
 +static void
 +buildop(Link *ctxt)
 +{
 +      int i, n, r;
 +
 +      for(i=0; i<C_NCLASS; i++)
 +              for(n=0; n<C_NCLASS; n++)
 +                      xcmp[i][n] = cmp(n, i);
 +      for(n=0; optab[n].as != AXXX; n++)
 +              ;
 +      qsort(optab, n, sizeof(optab[0]), ocmp);
 +      for(i=0; i<n; i++) {
 +              r = optab[i].as;
 +              oprange[r].start = optab+i;
 +              while(optab[i].as == r)
 +                      i++;
 +              oprange[r].stop = optab+i;
 +              i--;
 +              
 +              switch(r)
 +              {
 +              default:
 +                      ctxt->diag("unknown op in build: %A", r);
 +                      sysfatal("bad code");
 +              case ADCBF:     /* unary indexed: op (b+a); op (b) */
 +                      oprange[ADCBI] = oprange[r];
 +                      oprange[ADCBST] = oprange[r];
 +                      oprange[ADCBT] = oprange[r];
 +                      oprange[ADCBTST] = oprange[r];
 +                      oprange[ADCBZ] = oprange[r];
 +                      oprange[AICBI] = oprange[r];
 +                      break;
 +              case AECOWX:    /* indexed store: op s,(b+a); op s,(b) */
 +                      oprange[ASTWCCC] = oprange[r];
 +                      oprange[ASTDCCC] = oprange[r];
 +                      break;
 +              case AREM:      /* macro */
 +                      oprange[AREMCC] = oprange[r];
 +                      oprange[AREMV] = oprange[r];
 +                      oprange[AREMVCC] = oprange[r];
 +                      oprange[AREMU] = oprange[r];
 +                      oprange[AREMUCC] = oprange[r];
 +                      oprange[AREMUV] = oprange[r];
 +                      oprange[AREMUVCC] = oprange[r];
 +                      break;
 +              case AREMD:
 +                      oprange[AREMDCC] = oprange[r];
 +                      oprange[AREMDV] = oprange[r];
 +                      oprange[AREMDVCC] = oprange[r];
 +                      oprange[AREMDU] = oprange[r];
 +                      oprange[AREMDUCC] = oprange[r];
 +                      oprange[AREMDUV] = oprange[r];
 +                      oprange[AREMDUVCC] = oprange[r];
 +                      break;
 +              case ADIVW:     /* op Rb[,Ra],Rd */
 +                      oprange[AMULHW] = oprange[r];
 +                      oprange[AMULHWCC] = oprange[r];
 +                      oprange[AMULHWU] = oprange[r];
 +                      oprange[AMULHWUCC] = oprange[r];
 +                      oprange[AMULLWCC] = oprange[r];
 +                      oprange[AMULLWVCC] = oprange[r];
 +                      oprange[AMULLWV] = oprange[r];
 +                      oprange[ADIVWCC] = oprange[r];
 +                      oprange[ADIVWV] = oprange[r];
 +                      oprange[ADIVWVCC] = oprange[r];
 +                      oprange[ADIVWU] = oprange[r];
 +                      oprange[ADIVWUCC] = oprange[r];
 +                      oprange[ADIVWUV] = oprange[r];
 +                      oprange[ADIVWUVCC] = oprange[r];
 +                      oprange[AADDCC] = oprange[r];
 +                      oprange[AADDCV] = oprange[r];
 +                      oprange[AADDCVCC] = oprange[r];
 +                      oprange[AADDV] = oprange[r];
 +                      oprange[AADDVCC] = oprange[r];
 +                      oprange[AADDE] = oprange[r];
 +                      oprange[AADDECC] = oprange[r];
 +                      oprange[AADDEV] = oprange[r];
 +                      oprange[AADDEVCC] = oprange[r];
 +                      oprange[ACRAND] = oprange[r];
 +                      oprange[ACRANDN] = oprange[r];
 +                      oprange[ACREQV] = oprange[r];
 +                      oprange[ACRNAND] = oprange[r];
 +                      oprange[ACRNOR] = oprange[r];
 +                      oprange[ACROR] = oprange[r];
 +                      oprange[ACRORN] = oprange[r];
 +                      oprange[ACRXOR] = oprange[r];
 +                      oprange[AMULHD] = oprange[r];
 +                      oprange[AMULHDCC] = oprange[r];
 +                      oprange[AMULHDU] = oprange[r];
 +                      oprange[AMULHDUCC] = oprange[r];
 +                      oprange[AMULLD] = oprange[r];
 +                      oprange[AMULLDCC] = oprange[r];
 +                      oprange[AMULLDVCC] = oprange[r];
 +                      oprange[AMULLDV] = oprange[r];
 +                      oprange[ADIVD] = oprange[r];
 +                      oprange[ADIVDCC] = oprange[r];
 +                      oprange[ADIVDVCC] = oprange[r];
 +                      oprange[ADIVDV] = oprange[r];
 +                      oprange[ADIVDU] = oprange[r];
 +                      oprange[ADIVDUCC] = oprange[r];
 +                      oprange[ADIVDUVCC] = oprange[r];
 +                      oprange[ADIVDUCC] = oprange[r];
 +                      break;
 +              case AMOVBZ:    /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
 +                      oprange[AMOVH] = oprange[r];
 +                      oprange[AMOVHZ] = oprange[r];
 +                      break;
 +              case AMOVBZU:   /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
 +                      oprange[AMOVHU] = oprange[r];
 +                      oprange[AMOVHZU] = oprange[r];
 +                      oprange[AMOVWU] = oprange[r];
 +                      oprange[AMOVWZU] = oprange[r];
 +                      oprange[AMOVDU] = oprange[r];
 +                      oprange[AMOVMW] = oprange[r];
 +                      break;
 +              case AAND:      /* logical op Rb,Rs,Ra; no literal */
 +                      oprange[AANDN] = oprange[r];
 +                      oprange[AANDNCC] = oprange[r];
 +                      oprange[AEQV] = oprange[r];
 +                      oprange[AEQVCC] = oprange[r];
 +                      oprange[ANAND] = oprange[r];
 +                      oprange[ANANDCC] = oprange[r];
 +                      oprange[ANOR] = oprange[r];
 +                      oprange[ANORCC] = oprange[r];
 +                      oprange[AORCC] = oprange[r];
 +                      oprange[AORN] = oprange[r];
 +                      oprange[AORNCC] = oprange[r];
 +                      oprange[AXORCC] = oprange[r];
 +                      break;
 +              case AADDME:    /* op Ra, Rd */
 +                      oprange[AADDMECC] = oprange[r];
 +                      oprange[AADDMEV] = oprange[r];
 +                      oprange[AADDMEVCC] = oprange[r];
 +                      oprange[AADDZE] = oprange[r];
 +                      oprange[AADDZECC] = oprange[r];
 +                      oprange[AADDZEV] = oprange[r];
 +                      oprange[AADDZEVCC] = oprange[r];
 +                      oprange[ASUBME] = oprange[r];
 +                      oprange[ASUBMECC] = oprange[r];
 +                      oprange[ASUBMEV] = oprange[r];
 +                      oprange[ASUBMEVCC] = oprange[r];
 +                      oprange[ASUBZE] = oprange[r];
 +                      oprange[ASUBZECC] = oprange[r];
 +                      oprange[ASUBZEV] = oprange[r];
 +                      oprange[ASUBZEVCC] = oprange[r];
 +                      break;
 +              case AADDC:
 +                      oprange[AADDCCC] = oprange[r];
 +                      break;
 +              case ABEQ:
 +                      oprange[ABGE] = oprange[r];
 +                      oprange[ABGT] = oprange[r];
 +                      oprange[ABLE] = oprange[r];
 +                      oprange[ABLT] = oprange[r];
 +                      oprange[ABNE] = oprange[r];
 +                      oprange[ABVC] = oprange[r];
 +                      oprange[ABVS] = oprange[r];
 +                      break;
 +              case ABR:
 +                      oprange[ABL] = oprange[r];
 +                      break;
 +              case ABC:
 +                      oprange[ABCL] = oprange[r];
 +                      break;
 +              case AEXTSB:    /* op Rs, Ra */
 +                      oprange[AEXTSBCC] = oprange[r];
 +                      oprange[AEXTSH] = oprange[r];
 +                      oprange[AEXTSHCC] = oprange[r];
 +                      oprange[ACNTLZW] = oprange[r];
 +                      oprange[ACNTLZWCC] = oprange[r];
 +                      oprange[ACNTLZD] = oprange[r];
 +                      oprange[AEXTSW] = oprange[r];
 +                      oprange[AEXTSWCC] = oprange[r];
 +                      oprange[ACNTLZDCC] = oprange[r];
 +                      break;
 +              case AFABS:     /* fop [s,]d */
 +                      oprange[AFABSCC] = oprange[r];
 +                      oprange[AFNABS] = oprange[r];
 +                      oprange[AFNABSCC] = oprange[r];
 +                      oprange[AFNEG] = oprange[r];
 +                      oprange[AFNEGCC] = oprange[r];
 +                      oprange[AFRSP] = oprange[r];
 +                      oprange[AFRSPCC] = oprange[r];
 +                      oprange[AFCTIW] = oprange[r];
 +                      oprange[AFCTIWCC] = oprange[r];
 +                      oprange[AFCTIWZ] = oprange[r];
 +                      oprange[AFCTIWZCC] = oprange[r];
 +                      oprange[AFCTID] = oprange[r];
 +                      oprange[AFCTIDCC] = oprange[r];
 +                      oprange[AFCTIDZ] = oprange[r];
 +                      oprange[AFCTIDZCC] = oprange[r];
 +                      oprange[AFCFID] = oprange[r];
 +                      oprange[AFCFIDCC] = oprange[r];
 +                      oprange[AFRES] = oprange[r];
 +                      oprange[AFRESCC] = oprange[r];
 +                      oprange[AFRSQRTE] = oprange[r];
 +                      oprange[AFRSQRTECC] = oprange[r];
 +                      oprange[AFSQRT] = oprange[r];
 +                      oprange[AFSQRTCC] = oprange[r];
 +                      oprange[AFSQRTS] = oprange[r];
 +                      oprange[AFSQRTSCC] = oprange[r];
 +                      break;
 +              case AFADD:
 +                      oprange[AFADDS] = oprange[r];
 +                      oprange[AFADDCC] = oprange[r];
 +                      oprange[AFADDSCC] = oprange[r];
 +                      oprange[AFDIV] = oprange[r];
 +                      oprange[AFDIVS] = oprange[r];
 +                      oprange[AFDIVCC] = oprange[r];
 +                      oprange[AFDIVSCC] = oprange[r];
 +                      oprange[AFSUB] = oprange[r];
 +                      oprange[AFSUBS] = oprange[r];
 +                      oprange[AFSUBCC] = oprange[r];
 +                      oprange[AFSUBSCC] = oprange[r];
 +                      break;
 +              case AFMADD:
 +                      oprange[AFMADDCC] = oprange[r];
 +                      oprange[AFMADDS] = oprange[r];
 +                      oprange[AFMADDSCC] = oprange[r];
 +                      oprange[AFMSUB] = oprange[r];
 +                      oprange[AFMSUBCC] = oprange[r];
 +                      oprange[AFMSUBS] = oprange[r];
 +                      oprange[AFMSUBSCC] = oprange[r];
 +                      oprange[AFNMADD] = oprange[r];
 +                      oprange[AFNMADDCC] = oprange[r];
 +                      oprange[AFNMADDS] = oprange[r];
 +                      oprange[AFNMADDSCC] = oprange[r];
 +                      oprange[AFNMSUB] = oprange[r];
 +                      oprange[AFNMSUBCC] = oprange[r];
 +                      oprange[AFNMSUBS] = oprange[r];
 +                      oprange[AFNMSUBSCC] = oprange[r];
 +                      oprange[AFSEL] = oprange[r];
 +                      oprange[AFSELCC] = oprange[r];
 +                      break;
 +              case AFMUL:
 +                      oprange[AFMULS] = oprange[r];
 +                      oprange[AFMULCC] = oprange[r];
 +                      oprange[AFMULSCC] = oprange[r];
 +                      break;
 +              case AFCMPO:
 +                      oprange[AFCMPU] = oprange[r];
 +                      break;
 +              case AMTFSB0:
 +                      oprange[AMTFSB0CC] = oprange[r];
 +                      oprange[AMTFSB1] = oprange[r];
 +                      oprange[AMTFSB1CC] = oprange[r];
 +                      break;
 +              case ANEG:      /* op [Ra,] Rd */
 +                      oprange[ANEGCC] = oprange[r];
 +                      oprange[ANEGV] = oprange[r];
 +                      oprange[ANEGVCC] = oprange[r];
 +                      break;
 +              case AOR:       /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
 +                      oprange[AXOR] = oprange[r];
 +                      break;
 +              case ASLW:
 +                      oprange[ASLWCC] = oprange[r];
 +                      oprange[ASRW] = oprange[r];
 +                      oprange[ASRWCC] = oprange[r];
 +                      break;
 +              case ASLD:
 +                      oprange[ASLDCC] = oprange[r];
 +                      oprange[ASRD] = oprange[r];
 +                      oprange[ASRDCC] = oprange[r];
 +                      break;
 +              case ASRAW:     /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
 +                      oprange[ASRAWCC] = oprange[r];
 +                      break;
 +              case ASRAD:     /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
 +                      oprange[ASRADCC] = oprange[r];
 +                      break;
 +              case ASUB:      /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
 +                      oprange[ASUB] = oprange[r];
 +                      oprange[ASUBCC] = oprange[r];
 +                      oprange[ASUBV] = oprange[r];
 +                      oprange[ASUBVCC] = oprange[r];
 +                      oprange[ASUBCCC] = oprange[r];
 +                      oprange[ASUBCV] = oprange[r];
 +                      oprange[ASUBCVCC] = oprange[r];
 +                      oprange[ASUBE] = oprange[r];
 +                      oprange[ASUBECC] = oprange[r];
 +                      oprange[ASUBEV] = oprange[r];
 +                      oprange[ASUBEVCC] = oprange[r];
 +                      break;
 +              case ASYNC:
 +                      oprange[AISYNC] = oprange[r];
 +                      oprange[APTESYNC] = oprange[r];
 +                      oprange[ATLBSYNC] = oprange[r];
 +                      break;
 +              case ARLWMI:
 +                      oprange[ARLWMICC] = oprange[r];
 +                      oprange[ARLWNM] = oprange[r];
 +                      oprange[ARLWNMCC] = oprange[r];
 +                      break;
 +              case ARLDMI:
 +                      oprange[ARLDMICC] = oprange[r];
 +                      break;
 +              case ARLDC:
 +                      oprange[ARLDCCC] = oprange[r];
 +                      break;
 +              case ARLDCL:
 +                      oprange[ARLDCR] = oprange[r];
 +                      oprange[ARLDCLCC] = oprange[r];
 +                      oprange[ARLDCRCC] = oprange[r];
 +                      break;
 +              case AFMOVD:
 +                      oprange[AFMOVDCC] = oprange[r];
 +                      oprange[AFMOVDU] = oprange[r];
 +                      oprange[AFMOVS] = oprange[r];
 +                      oprange[AFMOVSU] = oprange[r];
 +                      break;
 +              case AECIWX:
 +                      oprange[ALWAR] = oprange[r];
 +                      oprange[ALDAR] = oprange[r];
 +                      break;
 +              case ASYSCALL:  /* just the op; flow of control */
 +                      oprange[ARFI] = oprange[r];
 +                      oprange[ARFCI] = oprange[r];
 +                      oprange[ARFID] = oprange[r];
 +                      oprange[AHRFID] = oprange[r];
 +                      break;
 +              case AMOVHBR:
 +                      oprange[AMOVWBR] = oprange[r];
 +                      break;
 +              case ASLBMFEE:
 +                      oprange[ASLBMFEV] = oprange[r];
 +                      break;
 +              case ATW:
 +                      oprange[ATD] = oprange[r];
 +                      break;
 +              case ATLBIE:
 +                      oprange[ASLBIE] = oprange[r];
 +                      oprange[ATLBIEL] = oprange[r];
 +                      break;
 +              case AEIEIO:
 +                      oprange[ASLBIA] = oprange[r];
 +                      break;
 +              case ACMP:
 +                      oprange[ACMPW] = oprange[r];
 +                      break;
 +              case ACMPU:
 +                      oprange[ACMPWU] = oprange[r];
 +                      break;
 +              case AADD:
 +              case AANDCC:    /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
 +              case ALSW:
 +              case AMOVW:     /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
 +              case AMOVWZ:    /* load/store/move word with zero extension; move 32-bit literals  */
 +              case AMOVD:     /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
 +              case AMOVB:     /* macro: move byte with sign extension */
 +              case AMOVBU:    /* macro: move byte with sign extension & update */
 +              case AMOVFL:
 +              case AMULLW:    /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
 +              case ASUBC:     /* op r1,$s,r3; op r1[,r2],r3 */
 +              case ASTSW:
 +              case ASLBMTE:
 +              case AWORD:
 +              case ADWORD:
 +              case ANOP:
 +              case ATEXT:
 +              case AUNDEF:
 +              case AUSEFIELD:
 +              case AFUNCDATA:
 +              case APCDATA:
 +              case ADUFFZERO:
 +              case ADUFFCOPY:
 +                      break;
 +              }
 +      }
 +}
 +
 +#define       OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
 +#define       OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
 +#define       OP(o,xo) OPVCC((o),(xo),0,0)
 +
 +/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
 +#define       AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
 +#define       AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
 +#define       LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
 +#define       LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
 +#define       OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
 +#define       OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
 +#define       OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
 +#define       OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
 +                                      (((mb)&31L)<<6)|(((me)&31L)<<1))
 +
 +#define       OP_ADD  OPVCC(31,266,0,0)
 +#define       OP_ADDI OPVCC(14,0,0,0)
 +#define       OP_ADDIS OPVCC(15,0,0,0)
 +#define       OP_ANDI OPVCC(28,0,0,0)
 +#define       OP_EXTSB        OPVCC(31,954,0,0)
 +#define       OP_EXTSH OPVCC(31,922,0,0)
 +#define       OP_EXTSW OPVCC(31,986,0,0)
 +#define       OP_MCRF OPVCC(19,0,0,0)
 +#define       OP_MCRFS OPVCC(63,64,0,0)
 +#define       OP_MCRXR OPVCC(31,512,0,0)
 +#define       OP_MFCR OPVCC(31,19,0,0)
 +#define       OP_MFFS OPVCC(63,583,0,0)
 +#define       OP_MFMSR OPVCC(31,83,0,0)
 +#define       OP_MFSPR OPVCC(31,339,0,0)
 +#define       OP_MFSR OPVCC(31,595,0,0)
 +#define       OP_MFSRIN       OPVCC(31,659,0,0)
 +#define       OP_MTCRF OPVCC(31,144,0,0)
 +#define       OP_MTFSF OPVCC(63,711,0,0)
 +#define       OP_MTFSFI OPVCC(63,134,0,0)
 +#define       OP_MTMSR OPVCC(31,146,0,0)
 +#define       OP_MTMSRD OPVCC(31,178,0,0)
 +#define       OP_MTSPR OPVCC(31,467,0,0)
 +#define       OP_MTSR OPVCC(31,210,0,0)
 +#define       OP_MTSRIN       OPVCC(31,242,0,0)
 +#define       OP_MULLW OPVCC(31,235,0,0)
 +#define       OP_MULLD OPVCC(31,233,0,0)
 +#define       OP_OR   OPVCC(31,444,0,0)
 +#define       OP_ORI  OPVCC(24,0,0,0)
 +#define       OP_ORIS OPVCC(25,0,0,0)
 +#define       OP_RLWINM       OPVCC(21,0,0,0)
 +#define       OP_SUBF OPVCC(31,40,0,0)
 +#define       OP_RLDIC        OPVCC(30,4,0,0)
 +#define       OP_RLDICR       OPVCC(30,2,0,0)
 +#define       OP_RLDICL       OPVCC(30,0,0,0)
 +
 +#define       oclass(v)       ((v).class-1)
 +
 +// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
 +static void
 +addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2)
 +{
 +      Reloc *rel;
 +
 +      rel = addrel(ctxt->cursym);
 +      rel->off = ctxt->pc;
 +      rel->siz = 8;
 +      rel->sym = s;
 +      rel->add = ((uvlong)*o1<<32) | (uint32)*o2;
 +      rel->type = R_ADDRPOWER;
 +}
 +
 +/*
 + * 32-bit masks
 + */
 +static int
 +getmask(uchar *m, uint32 v)
 +{
 +      int i;
 +
 +      m[0] = m[1] = 0;
 +      if(v != ~0U && v & (1<<31) && v & 1){   /* MB > ME */
 +              if(getmask(m, ~v)){
 +                      i = m[0]; m[0] = m[1]+1; m[1] = i-1;
 +                      return 1;
 +              }
 +              return 0;
 +      }
 +      for(i=0; i<32; i++)
 +              if(v & (1<<(31-i))){
 +                      m[0] = i;
 +                      do {
 +                              m[1] = i;
 +                      } while(++i<32 && (v & (1<<(31-i))) != 0);
 +                      for(; i<32; i++)
 +                              if(v & (1<<(31-i)))
 +                                      return 0;
 +                      return 1;
 +              }
 +      return 0;
 +}
 +
 +static void
 +maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v)
 +{
 +      if(!getmask(m, v))
 +              ctxt->diag("cannot generate mask #%lux\n%P", v, p);
 +}
 +
 +/*
 + * 64-bit masks (rldic etc)
 + */
 +static int
 +getmask64(uchar *m, uvlong v)
 +{
 +      int i;
 +
 +      m[0] = m[1] = 0;
 +      for(i=0; i<64; i++)
 +              if(v & ((uvlong)1<<(63-i))){
 +                      m[0] = i;
 +                      do {
 +                              m[1] = i;
 +                      } while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0);
 +                      for(; i<64; i++)
 +                              if(v & ((uvlong)1<<(63-i)))
 +                                      return 0;
 +                      return 1;
 +              }
 +      return 0;
 +}
 +
 +static void
 +maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v)
 +{
 +      if(!getmask64(m, v))
 +              ctxt->diag("cannot generate mask #%llux\n%P", v, p);
 +}
 +
 +static uint32
 +loadu32(int r, vlong d)
 +{
 +      int32 v;
 +
 +      v = d>>16;
 +      if(isuint32(d))
 +              return LOP_IRR(OP_ORIS, r, REGZERO, v);
 +      return AOP_IRR(OP_ADDIS, r, REGZERO, v);
 +}
 +
 +static uint16
 +high16adjusted(int32 d)
 +{
 +      if(d & 0x8000)
 +              return (d>>16) + 1;
 +      return d>>16;
 +}
 +
 +static void
 +asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
 +{
 +      int32 o1, o2, o3, o4, o5, v, t;
 +      vlong d;
 +      int r, a;
 +      uchar mask[2];
 +      Reloc *rel;
 +
 +      o1 = 0;
 +      o2 = 0;
 +      o3 = 0;
 +      o4 = 0;
 +      o5 = 0;
 +
 +//print("%P => case %d\n", p, o->type);
 +      switch(o->type) {
 +      default:
 +              ctxt->diag("unknown type %d", o->type);
 +              prasm(p);
 +              break;
 +
 +      case 0:         /* pseudo ops */
 +              break;
 +
 +      case 1:         /* mov r1,r2 ==> OR Rs,Rs,Ra */
 +              if(p->to.reg == REGZERO && p->from.type == D_CONST) {
 +                      v = regoff(ctxt, &p->from);
 +                      if(r0iszero && v != 0) {
 +                              //nerrors--;
 +                              ctxt->diag("literal operation on R0\n%P", p);
 +                      }
 +                      o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
 +                      break;
 +              }
 +              o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
 +              break;
 +
 +      case 2:         /* int/cr/fp op Rb,[Ra],Rd */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
 +              break;
 +
 +      case 3:         /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
 +              d = vregoff(ctxt, &p->from);
 +              v = d;
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
 +                      ctxt->diag("literal operation on R0\n%P", p);
 +              a = OP_ADDI;
 +              if(o->a1 == C_UCON) {
 +                      if((d&0xffff) != 0)
 +                              sysfatal("invalid handling of %P", p);
 +                      v >>= 16;
 +                      if(r == REGZERO && isuint32(d)){
 +                              o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v);
 +                              break;
 +                      }
 +                      a = OP_ADDIS;
 +              } else {
 +                      if((int16)d != d)
 +                              sysfatal("invalid handling of %P", p);
 +              }
 +              o1 = AOP_IRR(a, p->to.reg, r, v);
 +              break;
 +
 +      case 4:         /* add/mul $scon,[r1],r2 */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              if(r0iszero && p->to.reg == 0)
 +                      ctxt->diag("literal operation on R0\n%P", p);
 +              if((int16)v != v)
 +                      sysfatal("mishandled instruction %P", p);
 +              o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
 +              break;
 +
 +      case 5:         /* syscall */
 +              o1 = oprrr(ctxt, p->as);
 +              break;
 +
 +      case 6:         /* logical op Rb,[Rs,]Ra; no literal */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
 +              break;
 +
 +      case 7:         /* mov r, soreg ==> stw o(r) */
 +              r = p->to.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              v = regoff(ctxt, &p->to);
 +              if(p->to.type == D_OREG && p->reg != NREG) {
 +                      if(v)
 +                              ctxt->diag("illegal indexed instruction\n%P", p);
 +                      o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r);
 +              } else {
 +                      if((int16)v != v)
 +                              sysfatal("mishandled instruction %P", p);       
 +                      o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v);
 +              }
 +              break;
 +
 +      case 8:         /* mov soreg, r ==> lbz/lhz/lwz o(r) */
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              v = regoff(ctxt, &p->from);
 +              if(p->from.type == D_OREG && p->reg != NREG) {
 +                      if(v)
 +                              ctxt->diag("illegal indexed instruction\n%P", p);
 +                      o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
 +              } else {
 +                      if((int16)v != v)
 +                              sysfatal("mishandled instruction %P", p);
 +                      o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
 +              }
 +              break;
 +
 +      case 9:         /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              v = regoff(ctxt, &p->from);
 +              if(p->from.type == D_OREG && p->reg != NREG) {
 +                      if(v)
 +                              ctxt->diag("illegal indexed instruction\n%P", p);
 +                      o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
 +              } else
 +                      o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
 +              o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
 +              break;
 +
 +      case 10:                /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r);
 +              break;
 +
 +      case 11:        /* br/bl lbra */
 +              v = 0;
 +              if(p->pcond) {
 +                      v = p->pcond->pc - p->pc;
 +                      if(v & 03) {
 +                              ctxt->diag("odd branch target address\n%P", p);
 +                              v &= ~03;
 +                      }
 +                      if(v < -(1L<<25) || v >= (1L<<24))
 +                              ctxt->diag("branch too far\n%P", p);
 +              }
 +              o1 = OP_BR(opirr(ctxt, p->as), v, 0);
 +              if(p->to.sym != nil) {
 +                      rel = addrel(ctxt->cursym);
 +                      rel->off = ctxt->pc;
 +                      rel->siz = 4;
 +                      rel->sym = p->to.sym;
 +                      v += p->to.offset;
 +                      if(v & 03) {
 +                              ctxt->diag("odd branch target address\n%P", p);
 +                              v &= ~03;
 +                      }
 +                      rel->add = o1 | (v & 0x03FFFFFC);
 +                      rel->type = R_CALLPOWER;
 +              }
 +              break;
 +
 +      case 12:        /* movb r,r (extsb); movw r,r (extsw) */
 +              if(p->to.reg == REGZERO && p->from.type == D_CONST) {
 +                      v = regoff(ctxt, &p->from);
 +                      if(r0iszero && v != 0) {
 +                              ctxt->diag("literal operation on R0\n%P", p);
 +                      }
 +                      o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
 +                      break;
 +              }
 +              if(p->as == AMOVW)
 +                      o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0);
 +              else
 +                      o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
 +              break;
 +
 +      case 13:        /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
 +              if(p->as == AMOVBZ)
 +                      o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
 +              else if(p->as == AMOVH)
 +                      o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
 +              else if(p->as == AMOVHZ)
 +                      o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
 +              else if(p->as == AMOVWZ)
 +                      o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5);        /* MB=32 */
 +              else
 +                      ctxt->diag("internal: bad mov[bhw]z\n%P", p);
 +              break;
 +
 +      case 14:        /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              d = vregoff(ctxt, &p->from3);
 +              maskgen64(ctxt, p, mask, d);
 +              switch(p->as){
 +              case ARLDCL: case ARLDCLCC:
 +                      a = mask[0];    /* MB */
 +                      if(mask[1] != 63)
 +                              ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p);
 +                      break;
 +              case ARLDCR: case ARLDCRCC:
 +                      a = mask[1];    /* ME */
 +                      if(mask[0] != 0)
 +                              ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p);
 +                      break;
 +              default:
 +                      ctxt->diag("unexpected op in rldc case\n%P", p);
 +                      a = 0;
 +              }
 +              o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
 +              o1 |= (a&31L)<<6;
 +              if(a & 0x20)
 +                      o1 |= 1<<5;     /* mb[5] is top bit */
 +              break;
 +
 +      case 17:        /* bc bo,bi,lbra (same for now) */
 +      case 16:        /* bc bo,bi,sbra */
 +              a = 0;
 +              if(p->from.type == D_CONST)
 +                      a = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              v = 0;
 +              if(p->pcond)
 +                      v = p->pcond->pc - p->pc;
 +              if(v & 03) {
 +                      ctxt->diag("odd branch target address\n%P", p);
 +                      v &= ~03;
 +              }
 +              if(v < -(1L<<16) || v >= (1L<<15))
 +                      ctxt->diag("branch too far\n%P", p);
 +              o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0);
 +              break;
 +
 +      case 15:        /* br/bl (r) => mov r,lr; br/bl (lr) */
 +              if(p->as == ABC || p->as == ABCL)
 +                      v = regoff(ctxt, &p->to)&31L;
 +              else
 +                      v = 20; /* unconditional */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
 +              o2 = OPVCC(19, 16, 0, 0);
 +              if(p->as == ABL || p->as == ABCL)
 +                      o2 |= 1;
 +              o2 = OP_BCR(o2, v, r);
 +              break;
 +
 +      case 18:        /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
 +              if(p->as == ABC || p->as == ABCL)
 +                      v = regoff(ctxt, &p->from)&31L;
 +              else
 +                      v = 20; /* unconditional */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              switch(oclass(p->to)) {
 +              case C_CTR:
 +                      o1 = OPVCC(19, 528, 0, 0);
 +                      break;
 +              case C_LR:
 +                      o1 = OPVCC(19, 16, 0, 0);
 +                      break;
 +              default:
 +                      ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p);
 +                      v = 0;
 +              }
 +              if(p->as == ABL || p->as == ABCL)
 +                      o1 |= 1;
 +              o1 = OP_BCR(o1, v, r);
 +              break;
 +
 +      case 19:        /* mov $lcon,r ==> cau+or */
 +              d = vregoff(ctxt, &p->from);
 +              if(p->from.sym == nil) {
 +                      o1 = loadu32(p->to.reg, d);
 +                      o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d);
 +              } else {
 +                      o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d));
 +                      o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d);
 +                      addaddrreloc(ctxt, p->from.sym, &o1, &o2);
 +              }
 +              //if(dlm) reloc(&p->from, p->pc, 0);
 +              break;
 +
 +      case 20:        /* add $ucon,,r */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
 +                      ctxt->diag("literal operation on R0\n%P", p);
 +              o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);
 +              break;
 +
 +      case 22:        /* add $lcon,r1,r2 ==> cau+or+add */    /* could do add/sub more efficiently */
 +              if(p->to.reg == REGTMP || p->reg == REGTMP)
 +                      ctxt->diag("cant synthesize large constant\n%P", p);
 +              d = vregoff(ctxt, &p->from);
 +              o1 = loadu32(REGTMP, d);
 +              o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
 +              if(p->from.sym != nil)
 +                      ctxt->diag("%P is not supported", p);
 +              //if(dlm) reloc(&p->from, p->pc, 0);
 +              break;
 +
 +      case 23:        /* and $lcon,r1,r2 ==> cau+or+and */    /* masks could be done using rlnm etc. */
 +              if(p->to.reg == REGTMP || p->reg == REGTMP)
 +                      ctxt->diag("cant synthesize large constant\n%P", p);
 +              d = vregoff(ctxt, &p->from);
 +              o1 = loadu32(REGTMP, d);
 +              o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
 +              if(p->from.sym != nil)
 +                      ctxt->diag("%P is not supported", p);
 +              //if(dlm) reloc(&p->from, p->pc, 0);
 +              break;
 +/*24*/
 +
 +      case 25:        /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
 +              v = regoff(ctxt, &p->from);
 +              if(v < 0)
 +                      v = 0;
 +              else if(v > 63)
 +                      v = 63;
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              switch(p->as){
 +              case ASLD: case ASLDCC:
 +                      a = 63-v;
 +                      o1 = OP_RLDICR;
 +                      break;
 +              case ASRD: case ASRDCC:
 +                      a = v;
 +                      v = 64-v;
 +                      o1 = OP_RLDICL;
 +                      break;
 +              default:
 +                      ctxt->diag("unexpected op in sldi case\n%P", p);
 +                      a = 0;
 +                      o1 = 0;
 +              }
 +              o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F));
 +              o1 |= (a&31L)<<6;
 +              if(v & 0x20)
 +                      o1 |= 1<<1;
 +              if(a & 0x20)
 +                      o1 |= 1<<5;     /* mb[5] is top bit */
 +              if(p->as == ASLDCC || p->as == ASRDCC)
 +                      o1 |= 1;        /* Rc */
 +              break;
 +
 +      case 26:        /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
 +              if(p->to.reg == REGTMP)
 +                      ctxt->diag("can't synthesize large constant\n%P", p);
 +              v = regoff(ctxt, &p->from);
 +              if(v & 0x8000L)
 +                      v += 0x10000L;
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
 +              o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
 +              break;
 +
 +      case 27:                /* subc ra,$simm,rd => subfic rd,ra,$simm */
 +              v = regoff(ctxt, &p->from3);
 +              r = p->from.reg;
 +              o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
 +              break;
 +
 +      case 28:        /* subc r1,$lcon,r2 ==> cau+or+subfc */
 +              if(p->to.reg == REGTMP || p->from.reg == REGTMP)
 +                      ctxt->diag("can't synthesize large constant\n%P", p);
 +              v = regoff(ctxt, &p->from3);
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
 +              o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
 +              o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, REGTMP);
 +              if(p->from.sym != nil)
 +                      ctxt->diag("%P is not supported", p);
 +              //if(dlm) reloc(&p->from3, p->pc, 0);
 +              break;
 +
 +      case 29:        /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
 +              v = regoff(ctxt, &p->from);
 +              d = vregoff(ctxt, &p->from3);
 +              maskgen64(ctxt, p, mask, d);
 +              switch(p->as){
 +              case ARLDC: case ARLDCCC:
 +                      a = mask[0];    /* MB */
 +                      if(mask[1] != (63-v))
 +                              ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
 +                      break;
 +              case ARLDCL: case ARLDCLCC:
 +                      a = mask[0];    /* MB */
 +                      if(mask[1] != 63)
 +                              ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
 +                      break;
 +              case ARLDCR: case ARLDCRCC:
 +                      a = mask[1];    /* ME */
 +                      if(mask[0] != 0)
 +                              ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
 +                      break;
 +              default:
 +                      ctxt->diag("unexpected op in rldic case\n%P", p);
 +                      a = 0;
 +              }
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
 +              o1 |= (a&31L)<<6;
 +              if(v & 0x20)
 +                      o1 |= 1<<1;
 +              if(a & 0x20)
 +                      o1 |= 1<<5;     /* mb[5] is top bit */
 +              break;
 +
 +      case 30:        /* rldimi $sh,s,$mask,a */
 +              v = regoff(ctxt, &p->from);
 +              d = vregoff(ctxt, &p->from3);
 +              maskgen64(ctxt, p, mask, d);
 +              if(mask[1] != (63-v))
 +                      ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
 +              o1 |= (mask[0]&31L)<<6;
 +              if(v & 0x20)
 +                      o1 |= 1<<1;
 +              if(mask[0] & 0x20)
 +                      o1 |= 1<<5;     /* mb[5] is top bit */
 +              break;
 +
 +      case 31:        /* dword */
 +              d = vregoff(ctxt, &p->from);
 +              if(ctxt->arch->endian == BigEndian) {
 +                      o1 = d>>32;
 +                      o2 = d;
 +              } else {
 +                      o1 = d;
 +                      o2 = d>>32;
 +              }
 +              if(p->from.sym != nil) {
 +                      rel = addrel(ctxt->cursym);
 +                      rel->off = ctxt->pc;
 +                      rel->siz = 8;
 +                      rel->sym = p->from.sym;
 +                      rel->add = p->from.offset;
 +                      rel->type = R_ADDR;
 +                      o1 = o2 = 0;
 +              }
 +              break;
 +
 +      case 32:        /* fmul frc,fra,frd */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
 +              break;
 +
 +      case 33:        /* fabs [frb,]frd; fmr. frb,frd */
 +              r = p->from.reg;
 +              if(oclass(p->from) == C_NONE)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, r);
 +              break;
 +
 +      case 34:        /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
 +              break;
 +
 +      case 35:        /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
 +              v = regoff(ctxt, &p->to);
 +              if(v & 0x8000L)
 +                      v += 0x10000L;
 +              r = p->to.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
 +              o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
 +              break;
 +
 +      case 36:        /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
 +              v = regoff(ctxt, &p->from);
 +              if(v & 0x8000L)
 +                      v += 0x10000L;
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
 +              o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
 +              break;
 +
 +      case 37:        /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
 +              v = regoff(ctxt, &p->from);
 +              if(v & 0x8000L)
 +                      v += 0x10000L;
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = o->param;
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
 +              o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
 +              o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
 +              break;
 +
 +      case 40:        /* word */
 +              o1 = regoff(ctxt, &p->from);
 +              break;
 +
 +      case 41:        /* stswi */
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
 +              break;
 +
 +      case 42:        /* lswi */
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
 +              break;
 +
 +      case 43:        /* unary indexed source: dcbf (b); dcbf (a+b) */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg);
 +              break;
 +
 +      case 44:        /* indexed store */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg);
 +              break;
 +      case 45:        /* indexed load */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = 0;
 +              o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg);
 +              break;
 +
 +      case 46:        /* plain op */
 +              o1 = oprrr(ctxt, p->as);
 +              break;
 +
 +      case 47:        /* op Ra, Rd; also op [Ra,] Rd */
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
 +              break;
 +
 +      case 48:        /* op Rs, Ra */
 +              r = p->from.reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
 +              break;
 +
 +      case 49:        /* op Rb; op $n, Rb */
 +              if(p->from.type != D_REG){      /* tlbie $L, rB */
 +                      v = regoff(ctxt, &p->from) & 1;
 +                      o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21);
 +              }else
 +                      o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg);
 +              break;
 +
 +      case 50:        /* rem[u] r1[,r2],r3 */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              v = oprrr(ctxt, p->as);
 +              t = v & ((1<<10)|1);    /* OE|Rc */
 +              o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
 +              o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
 +              o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
 +              break;
 +
 +      case 51:        /* remd[u] r1[,r2],r3 */
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              v = oprrr(ctxt, p->as);
 +              t = v & ((1<<10)|1);    /* OE|Rc */
 +              o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
 +              o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg);
 +              o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
 +              break;
 +
 +      case 52:        /* mtfsbNx cr(n) */
 +              v = regoff(ctxt, &p->from)&31L;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0);
 +              break;
 +
 +      case 53:        /* mffsX ,fr1 */
 +              o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
 +              break;
 +
 +      case 54:        /* mov msr,r1; mov r1, msr*/
 +              if(oclass(p->from) == C_REG){
 +                      if(p->as == AMOVD)
 +                              o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0);
 +                      else
 +                              o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
 +              }else
 +                      o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
 +              break;
 +
 +      case 55:        /* op Rb, Rd */
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg);
 +              break;
 +
 +      case 56:        /* sra $sh,[s,]a; srd $sh,[s,]a */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L);
 +              if(p->as == ASRAD && (v&0x20))
 +                      o1 |= 1<<1;     /* mb[5] */
 +              break;
 +
 +      case 57:        /* slw $sh,[s,]a -> rlwinm ... */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              /*
 +               * Let user (gs) shoot himself in the foot. 
 +               * qc has already complained.
 +               *
 +              if(v < 0 || v > 31)
 +                      ctxt->diag("illegal shift %ld\n%P", v, p);
 +               */
 +              if(v < 0)
 +                      v = 0;
 +              else if(v > 32)
 +                      v = 32;
 +              if(p->as == ASRW || p->as == ASRWCC) {  /* shift right */
 +                      mask[0] = v;
 +                      mask[1] = 31;
 +                      v = 32-v;
 +              } else {
 +                      mask[0] = 0;
 +                      mask[1] = 31-v;
 +              }
 +              o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
 +              if(p->as == ASLWCC || p->as == ASRWCC)
 +                      o1 |= 1;        /* Rc */
 +              break;
 +
 +      case 58:                /* logical $andcon,[s],a */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
 +              break;
 +
 +      case 59:        /* or/and $ucon,,r */
 +              v = regoff(ctxt, &p->from);
 +              r = p->reg;
 +              if(r == NREG)
 +                      r = p->to.reg;
 +              o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);     /* oris, xoris, andis */
 +              break;
 +
 +      case 60:        /* tw to,a,b */
 +              r = regoff(ctxt, &p->from)&31L;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg);
 +              break;
 +
 +      case 61:        /* tw to,a,$simm */
 +              r = regoff(ctxt, &p->from)&31L;
 +              v = regoff(ctxt, &p->to);
 +              o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v);
 +              break;
 +
 +      case 62:        /* rlwmi $sh,s,$mask,a */
 +              v = regoff(ctxt, &p->from);
 +              maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v);
 +              o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
 +              break;
 +
 +      case 63:        /* rlwmi b,s,$mask,a */
 +              maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
 +              o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg);
 +              o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
 +              break;
 +
 +      case 64:        /* mtfsf fr[, $m] {,fpcsr} */
 +              if(p->from3.type != D_NONE)
 +                      v = regoff(ctxt, &p->from3)&255L;
 +              else
 +                      v = 255;
 +              o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
 +              break;
 +
 +      case 65:        /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
 +              if(p->to.reg == NREG)
 +                      ctxt->diag("must specify FPSCR(n)\n%P", p);
 +              o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12);
 +              break;
 +
 +      case 66:        /* mov spr,r1; mov r1,spr, also dcr */
 +              if(p->from.type == D_REG) {
 +                      r = p->from.reg;
 +                      v = p->to.offset;
 +                      if(p->to.type == D_DCR)
 +                              o1 = OPVCC(31,451,0,0); /* mtdcr */
 +                      else
 +                              o1 = OPVCC(31,467,0,0); /* mtspr */
 +              } else {
 +                      r = p->to.reg;
 +                      v = p->from.offset;
 +                      if(p->from.type == D_DCR)
 +                              o1 = OPVCC(31,323,0,0); /* mfdcr */
 +                      else
 +                              o1 = OPVCC(31,339,0,0); /* mfspr */
 +              }
 +              o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
 +              break;
 +
 +      case 67:        /* mcrf crfD,crfS */
 +              if(p->from.type != D_CREG || p->from.reg == NREG ||
 +                 p->to.type != D_CREG || p->to.reg == NREG)
 +                      ctxt->diag("illegal CR field number\n%P", p);
 +              o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
 +              break;
 +
 +      case 68:        /* mfcr rD; mfocrf CRM,rD */
 +              if(p->from.type == D_CREG && p->from.reg != NREG){
 +                      v = 1<<(7-(p->to.reg&7));       /* CR(n) */
 +                      o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12);     /* new form, mfocrf */
 +              }else
 +                      o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0); /* old form, whole register */
 +              break;
 +
 +      case 69:        /* mtcrf CRM,rS */
 +              if(p->from3.type != D_NONE) {
 +                      if(p->to.reg != NREG)
 +                              ctxt->diag("can't use both mask and CR(n)\n%P", p);
 +                      v = regoff(ctxt, &p->from3) & 0xff;
 +              } else {
 +                      if(p->to.reg == NREG)
 +                              v = 0xff;       /* CR */
 +                      else
 +                              v = 1<<(7-(p->to.reg&7));       /* CR(n) */
 +              }
 +              o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
 +              break;
 +
 +      case 70:        /* [f]cmp r,r,cr*/
 +              if(p->reg == NREG)
 +                      r = 0;
 +              else
 +                      r = (p->reg&7)<<2;
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg);
 +              break;
 +
 +      case 71:        /* cmp[l] r,i,cr*/
 +              if(p->reg == NREG)
 +                      r = 0;
 +              else
 +                      r = (p->reg&7)<<2;
 +              o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff);
 +              break;
 +
 +      case 72:        /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
 +              o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg);
 +              break;
 +
 +      case 73:        /* mcrfs crfD,crfS */
 +              if(p->from.type != D_FPSCR || p->from.reg == NREG ||
 +                 p->to.type != D_CREG || p->to.reg == NREG)
 +                      ctxt->diag("illegal FPSCR/CR field number\n%P", p);
 +              o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
 +              break;
 +
 +      case 77:        /* syscall $scon, syscall Rx */
 +              if(p->from.type == D_CONST) {
 +                      if(p->from.offset > BIG || p->from.offset < -BIG)
 +                              ctxt->diag("illegal syscall, sysnum too large: %P", p);
 +                      o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset);
 +              } else if(p->from.type == D_REG) {
 +                      o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg);
 +              } else {
 +                      ctxt->diag("illegal syscall: %P", p);
 +                      o1 = 0x7fe00008; // trap always
 +              }
 +              o2 = oprrr(ctxt, p->as);
 +              o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0
 +              break;
 +
 +      case 78:        /* undef */
 +              o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed
 +                         always to be an illegal instruction."  */
 +              break;
 +
 +      /* relocation operations */
 +
 +      case 74:
 +              v = regoff(ctxt, &p->to);
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
 +              o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
 +              addaddrreloc(ctxt, p->to.sym, &o1, &o2);
 +              //if(dlm) reloc(&p->to, p->pc, 1);
 +              break;
 +
 +      case 75:
 +              v = regoff(ctxt, &p->from);
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
 +              o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
 +              addaddrreloc(ctxt, p->from.sym, &o1, &o2);
 +              //if(dlm) reloc(&p->from, p->pc, 1);
 +              break;
 +
 +      case 76:
 +              v = regoff(ctxt, &p->from);
 +              o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
 +              o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
 +              addaddrreloc(ctxt, p->from.sym, &o1, &o2);
 +              o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
 +              //if(dlm) reloc(&p->from, p->pc, 1);
 +              break;
 +
 +      }
 +
 +      out[0] = o1;
 +      out[1] = o2;
 +      out[2] = o3;
 +      out[3] = o4;
 +      out[4] = o5;
 +      return;
 +
 +#if NOTDEF
 +      v = p->pc;
 +      switch(o->size) {
 +      default:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
 +              break;
 +      case 4:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
 +              lput(o1);
 +              break;
 +      case 8:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
 +              lput(o1);
 +              lput(o2);
 +              break;
 +      case 12:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
 +              lput(o1);
 +              lput(o2);
 +              lput(o3);
 +              break;
 +      case 16:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
 +                              v, o1, o2, o3, o4, p);
 +              lput(o1);
 +              lput(o2);
 +              lput(o3);
 +              lput(o4);
 +              break;
 +      case 20:
 +              if(debug['a'])
 +                      Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
 +                              v, o1, o2, o3, o4, o5, p);
 +              lput(o1);
 +              lput(o2);
 +              lput(o3);
 +              lput(o4);
 +              lput(o5);
 +              break;
 +      }
 +      return 0;
 +#endif
 +}
 +
 +static vlong
 +vregoff(Link *ctxt, Addr *a)
 +{
 +
 +      ctxt->instoffset = 0;
 +      aclass(ctxt, a);
 +      return ctxt->instoffset;
 +}
 +
 +static int32
 +regoff(Link *ctxt, Addr *a)
 +{
 +      return vregoff(ctxt, a);
 +}
 +
 +static int32
 +oprrr(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AADD:      return OPVCC(31,266,0,0);
 +      case AADDCC:    return OPVCC(31,266,0,1);
 +      case AADDV:     return OPVCC(31,266,1,0);
 +      case AADDVCC:   return OPVCC(31,266,1,1);
 +      case AADDC:     return OPVCC(31,10,0,0);
 +      case AADDCCC:   return OPVCC(31,10,0,1);
 +      case AADDCV:    return OPVCC(31,10,1,0);
 +      case AADDCVCC:  return OPVCC(31,10,1,1);
 +      case AADDE:     return OPVCC(31,138,0,0);
 +      case AADDECC:   return OPVCC(31,138,0,1);
 +      case AADDEV:    return OPVCC(31,138,1,0);
 +      case AADDEVCC:  return OPVCC(31,138,1,1);
 +      case AADDME:    return OPVCC(31,234,0,0);
 +      case AADDMECC:  return OPVCC(31,234,0,1);
 +      case AADDMEV:   return OPVCC(31,234,1,0);
 +      case AADDMEVCC: return OPVCC(31,234,1,1);
 +      case AADDZE:    return OPVCC(31,202,0,0);
 +      case AADDZECC:  return OPVCC(31,202,0,1);
 +      case AADDZEV:   return OPVCC(31,202,1,0);
 +      case AADDZEVCC: return OPVCC(31,202,1,1);
 +
 +      case AAND:      return OPVCC(31,28,0,0);
 +      case AANDCC:    return OPVCC(31,28,0,1);
 +      case AANDN:     return OPVCC(31,60,0,0);
 +      case AANDNCC:   return OPVCC(31,60,0,1);
 +
 +      case ACMP:      return OPVCC(31,0,0,0)|(1<<21); /* L=1 */
 +      case ACMPU:     return OPVCC(31,32,0,0)|(1<<21);
 +      case ACMPW:     return OPVCC(31,0,0,0); /* L=0 */
 +      case ACMPWU:    return OPVCC(31,32,0,0);
 +
 +      case ACNTLZW:   return OPVCC(31,26,0,0);
 +      case ACNTLZWCC: return OPVCC(31,26,0,1);
 +      case ACNTLZD:           return OPVCC(31,58,0,0);
 +      case ACNTLZDCC: return OPVCC(31,58,0,1);
 +
 +      case ACRAND:    return OPVCC(19,257,0,0);
 +      case ACRANDN:   return OPVCC(19,129,0,0);
 +      case ACREQV:    return OPVCC(19,289,0,0);
 +      case ACRNAND:   return OPVCC(19,225,0,0);
 +      case ACRNOR:    return OPVCC(19,33,0,0);
 +      case ACROR:     return OPVCC(19,449,0,0);
 +      case ACRORN:    return OPVCC(19,417,0,0);
 +      case ACRXOR:    return OPVCC(19,193,0,0);
 +
 +      case ADCBF:     return OPVCC(31,86,0,0);
 +      case ADCBI:     return OPVCC(31,470,0,0);
 +      case ADCBST:    return OPVCC(31,54,0,0);
 +      case ADCBT:     return OPVCC(31,278,0,0);
 +      case ADCBTST:   return OPVCC(31,246,0,0);
 +      case ADCBZ:     return OPVCC(31,1014,0,0);
 +
 +      case AREM:
 +      case ADIVW:     return OPVCC(31,491,0,0);
 +      case AREMCC:
 +      case ADIVWCC:   return OPVCC(31,491,0,1);
 +      case AREMV:
 +      case ADIVWV:    return OPVCC(31,491,1,0);
 +      case AREMVCC:
 +      case ADIVWVCC:  return OPVCC(31,491,1,1);
 +      case AREMU:
 +      case ADIVWU:    return OPVCC(31,459,0,0);
 +      case AREMUCC:
 +      case ADIVWUCC:  return OPVCC(31,459,0,1);
 +      case AREMUV:
 +      case ADIVWUV:   return OPVCC(31,459,1,0);
 +      case AREMUVCC:
 +      case ADIVWUVCC: return OPVCC(31,459,1,1);
 +
 +      case AREMD:
 +      case ADIVD:     return OPVCC(31,489,0,0);
 +      case AREMDCC:
 +      case ADIVDCC:   return OPVCC(31,489,0,1);
 +      case AREMDV:
 +      case ADIVDV:    return OPVCC(31,489,1,0);
 +      case AREMDVCC:
 +      case ADIVDVCC:  return OPVCC(31,489,1,1);
 +      case AREMDU:
 +      case ADIVDU:    return OPVCC(31,457,0,0);
 +      case AREMDUCC:
 +      case ADIVDUCC:  return OPVCC(31,457,0,1);
 +      case AREMDUV:
 +      case ADIVDUV:   return OPVCC(31,457,1,0);
 +      case AREMDUVCC:
 +      case ADIVDUVCC: return OPVCC(31,457,1,1);
 +
 +      case AEIEIO:    return OPVCC(31,854,0,0);
 +
 +      case AEQV:      return OPVCC(31,284,0,0);
 +      case AEQVCC:    return OPVCC(31,284,0,1);
 +
 +      case AEXTSB:    return OPVCC(31,954,0,0);
 +      case AEXTSBCC:  return OPVCC(31,954,0,1);
 +      case AEXTSH:    return OPVCC(31,922,0,0);
 +      case AEXTSHCC:  return OPVCC(31,922,0,1);
 +      case AEXTSW:    return OPVCC(31,986,0,0);
 +      case AEXTSWCC:  return OPVCC(31,986,0,1);
 +
 +      case AFABS:     return OPVCC(63,264,0,0);
 +      case AFABSCC:   return OPVCC(63,264,0,1);
 +      case AFADD:     return OPVCC(63,21,0,0);
 +      case AFADDCC:   return OPVCC(63,21,0,1);
 +      case AFADDS:    return OPVCC(59,21,0,0);
 +      case AFADDSCC:  return OPVCC(59,21,0,1);
 +      case AFCMPO:    return OPVCC(63,32,0,0);
 +      case AFCMPU:    return OPVCC(63,0,0,0);
 +      case AFCFID:    return OPVCC(63,846,0,0);
 +      case AFCFIDCC:  return OPVCC(63,846,0,1);
 +      case AFCTIW:    return OPVCC(63,14,0,0);
 +      case AFCTIWCC:  return OPVCC(63,14,0,1);
 +      case AFCTIWZ:   return OPVCC(63,15,0,0);
 +      case AFCTIWZCC: return OPVCC(63,15,0,1);
 +      case AFCTID:    return OPVCC(63,814,0,0);
 +      case AFCTIDCC:  return OPVCC(63,814,0,1);
 +      case AFCTIDZ:   return OPVCC(63,815,0,0);
 +      case AFCTIDZCC: return OPVCC(63,815,0,1);
 +      case AFDIV:     return OPVCC(63,18,0,0);
 +      case AFDIVCC:   return OPVCC(63,18,0,1);
 +      case AFDIVS:    return OPVCC(59,18,0,0);
 +      case AFDIVSCC:  return OPVCC(59,18,0,1);
 +      case AFMADD:    return OPVCC(63,29,0,0);
 +      case AFMADDCC:  return OPVCC(63,29,0,1);
 +      case AFMADDS:   return OPVCC(59,29,0,0);
 +      case AFMADDSCC: return OPVCC(59,29,0,1);
 +      case AFMOVS:
 +      case AFMOVD:    return OPVCC(63,72,0,0);        /* load */
 +      case AFMOVDCC:  return OPVCC(63,72,0,1);
 +      case AFMSUB:    return OPVCC(63,28,0,0);
 +      case AFMSUBCC:  return OPVCC(63,28,0,1);
 +      case AFMSUBS:   return OPVCC(59,28,0,0);
 +      case AFMSUBSCC: return OPVCC(59,28,0,1);
 +      case AFMUL:     return OPVCC(63,25,0,0);
 +      case AFMULCC:   return OPVCC(63,25,0,1);
 +      case AFMULS:    return OPVCC(59,25,0,0);
 +      case AFMULSCC:  return OPVCC(59,25,0,1);
 +      case AFNABS:    return OPVCC(63,136,0,0);
 +      case AFNABSCC:  return OPVCC(63,136,0,1);
 +      case AFNEG:     return OPVCC(63,40,0,0);
 +      case AFNEGCC:   return OPVCC(63,40,0,1);
 +      case AFNMADD:   return OPVCC(63,31,0,0);
 +      case AFNMADDCC: return OPVCC(63,31,0,1);
 +      case AFNMADDS:  return OPVCC(59,31,0,0);
 +      case AFNMADDSCC:        return OPVCC(59,31,0,1);
 +      case AFNMSUB:   return OPVCC(63,30,0,0);
 +      case AFNMSUBCC: return OPVCC(63,30,0,1);
 +      case AFNMSUBS:  return OPVCC(59,30,0,0);
 +      case AFNMSUBSCC:        return OPVCC(59,30,0,1);
 +      case AFRES:     return OPVCC(59,24,0,0);
 +      case AFRESCC:   return OPVCC(59,24,0,1);
 +      case AFRSP:     return OPVCC(63,12,0,0);
 +      case AFRSPCC:   return OPVCC(63,12,0,1);
 +      case AFRSQRTE:  return OPVCC(63,26,0,0);
 +      case AFRSQRTECC:        return OPVCC(63,26,0,1);
 +      case AFSEL:     return OPVCC(63,23,0,0);
 +      case AFSELCC:   return OPVCC(63,23,0,1);
 +      case AFSQRT:    return OPVCC(63,22,0,0);
 +      case AFSQRTCC:  return OPVCC(63,22,0,1);
 +      case AFSQRTS:   return OPVCC(59,22,0,0);
 +      case AFSQRTSCC: return OPVCC(59,22,0,1);
 +      case AFSUB:     return OPVCC(63,20,0,0);
 +      case AFSUBCC:   return OPVCC(63,20,0,1);
 +      case AFSUBS:    return OPVCC(59,20,0,0);
 +      case AFSUBSCC:  return OPVCC(59,20,0,1);
 +
 +      case AICBI:     return OPVCC(31,982,0,0);
 +      case AISYNC:    return OPVCC(19,150,0,0);
 +
 +      case AMTFSB0:   return OPVCC(63,70,0,0);
 +      case AMTFSB0CC: return OPVCC(63,70,0,1);
 +      case AMTFSB1:   return OPVCC(63,38,0,0);
 +      case AMTFSB1CC: return OPVCC(63,38,0,1);
 +
 +      case AMULHW:    return OPVCC(31,75,0,0);
 +      case AMULHWCC:  return OPVCC(31,75,0,1);
 +      case AMULHWU:   return OPVCC(31,11,0,0);
 +      case AMULHWUCC: return OPVCC(31,11,0,1);
 +      case AMULLW:    return OPVCC(31,235,0,0);
 +      case AMULLWCC:  return OPVCC(31,235,0,1);
 +      case AMULLWV:   return OPVCC(31,235,1,0);
 +      case AMULLWVCC: return OPVCC(31,235,1,1);
 +
 +      case AMULHD:    return OPVCC(31,73,0,0);
 +      case AMULHDCC:  return OPVCC(31,73,0,1);
 +      case AMULHDU:   return OPVCC(31,9,0,0);
 +      case AMULHDUCC: return OPVCC(31,9,0,1);
 +      case AMULLD:    return OPVCC(31,233,0,0);
 +      case AMULLDCC:  return OPVCC(31,233,0,1);
 +      case AMULLDV:   return OPVCC(31,233,1,0);
 +      case AMULLDVCC: return OPVCC(31,233,1,1);
 +
 +      case ANAND:     return OPVCC(31,476,0,0);
 +      case ANANDCC:   return OPVCC(31,476,0,1);
 +      case ANEG:      return OPVCC(31,104,0,0);
 +      case ANEGCC:    return OPVCC(31,104,0,1);
 +      case ANEGV:     return OPVCC(31,104,1,0);
 +      case ANEGVCC:   return OPVCC(31,104,1,1);
 +      case ANOR:      return OPVCC(31,124,0,0);
 +      case ANORCC:    return OPVCC(31,124,0,1);
 +      case AOR:       return OPVCC(31,444,0,0);
 +      case AORCC:     return OPVCC(31,444,0,1);
 +      case AORN:      return OPVCC(31,412,0,0);
 +      case AORNCC:    return OPVCC(31,412,0,1);
 +
 +      case ARFI:      return OPVCC(19,50,0,0);
 +      case ARFCI:     return OPVCC(19,51,0,0);
 +      case ARFID:     return OPVCC(19,18,0,0);
 +      case AHRFID: return OPVCC(19,274,0,0);
 +
 +      case ARLWMI:    return OPVCC(20,0,0,0);
 +      case ARLWMICC: return OPVCC(20,0,0,1);
 +      case ARLWNM:    return OPVCC(23,0,0,0);
 +      case ARLWNMCC:  return OPVCC(23,0,0,1);
 +
 +      case ARLDCL:    return OPVCC(30,8,0,0);
 +      case ARLDCR:    return OPVCC(30,9,0,0);
 +
 +      case ASYSCALL:  return OPVCC(17,1,0,0);
 +
 +      case ASLW:      return OPVCC(31,24,0,0);
 +      case ASLWCC:    return OPVCC(31,24,0,1);
 +      case ASLD:      return OPVCC(31,27,0,0);
 +      case ASLDCC:    return OPVCC(31,27,0,1);
 +
 +      case ASRAW:     return OPVCC(31,792,0,0);
 +      case ASRAWCC:   return OPVCC(31,792,0,1);
 +      case ASRAD:     return OPVCC(31,794,0,0);
 +      case ASRADCC:   return OPVCC(31,794,0,1);
 +
 +      case ASRW:      return OPVCC(31,536,0,0);
 +      case ASRWCC:    return OPVCC(31,536,0,1);
 +      case ASRD:      return OPVCC(31,539,0,0);
 +      case ASRDCC:    return OPVCC(31,539,0,1);
 +
 +      case ASUB:      return OPVCC(31,40,0,0);
 +      case ASUBCC:    return OPVCC(31,40,0,1);
 +      case ASUBV:     return OPVCC(31,40,1,0);
 +      case ASUBVCC:   return OPVCC(31,40,1,1);
 +      case ASUBC:     return OPVCC(31,8,0,0);
 +      case ASUBCCC:   return OPVCC(31,8,0,1);
 +      case ASUBCV:    return OPVCC(31,8,1,0);
 +      case ASUBCVCC:  return OPVCC(31,8,1,1);
 +      case ASUBE:     return OPVCC(31,136,0,0);
 +      case ASUBECC:   return OPVCC(31,136,0,1);
 +      case ASUBEV:    return OPVCC(31,136,1,0);
 +      case ASUBEVCC:  return OPVCC(31,136,1,1);
 +      case ASUBME:    return OPVCC(31,232,0,0);
 +      case ASUBMECC:  return OPVCC(31,232,0,1);
 +      case ASUBMEV:   return OPVCC(31,232,1,0);
 +      case ASUBMEVCC: return OPVCC(31,232,1,1);
 +      case ASUBZE:    return OPVCC(31,200,0,0);
 +      case ASUBZECC:  return OPVCC(31,200,0,1);
 +      case ASUBZEV:   return OPVCC(31,200,1,0);
 +      case ASUBZEVCC: return OPVCC(31,200,1,1);
 +
 +      case ASYNC:     return OPVCC(31,598,0,0);
 +      case APTESYNC:  return OPVCC(31,598,0,0) | (2<<21);
 +
 +      case ATLBIE:    return OPVCC(31,306,0,0);
 +      case ATLBIEL:   return OPVCC(31,274,0,0);
 +      case ATLBSYNC:  return OPVCC(31,566,0,0);
 +      case ASLBIA:    return OPVCC(31,498,0,0);
 +      case ASLBIE:    return OPVCC(31,434,0,0);
 +      case ASLBMFEE:  return OPVCC(31,915,0,0);
 +      case ASLBMFEV:  return OPVCC(31,851,0,0);
 +      case ASLBMTE:           return OPVCC(31,402,0,0);
 +
 +      case ATW:       return OPVCC(31,4,0,0);
 +      case ATD:       return OPVCC(31,68,0,0);
 +
 +      case AXOR:      return OPVCC(31,316,0,0);
 +      case AXORCC:    return OPVCC(31,316,0,1);
 +      }
 +      ctxt->diag("bad r/r opcode %A", a);
 +      return 0;
 +}
 +
 +static int32
 +opirr(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AADD:      return OPVCC(14,0,0,0);
 +      case AADDC:     return OPVCC(12,0,0,0);
 +      case AADDCCC:   return OPVCC(13,0,0,0);
 +      case AADD+AEND: return OPVCC(15,0,0,0);         /* ADDIS/CAU */
 +
 +      case AANDCC:    return OPVCC(28,0,0,0);
 +      case AANDCC+AEND:       return OPVCC(29,0,0,0);         /* ANDIS./ANDIU. */
 +
 +      case ABR:       return OPVCC(18,0,0,0);
 +      case ABL:       return OPVCC(18,0,0,0) | 1;
 +      case ADUFFZERO: return OPVCC(18,0,0,0) | 1;
 +      case ADUFFCOPY: return OPVCC(18,0,0,0) | 1;
 +      case ABC:       return OPVCC(16,0,0,0);
 +      case ABCL:      return OPVCC(16,0,0,0) | 1;
 +
 +      case ABEQ:      return AOP_RRR(16<<26,12,2,0);
 +      case ABGE:      return AOP_RRR(16<<26,4,0,0);
 +      case ABGT:      return AOP_RRR(16<<26,12,1,0);
 +      case ABLE:      return AOP_RRR(16<<26,4,1,0);
 +      case ABLT:      return AOP_RRR(16<<26,12,0,0);
 +      case ABNE:      return AOP_RRR(16<<26,4,2,0);
 +      case ABVC:      return AOP_RRR(16<<26,4,3,0);
 +      case ABVS:      return AOP_RRR(16<<26,12,3,0);
 +
 +      case ACMP:      return OPVCC(11,0,0,0)|(1<<21); /* L=1 */
 +      case ACMPU:     return OPVCC(10,0,0,0)|(1<<21);
 +      case ACMPW:     return OPVCC(11,0,0,0); /* L=0 */
 +      case ACMPWU:    return OPVCC(10,0,0,0);
 +      case ALSW:      return OPVCC(31,597,0,0);
 +
 +      case AMULLW:    return OPVCC(7,0,0,0);
 +
 +      case AOR:       return OPVCC(24,0,0,0);
 +      case AOR+AEND:  return OPVCC(25,0,0,0);         /* ORIS/ORIU */
 +
 +      case ARLWMI:    return OPVCC(20,0,0,0);         /* rlwimi */
 +      case ARLWMICC:  return OPVCC(20,0,0,1);
 +      case ARLDMI:    return OPVCC(30,0,0,0) | (3<<2);        /* rldimi */
 +      case ARLDMICC:  return OPVCC(30,0,0,1) | (3<<2);
 +
 +      case ARLWNM:    return OPVCC(21,0,0,0);         /* rlwinm */
 +      case ARLWNMCC:  return OPVCC(21,0,0,1);
 +
 +      case ARLDCL:    return OPVCC(30,0,0,0);         /* rldicl */
 +      case ARLDCLCC:  return OPVCC(30,0,0,1);
 +      case ARLDCR:    return OPVCC(30,1,0,0);         /* rldicr */
 +      case ARLDCRCC:  return OPVCC(30,1,0,1);
 +      case ARLDC:     return OPVCC(30,0,0,0) | (2<<2);
 +      case ARLDCCC:   return OPVCC(30,0,0,1) | (2<<2);
 +
 +      case ASRAW:     return OPVCC(31,824,0,0);
 +      case ASRAWCC:   return OPVCC(31,824,0,1);
 +      case ASRAD:     return OPVCC(31,(413<<1),0,0);
 +      case ASRADCC:   return OPVCC(31,(413<<1),0,1);
 +
 +      case ASTSW:     return OPVCC(31,725,0,0);
 +
 +      case ASUBC:     return OPVCC(8,0,0,0);
 +
 +      case ATW:       return OPVCC(3,0,0,0);
 +      case ATD:       return OPVCC(2,0,0,0);
 +
 +      case AXOR:      return OPVCC(26,0,0,0);         /* XORIL */
 +      case AXOR+AEND: return OPVCC(27,0,0,0);         /* XORIU */
 +      }
 +      ctxt->diag("bad opcode i/r %A", a);
 +      return 0;
 +}
 +
 +/*
 + * load o(a),d
 + */
 +static int32
 +opload(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AMOVD:     return OPVCC(58,0,0,0); /* ld */
 +      case AMOVDU:    return OPVCC(58,0,0,1); /* ldu */
 +      case AMOVWZ:    return OPVCC(32,0,0,0);         /* lwz */
 +      case AMOVWZU:   return OPVCC(33,0,0,0);         /* lwzu */
 +      case AMOVW:             return OPVCC(58,0,0,0)|(1<<1);  /* lwa */
 +      /* no AMOVWU */
 +      case AMOVB:
 +      case AMOVBZ:    return OPVCC(34,0,0,0);         /* load */
 +      case AMOVBU:
 +      case AMOVBZU:   return OPVCC(35,0,0,0);
 +      case AFMOVD:    return OPVCC(50,0,0,0);
 +      case AFMOVDU:   return OPVCC(51,0,0,0);
 +      case AFMOVS:    return OPVCC(48,0,0,0);
 +      case AFMOVSU:   return OPVCC(49,0,0,0);
 +      case AMOVH:     return OPVCC(42,0,0,0);
 +      case AMOVHU:    return OPVCC(43,0,0,0);
 +      case AMOVHZ:    return OPVCC(40,0,0,0);
 +      case AMOVHZU:   return OPVCC(41,0,0,0);
 +      case AMOVMW:    return OPVCC(46,0,0,0); /* lmw */
 +      }
 +      ctxt->diag("bad load opcode %A", a);
 +      return 0;
 +}
 +
 +/*
 + * indexed load a(b),d
 + */
 +static int32
 +oploadx(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AMOVWZ: return OPVCC(31,23,0,0);   /* lwzx */
 +      case AMOVWZU:   return OPVCC(31,55,0,0); /* lwzux */
 +      case AMOVW:     return OPVCC(31,341,0,0);       /* lwax */
 +      case AMOVWU:    return OPVCC(31,373,0,0);       /* lwaux */
 +      case AMOVB:
 +      case AMOVBZ: return OPVCC(31,87,0,0);   /* lbzx */
 +      case AMOVBU:
 +      case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */
 +      case AFMOVD:    return OPVCC(31,599,0,0);       /* lfdx */
 +      case AFMOVDU:   return OPVCC(31,631,0,0);       /*  lfdux */
 +      case AFMOVS:    return OPVCC(31,535,0,0);       /* lfsx */
 +      case AFMOVSU:   return OPVCC(31,567,0,0);       /* lfsux */
 +      case AMOVH:     return OPVCC(31,343,0,0);       /* lhax */
 +      case AMOVHU:    return OPVCC(31,375,0,0);       /* lhaux */
 +      case AMOVHBR:   return OPVCC(31,790,0,0);       /* lhbrx */
 +      case AMOVWBR:   return OPVCC(31,534,0,0);       /* lwbrx */
 +      case AMOVHZ:    return OPVCC(31,279,0,0);       /* lhzx */
 +      case AMOVHZU:   return OPVCC(31,311,0,0);       /* lhzux */
 +      case AECIWX:    return OPVCC(31,310,0,0);       /* eciwx */
 +      case ALWAR:     return OPVCC(31,20,0,0);        /* lwarx */
 +      case ALDAR:     return OPVCC(31,84,0,0);
 +      case ALSW:      return OPVCC(31,533,0,0);       /* lswx */
 +      case AMOVD:     return OPVCC(31,21,0,0);        /* ldx */
 +      case AMOVDU:    return OPVCC(31,53,0,0);        /* ldux */
 +      }
 +      ctxt->diag("bad loadx opcode %A", a);
 +      return 0;
 +}
 +
 +/*
 + * store s,o(d)
 + */
 +static int32
 +opstore(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AMOVB:
 +      case AMOVBZ:    return OPVCC(38,0,0,0); /* stb */
 +      case AMOVBU:
 +      case AMOVBZU:   return OPVCC(39,0,0,0); /* stbu */
 +      case AFMOVD:    return OPVCC(54,0,0,0); /* stfd */
 +      case AFMOVDU:   return OPVCC(55,0,0,0); /* stfdu */
 +      case AFMOVS:    return OPVCC(52,0,0,0); /* stfs */
 +      case AFMOVSU:   return OPVCC(53,0,0,0); /* stfsu */
 +      case AMOVHZ:
 +      case AMOVH:     return OPVCC(44,0,0,0); /* sth */
 +      case AMOVHZU:
 +      case AMOVHU:    return OPVCC(45,0,0,0); /* sthu */
 +      case AMOVMW:    return OPVCC(47,0,0,0); /* stmw */
 +      case ASTSW:     return OPVCC(31,725,0,0);       /* stswi */
 +      case AMOVWZ:
 +      case AMOVW:     return OPVCC(36,0,0,0); /* stw */
 +      case AMOVWZU:
 +      case AMOVWU:    return OPVCC(37,0,0,0); /* stwu */
 +      case AMOVD:     return OPVCC(62,0,0,0); /* std */
 +      case AMOVDU:    return OPVCC(62,0,0,1); /* stdu */
 +      }
 +      ctxt->diag("unknown store opcode %A", a);
 +      return 0;
 +}
 +
 +/*
 + * indexed store s,a(b)
 + */
 +static int32
 +opstorex(Link *ctxt, int a)
 +{
 +      switch(a) {
 +      case AMOVB:
 +      case AMOVBZ:    return OPVCC(31,215,0,0);       /* stbx */
 +      case AMOVBU:
 +      case AMOVBZU:   return OPVCC(31,247,0,0);       /* stbux */
 +      case AFMOVD:    return OPVCC(31,727,0,0);       /* stfdx */
 +      case AFMOVDU:   return OPVCC(31,759,0,0);       /* stfdux */
 +      case AFMOVS:    return OPVCC(31,663,0,0);       /* stfsx */
 +      case AFMOVSU:   return OPVCC(31,695,0,0);       /* stfsux */
 +      case AMOVHZ:
 +      case AMOVH:     return OPVCC(31,407,0,0);       /* sthx */
 +      case AMOVHBR:   return OPVCC(31,918,0,0);       /* sthbrx */
 +      case AMOVHZU:
 +      case AMOVHU:    return OPVCC(31,439,0,0);       /* sthux */
 +      case AMOVWZ:
 +      case AMOVW:     return OPVCC(31,151,0,0);       /* stwx */
 +      case AMOVWZU:
 +      case AMOVWU:    return OPVCC(31,183,0,0);       /* stwux */
 +      case ASTSW:     return OPVCC(31,661,0,0);       /* stswx */
 +      case AMOVWBR:   return OPVCC(31,662,0,0);       /* stwbrx */
 +      case ASTWCCC:   return OPVCC(31,150,0,1);       /* stwcx. */
 +      case ASTDCCC:   return OPVCC(31,214,0,1);       /* stwdx. */
 +      case AECOWX:    return OPVCC(31,438,0,0);       /* ecowx */
 +      case AMOVD:     return OPVCC(31,149,0,0);       /* stdx */
 +      case AMOVDU:    return OPVCC(31,181,0,0);       /* stdux */
 +      }
 +      ctxt->diag("unknown storex opcode %A", a);
 +      return 0;
 +}
 +
index d0c14dfb5737214396247d2be2156cb586403572,0000000000000000000000000000000000000000..3906181a31dba5a4e749f2a078855c49c15a1c59
mode 100644,000000..100644
--- /dev/null
@@@ -1,1072 -1,0 +1,1072 @@@
- #include "../pkg/runtime/stack.h"
- #include "../pkg/runtime/funcdata.h"
 +// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
 +//
 +//    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-2008 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-2008 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 <u.h>
 +#include <libc.h>
 +#include <bio.h>
 +#include <link.h>
 +#include "../cmd/9l/9.out.h"
++#include "../runtime/stack.h"
++#include "../runtime/funcdata.h"
 +
 +static Prog zprg = {
 +      .as = AGOK,
 +      .reg = NREG,
 +      .from = {
 +              .name = D_NONE,
 +              .type = D_NONE,
 +              .reg = NREG,
 +      },
 +      .from3 = {
 +              .name = D_NONE,
 +              .type = D_NONE,
 +              .reg = NREG,
 +      },
 +      .to = {
 +              .name = D_NONE,
 +              .type = D_NONE,
 +              .reg = NREG,
 +      },
 +};
 +
 +static int
 +symtype(Addr *a)
 +{
 +      return a->name;
 +}
 +
 +static int
 +isdata(Prog *p)
 +{
 +      return p->as == ADATA || p->as == AGLOBL;
 +}
 +
 +static int
 +iscall(Prog *p)
 +{
 +      return p->as == ABL;
 +}
 +
 +static int
 +datasize(Prog *p)
 +{
 +      return p->reg;
 +}
 +
 +static int
 +textflag(Prog *p)
 +{
 +      return p->reg;
 +}
 +
 +static void
 +settextflag(Prog *p, int f)
 +{
 +      p->reg = f;
 +}
 +
 +static void
 +progedit(Link *ctxt, Prog *p)
 +{
 +      char literal[64];
 +      LSym *s;
 +
 +      USED(ctxt);
 +
 +      p->from.class = 0;
 +      p->to.class = 0;
 +
 +      // Rewrite BR/BL to symbol as D_BRANCH.
 +      switch(p->as) {
 +      case ABR:
 +      case ABL:
 +      case ARETURN:
 +      case ADUFFZERO:
 +      case ADUFFCOPY:
 +              if(p->to.sym != nil)
 +                      p->to.type = D_BRANCH;
 +              break;
 +      }
 +
 +      // Rewrite float constants to values stored in memory.
 +      switch(p->as) {
 +      case AFMOVS:
 +              if(p->from.type == D_FCONST) {
 +                      int32 i32;
 +                      float32 f32;
 +                      f32 = p->from.u.dval;
 +                      memmove(&i32, &f32, 4);
 +                      sprint(literal, "$f32.%08ux", (uint32)i32);
 +                      s = linklookup(ctxt, literal, 0);
 +                      s->size = 4;
 +                      p->from.type = D_OREG;
 +                      p->from.sym = s;
 +                      p->from.name = D_EXTERN;
 +                      p->from.offset = 0;
 +              }
 +              break;
 +      case AFMOVD:
 +              if(p->from.type == D_FCONST) {
 +                      int64 i64;
 +                      memmove(&i64, &p->from.u.dval, 8);
 +                      sprint(literal, "$f64.%016llux", (uvlong)i64);
 +                      s = linklookup(ctxt, literal, 0);
 +                      s->size = 8;
 +                      p->from.type = D_OREG;
 +                      p->from.sym = s;
 +                      p->from.name = D_EXTERN;
 +                      p->from.offset = 0;
 +              }
 +              break;
 +      case AMOVD:
 +              if(p->from.type == D_CONST && p->from.name == D_NONE && (int64)(uint32)p->from.offset != p->from.offset) {
 +                      sprint(literal, "$i64.%016llux", (uvlong)p->from.offset);
 +                      s = linklookup(ctxt, literal, 0);
 +                      s->size = 8;
 +                      p->from.type = D_OREG;
 +                      p->from.sym = s;
 +                      p->from.name = D_EXTERN;
 +                      p->from.offset = 0;
 +              }
 +      }
 +
 +      // Rewrite SUB constants into ADD.
 +      switch(p->as) {
 +      case ASUBC:
 +              if(p->from.type == D_CONST) {
 +                      p->from.offset = -p->from.offset;
 +                      p->as = AADDC;
 +              }
 +              break;
 +
 +      case ASUBCCC:
 +              if(p->from.type == D_CONST) {
 +                      p->from.offset = -p->from.offset;
 +                      p->as = AADDCCC;
 +              }
 +              break;
 +
 +      case ASUB:
 +              if(p->from.type == D_CONST) {
 +                      p->from.offset = -p->from.offset;
 +                      p->as = AADD;
 +              }
 +              break;
 +      }
 +}
 +
 +static Prog*  stacksplit(Link*, Prog*, int32, int);
 +
 +static void
 +parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
 +{
 +      *textstksiz = arg & 0xffffffffLL;
 +      if(*textstksiz & 0x80000000LL)
 +              *textstksiz = -(-*textstksiz & 0xffffffffLL);
 +
 +      *textarg = (arg >> 32) & 0xffffffffLL;
 +      if(*textarg & 0x80000000LL)
 +              *textarg = 0;
 +      *textarg = (*textarg+7) & ~7LL;
 +}
 +
 +static void
 +addstacksplit(Link *ctxt, LSym *cursym)
 +{
 +      Prog *p, *q, *q1;
 +      int o, mov, aoffset;
 +      vlong textstksiz, textarg;
 +      int32 autoffset, autosize;
 +
 +      if(ctxt->symmorestack[0] == nil) {
 +              ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
 +              ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
 +              // TODO(minux): add morestack short-cuts with small fixed frame-size.
 +      }
 +
 +      ctxt->cursym = cursym;
 +
 +      if(cursym->text == nil || cursym->text->link == nil)
 +              return;                         
 +
 +      p = cursym->text;
 +      parsetextconst(p->to.offset, &textstksiz, &textarg);
 +      autoffset = textstksiz;
 +      if(autoffset < 0)
 +              autoffset = 0;
 +      
 +      cursym->args = p->to.offset>>32;
 +      cursym->locals = textstksiz;
 +
 +      /*
 +       * find leaf subroutines
 +       * strip NOPs
 +       * expand RET
 +       * expand BECOME pseudo
 +       */
 +
 +      if(ctxt->debugvlog)
 +              Bprint(ctxt->bso, "%5.2f noops\n", cputime());
 +      Bflush(ctxt->bso);
 +
 +      q = nil;
 +      for(p = cursym->text; p != nil; p = p->link) {
 +              switch(p->as) {
 +              /* too hard, just leave alone */
 +              case ATEXT:
 +                      q = p;
 +                      p->mark |= LABEL|LEAF|SYNC;
 +                      if(p->link)
 +                              p->link->mark |= LABEL;
 +                      break;
 +
 +              case ANOR:
 +                      q = p;
 +                      if(p->to.type == D_REG)
 +                              if(p->to.reg == REGZERO)
 +                                      p->mark |= LABEL|SYNC;
 +                      break;
 +
 +              case ALWAR:
 +              case ASTWCCC:
 +              case AECIWX:
 +              case AECOWX:
 +              case AEIEIO:
 +              case AICBI:
 +              case AISYNC:
 +              case ATLBIE:
 +              case ATLBIEL:
 +              case ASLBIA:
 +              case ASLBIE:
 +              case ASLBMFEE:
 +              case ASLBMFEV:
 +              case ASLBMTE:
 +              case ADCBF:
 +              case ADCBI:
 +              case ADCBST:
 +              case ADCBT:
 +              case ADCBTST:
 +              case ADCBZ:
 +              case ASYNC:
 +              case ATLBSYNC:
 +              case APTESYNC:
 +              case ATW:
 +              case AWORD:
 +              case ARFI:
 +              case ARFCI:
 +              case ARFID:
 +              case AHRFID:
 +                      q = p;
 +                      p->mark |= LABEL|SYNC;
 +                      continue;
 +
 +              case AMOVW:
 +              case AMOVWZ:
 +              case AMOVD:
 +                      q = p;
 +                      switch(p->from.type) {
 +                      case D_MSR:
 +                      case D_SPR:
 +                      case D_FPSCR:
 +                      case D_CREG:
 +                      case D_DCR:
 +                              p->mark |= LABEL|SYNC;
 +                      }
 +                      switch(p->to.type) {
 +                      case D_MSR:
 +                      case D_SPR:
 +                      case D_FPSCR:
 +                      case D_CREG:
 +                      case D_DCR:
 +                              p->mark |= LABEL|SYNC;
 +                      }
 +                      continue;
 +
 +              case AFABS:
 +              case AFABSCC:
 +              case AFADD:
 +              case AFADDCC:
 +              case AFCTIW:
 +              case AFCTIWCC:
 +              case AFCTIWZ:
 +              case AFCTIWZCC:
 +              case AFDIV:
 +              case AFDIVCC:
 +              case AFMADD:
 +              case AFMADDCC:
 +              case AFMOVD:
 +              case AFMOVDU:
 +              /* case AFMOVDS: */
 +              case AFMOVS:
 +              case AFMOVSU:
 +              /* case AFMOVSD: */
 +              case AFMSUB:
 +              case AFMSUBCC:
 +              case AFMUL:
 +              case AFMULCC:
 +              case AFNABS:
 +              case AFNABSCC:
 +              case AFNEG:
 +              case AFNEGCC:
 +              case AFNMADD:
 +              case AFNMADDCC:
 +              case AFNMSUB:
 +              case AFNMSUBCC:
 +              case AFRSP:
 +              case AFRSPCC:
 +              case AFSUB:
 +              case AFSUBCC:
 +                      q = p;
 +                      p->mark |= FLOAT;
 +                      continue;
 +
 +              case ABL:
 +              case ABCL:
 +              case ADUFFZERO:
 +              case ADUFFCOPY:
 +                      cursym->text->mark &= ~LEAF;
 +
 +              case ABC:
 +              case ABEQ:
 +              case ABGE:
 +              case ABGT:
 +              case ABLE:
 +              case ABLT:
 +              case ABNE:
 +              case ABR:
 +              case ABVC:
 +              case ABVS:
 +                      p->mark |= BRANCH;
 +                      q = p;
 +                      q1 = p->pcond;
 +                      if(q1 != nil) {
 +                              while(q1->as == ANOP) {
 +                                      q1 = q1->link;
 +                                      p->pcond = q1;
 +                              }
 +                              if(!(q1->mark & LEAF))
 +                                      q1->mark |= LABEL;
 +                      } else
 +                              p->mark |= LABEL;
 +                      q1 = p->link;
 +                      if(q1 != nil)
 +                              q1->mark |= LABEL;
 +                      continue;
 +
 +              case AFCMPO:
 +              case AFCMPU:
 +                      q = p;
 +                      p->mark |= FCMP|FLOAT;
 +                      continue;
 +
 +              case ARETURN:
 +                      q = p;
 +                      if(p->link != nil)
 +                              p->link->mark |= LABEL;
 +                      continue;
 +
 +              case ANOP:
 +                      q1 = p->link;
 +                      q->link = q1;           /* q is non-nop */
 +                      q1->mark |= p->mark;
 +                      continue;
 +
 +              default:
 +                      q = p;
 +                      continue;
 +              }
 +      }
 +
 +      autosize = 0;
 +      for(p = cursym->text; p != nil; p = p->link) {
 +              o = p->as;
 +              switch(o) {
 +              case ATEXT:
 +                      mov = AMOVD;
 +                      aoffset = 0;
 +                      autosize = textstksiz + 8;
 +                      if((p->mark & LEAF) && autosize <= 8)
 +                              autosize = 0;
 +                      else
 +                              if(autosize & 4)
 +                                      autosize += 4;
 +                      p->to.offset = (p->to.offset & (0xffffffffull<<32)) | (uint32)(autosize-8);
 +
 +                      if(!(p->reg & NOSPLIT))
 +                              p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check
 +
 +                      q = p;
 +                      if(autosize) {
 +                              /* use MOVDU to adjust R1 when saving R31, if autosize is small */
 +                              if(!(cursym->text->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
 +                                      mov = AMOVDU;
 +                                      aoffset = -autosize;
 +                              } else {
 +                                      q = appendp(ctxt, p);
 +                                      q->as = AADD;
 +                                      q->lineno = p->lineno;
 +                                      q->from.type = D_CONST;
 +                                      q->from.offset = -autosize;
 +                                      q->to.type = D_REG;
 +                                      q->to.reg = REGSP;
 +                                      q->spadj = +autosize;
 +                              }
 +                      } else
 +                      if(!(cursym->text->mark & LEAF)) {
 +                              if(ctxt->debugvlog) {
 +                                      Bprint(ctxt->bso, "save suppressed in: %s\n",
 +                                              cursym->name);
 +                                      Bflush(ctxt->bso);
 +                              }
 +                              cursym->text->mark |= LEAF;
 +                      }
 +
 +                      if(cursym->text->mark & LEAF) {
 +                              cursym->leaf = 1;
 +                              break;
 +                      }
 +
 +                      q = appendp(ctxt, q);
 +                      q->as = AMOVD;
 +                      q->lineno = p->lineno;
 +                      q->from.type = D_SPR;
 +                      q->from.offset = D_LR;
 +                      q->to.type = D_REG;
 +                      q->to.reg = REGTMP;
 +
 +                      q = appendp(ctxt, q);
 +                      q->as = mov;
 +                      q->lineno = p->lineno;
 +                      q->from.type = D_REG;
 +                      q->from.reg = REGTMP;
 +                      q->to.type = D_OREG;
 +                      q->to.offset = aoffset;
 +                      q->to.reg = REGSP;
 +                      if(q->as == AMOVDU)
 +                              q->spadj = -aoffset;
 +
 +                      if(cursym->text->reg & WRAPPER) {
 +                              // g->panicwrap += autosize;
 +                              // MOVWZ panicwrap_offset(g), R3
 +                              // ADD $autosize, R3
 +                              // MOVWZ R3, panicwrap_offset(g)
 +                              p = appendp(ctxt, q);
 +                              p->as = AMOVWZ;
 +                              p->from.type = D_OREG;
 +                              p->from.reg = REGG;
 +                              p->from.offset = 2*ctxt->arch->ptrsize;
 +                              p->to.type = D_REG;
 +                              p->to.reg = 3;
 +
 +                              p = appendp(ctxt, p);
 +                              p->as = AADD;
 +                              p->from.type = D_CONST;
 +                              p->from.offset = autosize;
 +                              p->to.type = D_REG;
 +                              p->to.reg = 3;
 +
 +                              p = appendp(ctxt, p);
 +                              p->as = AMOVWZ;
 +                              p->from.type = D_REG;
 +                              p->from.reg = 3;
 +                              p->to.type = D_OREG;
 +                              p->to.reg = REGG;
 +                              p->to.offset = 2*ctxt->arch->ptrsize;
 +                      }
 +
 +                      break;
 +
 +              case ARETURN:
 +                      if(p->from.type == D_CONST) {
 +                              ctxt->diag("using BECOME (%P) is not supported!", p);
 +                              break;
 +                      }
 +                      if(p->to.sym) { // retjmp
 +                              p->as = ABR;
 +                              p->to.type = D_BRANCH;
 +                              break;
 +                      }
 +                      if(cursym->text->reg & WRAPPER) {
 +                              // g->panicwrap -= autosize;
 +                              // MOVWZ panicwrap_offset(g), R3
 +                              // ADD $-autosize, R3
 +                              // MOVWZ R3, panicwrap_offset(g)
 +                              p->as = AMOVWZ;
 +                              p->from.type = D_OREG;
 +                              p->from.reg = REGG;
 +                              p->from.offset = 2*ctxt->arch->ptrsize;
 +                              p->to.type = D_REG;
 +                              p->to.reg = 3;
 +                              p = appendp(ctxt, p);
 +
 +                              p->as = AADD;
 +                              p->from.type = D_CONST;
 +                              p->from.offset = -autosize;
 +                              p->to.type = D_REG;
 +                              p->to.reg = 3;
 +                              p = appendp(ctxt, p);
 +
 +                              p->as = AMOVWZ;
 +                              p->from.type = D_REG;
 +                              p->from.reg = 3;
 +                              p->to.type = D_OREG;
 +                              p->to.reg = REGG;
 +                              p->to.offset = 2*ctxt->arch->ptrsize;
 +                              p = appendp(ctxt, p);
 +
 +                              p->as = ARETURN;
 +                      }
 +                      if(cursym->text->mark & LEAF) {
 +                              if(!autosize) {
 +                                      p->as = ABR;
 +                                      p->from = zprg.from;
 +                                      p->to.type = D_SPR;
 +                                      p->to.offset = D_LR;
 +                                      p->mark |= BRANCH;
 +                                      break;
 +                              }
 +
 +                              p->as = AADD;
 +                              p->from.type = D_CONST;
 +                              p->from.offset = autosize;
 +                              p->to.type = D_REG;
 +                              p->to.reg = REGSP;
 +                              p->spadj = -autosize;
 +
 +                              q = ctxt->arch->prg();
 +                              q->as = ABR;
 +                              q->lineno = p->lineno;
 +                              q->to.type = D_SPR;
 +                              q->to.offset = D_LR;
 +                              q->mark |= BRANCH;
 +                              q->spadj = +autosize;
 +
 +                              q->link = p->link;
 +                              p->link = q;
 +                              break;
 +                      }
 +
 +                      p->as = AMOVD;
 +                      p->from.type = D_OREG;
 +                      p->from.offset = 0;
 +                      p->from.reg = REGSP;
 +                      p->to.type = D_REG;
 +                      p->to.reg = REGTMP;
 +
 +                      q = ctxt->arch->prg();
 +                      q->as = AMOVD;
 +                      q->lineno = p->lineno;
 +                      q->from.type = D_REG;
 +                      q->from.reg = REGTMP;
 +                      q->to.type = D_SPR;
 +                      q->to.offset = D_LR;
 +
 +                      q->link = p->link;
 +                      p->link = q;
 +                      p = q;
 +
 +                      if(autosize) {
 +                              q = ctxt->arch->prg();
 +                              q->as = AADD;
 +                              q->lineno = p->lineno;
 +                              q->from.type = D_CONST;
 +                              q->from.offset = autosize;
 +                              q->to.type = D_REG;
 +                              q->to.reg = REGSP;
 +                              q->spadj = -autosize;
 +
 +                              q->link = p->link;
 +                              p->link = q;
 +                      }
 +
 +                      q1 = ctxt->arch->prg();
 +                      q1->as = ABR;
 +                      q1->lineno = p->lineno;
 +                      q1->to.type = D_SPR;
 +                      q1->to.offset = D_LR;
 +                      q1->mark |= BRANCH;
 +                      q1->spadj = +autosize;
 +
 +                      q1->link = q->link;
 +                      q->link = q1;
 +                      break;
 +
 +              case AADD:
 +                      if(p->to.type == D_REG && p->to.reg == REGSP && p->from.type == D_CONST)
 +                              p->spadj = -p->from.offset;
 +                      break;
 +              }
 +      }
 +
 +#if 0 // instruction scheduling
 +      if(debug['Q'] == 0)
 +              return;
 +
 +      curtext = nil;
 +      q = nil;        /* p - 1 */
 +      q1 = firstp;    /* top of block */
 +      o = 0;          /* count of instructions */
 +      for(p = firstp; p != nil; p = p1) {
 +              p1 = p->link;
 +              o++;
 +              if(p->mark & NOSCHED){
 +                      if(q1 != p){
 +                              sched(q1, q);
 +                      }
 +                      for(; p != nil; p = p->link){
 +                              if(!(p->mark & NOSCHED))
 +                                      break;
 +                              q = p;
 +                      }
 +                      p1 = p;
 +                      q1 = p;
 +                      o = 0;
 +                      continue;
 +              }
 +              if(p->mark & (LABEL|SYNC)) {
 +                      if(q1 != p)
 +                              sched(q1, q);
 +                      q1 = p;
 +                      o = 1;
 +              }
 +              if(p->mark & (BRANCH|SYNC)) {
 +                      sched(q1, p);
 +                      q1 = p1;
 +                      o = 0;
 +              }
 +              if(o >= NSCHED) {
 +                      sched(q1, p);
 +                      q1 = p1;
 +                      o = 0;
 +              }
 +              q = p;
 +      }
 +#endif
 +}
 +
 +static Prog*
 +stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
 +{
 +      int32 arg;
 +      Prog *q, *q1;
 +
 +      // MOVD g_stackguard(g), R3
 +      p = appendp(ctxt, p);
 +      p->as = AMOVD;
 +      p->from.type = D_OREG;
 +      p->from.reg = REGG;
 +      p->to.type = D_REG;
 +      p->to.reg = 3;
 +
 +      q = nil;
 +      if(framesize <= StackSmall) {
 +              // small stack: SP < stackguard
 +              //      CMP     stackguard, SP
 +              p = appendp(ctxt, p);
 +              p->as = ACMPU;
 +              p->from.type = D_REG;
 +              p->from.reg = 3;
 +              p->to.type = D_REG;
 +              p->to.reg = REGSP;
 +      } else if(framesize <= StackBig) {
 +              // large stack: SP-framesize < stackguard-StackSmall
 +              //      ADD $-framesize, SP, R4
 +              //      CMP stackguard, R4
 +              p = appendp(ctxt, p);
 +              p->as = AADD;
 +              p->from.type = D_CONST;
 +              p->from.offset = -framesize;
 +              p->reg = REGSP;
 +              p->to.type = D_REG;
 +              p->to.reg = 4;
 +
 +              p = appendp(ctxt, p);
 +              p->as = ACMPU;
 +              p->from.type = D_REG;
 +              p->from.reg = 3;
 +              p->to.type = D_REG;
 +              p->to.reg = 4;
 +      } else {
 +              // Such a large stack we need to protect against wraparound.
 +              // If SP is close to zero:
 +              //      SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
 +              // The +StackGuard on both sides is required to keep the left side positive:
 +              // SP is allowed to be slightly below stackguard. See stack.h.
 +              //
 +              // Preemption sets stackguard to StackPreempt, a very large value.
 +              // That breaks the math above, so we have to check for that explicitly.
 +              //      // stackguard is R3
 +              //      CMP     R3, $StackPreempt
 +              //      BEQ     label-of-call-to-morestack
 +              //      ADD     $StackGuard, SP, R4
 +              //      SUB     R3, R4
 +              //      MOVD    $(framesize+(StackGuard-StackSmall)), R31
 +              //      CMPU    R31, R4
 +              p = appendp(ctxt, p);
 +              p->as = ACMP;
 +              p->from.type = D_REG;
 +              p->from.reg = 3;
 +              p->to.type = D_CONST;
 +              p->to.offset = StackPreempt;
 +
 +              q = p = appendp(ctxt, p);
 +              p->as = ABEQ;
 +              p->to.type = D_BRANCH;
 +
 +              p = appendp(ctxt, p);
 +              p->as = AADD;
 +              p->from.type = D_CONST;
 +              p->from.offset = StackGuard;
 +              p->reg = REGSP;
 +              p->to.type = D_REG;
 +              p->to.reg = 4;
 +
 +              p = appendp(ctxt, p);
 +              p->as = ASUB;
 +              p->from.type = D_REG;
 +              p->from.reg = 3;
 +              p->to.type = D_REG;
 +              p->to.reg = 4;
 +
 +              p = appendp(ctxt, p);
 +              p->as = AMOVD;
 +              p->from.type = D_CONST;
 +              p->from.offset = framesize + StackGuard - StackSmall;
 +              p->to.type = D_REG;
 +              p->to.reg = REGTMP;
 +
 +              p = appendp(ctxt, p);
 +              p->as = ACMPU;
 +              p->from.type = D_REG;
 +              p->from.reg = REGTMP;
 +              p->to.type = D_REG;
 +              p->to.reg = 4;
 +      }
 +
 +      // q1: BLT      done
 +      q1 = p = appendp(ctxt, p);
 +      p->as = ABLT;
 +      p->to.type = D_BRANCH;
 +
 +      // MOVD $framesize, R3
 +      p = appendp(ctxt, p);
 +      p->as = AMOVD;
 +      p->from.type = D_CONST;
 +      p->from.offset = framesize;
 +      p->to.type = D_REG;
 +      p->to.reg = 3;
 +      if(q)
 +              q->pcond = p;
 +
 +      // MOVD $args, R4
 +      p = appendp(ctxt, p);
 +      p->as = AMOVD;
 +      p->from.type = D_CONST;
 +      arg = (ctxt->cursym->text->to.offset >> 32) & 0xffffffffull;
 +      if(arg == 1) // special marker for known 0
 +              arg = 0;
 +      else if(arg == ArgsSizeUnknown)
 +              ctxt->diag("%s: arg size unknown, but split stack", ctxt->cursym->name);
 +      if(arg&7)
 +              ctxt->diag("misaligned argument size in stack split: %d", arg);
 +      p->from.offset = arg;
 +      p->to.type = D_REG;
 +      p->to.reg = 4;
 +
 +      // MOVD LR, R5
 +      p = appendp(ctxt, p);
 +      p->as = AMOVD;
 +      p->from.type = D_SPR;
 +      p->from.offset = D_LR;
 +      p->to.type = D_REG;
 +      p->to.reg = 5;
 +
 +      // BL   runtime.morestack(SB)
 +      p = appendp(ctxt, p);
 +      p->as = ABL;
 +      p->to.type = D_BRANCH;
 +      p->to.sym = ctxt->symmorestack[noctxt];
 +
 +      // BR   start
 +      p = appendp(ctxt, p);
 +      p->as = ABR;
 +      p->to.type = D_BRANCH;
 +      p->pcond = ctxt->cursym->text->link;
 +
 +      // placeholder for q1's jump target
 +      p = appendp(ctxt, p);
 +      p->as = ANOP; // zero-width place holder
 +      q1->pcond = p;
 +
 +      return p;
 +}
 +
 +static void xfol(Link*, Prog*, Prog**);
 +
 +static void
 +follow(Link *ctxt, LSym *s)
 +{
 +      Prog *firstp, *lastp;
 +
 +      ctxt->cursym = s;
 +
 +      firstp = ctxt->arch->prg();
 +      lastp = firstp;
 +      xfol(ctxt, s->text, &lastp);
 +      lastp->link = nil;
 +      s->text = firstp->link;
 +}
 +
 +static int
 +relinv(int a)
 +{
 +
 +      switch(a) {
 +      case ABEQ:      return ABNE;
 +      case ABNE:      return ABEQ;
 +
 +      case ABGE:      return ABLT;
 +      case ABLT:      return ABGE;
 +
 +      case ABGT:      return ABLE;
 +      case ABLE:      return ABGT;
 +
 +      case ABVC:      return ABVS;
 +      case ABVS:      return ABVC;
 +      }
 +      return 0;
 +}
 +
 +static void
 +xfol(Link *ctxt, Prog *p, Prog **last)
 +{
 +      Prog *q, *r;
 +      int a, b, i;
 +
 +loop:
 +      if(p == nil)
 +              return;
 +      a = p->as;
 +      if(a == ABR) {
 +              q = p->pcond;
 +              if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
 +                      p->mark |= FOLL;
 +                      (*last)->link = p;
 +                      *last = p;
 +                      p = p->link;
 +                      xfol(ctxt, p, last);
 +                      p = q;
 +                      if(p && !(p->mark & FOLL))
 +                              goto loop;
 +                      return;
 +              }
 +              if(q != nil) {
 +                      p->mark |= FOLL;
 +                      p = q;
 +                      if(!(p->mark & FOLL))
 +                              goto loop;
 +              }
 +      }
 +      if(p->mark & FOLL) {
 +              for(i=0,q=p; i<4; i++,q=q->link) {
 +                      if(q == *last || (q->mark&NOSCHED))
 +                              break;
 +                      b = 0;          /* set */
 +                      a = q->as;
 +                      if(a == ANOP) {
 +                              i--;
 +                              continue;
 +                      }
 +                      if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
 +                              goto copy;
 +                      if(!q->pcond || (q->pcond->mark&FOLL))
 +                              continue;
 +                      b = relinv(a);
 +                      if(!b)
 +                              continue;
 +              copy:
 +                      for(;;) {
 +                              r = ctxt->arch->prg();
 +                              *r = *p;
 +                              if(!(r->mark&FOLL))
 +                                      print("cant happen 1\n");
 +                              r->mark |= FOLL;
 +                              if(p != q) {
 +                                      p = p->link;
 +                                      (*last)->link = r;
 +                                      *last = r;
 +                                      continue;
 +                              }
 +                              (*last)->link = r;
 +                              *last = r;
 +                              if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
 +                                      return;
 +                              r->as = b;
 +                              r->pcond = p->link;
 +                              r->link = p->pcond;
 +                              if(!(r->link->mark&FOLL))
 +                                      xfol(ctxt, r->link, last);
 +                              if(!(r->pcond->mark&FOLL))
 +                                      print("cant happen 2\n");
 +                              return;
 +                      }
 +              }
 +
 +              a = ABR;
 +              q = ctxt->arch->prg();
 +              q->as = a;
 +              q->lineno = p->lineno;
 +              q->to.type = D_BRANCH;
 +              q->to.offset = p->pc;
 +              q->pcond = p;
 +              p = q;
 +      }
 +      p->mark |= FOLL;
 +      (*last)->link = p;
 +      *last = p;
 +      if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID){
 +              if(p->mark & NOSCHED){
 +                      p = p->link;
 +                      goto loop;
 +              }
 +              return;
 +      }
 +      if(p->pcond != nil)
 +      if(a != ABL && p->link != nil) {
 +              xfol(ctxt, p->link, last);
 +              p = p->pcond;
 +              if(p == nil || (p->mark&FOLL))
 +                      return;
 +              goto loop;
 +      }
 +      p = p->link;
 +      goto loop;
 +}
 +
 +static Prog*
 +prg(void)
 +{
 +      Prog *p;
 +
 +      p = emallocz(sizeof(*p));
 +      *p = zprg;
 +      return p;
 +}
 +
 +LinkArch linkpower64 = {
 +      .name = "power64",
 +      .thechar = '9',
 +      .endian = BigEndian,
 +
 +      .addstacksplit = addstacksplit,
 +      .assemble = span9,
 +      .datasize = datasize,
 +      .follow = follow,
 +      .iscall = iscall,
 +      .isdata = isdata,
 +      .prg = prg,
 +      .progedit = progedit,
 +      .settextflag = settextflag,
 +      .symtype = symtype,
 +      .textflag = textflag,
 +
 +      .minlc = 4,
 +      .ptrsize = 8,
 +      .regsize = 8,
 +
 +      .D_ADDR = D_ADDR,
 +      .D_AUTO = D_AUTO,
 +      .D_BRANCH = D_BRANCH,
 +      .D_CONST = D_CONST,
 +      .D_EXTERN = D_EXTERN,
 +      .D_FCONST = D_FCONST,
 +      .D_NONE = D_NONE,
 +      .D_PARAM = D_PARAM,
 +      .D_SCONST = D_SCONST,
 +      .D_STATIC = D_STATIC,
 +
 +      .ACALL = ABL,
 +      .ADATA = ADATA,
 +      .AEND = AEND,
 +      .AFUNCDATA = AFUNCDATA,
 +      .AGLOBL = AGLOBL,
 +      .AJMP = ABR,
 +      .ANOP = ANOP,
 +      .APCDATA = APCDATA,
 +      .ARET = ARETURN,
 +      .ATEXT = ATEXT,
 +      .ATYPE = ATYPE,
 +      .AUSEFIELD = AUSEFIELD,
 +};
 +
 +LinkArch linkpower64le = {
 +      .name = "power64le",
 +      .thechar = '9',
 +      .endian = LittleEndian,
 +
 +      .addstacksplit = addstacksplit,
 +      .assemble = span9,
 +      .datasize = datasize,
 +      .follow = follow,
 +      .iscall = iscall,
 +      .isdata = isdata,
 +      .prg = prg,
 +      .progedit = progedit,
 +      .settextflag = settextflag,
 +      .symtype = symtype,
 +      .textflag = textflag,
 +
 +      .minlc = 4,
 +      .ptrsize = 8,
 +      .regsize = 8,
 +
 +      .D_ADDR = D_ADDR,
 +      .D_AUTO = D_AUTO,
 +      .D_BRANCH = D_BRANCH,
 +      .D_CONST = D_CONST,
 +      .D_EXTERN = D_EXTERN,
 +      .D_FCONST = D_FCONST,
 +      .D_NONE = D_NONE,
 +      .D_PARAM = D_PARAM,
 +      .D_SCONST = D_SCONST,
 +      .D_STATIC = D_STATIC,
 +
 +      .ACALL = ABL,
 +      .ADATA = ADATA,
 +      .AEND = AEND,
 +      .AFUNCDATA = AFUNCDATA,
 +      .AGLOBL = AGLOBL,
 +      .AJMP = ABR,
 +      .ANOP = ANOP,
 +      .APCDATA = APCDATA,
 +      .ARET = ARETURN,
 +      .ATEXT = ATEXT,
 +      .ATYPE = ATYPE,
 +      .AUSEFIELD = AUSEFIELD,
 +};
index 3ba8201b3be048923cdbc53481b40d867fe6ec34,0000000000000000000000000000000000000000..3ba8201b3be048923cdbc53481b40d867fe6ec34
mode 100644,000000..100644
--- /dev/null
index c33a9209f1cb9d664ddae00a464b5167f64bbff7,0000000000000000000000000000000000000000..c33a9209f1cb9d664ddae00a464b5167f64bbff7
mode 100644,000000..100644
--- /dev/null
index 0cb86144a771f079c33c0c542ccde827568f0271,0000000000000000000000000000000000000000..0cb86144a771f079c33c0c542ccde827568f0271
mode 100644,000000..100644
--- /dev/null
Simple merge
Simple merge
index e430cdf04c98374e29bed0ffdc3c7e3072bb12e9,0000000000000000000000000000000000000000..e430cdf04c98374e29bed0ffdc3c7e3072bb12e9
mode 100644,000000..100644
--- /dev/null
Simple merge
index 7cfb9da2fcdb9df14e69ecab73ce5f2cb0b4a243,0000000000000000000000000000000000000000..7cfb9da2fcdb9df14e69ecab73ce5f2cb0b4a243
mode 100644,000000..100644
--- /dev/null
index 684ac9953bae7eb9d9eaca3dc0a5c848cf198af8,0000000000000000000000000000000000000000..684ac9953bae7eb9d9eaca3dc0a5c848cf198af8
mode 100644,000000..100644
--- /dev/null
index a0511de8e6ae3b1edc4d8db5127752051bc3aabc,0000000000000000000000000000000000000000..a0511de8e6ae3b1edc4d8db5127752051bc3aabc
mode 100644,000000..100644
--- /dev/null
index c08590ac979cc4773713d74a2ca7b43aa6740933,0000000000000000000000000000000000000000..c08590ac979cc4773713d74a2ca7b43aa6740933
mode 100644,000000..100644
--- /dev/null
Simple merge
index eb65f9d1ed105383b593fb85b1a957a9995d3b56,0000000000000000000000000000000000000000..eb65f9d1ed105383b593fb85b1a957a9995d3b56
mode 100644,000000..100644
--- /dev/null
Simple merge
index 64f145672c54d80d834a2d82400edb7f78258905,0000000000000000000000000000000000000000..64f145672c54d80d834a2d82400edb7f78258905
mode 100644,000000..100644
--- /dev/null
index 41db45ca14164493008f29da7dbcb51d3073b13b,0000000000000000000000000000000000000000..41db45ca14164493008f29da7dbcb51d3073b13b
mode 100644,000000..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 4a2437c209e2cb2d1136ae7f0cfe5943a767414f,0000000000000000000000000000000000000000..4a2437c209e2cb2d1136ae7f0cfe5943a767414f
mode 100644,000000..100644
--- /dev/null
index b618f0ad7b29aa76d4d8b552a4bbbb319b47aa43,0000000000000000000000000000000000000000..b618f0ad7b29aa76d4d8b552a4bbbb319b47aa43
mode 100644,000000..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e944bcdbf8cad6dbfb54b759dd9da1017bf58ca7,0000000000000000000000000000000000000000..e944bcdbf8cad6dbfb54b759dd9da1017bf58ca7
mode 100644,000000..100644
--- /dev/null
index 051815dbcecca2165771e5f88282b68eb6552b49,0000000000000000000000000000000000000000..051815dbcecca2165771e5f88282b68eb6552b49
mode 100644,000000..100644
--- /dev/null
index 840648920967ff08ad25418d52993537151473f7,0000000000000000000000000000000000000000..840648920967ff08ad25418d52993537151473f7
mode 100644,000000..100644
--- /dev/null
index 840648920967ff08ad25418d52993537151473f7,0000000000000000000000000000000000000000..840648920967ff08ad25418d52993537151473f7
mode 100644,000000..100644
--- /dev/null
index 89c5c78485d2bdfbba1dd2b04e009b89c02e2f86,0000000000000000000000000000000000000000..89c5c78485d2bdfbba1dd2b04e009b89c02e2f86
mode 100644,000000..100644
--- /dev/null
Simple merge
Simple merge
index fbd59a052f129930b5999b46fe00e4aa93020012,0000000000000000000000000000000000000000..fbd59a052f129930b5999b46fe00e4aa93020012
mode 100644,000000..100644
--- /dev/null
index 79d976255f5b5b22d3de7580e7d128765aa27507,0000000000000000000000000000000000000000..79d976255f5b5b22d3de7580e7d128765aa27507
mode 100644,000000..100644
--- /dev/null
Simple merge
index bdb1dcff4965634455eb4f1cd1e56679841695a1,0000000000000000000000000000000000000000..bdb1dcff4965634455eb4f1cd1e56679841695a1
mode 100644,000000..100644
--- /dev/null
index c9b0fe320c6ae8f6a85f36b68082bfdac12759ca,0000000000000000000000000000000000000000..c9b0fe320c6ae8f6a85f36b68082bfdac12759ca
mode 100644,000000..100644
--- /dev/null
Simple merge
Simple merge
index fd043627a2e2b116bf496d7fa7b6027d14ba4051,0000000000000000000000000000000000000000..fd043627a2e2b116bf496d7fa7b6027d14ba4051
mode 100644,000000..100644
--- /dev/null
Simple merge
index 15e0770c18bea89a94d3becb50ecf28c37355690,0000000000000000000000000000000000000000..15e0770c18bea89a94d3becb50ecf28c37355690
mode 100644,000000..100644
--- /dev/null
index fdecdf24dd3e83114f6070652baf8d8b467d2433,0000000000000000000000000000000000000000..fdecdf24dd3e83114f6070652baf8d8b467d2433
mode 100644,000000..100644
--- /dev/null
index 7808059cc8b76facf8b9803d02057eb2e4bd053a,0000000000000000000000000000000000000000..7808059cc8b76facf8b9803d02057eb2e4bd053a
mode 100644,000000..100644
--- /dev/null
index 7808059cc8b76facf8b9803d02057eb2e4bd053a,0000000000000000000000000000000000000000..7808059cc8b76facf8b9803d02057eb2e4bd053a
mode 100644,000000..100644
--- /dev/null
index 0567fd0ea852ac8f91d2b7a4abcf7a58a4297cd9,0000000000000000000000000000000000000000..0567fd0ea852ac8f91d2b7a4abcf7a58a4297cd9
mode 100644,000000..100644
--- /dev/null
index 52c63e3d3e9981cd53a30516ea54c406e997afdc,0000000000000000000000000000000000000000..52c63e3d3e9981cd53a30516ea54c406e997afdc
mode 100644,000000..100644
--- /dev/null
index 204d8068532cc42b6badc43dd4ca4b2c1b9eadc8,0000000000000000000000000000000000000000..204d8068532cc42b6badc43dd4ca4b2c1b9eadc8
mode 100644,000000..100644
--- /dev/null
index df481f5c760275e69e546b9a7434314d00023495,0000000000000000000000000000000000000000..df481f5c760275e69e546b9a7434314d00023495
mode 100644,000000..100644
--- /dev/null